From 051aa612f83c32ce5fa45aa3cae061499982deff Mon Sep 17 00:00:00 2001 From: Fiber Date: Sat, 17 Oct 2026 20:23:35 +0800 Subject: [PATCH] feat: expose week-one admin settings and preserve omitted limits --- README.md | 2 +- frontend/src/Access.test.tsx | 2 + frontend/src/ConsolidationReport.tsx | 88 +++++- frontend/src/ConsolidationSettings.test.tsx | 15 +- frontend/src/ConsolidationSettings.tsx | 171 +++++------ frontend/src/ConsolidationStatus.test.tsx | 8 +- frontend/src/ImageSettings.test.tsx | 13 +- frontend/src/Maintenance.tsx | 17 +- frontend/src/Media.test.tsx | 6 +- frontend/src/RuntimeSettings.tsx | 297 ++++++++++++++++++++ frontend/src/Settings.tsx | 208 +++----------- frontend/src/StateSettings.test.tsx | 4 +- frontend/src/Week1Maintenance.test.tsx | 160 +++++++++++ frontend/src/Week1Settings.test.tsx | 293 +++++++++++++++++++ frontend/src/consolidation-labels.ts | 15 + frontend/src/consolidation-types.ts | 8 + frontend/src/settings-draft.ts | 26 ++ frontend/src/types.ts | 2 + src/iris/settings_api.py | 12 +- src/iris/web/assets/index-Bn6dsR4V.js | 11 - src/iris/web/assets/index-CxPLpCWk.js | 11 + src/iris/web/index.html | 2 +- tests/test_limits_partial_settings.py | 72 +++++ 23 files changed, 1131 insertions(+), 312 deletions(-) create mode 100644 frontend/src/RuntimeSettings.tsx create mode 100644 frontend/src/Week1Maintenance.test.tsx create mode 100644 frontend/src/Week1Settings.test.tsx create mode 100644 frontend/src/settings-draft.ts delete mode 100644 src/iris/web/assets/index-Bn6dsR4V.js create mode 100644 src/iris/web/assets/index-CxPLpCWk.js create mode 100644 tests/test_limits_partial_settings.py diff --git a/README.md b/README.md index e19047b2..53eff0b6 100644 --- a/README.md +++ b/README.md @@ -147,7 +147,7 @@ docker start iris | `PUT /settings/models/{chat\|embedding}` | 保存模型;api_key 省略保留,空字符串清除,enabled=false 停用 | | `POST /settings/models/{chat\|embedding}/test` | 空 JSON 测已保存配置,模型 JSON 测草稿 | | `POST /settings/models/{chat\|embedding}/retry` | 对暂时不可用/账户问题请求重试 | -| `PATCH /settings/limits` | daily_token_limit(null 不限)、learning_concurrency、learning_image_limit、native_image_learning、media_retention_days(默认 7,整数 1—36500) | +| `PATCH /settings/limits` | daily_token_limit(null 不限)、learning_concurrency、learning_image_limit、native_image_learning、media_retention_days(默认 7,整数 1—36500);所有字段省略即保留现值,daily_token_limit 显式 null 才表示不限;操作记录只包含实际提交的字段 | ## 中文试用与管理界面 diff --git a/frontend/src/Access.test.tsx b/frontend/src/Access.test.tsx index 38b5dcb3..5ff9cc7f 100644 --- a/frontend/src/Access.test.tsx +++ b/frontend/src/Access.test.tsx @@ -160,6 +160,8 @@ test.each(["high", "medium"])( await user.click(screen.getByRole("button", { name: "测试对话模型连接" })); expect(await screen.findByText(/密钥无效.*12/)).toBeInTheDocument(); await user.click(screen.getByRole("button", { name: "保存对话模型" })); + await user.clear(screen.getByLabelText("学习并发")); + await user.type(screen.getByLabelText("学习并发"), "3"); await user.click(screen.getByRole("button", { name: "保存用量与学习" })); const saved = calls.find( (c) => diff --git a/frontend/src/ConsolidationReport.tsx b/frontend/src/ConsolidationReport.tsx index e8d79877..f5e6fdfc 100644 --- a/frontend/src/ConsolidationReport.tsx +++ b/frontend/src/ConsolidationReport.tsx @@ -9,6 +9,8 @@ import { Badge, Pagination, RoleTime, seconds } from "./ui"; import { PersonaChecks } from "./PersonaDetails"; import { personaDegrees } from "./persona-labels"; import { + consolidationBudgets, + consolidationSteps, consolidationReason, consolidationSwitches, suggestionKinds, @@ -334,6 +336,80 @@ function PersonSummaryReport({ data }: { data: MaintenanceReport }) { ); } +function StepBudgetReport({ data }: { data: MaintenanceReport }) { + const budgets = data.items.filter( + (item) => item.outcome === "model_step_budget", + ); + const trimmed = data.items.filter( + (item) => item.outcome === "backlog_trimmed", + ); + const expiry = data.question_expiry; + return ( + <> + {(data.consolidation || budgets.length > 0) && ( +
+

各步骤模型调用上限与用量

+

+ 每一步独立计数,包含重试和修正;上限沿用本次运行接受时的设置。未到期、关闭或没有任务的步骤可能没有记录。 +

+ {!budgets.length &&

本次未记录步骤用量。

} + {budgets.map((item) => ( +
+

+ {consolidationSteps[item.details.step || ""] || + item.details.step || + "未知步骤"} +

+

+ 本轮上限:{item.details.max_calls ?? "未记录"} 次 · 已用: + {item.details.calls_used ?? "未记录"} 次 +

+

+ 停止原因: + {item.reason ? consolidationReason(item.reason) : "未记录"} +

+
+ ))} +
+ )} + {!!trimmed.length && ( +
+

配对积压修剪

+ {trimmed.map((item) => ( +

+ 配对积压修剪:{item.details.count ?? "未记录"} 项 · + 待处理配对上限:{item.details.limit ?? "未记录"} 项 +

+ ))} +

+ 仅修剪待处理配对,不改变记忆;相关记忆发生变化后可重新规划。 +

+
+ )} + {expiry && ( +
+

询问到期结束

+

到期自动结束的询问:{expiry.count} 条

+

+ 仅学习产生且超过保留天数仍未结束的询问;宿主或管理员创建的询问和普通目标不受影响。 +

+
+ )} + + ); +} + export function ConsolidationReportSections({ data, openMemory, @@ -362,17 +438,18 @@ export function ConsolidationReportSections({

{calls.unknown_usage_calls ?? 0}{" "} - 次调用用量未知;用量为已知合计,包含实际重试、persona + 次调用用量未知;用量为四步骤已知合计,包含实际重试、入口画像、persona 及人物摘要调用。

)}
本次接受任务时的整理设置 -

- 模型调用次数预算: - {data.consolidation.settings.max_calls ?? "未记录"} -

+ {consolidationBudgets.map(([key, label]) => ( +

+ {label}:{data.consolidation?.settings[key] ?? "未记录"} +

+ ))} {consolidationSwitches.map(([key, label]) => (

{label}: @@ -387,6 +464,7 @@ export function ConsolidationReportSections({

)} + {(data.consolidation || data.items.some((i) => i.phase === "consolidation")) && ( <> diff --git a/frontend/src/ConsolidationSettings.test.tsx b/frontend/src/ConsolidationSettings.test.tsx index 3a7dc09b..556b77ba 100644 --- a/frontend/src/ConsolidationSettings.test.tsx +++ b/frontend/src/ConsolidationSettings.test.tsx @@ -78,7 +78,8 @@ beforeEach(() => { ); if (url.endsWith("/consolidation")) { settings.consolidation = { ...settings.consolidation, ...body }; - settings.lifecycle.maintenance_time = body.maintenance_time; + if ("maintenance_time" in body) + settings.lifecycle.maintenance_time = body.maintenance_time; } if (url.endsWith("/goal-dedup-judge")) settings.goal_dedup_judge = body; settings.operations = [ @@ -107,7 +108,7 @@ test("整理设置保存时间、调用预算与所有开关,并显示操作 target: { value: "04:15" }, }); fireEvent.change( - within(section).getByLabelText("每次整理的模型调用次数预算"), + within(section).getByLabelText("记忆整理(合并/矛盾/依赖)每轮调用上限"), { target: { value: "0" } }, ); await userEvent.click(within(section).getByLabelText("矛盾检查与建议")); @@ -122,12 +123,8 @@ test("整理设置保存时间、调用预算与所有开关,并显示操作 expect(request.body).toEqual({ maintenance_time: "04:15", max_calls: 0, - merge_enabled: true, conflict_enabled: false, - dependency_enabled: true, - persona_enabled: true, person_summary_enabled: false, - goal_review_enabled: true, }); expect((request.init?.headers as any)["X-Iris-CSRF"]).toBe( "consolidation-settings-test", @@ -136,19 +133,19 @@ test("整理设置保存时间、调用预算与所有开关,并显示操作 expect(within(section).getByText(/只影响之后接受的新运行/)).toBeVisible(); }); -test.each(["", "51", "1.5"])( +test.each(["", "-1", "1001", "1.5"])( "整理预算 %s 被阻止,未发送请求", async (input) => { render(); fireEvent.change( - await screen.findByLabelText("每次整理的模型调用次数预算"), + await screen.findByLabelText("记忆整理(合并/矛盾/依赖)每轮调用上限"), { target: { value: input } }, ); await userEvent.click( screen.getByRole("button", { name: "保存梦境整理设置" }), ); expect( - await screen.findByText(/模型调用次数预算须为 0—50 的整数/), + await screen.findByText(/每轮调用上限须为 0—1000 的整数/), ).toBeVisible(); expect(requests.some((r) => r.init?.method === "PATCH")).toBe(false); }, diff --git a/frontend/src/ConsolidationSettings.tsx b/frontend/src/ConsolidationSettings.tsx index 02cbd093..cfcd99dd 100644 --- a/frontend/src/ConsolidationSettings.tsx +++ b/frontend/src/ConsolidationSettings.tsx @@ -1,46 +1,48 @@ import { useEffect, useRef, useState, type FormEvent } from "react"; import { Notice } from "./ui"; -import { consolidationSwitches } from "./consolidation-labels"; +import { + consolidationBudgets, + consolidationSwitches, +} from "./consolidation-labels"; +import { changedSettings, useSettingsDraft } from "./settings-draft"; import type { ConsolidationConfig, GoalDedupConfig, } from "./consolidation-types"; +const configOf = (value: ConsolidationConfig) => ({ + ...value, + person_summary_enabled: value.person_summary_enabled ?? true, + entry_profile_max_calls: value.entry_profile_max_calls ?? 60, + person_summary_max_calls: value.person_summary_max_calls ?? 40, + persona_max_calls: value.persona_max_calls ?? 30, +}); + export function ConsolidationSettings({ value, timezone, busy, + saveError, save, }: { value: ConsolidationConfig; timezone: string | null; busy: boolean; - save: (value: ConsolidationConfig) => Promise; + saveError?: string; + save: ( + value: Partial, + ) => Promise; }) { - const [draft, setDraft] = useState(() => ({ - ...value, - person_summary_enabled: value.person_summary_enabled ?? true, - max_calls: String(value.max_calls), - })); - const dirty = useRef(false); + const current = configOf(value); + const { draft, change, reset } = useSettingsDraft({ + ...current, + max_calls: String(current.max_calls), + entry_profile_max_calls: String(current.entry_profile_max_calls), + person_summary_max_calls: String(current.person_summary_max_calls), + persona_max_calls: String(current.persona_max_calls), + }); const [error, setError] = useState(""), [saved, setSaved] = useState(false); - useEffect(() => { - if (!dirty.current) - setDraft({ - ...value, - person_summary_enabled: value.person_summary_enabled ?? true, - max_calls: String(value.max_calls), - }); - }, [value]); - function change( - key: K, - next: (typeof draft)[K], - ) { - dirty.current = true; - setSaved(false); - setDraft((d) => ({ ...d, [key]: next })); - } async function submit(e: FormEvent) { e.preventDefault(); if (busy) return; @@ -50,24 +52,28 @@ export function ConsolidationSettings({ setError("整理运行时间须为 HH:MM,范围 00:00—23:59"); return; } - const calls = Number(draft.max_calls); - if ( - !draft.max_calls.trim() || - !Number.isInteger(calls) || - calls < 0 || - calls > 50 - ) { - setError("模型调用次数预算须为 0—50 的整数"); - return; + for (const [key, label] of consolidationBudgets) { + const calls = Number(draft[key]); + if ( + !draft[key].trim() || + !Number.isInteger(calls) || + calls < 0 || + calls > 1000 + ) { + setError(`${label}须为 0—1000 的整数`); + return; + } } - const result = await save({ ...draft, max_calls: calls }); - if (result) { - dirty.current = false; - setDraft({ - ...result, - person_summary_enabled: result.person_summary_enabled ?? true, - max_calls: String(result.max_calls), - }); + const changes = changedSettings(current, { + ...draft, + max_calls: Number(draft.max_calls), + entry_profile_max_calls: Number(draft.entry_profile_max_calls), + person_summary_max_calls: Number(draft.person_summary_max_calls), + persona_max_calls: Number(draft.persona_max_calls), + }); + if (!Object.keys(changes).length) return; + if (await save(changes)) { + reset(); setSaved(true); } } @@ -81,42 +87,46 @@ export function ConsolidationSettings({

整理不中断接收和学习。修改只影响之后接受的新运行,已接受的运行与续跑沿用其设置快照。

-
+ setSaved(false)}>
+
- - + {consolidationBudgets.map(([key, label, fallback]) => ( + + ))}
+

+ 以上均为每轮调用上限,各步骤互不占用;HTTP 重试和 JSON + 修正计入所属步骤。0 + 表示停用该步骤的模型调用,其他步骤、记忆生命周期维护与开启的目标依据复核仍会执行。 +

{consolidationSwitches.map(([key, label]) => (
+
+ + ); +} + +export function GoalSettings({ + value, + busy, + saveError, + save, +}: { + value: GoalConfig; + busy: boolean; + saveError?: string; + save: ( + changes: Partial, + ) => Promise; +}) { + const current = { + ...value, + internal_question_expiry_days: value.internal_question_expiry_days ?? 7, + }; + const { draft, change, reset } = useSettingsDraft({ + default_reminder_minutes: String(current.default_reminder_minutes), + overdue_reminders: current.overdue_reminders, + internal_question_expiry_days: String( + current.internal_question_expiry_days, + ), + }); + const [error, setError] = useState(""), + [saved, setSaved] = useState(false); + async function submit(e: FormEvent) { + e.preventDefault(); + if (busy) return; + setError(""); + setSaved(false); + const minutes = Number(draft.default_reminder_minutes), + days = Number(draft.internal_question_expiry_days); + if ( + !draft.default_reminder_minutes.trim() || + !Number.isInteger(minutes) || + minutes < 0 || + minutes > 525600 + ) { + setError("默认提醒提前量须为 0—525600 的整数"); + return; + } + if ( + !draft.internal_question_expiry_days.trim() || + !Number.isInteger(days) || + days < 1 || + days > 365 + ) { + setError("学习产生的询问保留天数须为 1—365 的整数"); + return; + } + const changes = changedSettings(current, { + default_reminder_minutes: minutes, + overdue_reminders: draft.overdue_reminders, + internal_question_expiry_days: days, + }); + if (!Object.keys(changes).length) return; + if (await save(changes)) { + reset(); + setSaved(true); + } + } + return ( +
+

目标与提醒

+

+ 未单独填写提前量的普通目标使用默认值。询问不安排提醒,过期不会自动放弃目标。 +

+
setSaved(false)}> +
+ + +

+ 过期提醒每日最多一次。 + 查看提醒 + ;“已取走”只表示宿主拿到了。 +

+ +

+ 只作用于学习产生且仍未结束的询问,到期由每日维护自动结束。宿主或管理员创建的询问和普通目标不受影响。 +

+ {(error || saveError) && {error || saveError}} + {saved && 目标与提醒设置已保存} + +
+
+
+ ); +} diff --git a/frontend/src/Settings.tsx b/frontend/src/Settings.tsx index 1c4c1b8d..47acfbb6 100644 --- a/frontend/src/Settings.tsx +++ b/frontend/src/Settings.tsx @@ -1,3 +1,4 @@ +import { GoalSettings, LimitsSettings } from "./RuntimeSettings"; import { ConsolidationSettings, GoalDedupSettings, @@ -67,6 +68,7 @@ export type Settings = { daily_token_limit: number | null; learning_concurrency: number; native_image_learning?: boolean; + media_retention_days?: number; lifecycle: LifecycleConfig; recall_judge: RecallJudgeConfig; state: StateConfig; @@ -477,48 +479,19 @@ function SettingsForm({ settings: initial }: { settings: Settings }) { timezone: settings.role.timezone || timezone(), }), [models, setModels] = useState(settings.models); - const [limit, setLimit] = useState( - settings.daily_token_limit?.toString() || "", - ), - [concurrency, setConcurrency] = useState(settings.learning_concurrency), - [error, setError] = useState(""), + const [errorPath, setErrorPath] = useState(""); + const [error, setError] = useState(""), [saved, setSaved] = useState(""), [busy, setBusy] = useState(false); const [staleMinutes, setStaleMinutes] = useState( String(settings.state.stale_after_minutes), ); - const [nativeImages, setNativeImages] = useState( - settings.native_image_learning === true, - ); - const nativeImagesDirty = useRef(false); - const nativeImagesAvailable = - settings.models.chat.enabled && settings.models.chat.vision === true; - useEffect(() => { - if (!nativeImagesDirty.current) - setNativeImages(settings.native_image_learning === true); - }, [settings.native_image_learning]); const stateDirty = useRef(false); const modelDirty = useRef(new Set()); useEffect(() => { if (!stateDirty.current) setStaleMinutes(String(settings.state.stale_after_minutes)); }, [settings.state.stale_after_minutes]); - const [reminderMinutes, setReminderMinutes] = useState( - String(settings.goals.default_reminder_minutes), - ); - const [overdueReminders, setOverdueReminders] = useState( - settings.goals.overdue_reminders, - ); - const goalsDirty = useRef(false); - useEffect(() => { - if (!goalsDirty.current) { - setReminderMinutes(String(settings.goals.default_reminder_minutes)); - setOverdueReminders(settings.goals.overdue_reminders); - } - }, [ - settings.goals.default_reminder_minutes, - settings.goals.overdue_reminders, - ]); const save = async (path: string, method: string, value: unknown) => { if (busy) return; setBusy(true); @@ -527,19 +500,10 @@ function SettingsForm({ settings: initial }: { settings: Settings }) { try { const latest = await api(path, json(method, value)); setSettings(latest); - if (path === "/settings/limits") { - nativeImagesDirty.current = false; - setNativeImages(latest.native_image_learning === true); - } if (path === "/settings/state") { stateDirty.current = false; setStaleMinutes(String(latest.state.stale_after_minutes)); } - if (path === "/settings/goals") { - goalsDirty.current = false; - setReminderMinutes(String(latest.goals.default_reminder_minutes)); - setOverdueReminders(latest.goals.overdue_reminders); - } for (const kind of modelKinds) { if (path === `/settings/models/${kind}`) { modelDirty.current.delete(kind); @@ -559,6 +523,7 @@ function SettingsForm({ settings: initial }: { settings: Settings }) { setSaved("已保存"); return latest; } catch (e) { + setErrorPath(path); setError(errorText(e)); return null; } finally { @@ -567,7 +532,12 @@ function SettingsForm({ settings: initial }: { settings: Settings }) { }; return (
- {error && {error}} + {error && + ![ + "/settings/limits", + "/settings/goals", + "/settings/consolidation", + ].includes(errorPath) && {error}} {saved && {saved}}

角色

@@ -673,72 +643,17 @@ function SettingsForm({ settings: initial }: { settings: Settings }) { )}
))} -
-

用量与学习

-
{ - e.preventDefault(); - void save("/settings/limits", "PATCH", { - daily_token_limit: limit ? Number(limit) : null, - learning_concurrency: concurrency, - native_image_learning: nativeImages, - }); - }} - > - - -

- 按角色时区每日恢复;在途调用和未报告的 token - 可能使实际用量超过上限。 -

- -

- 默认关闭。开启后,后续学习把原图交给对话模型;图片描述仍用于回复准备、检索与管理页。超限或不可用的图片沿用描述或占位。 -

-

- {!nativeImagesAvailable - ? `${!settings.models.chat.enabled ? "当前对话模型未启用,无法直接看原图。" : "当前对话模型未启用图片输入(vision),此设置暂不生效。"}${settings.model_source === "external" ? "请在外部模型配置中启用对话模型及 vision。" : "请先启用并保存对话模型的“支持图片输入(vision)”。"}` - : settings.model_source === "external" - ? "这是运行设置,使用外部模型配置时也可以保存。" - : "使用已保存的对话模型图片能力;保存后对后续学习生效。"} -

- -
-
+ save("/settings/limits", "PATCH", value)} + />

当前状态

@@ -757,6 +672,7 @@ function SettingsForm({ settings: initial }: { settings: Settings }) { minutes > 525600 ) { setSaved(""); + setErrorPath("/settings/state"); setError("可能过时的分钟数须为 1—525600 的整数"); return; } @@ -792,78 +708,18 @@ function SettingsForm({ settings: initial }: { settings: Settings }) {

-
-

目标与提醒

-

- 未单独填写提前量的普通目标使用默认值。询问不安排提醒,过期不会自动放弃目标。 -

-
{ - e.preventDefault(); - if (busy) return; - const minutes = Number(reminderMinutes); - if ( - !reminderMinutes.trim() || - !Number.isInteger(minutes) || - minutes < 0 || - minutes > 525600 - ) { - setSaved(""); - setError("默认提醒提前量须为 0—525600 的整数"); - return; - } - void save("/settings/goals", "PATCH", { - default_reminder_minutes: minutes, - overdue_reminders: overdueReminders, - }); - }} - > - - -

- 过期提醒每日最多一次。 - 查看提醒 - ;“已取走”只表示宿主拿到了。 -

- -
-
+ + (await save("/settings/goals", "PATCH", value))?.goals || null + } + /> {settings.consolidation && ( diff --git a/frontend/src/StateSettings.test.tsx b/frontend/src/StateSettings.test.tsx index cce339fd..f0cefe49 100644 --- a/frontend/src/StateSettings.test.tsx +++ b/frontend/src/StateSettings.test.tsx @@ -84,7 +84,7 @@ beforeEach(() => { ); settings = { ...settings, - goals: body, + goals: { ...settings.goals, ...body }, operations: [ { id: 2, @@ -262,7 +262,7 @@ test("目标设置轮询保留草稿,保存失败后可以重试", async () => await vi.advanceTimersByTimeAsync(2000); }); expect(input).toHaveValue(90); - expect(screen.getByLabelText("启用过期提醒")).not.toBeChecked(); + expect(screen.getByLabelText("启用过期提醒")).toBeChecked(); fail = true; fireEvent.click(screen.getByRole("button", { name: "保存目标与提醒设置" })); await act(async () => {}); diff --git a/frontend/src/Week1Maintenance.test.tsx b/frontend/src/Week1Maintenance.test.tsx new file mode 100644 index 00000000..4982f61c --- /dev/null +++ b/frontend/src/Week1Maintenance.test.tsx @@ -0,0 +1,160 @@ +import { render, screen, within } from "@testing-library/react"; +import { afterEach, expect, test, vi } from "vitest"; +import { MaintenanceReportDialog } from "./Maintenance"; +import { response } from "./lifecycle-fixtures"; +import type { MaintenanceReport } from "./types"; + +const stamp = "2026-10-17T03:00:00+08:00"; +const report: MaintenanceReport = { + id: 14, + trigger: "manual", + state: "completed", + phase: 8, + created_at: stamp, + finished_at: stamp, + timezone: "Asia/Shanghai", + summary: { + model_step_budget: { count: 4 }, + backlog_trimmed: { count: 1 }, + questions_expired: { count: 2 }, + model_calls: { count: 309 }, + }, + consolidation: { + settings: { + max_calls: 300, + entry_profile_max_calls: 60, + person_summary_max_calls: 40, + persona_max_calls: 30, + }, + deferred: 2000, + skip_reason: "call_budget", + }, + question_expiry: { count: 2, goal_ids: [41, 42] }, + items: [ + { + phase: "consolidation", + item_key: "budget:memory", + memory_id: null, + object_id: 14, + outcome: "model_step_budget", + reason: "call_budget", + details: { step: "memory", max_calls: 300, calls_used: 300 }, + created_at: stamp, + }, + { + phase: "consolidation", + item_key: "budget:entry_profile", + memory_id: null, + object_id: 14, + outcome: "model_step_budget", + reason: "usage_limit", + details: { step: "entry_profile", max_calls: 60, calls_used: 5 }, + created_at: stamp, + }, + { + phase: "consolidation", + item_key: "budget:person_summary", + memory_id: null, + object_id: 14, + outcome: "model_step_budget", + reason: "paused", + details: { step: "person_summary", max_calls: 40, calls_used: 4 }, + created_at: stamp, + }, + { + phase: "consolidation", + item_key: "budget:persona", + memory_id: null, + object_id: 14, + outcome: "model_step_budget", + reason: "interrupted", + details: { step: "persona", max_calls: 30, calls_used: 0 }, + created_at: stamp, + }, + { + phase: "consolidation", + item_key: "backlog:pair", + memory_id: null, + object_id: 14, + outcome: "backlog_trimmed", + reason: "backlog_trimmed", + details: { count: 125, limit: 2000 }, + created_at: stamp, + }, + ], +}; +afterEach(() => vi.unstubAllGlobals()); +function show(data: MaintenanceReport) { + const fetcher = vi.fn(async (_url: string, _init?: RequestInit) => + response(data), + ); + vi.stubGlobal("fetch", fetcher); + render( + , + ); + return fetcher; +} +test("已有维护报告显示各步骤上限、已用与停止原因,修剪数来自 details.count,询问数来自 question_expiry", async () => { + const fetcher = show(report); + const budget = await screen.findByRole("region", { + name: "各步骤模型调用上限与用量", + }); + const cases = [ + [ + "记忆整理(合并/矛盾/依赖)", + "本轮上限:300 次 · 已用:300 次", + "模型调用次数预算已用尽", + ], + ["入口画像", "本轮上限:60 次 · 已用:5 次", "每日 token 上限已用尽"], + ["人物摘要", "本轮上限:40 次 · 已用:4 次", "模型用途已暂停"], + ["persona", "本轮上限:30 次 · 已用:0 次", "运行已中断"], + ]; + for (const [name, usage, reason] of cases) { + const step = within(budget).getByRole("article", { name }); + expect(within(step).getByText(usage)).toBeVisible(); + expect(step).toHaveTextContent(`停止原因:${reason}`); + } + expect( + screen.getByText("配对积压修剪:125 项 · 待处理配对上限:2000 项"), + ).toBeVisible(); + expect(screen.getByText("到期自动结束的询问:2 条")).toBeVisible(); + expect(screen.queryByText("model_step_budget")).not.toBeInTheDocument(); + expect(screen.queryByText("backlog_trimmed")).not.toBeInTheDocument(); + expect(screen.getByText(/模型调用 309 次/)).toBeVisible(); + expect(fetcher).toHaveBeenCalledTimes(1); + expect(fetcher.mock.calls[0][0]).toBe("/admin/api/maintenance/14"); + expect(fetcher.mock.calls[0][1]?.method).toBeUndefined(); +}); +test("零用量与零到期如实显示;未记录停止原因不推断为上限耗尽或已完成", async () => { + const data = structuredClone(report); + data.items = [ + { + ...data.items[3], + reason: null, + details: { step: "persona", max_calls: 0, calls_used: 0 }, + }, + ]; + data.question_expiry = { count: 0, goal_ids: [] }; + show(data); + const budget = await screen.findByRole("region", { + name: "各步骤模型调用上限与用量", + }); + expect(budget).toHaveTextContent("本轮上限:0 次 · 已用:0 次"); + expect(budget).toHaveTextContent("停止原因:未记录"); + expect(screen.getByText("到期自动结束的询问:0 条")).toBeVisible(); + expect( + screen.queryByRole("region", { name: "配对积压修剪" }), + ).not.toBeInTheDocument(); +}); +test("旧报告缺少新增字段时显示未记录,不虚构新步骤用量或到期数量", async () => { + const data = structuredClone(report); + data.items = []; + delete data.question_expiry; + data.consolidation!.settings = { max_calls: 50 }; + show(data); + expect(await screen.findByText("本次未记录步骤用量。")).toBeVisible(); + expect( + screen.queryByRole("region", { name: "询问到期结束" }), + ).not.toBeInTheDocument(); + expect(screen.queryByText(/本轮上限:60 次/)).not.toBeInTheDocument(); +}); diff --git a/frontend/src/Week1Settings.test.tsx b/frontend/src/Week1Settings.test.tsx new file mode 100644 index 00000000..0b49844a --- /dev/null +++ b/frontend/src/Week1Settings.test.tsx @@ -0,0 +1,293 @@ +import { act, fireEvent, render, screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { afterEach, beforeEach, expect, test, vi } from "vitest"; +import SettingsPage from "./Settings"; +import { lifecycleFixture, response } from "./lifecycle-fixtures"; +import { personaSettingsFixture } from "./persona-fixtures"; +import { setCSRF } from "./api"; + +const budgets = [ + ["max_calls", "记忆整理(合并/矛盾/依赖)每轮调用上限", 300], + ["entry_profile_max_calls", "入口画像每轮调用上限", 60], + ["person_summary_max_calls", "人物摘要每轮调用上限", 40], + ["persona_max_calls", "persona 每轮调用上限", 30], +] as const; +const days = [ + [ + "internal_question_expiry_days", + "学习产生的询问保留天数", + "goals", + "保存目标与提醒设置", + 365, + ], + ["media_retention_days", "原图保留天数", "limits", "保存用量与学习", 36500], +] as const; +let settings: any; +let writes: { url: string; body: any; init: RequestInit }[]; +let failure = false; +beforeEach(() => { + failure = false; + writes = []; + setCSRF("week1-settings-test"); + const model = { + enabled: false, + base_url: "", + model: "", + key_set: false, + dimensions: null, + reasoning_effort: null, + }; + settings = { + role: { name: "Iris", background: "", timezone: "Asia/Shanghai" }, + models: { + chat: { ...model, enabled: true, vision: true }, + embedding: model, + }, + model_source: "external", + daily_token_limit: 12000, + learning_concurrency: 5, + media_retention_days: 7, + native_image_learning: false, + lifecycle: { ...lifecycleFixture }, + recall_judge: { enabled: true, concurrency: 1, queue_limit: 8 }, + state: { stale_after_minutes: 30 }, + goals: { + default_reminder_minutes: 90, + overdue_reminders: false, + internal_question_expiry_days: 7, + }, + persona: personaSettingsFixture, + consolidation: { + maintenance_time: "03:00", + max_calls: 300, + entry_profile_max_calls: 60, + person_summary_max_calls: 40, + persona_max_calls: 30, + merge_enabled: true, + conflict_enabled: true, + dependency_enabled: true, + persona_enabled: true, + person_summary_enabled: true, + goal_review_enabled: true, + }, + presets: [], + health: {}, + operations: [], + }; + vi.stubGlobal( + "fetch", + vi.fn(async (url: string, init?: RequestInit) => { + if (init?.method === "PATCH") { + const body = JSON.parse(String(init.body)); + writes.push({ url, body, init }); + if (failure) + return response( + { + error: { + code: "invalid_request", + message: "请求参数无效,请检查设置", + }, + }, + 400, + ); + if (url.endsWith("/limits")) settings = { ...settings, ...body }; + else if (url.endsWith("/goals")) + settings.goals = { ...settings.goals, ...body }; + else if (url.endsWith("/consolidation")) + settings.consolidation = { ...settings.consolidation, ...body }; + } + return response(settings); + }), + ); +}); +afterEach(() => { + vi.useRealTimers(); + vi.unstubAllGlobals(); + setCSRF(""); +}); + +for (const [key, label, initial] of budgets) { + test.each([0, 51, 1000])( + `${label} 支持 %s 且只提交改动字段`, + async (value) => { + render(); + const input = await screen.findByLabelText(label); + expect(input).toHaveValue(initial); + expect(input).toHaveAttribute("min", "0"); + expect(input).toHaveAttribute("max", "1000"); + fireEvent.change(input, { target: { value: String(value) } }); + await userEvent.click( + screen.getByRole("button", { name: "保存梦境整理设置" }), + ); + expect(await screen.findByText("梦境整理设置已保存")).toBeVisible(); + expect(writes).toHaveLength(1); + expect(writes[0].body).toEqual({ [key]: value }); + expect(input).toHaveValue(value); + }, + ); + test.each(["", "-1", "1001", "1.5"])( + `${label} 拦截非法值 %s`, + async (value) => { + render(); + fireEvent.change(await screen.findByLabelText(label), { + target: { value }, + }); + await userEvent.click( + screen.getByRole("button", { name: "保存梦境整理设置" }), + ); + expect(await screen.findByRole("alert")).toHaveTextContent( + "0—1000 的整数", + ); + expect(writes).toHaveLength(0); + }, + ); +} +for (const [key, label, endpoint, button, max] of days) { + test.each([1, max])( + `${label} 读取默认值并保存边界 %s,省略其他字段`, + async (value) => { + render(); + const input = await screen.findByLabelText(label); + expect(input).toHaveValue(7); + fireEvent.change(input, { target: { value: String(value) } }); + await userEvent.click(screen.getByRole("button", { name: button })); + expect(await screen.findByText("已保存")).toBeVisible(); + expect(writes[0].url).toBe(`/admin/api/settings/${endpoint}`); + expect(writes[0].body).toEqual({ [key]: value }); + expect(writes[0].init.headers).toMatchObject({ + "X-Iris-CSRF": "week1-settings-test", + }); + expect(settings.daily_token_limit).toBe(12000); + expect(settings.learning_concurrency).toBe(5); + expect(settings.goals.default_reminder_minutes).toBe(90); + expect(settings.goals.overdue_reminders).toBe(false); + expect(input).toHaveValue(value); + }, + ); + test.each(["", "0", String(max + 1), "1.5"])( + `${label} 拦截非法值 %s`, + async (value) => { + render(); + fireEvent.change(await screen.findByLabelText(label), { + target: { value }, + }); + await userEvent.click(screen.getByRole("button", { name: button })); + expect(await screen.findByRole("alert")).toHaveTextContent( + `1—${max} 的整数`, + ); + expect(writes).toHaveLength(0); + }, + ); +} + +test.each([ + ["原图保留天数", "保存用量与学习"], + ["学习产生的询问保留天数", "保存目标与提醒设置"], + ["入口画像每轮调用上限", "保存梦境整理设置"], +])("%s 的后端 400 清楚显示,保留草稿供重试", async (label, button) => { + failure = true; + render(); + const input = await screen.findByLabelText(label); + fireEvent.change(input, { target: { value: "14" } }); + await userEvent.click(screen.getByRole("button", { name: button })); + expect(await screen.findByRole("alert")).toHaveTextContent( + "请求参数无效,请检查设置", + ); + expect(input).toHaveValue(14); + failure = false; + await userEvent.click(screen.getByRole("button", { name: button })); + expect(await screen.findByText("已保存")).toBeVisible(); + expect(writes).toHaveLength(2); + expect(writes[1].body).toEqual(writes[0].body); +}); + +test("轮询更新未编辑字段并保留三个表单的草稿,保存不回传未编辑字段", async () => { + vi.useFakeTimers(); + render(); + await act(async () => {}); + fireEvent.change(screen.getByLabelText("原图保留天数"), { + target: { value: "14" }, + }); + fireEvent.change(screen.getByLabelText("学习产生的询问保留天数"), { + target: { value: "21" }, + }); + fireEvent.change(screen.getByLabelText("入口画像每轮调用上限"), { + target: { value: "90" }, + }); + settings = { + ...settings, + daily_token_limit: 8000, + media_retention_days: 30, + goals: { + ...settings.goals, + default_reminder_minutes: 120, + internal_question_expiry_days: 30, + }, + consolidation: { + ...settings.consolidation, + entry_profile_max_calls: 80, + max_calls: 500, + }, + }; + await act(async () => { + await vi.advanceTimersByTimeAsync(2000); + }); + expect(screen.getByLabelText("每日 token 上限")).toHaveValue(8000); + expect(screen.getByLabelText("默认提醒提前量(分钟)")).toHaveValue(120); + expect(screen.getByLabelText(budgets[0][1])).toHaveValue(500); + expect(screen.getByLabelText("原图保留天数")).toHaveValue(14); + expect(screen.getByLabelText("学习产生的询问保留天数")).toHaveValue(21); + expect(screen.getByLabelText("入口画像每轮调用上限")).toHaveValue(90); + for (const button of [ + "保存用量与学习", + "保存目标与提醒设置", + "保存梦境整理设置", + ]) { + await act(async () => { + fireEvent.click(screen.getByRole("button", { name: button })); + }); + } + expect(writes.map((r) => r.body)).toEqual([ + { media_retention_days: 14 }, + { internal_question_expiry_days: 21 }, + { entry_profile_max_calls: 90 }, + ]); +}); + +test("清空 token 额度显式提交 null,只改并发时省略额度", async () => { + render(); + fireEvent.change(await screen.findByLabelText("每日 token 上限"), { + target: { value: "" }, + }); + await userEvent.click(screen.getByRole("button", { name: "保存用量与学习" })); + await screen.findByText("已保存"); + expect(writes[0].body).toEqual({ daily_token_limit: null }); + fireEvent.change(screen.getByLabelText("学习并发"), { + target: { value: "3" }, + }); + await userEvent.click(screen.getByRole("button", { name: "保存用量与学习" })); + expect(writes[1].body).toEqual({ learning_concurrency: 3 }); +}); + +test("改回原值与未编辑的表单不发送 PATCH,并说明保留策略", async () => { + render(); + const input = await screen.findByLabelText("原图保留天数"); + fireEvent.change(input, { target: { value: "8" } }); + fireEvent.change(input, { target: { value: "7" } }); + for (const button of [ + "保存用量与学习", + "保存目标与提醒设置", + "保存梦境整理设置", + ]) { + await userEvent.click(screen.getByRole("button", { name: button })); + } + expect(writes).toHaveLength(0); + expect(screen.getByText(/各步骤互不占用/)).toBeVisible(); + expect(screen.getByText(/只清理原图字节.*理解文本保留/)).toBeVisible(); + expect( + screen.getByText(/宿主或管理员创建的询问和普通目标不受影响/), + ).toBeVisible(); + expect(screen.getByLabelText("消息保留天数")).toHaveValue( + lifecycleFixture.message_retention_days, + ); +}); diff --git a/frontend/src/consolidation-labels.ts b/frontend/src/consolidation-labels.ts index db045e5a..15628b92 100644 --- a/frontend/src/consolidation-labels.ts +++ b/frontend/src/consolidation-labels.ts @@ -10,6 +10,18 @@ export const suggestionStatuses = { confirmed: "已确认", cleared: "已清除", }; +export const consolidationBudgets = [ + ["max_calls", "记忆整理(合并/矛盾/依赖)每轮调用上限", 300], + ["entry_profile_max_calls", "入口画像每轮调用上限", 60], + ["person_summary_max_calls", "人物摘要每轮调用上限", 40], + ["persona_max_calls", "persona 每轮调用上限", 30], +] as const; +export const consolidationSteps: Record = { + memory: "记忆整理(合并/矛盾/依赖)", + entry_profile: "入口画像", + person_summary: "人物摘要", + persona: "persona", +}; export const consolidationSwitches = [ ["merge_enabled", "合并重复记忆"], ["conflict_enabled", "矛盾检查与建议"], @@ -22,6 +34,9 @@ export function consolidationReason(reason: string) { const labels: Record = { disabled: "本次设置已关闭", model_items_disabled: "记忆模型整理项目均已关闭", + usage_limit: "每日 token 上限已用尽", + paused: "模型用途已暂停", + interrupted: "运行已中断", call_budget: "模型调用次数预算已用尽", persona_busy: "已有 persona 任务正在运行", checks_rejected: "persona 检查未通过,候选被拒绝", diff --git a/frontend/src/consolidation-types.ts b/frontend/src/consolidation-types.ts index 9c47b8eb..82a14ddc 100644 --- a/frontend/src/consolidation-types.ts +++ b/frontend/src/consolidation-types.ts @@ -3,6 +3,9 @@ import type { PersonaVersion } from "./persona-types"; export type ConsolidationConfig = { maintenance_time: string; max_calls: number; + entry_profile_max_calls?: number; + person_summary_max_calls?: number; + persona_max_calls?: number; merge_enabled: boolean; conflict_enabled: boolean; dependency_enabled: boolean; @@ -63,6 +66,11 @@ export type MemorySuggestion = Suggestion & { }; }; export type ConsolidationDetails = { + step?: string; + max_calls?: number; + calls_used?: number; + count?: number; + limit?: number; subject_id?: string; version?: number | null; attempt_id?: number | null; diff --git a/frontend/src/settings-draft.ts b/frontend/src/settings-draft.ts new file mode 100644 index 00000000..f8e210b5 --- /dev/null +++ b/frontend/src/settings-draft.ts @@ -0,0 +1,26 @@ +import { useState } from "react"; + +export function changedSettings( + current: T, + next: T, +): Partial { + return Object.fromEntries( + (Object.keys(next) as (keyof T)[]) + .filter((key) => !Object.is(current[key], next[key])) + .map((key) => [key, next[key]]), + ) as Partial; +} + +// Polling refreshes untouched fields; only explicit edits stay in the draft. +export function useSettingsDraft(value: T) { + const [edits, setEdits] = useState>({}); + function change(key: K, next: T[K]) { + setEdits((previous) => { + const updated = { ...previous }; + if (Object.is(value[key], next)) delete updated[key]; + else updated[key] = next; + return updated; + }); + } + return { draft: { ...value, ...edits }, change, reset: () => setEdits({}) }; +} diff --git a/frontend/src/types.ts b/frontend/src/types.ts index f88b2370..8a3bedce 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -213,6 +213,7 @@ export type Goal = { basis_annotations?: GoalBasisAnnotation[]; }; export type GoalConfig = { + internal_question_expiry_days?: number; default_reminder_minutes: number; overdue_reminders: boolean; }; @@ -413,6 +414,7 @@ export type MaintenanceItem = { export type MaintenanceReport = MaintenanceRun & ConsolidationProjection & { timezone: string; + question_expiry?: { count: number; goal_ids: number[] }; items: MaintenanceItem[]; }; export type TrialCatalog = { diff --git a/src/iris/settings_api.py b/src/iris/settings_api.py index 65e772b4..c2ad8212 100644 --- a/src/iris/settings_api.py +++ b/src/iris/settings_api.py @@ -344,17 +344,15 @@ def save_goal_settings(payload: GoalsSettings): @router.patch('/settings/limits') def limits(payload: Limits): - changes = payload.model_dump() - # Existing clients do not know these fields; omission preserves their values. - for key in ('learning_image_limit', 'native_image_learning', 'media_retention_days'): - if key not in payload.model_fields_set: - changes.pop(key) + changes = payload.model_dump(exclude_unset=True) with app.state.store.write() as conn: for key, value in changes.items(): conn.execute('INSERT OR REPLACE INTO runtime_settings VALUES(?,?)', (key, dumps(value))) audit(conn, 'limits_saved', changes) - app.state.health.set_daily_token_limit(payload.daily_token_limit) - app.state.scheduler.set_concurrency(payload.learning_concurrency) + if 'daily_token_limit' in changes: + app.state.health.set_daily_token_limit(payload.daily_token_limit) + if 'learning_concurrency' in changes: + app.state.scheduler.set_concurrency(payload.learning_concurrency) return snapshot() @router.post('/settings/models/{kind}/retry') diff --git a/src/iris/web/assets/index-Bn6dsR4V.js b/src/iris/web/assets/index-Bn6dsR4V.js deleted file mode 100644 index 645dc04f..00000000 --- a/src/iris/web/assets/index-Bn6dsR4V.js +++ /dev/null @@ -1,11 +0,0 @@ -var e=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports);(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var t=e((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`react.fragment`),i=Symbol.for(`react.strict_mode`),a=Symbol.for(`react.profiler`),o=Symbol.for(`react.consumer`),s=Symbol.for(`react.context`),c=Symbol.for(`react.forward_ref`),l=Symbol.for(`react.suspense`),u=Symbol.for(`react.memo`),d=Symbol.for(`react.lazy`),f=Symbol.for(`react.activity`),p=Symbol.for(`react.view_transition`),m=Symbol.iterator;function h(e){return typeof e!=`object`||!e?null:(e=m&&e[m]||e[`@@iterator`],typeof e==`function`?e:null)}var g={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},_=Object.assign,v={};function y(e,t,n){this.props=e,this.context=t,this.refs=v,this.updater=n||g}y.prototype.isReactComponent={},y.prototype.setState=function(e,t){if(typeof e!=`object`&&typeof e!=`function`&&e!=null)throw Error(`takes an object of state variables to update or a function which returns an object of state variables.`);this.updater.enqueueSetState(this,e,t,`setState`)},y.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,`forceUpdate`)};function b(){}b.prototype=y.prototype;function x(e,t,n){this.props=e,this.context=t,this.refs=v,this.updater=n||g}var S=x.prototype=new b;S.constructor=x,_(S,y.prototype),S.isPureReactComponent=!0;var C=Array.isArray;function w(){}var T={H:null,A:null,T:null,S:null},E=Object.prototype.hasOwnProperty;function D(e,n,r){var i=r.ref;return{$$typeof:t,type:e,key:n,ref:i===void 0?null:i,props:r}}function O(e,t){return D(e.type,t,e.props)}function k(e){return typeof e==`object`&&!!e&&e.$$typeof===t}function A(e){var t={"=":`=0`,":":`=2`};return`$`+e.replace(/[=:]/g,function(e){return t[e]})}var j=/\/+/g;function M(e,t){return typeof e==`object`&&e&&e.key!=null?A(``+e.key):t.toString(36)}function N(e){switch(e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason;default:switch(typeof e.status==`string`?e.then(w,w):(e.status=`pending`,e.then(function(t){e.status===`pending`&&(e.status=`fulfilled`,e.value=t)},function(t){e.status===`pending`&&(e.status=`rejected`,e.reason=t)})),e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason}}throw e}function P(e,r,i,a,o){var s=typeof e;(s===`undefined`||s===`boolean`)&&(e=null);var c=!1;if(e===null)c=!0;else switch(s){case`bigint`:case`string`:case`number`:c=!0;break;case`object`:switch(e.$$typeof){case t:case n:c=!0;break;case d:return c=e._init,P(c(e._payload),r,i,a,o)}}if(c)return o=o(e),c=a===``?`.`+M(e,0):a,C(o)?(i=``,c!=null&&(i=c.replace(j,`$&/`)+`/`),P(o,r,i,``,function(e){return e})):o!=null&&(k(o)&&(o=O(o,i+(o.key==null||e&&e.key===o.key?``:(``+o.key).replace(j,`$&/`)+`/`)+c)),r.push(o)),1;c=0;var l=a===``?`.`:a+`:`;if(C(e))for(var u=0;u{n.exports=t()})),r=e((e=>{function t(e,t){var n=e.length;e.push(t);a:for(;0>>1,a=e[r];if(0>>1;ri(c,n))li(u,c)?(e[r]=u,e[l]=n,r=l):(e[r]=c,e[s]=n,r=s);else if(li(u,n))e[r]=u,e[l]=n,r=l;else break a}}return t}function i(e,t){var n=e.sortIndex-t.sortIndex;return n===0?e.id-t.id:n}if(e.unstable_now=void 0,typeof performance==`object`&&typeof performance.now==`function`){var a=performance;e.unstable_now=function(){return a.now()}}else{var o=Date,s=o.now();e.unstable_now=function(){return o.now()-s}}var c=[],l=[],u=1,d=null,f=3,p=!1,m=!1,h=!1,g=!1,_=typeof setTimeout==`function`?setTimeout:null,v=typeof clearTimeout==`function`?clearTimeout:null,y=typeof setImmediate<`u`?setImmediate:null;function b(e){for(var i=n(l);i!==null;){if(i.callback===null)r(l);else if(i.startTime<=e)r(l),i.sortIndex=i.expirationTime,t(c,i);else break;i=n(l)}}function x(e){if(h=!1,b(e),!m){if(n(c)!==null)m=!0,S||(S=!0,O());else{var t=n(l);t!==null&&j(x,t.startTime-e)}}}var S=!1,C=-1,w=5,T=-1;function E(){return g?!0:!(e.unstable_now()-Tt&&E());){var o=d.callback;if(typeof o==`function`){d.callback=null,f=d.priorityLevel;var s=o(d.expirationTime<=t);if(t=e.unstable_now(),typeof s==`function`){d.callback=s,b(t),i=!0;break b}d===n(c)&&r(c),b(t)}else r(c);d=n(c)}if(d!==null)i=!0;else{var u=n(l);u!==null&&j(x,u.startTime-t),i=!1}}break a}finally{d=null,f=a,p=!1}i=void 0}}finally{i?O():S=!1}}}var O;if(typeof y==`function`)O=function(){y(D)};else if(typeof MessageChannel<`u`){var k=new MessageChannel,A=k.port2;k.port1.onmessage=D,O=function(){A.postMessage(null)}}else O=function(){_(D,0)};function j(t,n){C=_(function(){t(e.unstable_now())},n)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(e){e.callback=null},e.unstable_forceFrameRate=function(e){0>e||125o?(r.sortIndex=a,t(l,r),n(c)===null&&r===n(l)&&(h?(v(C),C=-1):h=!0,j(x,a-o))):(r.sortIndex=s,t(c,r),m||p||(m=!0,S||(S=!0,O()))),r},e.unstable_shouldYield=E,e.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}})),i=e(((e,t)=>{t.exports=r()})),a=e((e=>{var t=n();function r(e){var t=`https://react.dev/errors/`+e;if(1{function n(){if(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<`u`&&typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE==`function`)try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=a()})),s=e((e=>{var t=i(),r=n(),a=o();function s(e){var t=`https://react.dev/errors/`+e;if(1me||(e.current=pe[me],pe[me]=null,me--)}function V(e,t){me++,pe[me]=e.current,e.current=t}var H=he(null),_e=he(null),ve=he(null),ye=he(null);function be(e,t){switch(V(ve,t),V(_e,e),V(H,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?up(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=up(t),e=dp(t,e);else switch(e){case`svg`:e=1;break;case`math`:e=2;break;default:e=0}}ge(H),V(H,e)}function xe(){ge(H),ge(_e),ge(ve)}function Se(e){var t=e.memoizedState;t!==null&&(sh._currentValue=t.memoizedState,V(ye,e)),t=H.current;var n=dp(t,e.type);t!==n&&(V(_e,e),V(H,n))}function Ce(e){_e.current===e&&(ge(H),ge(_e)),ye.current===e&&(ge(ye),sh._currentValue=B)}var we,Te;function Ee(e){if(we===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);we=t&&t[1]||``,Te=-1)`:-1i||c[r]!==l[i]){var u=` -`+c[r].replace(` at new `,` at `);return e.displayName&&u.includes(``)&&(u=u.replace(``,e.displayName)),u}while(1<=r&&0<=i);break}}}finally{De=!1,Error.prepareStackTrace=n}return(n=e?e.displayName||e.name:``)?Ee(n):``}function ke(e,t){switch(e.tag){case 26:case 27:case 5:return Ee(e.type);case 16:return Ee(`Lazy`);case 13:return e.child!==t&&t!==null?Ee(`Suspense Fallback`):Ee(`Suspense`);case 19:return Ee(`SuspenseList`);case 0:case 15:return Oe(e.type,!1);case 11:return Oe(e.type.render,!1);case 1:return Oe(e.type,!0);case 31:return Ee(`Activity`);case 30:return Ee(`ViewTransition`);default:return``}}function Ae(e){try{var t=``,n=null;do t+=ke(e,n),n=e,e=e.return;while(e);return t}catch(e){return` -Error generating stack: `+e.message+` -`+e.stack}}var je=Object.prototype.hasOwnProperty,Me=t.unstable_scheduleCallback,Ne=t.unstable_cancelCallback,Pe=t.unstable_shouldYield,Fe=t.unstable_requestPaint,Ie=t.unstable_now,Le=t.unstable_getCurrentPriorityLevel,Re=t.unstable_ImmediatePriority,ze=t.unstable_UserBlockingPriority,Be=t.unstable_NormalPriority,Ve=t.unstable_LowPriority,He=t.unstable_IdlePriority,Ue=t.log,We=t.unstable_setDisableYieldValue,Ge=null,Ke=null;function qe(e){if(typeof Ue==`function`&&We(e),Ke&&typeof Ke.setStrictMode==`function`)try{Ke.setStrictMode(Ge,e)}catch{}}var Je=Math.clz32?Math.clz32:Ze,Ye=Math.log,Xe=Math.LN2;function Ze(e){return e>>>=0,e===0?32:31-(Ye(e)/Xe|0)|0}var Qe=256,$e=262144,et=4194304;function tt(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&-e;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function nt(e,t,n){var r=e.pendingLanes;if(r===0)return 0;var i=0,a=e.suspendedLanes,o=e.pingedLanes;e=e.warmLanes;var s=r&134217727;return s===0?(s=r&~a,s===0?o===0?n||(n=r&~e,n!==0&&(i=tt(n))):i=tt(o):i=tt(s)):(r=s&~a,r===0?(o&=s,o===0?n||(n=s&~e,n!==0&&(i=tt(n))):i=tt(o)):i=tt(r)),i===0?0:t!==0&&t!==i&&(t&a)===0&&(a=i&-i,n=t&-t,a>=n||a===32&&n&4194048)?t:i}function rt(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function it(e,t){t&8&&(t|=t&32);var n=e.entangledLanes;if(n!==0)for(e=e.entanglements,n&=t;0n;n++)t.push(e);return t}function ct(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function lt(e,t,n,r,i,a){var o=e.pendingLanes;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=n,e.entangledLanes&=n,e.errorRecoveryDisabledLanes&=n,e.shellSuspendCounter=0;var s=e.entanglements,c=e.expirationTimes,l=e.hiddenUpdates;for(n=o&~n;0=cr),dr=` `,fr=!1;function pr(e,t){switch(e){case`keyup`:return or.indexOf(t.keyCode)!==-1;case`keydown`:return t.keyCode!==229;case`keypress`:case`mousedown`:case`focusout`:return!0;default:return!1}}function mr(e){return e=e.detail,typeof e==`object`&&`data`in e?e.data:null}var hr=!1;function gr(e,t){switch(e){case`compositionend`:return mr(t);case`keypress`:return t.which===32?(fr=!0,dr):null;case`textInput`:return e=t.data,e===dr&&fr?null:e;default:return null}}function _r(e,t){if(hr)return e===`compositionend`||!sr&&pr(e,t)?(e=kn(),On=Dn=En=null,hr=!1,e):null;switch(e){case`paste`:return null;case`keypress`:if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}a:{for(;n;){if(n.nextSibling){n=n.nextSibling;break a}n=n.parentNode}n=void 0}n=Br(n)}}function Hr(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?Hr(e,t.parentNode):`contains`in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Ur(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=zr(e.document);t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href==`string`}catch{n=!1}if(n)e=t.contentWindow;else break;t=zr(e.document)}return t}function Wr(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t===`input`&&(e.type===`text`||e.type===`search`||e.type===`tel`||e.type===`url`||e.type===`password`)||t===`textarea`||e.contentEditable===`true`)}var Gr=Cn&&`documentMode`in document&&11>=document.documentMode,Kr=null,qr=null,Jr=null,Yr=!1;function Xr(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;Yr||Kr==null||Kr!==zr(r)||(r=Kr,`selectionStart`in r&&Wr(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),Jr&&Rr(Jr,r)||(Jr=r,r=Jf(qr,`onSelect`),0>=o,i-=o,Ki=1<<32-Je(t)+i|n<h?(g=d,d=null):g=d.sibling;var _=p(i,d,s[h],c);if(_===null){d===null&&(d=g);break}e&&d&&_.alternate===null&&t(i,d),o=a(_,o,h),u===null?l=_:u.sibling=_,u=_,d=g}if(h===s.length)return n(i,d),W&&Ji(i,h),l;if(d===null){for(;hg?(_=h,h=null):_=h.sibling;var y=p(i,h,v.value,l);if(y===null){h===null&&(h=_);break}e&&h&&y.alternate===null&&t(i,h),o=a(y,o,g),d===null?u=y:d.sibling=y,d=y,h=_}if(v.done)return n(i,h),W&&Ji(i,g),u;if(h===null){for(;!v.done;g++,v=c.next())v=f(i,v.value,l),v!==null&&(o=a(v,o,g),d===null?u=v:d.sibling=v,d=v);return W&&Ji(i,g),u}for(h=r(h);!v.done;g++,v=c.next())v=m(h,i,g,v.value,l),v!==null&&(e&&(_=v.alternate,_!==null&&h.delete(_.key===null?g:_.key)),o=a(v,o,g),d===null?u=v:d.sibling=v,d=v);return e&&h.forEach(function(e){return t(i,e)}),W&&Ji(i,g),u}function _(e,r,a,c){if(typeof a==`object`&&a&&a.type===j&&a.key===null&&a.props.ref===void 0&&(a=a.props.children),typeof a==`object`&&a){switch(a.$$typeof){case k:a:{for(var l=a.key;r!==null;){if(r.key===l){if(l=a.type,l===j){if(r.tag===7){n(e,r.sibling),c=i(r,a.props.children),io(c,a),c.return=e,e=c;break a}}else if(r.elementType===l||typeof l==`object`&&l&&l.$$typeof===ne&&Za(l)===r.type){n(e,r.sibling),c=i(r,a.props),io(c,a),c.return=e,e=c;break a}n(e,r);break}t(e,r),r=r.sibling}a.type===j?(c=Ni(a.props.children,e.mode,c,a.key),io(c,a),c.return=e,e=c):(c=Mi(a.type,a.key,a.props,null,e.mode,c),io(c,a),c.return=e,e=c)}return o(e);case A:a:{for(l=a.key;r!==null;){if(r.key===l){if(r.tag===4&&r.stateNode.containerInfo===a.containerInfo&&r.stateNode.implementation===a.implementation){n(e,r.sibling),c=i(r,a.children||[]),c.return=e,e=c;break a}n(e,r);break}t(e,r),r=r.sibling}c=Ii(a,e.mode,c),c.return=e,e=c}return o(e);case ne:return a=Za(a),_(e,r,a,c)}if(fe(a))return h(e,r,a,c);if(le(a)){if(l=le(a),typeof l!=`function`)throw Error(s(150));return a=l.call(a),g(e,r,a,c)}if(typeof a.then==`function`)return _(e,r,ro(a),c);if(a.$$typeof===F)return _(e,r,Sa(e,a),c);ao(e,a)}return typeof a==`string`&&a!==``||typeof a==`number`||typeof a==`bigint`?(a=``+a,r!==null&&r.tag===6?(n(e,r.sibling),c=i(r,a),c.return=e,e=c):(n(e,r),c=Pi(a,e.mode,c),c.return=e,e=c),o(e)):n(e,r)}return function(e,t,n,r){try{no=0;var i=_(e,t,n,r);return to=null,i}catch(t){if(t===Ga||t===qa)throw t;var a=Oi(29,t,null,e.mode);return a.lanes=r,a.return=e,a}}}var so=oo(!0),co=oo(!1),lo=!1;function uo(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function fo(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function po(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function mo(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,q&2){var i=r.pending;return i===null?t.next=t:(t.next=i.next,i.next=t),r.pending=t,t=Ti(e),wi(e,null,n),t}return xi(e,r,t,n),Ti(e)}function ho(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,n&4194048)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,dt(e,n)}}function go(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var i=null,a=null;if(n=n.firstBaseUpdate,n!==null){do{var o={lane:n.lane,tag:n.tag,payload:n.payload,callback:null,next:null};a===null?i=a=o:a=a.next=o,n=n.next}while(n!==null);a===null?i=a=t:a=a.next=t}else i=a=t;n={baseState:r.baseState,firstBaseUpdate:i,lastBaseUpdate:a,shared:r.shared,callbacks:r.callbacks},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}var _o=!1;function vo(){if(_o){var e=Ia;if(e!==null)throw e}}function yo(e,t,n,r){_o=!1;var i=e.updateQueue;lo=!1;var a=i.firstBaseUpdate,o=i.lastBaseUpdate,s=i.shared.pending;if(s!==null){i.shared.pending=null;var c=s,l=c.next;c.next=null,o===null?a=l:o.next=l,o=c;var u=e.alternate;u!==null&&(u=u.updateQueue,s=u.lastBaseUpdate,s!==o&&(s===null?u.firstBaseUpdate=l:s.next=l,u.lastBaseUpdate=c))}if(a!==null){var d=i.baseState;o=0,u=l=c=null,s=a;do{var f=s.lane&-536870913,p=f!==s.lane;if(p?(Y&f)===f:(r&f)===f){f!==0&&f===Fa&&(_o=!0),u!==null&&(u=u.next={lane:0,tag:s.tag,payload:s.payload,callback:null,next:null});a:{var m=e,h=s;f=t;var g=n;switch(h.tag){case 1:if(m=h.payload,typeof m==`function`){d=m.call(g,d,f);break a}d=m;break a;case 3:m.flags=m.flags&-65537|128;case 0:if(m=h.payload,f=typeof m==`function`?m.call(g,d,f):m,f==null)break a;d=D({},d,f);break a;case 2:lo=!0}}f=s.callback,f!==null&&(e.flags|=64,p&&(e.flags|=8192),p=i.callbacks,p===null?i.callbacks=[f]:p.push(f))}else p={lane:f,tag:s.tag,payload:s.payload,callback:s.callback,next:null},u===null?(l=u=p,c=d):u=u.next=p,o|=f;if(s=s.next,s===null){if(s=i.shared.pending,s===null)break;p=s,s=p.next,p.next=null,i.lastBaseUpdate=p,i.shared.pending=null}}while(1);u===null&&(c=d),i.baseState=c,i.firstBaseUpdate=l,i.lastBaseUpdate=u,a===null&&(i.shared.lanes=0),od|=o,e.lanes=o,e.memoizedState=d}}function bo(e,t){if(typeof e!=`function`)throw Error(s(191,e));e.call(t)}function xo(e,t){var n=e.callbacks;if(n!==null)for(e.callbacks=null,e=0;ea?a:8;var o=R.T,s={};s.types=o===null?null:o.types,R.T=s,cc(e,!1,t,n);try{var c=i(),l=R.S;l!==null&&l(s,c),typeof c==`object`&&c&&typeof c.then==`function`?sc(e,t,za(c,r),jd(e)):sc(e,t,r,jd(e))}catch(n){sc(e,t,{then:function(){},status:`rejected`,reason:n},jd())}finally{z.p=a,o!==null&&s.types!==null&&(o.types=s.types),R.T=o}}function Zs(){}function Qs(e,t,n,r){if(e.tag!==5)throw Error(s(476));var i=$s(e).queue;Xs(e,i,t,B,n===null?Zs:function(){return ec(e),n(r)})}function $s(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:B,baseState:B,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ls,lastRenderedState:B},next:null};var n={};return t.next={memoizedState:n,baseState:n,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ls,lastRenderedState:n},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function ec(e){var t=$s(e);t.next===null&&(t=e.alternate.memoizedState),sc(e,t.next.queue,{},jd())}function tc(){return xa(sh)}function nc(){return is().memoizedState}function rc(){return is().memoizedState}function ic(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var n=jd();e=po(n);var r=mo(t,e,n);r!==null&&(Pd(r,t,n),ho(r,t,n)),t={cache:Oa()},e.payload=t;return}t=t.return}}function ac(e,t,n){var r=jd();n={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null},lc(e)?uc(t,n):(n=Si(e,t,n,r),n!==null&&(Pd(n,e,r),dc(n,t,r)))}function oc(e,t,n){sc(e,t,n,jd())}function sc(e,t,n,r){var i={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null};if(lc(e))uc(t,i);else{var a=e.alternate;if(e.lanes===0&&(a===null||a.lanes===0)&&(a=t.lastRenderedReducer,a!==null))try{var o=t.lastRenderedState,s=a(o,n);if(i.hasEagerState=!0,i.eagerState=s,Lr(s,o))return xi(e,t,i,0),$u===null&&bi(),!1}catch{}if(n=Si(e,t,i,r),n!==null)return Pd(n,e,r),dc(n,t,r),!0}return!1}function cc(e,t,n,r){if(r={lane:2,revertLane:Pf(),gesture:null,action:r,hasEagerState:!1,eagerState:null,next:null},lc(e)){if(t)throw Error(s(479))}else t=Si(e,n,r,2),t!==null&&Pd(t,e,2)}function lc(e){var t=e.alternate;return e===G||t!==null&&t===G}function uc(e,t){Ho=Vo=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function dc(e,t,n){if(n&4194048){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,dt(e,n)}}var fc={readContext:xa,use:ss,useCallback:Jo,useContext:Jo,useEffect:Jo,useImperativeHandle:Jo,useLayoutEffect:Jo,useInsertionEffect:Jo,useMemo:Jo,useReducer:Jo,useRef:Jo,useState:Jo,useDebugValue:Jo,useDeferredValue:Jo,useTransition:Jo,useSyncExternalStore:Jo,useId:Jo,useHostTransitionStatus:Jo,useFormState:Jo,useActionState:Jo,useOptimistic:Jo,useMemoCache:Jo,useCacheRefresh:Jo,useEffectEvent:Jo},pc={readContext:xa,use:ss,useCallback:function(e,t){return rs().memoizedState=[e,t===void 0?null:t],e},useContext:xa,useEffect:Ls,useImperativeHandle:function(e,t,n){n=n==null?null:n.concat([e]),Fs(4194308,4,Us.bind(null,t,e),n)},useLayoutEffect:function(e,t){return Fs(4194308,4,e,t)},useInsertionEffect:function(e,t){Fs(4,2,e,t)},useMemo:function(e,t){var n=rs();t=t===void 0?null:t;var r=e();if(Uo){qe(!0);try{e()}finally{qe(!1)}}return n.memoizedState=[r,t],r},useReducer:function(e,t,n){var r=rs();if(n!==void 0){var i=n(t);if(Uo){qe(!0);try{n(t)}finally{qe(!1)}}}else i=t;return r.memoizedState=r.baseState=i,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:i},r.queue=e,e=e.dispatch=ac.bind(null,G,e),[r.memoizedState,e]},useRef:function(e){var t=rs();return e={current:e},t.memoizedState=e},useState:function(e){e=ys(e);var t=e.queue,n=oc.bind(null,G,t);return t.dispatch=n,[e.memoizedState,n]},useDebugValue:Gs,useDeferredValue:function(e,t){return Js(rs(),e,t)},useTransition:function(){var e=ys(!1);return e=Xs.bind(null,G,e.queue,!0,!1),rs().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,n){var r=G,i=rs();if(W){if(n===void 0)throw Error(s(407));n=n()}else{if(n=t(),$u===null)throw Error(s(349));Y&127||ms(r,t,n)}i.memoizedState=n;var a={value:n,getSnapshot:t};return i.queue=a,Ls(gs.bind(null,r,a,e),[e]),r.flags|=2048,Ns(9,{destroy:void 0},hs.bind(null,r,a,n,t),null),n},useId:function(){var e=rs(),t=$u.identifierPrefix;if(W){var n=qi,r=Ki;n=(r&~(1<<32-Je(r)-1)).toString(32)+n,t=`_`+t+`R_`+n,n=Wo++,0<\/script>`,a=a.removeChild(a.firstChild);break;case`select`:a=typeof r.is==`string`?o.createElement(`select`,{is:r.is}):o.createElement(`select`),r.multiple?a.multiple=!0:r.size&&(a.size=r.size);break;default:a=typeof r.is==`string`?o.createElement(i,{is:r.is}):o.createElement(i)}}a[vt]=t,a[yt]=r;a:for(o=t.child;o!==null;){if(o.tag===5||o.tag===6)a.appendChild(o.stateNode);else if(o.tag!==4&&o.tag!==27&&o.child!==null){o.child.return=o,o=o.child;continue}if(o===t)break a;for(;o.sibling===null;){if(o.return===null||o.return===t)break a;o=o.return}o.sibling.return=o.return,o=o.sibling}t.stateNode=a;a:switch(np(a,i,r),i){case`button`:case`input`:case`select`:case`textarea`:r=!!r.autoFocus;break a;case`img`:r=!0;break a;default:r=!1}r&&dl(t)}}return gl(t),t.subtreeFlags&=-33554433,fl(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,n),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==r&&dl(t);else{if(typeof r!=`string`&&t.stateNode===null)throw Error(s(166));if(e=ve.current,sa(t)){if(e=t.stateNode,n=t.memoizedProps,r=null,i=$i,i!==null)switch(i.tag){case 27:case 5:r=i.memoizedProps}e[vt]=t,e=!!(e.nodeValue===n||r!==null&&!0===r.suppressHydrationWarning||ep(e.nodeValue,n)),e||ia(t,!0)}else e=lp(e).createTextNode(r),e[vt]=t,t.stateNode=e}return gl(t),null;case 31:if(n=t.memoizedState,e===null||e.memoizedState!==null){if(r=sa(t),n!==null){if(e===null){if(!r)throw Error(s(318));if(e=t.memoizedState,e=e===null?null:e.dehydrated,!e)throw Error(s(557));e[vt]=t}else ca(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;gl(t),e=!1}else n=la(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),e=!0;if(!e)return t.flags&256?(No(t),t):(No(t),null);if(t.flags&128)throw Error(s(558))}return gl(t),null;case 13:if(r=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(i=sa(t),r!==null&&r.dehydrated!==null){if(e===null){if(!i)throw Error(s(318));if(i=t.memoizedState,i=i===null?null:i.dehydrated,!i)throw Error(s(317));i[vt]=t}else ca(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;gl(t),i=!1}else i=la(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=i),i=!0;if(!i)return t.flags&256?(No(t),t):(No(t),null)}return No(t),t.flags&128?(t.lanes=n,t):(n=r!==null,e=e!==null&&e.memoizedState!==null,n&&(r=t.child,i=null,r.alternate!==null&&r.alternate.memoizedState!==null&&r.alternate.memoizedState.cachePool!==null&&(i=r.alternate.memoizedState.cachePool.pool),a=null,r.memoizedState!==null&&r.memoizedState.cachePool!==null&&(a=r.memoizedState.cachePool.pool),a!==i&&(r.flags|=2048)),n!==e&&n&&(t.child.flags|=8192),ml(t,t.updateQueue),gl(t),null);case 4:return xe(),e===null&&Wf(t.stateNode.containerInfo),t.flags|=67108864,gl(t),null;case 10:return ha(t.type),gl(t),null;case 19:if(Io(t),r=t.memoizedState,r===null)return gl(t),null;if(i=!!(t.flags&128),a=r.rendering,a===null){if(i)hl(r,!1);else{if(ad!==0||e!==null&&e.flags&128)for(e=t.child;e!==null;){if(a=Lo(e),a!==null){for(t.flags|=128,hl(r,!1),e=a.updateQueue,t.updateQueue=e,ml(t,e),t.subtreeFlags=0,e=n,n=t.child;n!==null;)ji(n,e),n=n.sibling;return Fo(t,Po.current&1|2),W&&Ji(t,r.treeForkCount),t.child}e=e.sibling}r.tail!==null&&Ie()>gd&&(t.flags|=128,i=!0,hl(r,!1),t.lanes=4194304)}}else{if(!i){if(e=Lo(a),e!==null){if(t.flags|=128,i=!0,e=e.updateQueue,t.updateQueue=e,ml(t,e),hl(r,!0),r.tail===null&&r.tailMode!==`collapsed`&&r.tailMode!==`visible`&&!a.alternate&&!W)return gl(t),null}else 2*Ie()-r.renderingStartTime>gd&&n!==536870912&&(t.flags|=128,i=!0,hl(r,!1),t.lanes=4194304)}r.isBackwards?(a.sibling=t.child,t.child=a):(e=r.last,e===null?t.child=a:e.sibling=a,r.last=a)}if(r.tail!==null){e=r.tail;a:{for(n=e;n!==null;){if(n.alternate!==null){n=!1;break a}n=n.sibling}n=!0}return r.rendering=e,r.tail=e.sibling,r.renderingStartTime=Ie(),e.sibling=null,a=Po.current,a=i?a&1|2:a&1,r.tailMode===`visible`||r.tailMode===`collapsed`||!n||W?Fo(t,a):(n=a,V(Do,t),V(Po,n),Oo===null&&(Oo=t)),W&&Ji(t,r.treeForkCount),e}return gl(t),null;case 22:case 23:return No(t),Eo(),r=t.memoizedState!==null,e===null?r&&(t.flags|=8192):e.memoizedState!==null!==r&&(t.flags|=8192),r?n&536870912&&!(t.flags&128)&&(gl(t),t.subtreeFlags&6&&(t.flags|=8192)):gl(t),n=t.updateQueue,n!==null&&ml(t,n.retryQueue),n=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(n=e.memoizedState.cachePool.pool),r=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(r=t.memoizedState.cachePool.pool),r!==n&&(t.flags|=2048),e!==null&&ge(Va),null;case 24:return n=null,e!==null&&(n=e.memoizedState.cache),t.memoizedState.cache!==n&&(t.flags|=2048),ha(Da),gl(t),null;case 25:return null;case 30:return t.flags|=33554432,gl(t),null}throw Error(s(156,t.tag))}function vl(e,t){switch(Zi(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return ha(Da),xe(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return Ce(t),null;case 31:if(t.memoizedState!==null){if(No(t),t.alternate===null)throw Error(s(340));ca()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(No(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(s(340));ca()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return Io(t),e=t.flags,e&65536?(t.flags=e&-65537|128,e=t.memoizedState,e!==null&&(e.rendering=null,e.tail=null),t.flags|=4,t):null;case 4:return xe(),null;case 10:return ha(t.type),null;case 22:case 23:return No(t),Eo(),e!==null&&ge(Va),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return ha(Da),null;case 25:return null;default:return null}}function yl(e,t){switch(Zi(t),t.tag){case 3:ha(Da),xe();break;case 26:case 27:case 5:Ce(t);break;case 4:xe();break;case 31:t.memoizedState!==null&&No(t);break;case 13:No(t);break;case 19:Io(t);break;case 10:ha(t.type);break;case 22:case 23:No(t),Eo(),e!==null&&ge(Va);break;case 24:ha(Da)}}function bl(e,t){try{var n=t.updateQueue,r=n===null?null:n.lastEffect;if(r!==null){var i=r.next;n=i;do{if((n.tag&e)===e){r=void 0;var a=n.create,o=n.inst;r=a(),o.destroy=r}n=n.next}while(n!==i)}}catch(e){Z(t,t.return,e)}}function xl(e,t,n){try{var r=t.updateQueue,i=r===null?null:r.lastEffect;if(i!==null){var a=i.next;r=a;do{if((r.tag&e)===e){var o=r.inst,s=o.destroy;if(s!==void 0){o.destroy=void 0,i=t;var c=n,l=s;try{l()}catch(e){Z(i,c,e)}}}r=r.next}while(r!==a)}}catch(e){Z(t,t.return,e)}}function Sl(e){var t=e.updateQueue;if(t!==null){var n=e.stateNode;try{xo(t,n)}catch(t){Z(e,e.return,t)}}}function Cl(e,t,n){n.props=bc(e.type,e.memoizedProps),n.state=e.memoizedState;try{n.componentWillUnmount()}catch(n){Z(e,t,n)}}function wl(e,t){try{var n=e.ref;if(n!==null){switch(e.tag){case 26:case 27:case 5:var r=e.stateNode;break;case 30:var i=e.stateNode,a=pi(e.memoizedProps,i);(i.ref===null||i.ref.name!==a)&&(i.ref=Pp(a)),r=i.ref;break;case 7:if(e.stateNode===null){var o=new Fp(e);h(e.child,!1,Qp,o,void 0,void 0),e.stateNode=o}r=e.stateNode;break;default:r=e.stateNode}typeof n==`function`?e.refCleanup=n(r):n.current=r}}catch(n){Z(e,t,n)}}function Tl(e,t){var n=e.ref,r=e.refCleanup;if(n!==null){if(typeof r==`function`)try{r()}catch(n){Z(e,t,n)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof n==`function`)try{n(null)}catch(n){Z(e,t,n)}else n.current=null}}function El(e,t){if((e.tag===5||e.tag===27||e.tag===6)&&e.alternate===null&&t!==null)for(var n=0;n title`))),np(r,t,n),r[vt]=e,Mt(r),t=r;break a;case`link`:if(a=Gm(`link`,`href`,i).get(t+(n.href||``))){for(o=0;og&&(o=g,g=h,h=o);var _=Vr(s,h),v=Vr(s,g);if(_&&v&&(p.rangeCount!==1||p.anchorNode!==_.node||p.anchorOffset!==_.offset||p.focusNode!==v.node||p.focusOffset!==v.offset)){var y=d.createRange();y.setStart(_.node,_.offset),p.removeAllRanges(),h>g?(p.addRange(y),p.extend(v.node,v.offset)):(y.setEnd(v.node,v.offset),p.addRange(y))}}}}for(d=[],p=s;p=p.parentNode;)p.nodeType===1&&d.push({element:p,left:p.scrollLeft,top:p.scrollTop});for(typeof s.focus==`function`&&s.focus(),s=0;sn?32:n,R.T=null,n=wd,wd=null;var a=bd,o=Sd;if(yd=0,xd=bd=null,Sd=0,q&6)throw Error(s(331));var c=q;if(q|=4,Ju(a.current),Bu(a,a.current,o,n),q=c,Df(0,!1),Ke&&typeof Ke.onPostCommitFiberRoot==`function`)try{Ke.onPostCommitFiberRoot(Ge,a)}catch{}return!0}finally{z.p=i,R.T=r,uf(e,t)}}function pf(e,t,n){t=Ri(n,t),t=Ec(e.stateNode,t,2),e=mo(e,t,2),e!==null&&(ct(e,2),Ef(e))}function Z(e,t,n){if(e.tag===3)pf(e,e,n);else for(;t!==null;){if(t.tag===3){pf(t,e,n);break}if(t.tag===1){var r=t.stateNode;if(typeof t.type.getDerivedStateFromError==`function`||typeof r.componentDidCatch==`function`&&(vd===null||!vd.has(r))){e=Ri(n,e),n=Dc(2),r=mo(t,n,2),r!==null&&(Oc(n,r,t,e),ct(r,2),Ef(r));break}}t=t.return}}function mf(e,t,n){var r=e.pingCache;if(r===null){r=e.pingCache=new Qu;var i=new Set;r.set(t,i)}else i=r.get(t),i===void 0&&(i=new Set,r.set(t,i));i.has(n)||(rd=!0,i.add(n),e=hf.bind(null,e,t,n),t.then(e,e))}function hf(e,t,n){var r=e.pingCache;r!==null&&r.delete(t),e.pingedLanes|=e.suspendedLanes&n,e.warmLanes&=~n,$u===e&&(Y&n)===n&&(ad===4||ad===3&&(Y&62914560)===Y&&300>Ie()-md?q&2?cd|=n:Vd(e,0):cd|=n,ud===Y&&(ud=0)),Ef(e)}function gf(e,t){t===0&&(t=ot()),e=Ci(e,t),e!==null&&(ct(e,t),Ef(e))}function _f(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),gf(e,n)}function vf(e,t){var n=0;switch(e.tag){case 31:case 13:var r=e.stateNode,i=e.memoizedState;i!==null&&(n=i.retryLane);break;case 19:r=e.stateNode;break;case 22:r=e.stateNode._retryCache;break;default:throw Error(s(314))}r!==null&&r.delete(t),gf(e,n)}function yf(e,t){return Me(e,t)}var bf=null,xf=null,Sf=!1,Cf=!1,wf=!1,Tf=0;function Ef(e){e!==xf&&e.next===null&&(xf===null?bf=xf=e:xf=xf.next=e),Cf=!0,Sf||(Sf=!0,Nf())}function Df(e,t){if(!wf&&Cf){wf=!0;do for(var n=!1,r=bf;r!==null;){if(!t){if(e!==0){var i=r.pendingLanes;if(i===0)var a=0;else{var o=r.suspendedLanes,s=r.pingedLanes;a=(1<<31-Je(42|e)+1)-1,a&=i&~(o&~s),a=a&201326741?a&201326741|1:a?a|2:0}a!==0&&(n=!0,Mf(r,a))}else a=Y,a=nt(r,r===$u?a:0,r.cancelPendingCommit!==null||r.timeoutHandle!==-1),!(a&3)||rt(r,a)||(n=!0,Mf(r,a))}r=r.next}while(n);wf=!1}}function Of(){kf()}function kf(){Cf=Sf=!1;var e=0;Tf!==0&&hp()&&(e=Tf);for(var t=Ie(),n=null,r=bf;r!==null;){var i=r.next,a=Af(r,t);a===0?(r.next=null,n===null?bf=i:n.next=i,i===null&&(xf=n)):(n=r,(e!==0||a&3)&&(Cf=!0)),r=i}yd!==0&&yd!==5||Df(e,!1),Tf!==0&&(Tf=0)}function Af(e,t){for(var n=e.suspendedLanes,r=e.pingedLanes,i=e.expirationTimes,a=e.pendingLanes&-62914561;0s)break;var u=c.transferSize,d=c.initiatorType;u&&ap(d)&&(c=c.responseEnd,o+=u*(c$m){s.length=o;break}f=new Promise(jp.bind(f)),s.push(f)}}}if(0`u`?null:document;function Tm(e,t,n){var r=wm;if(r&&typeof t==`string`&&t){var i=Qt(t);i=`link[rel="`+e+`"][href="`+i+`"]`,typeof n==`string`&&(i+=`[crossorigin="`+n+`"]`),ym.has(i)||(ym.add(i),e={rel:e,crossOrigin:n,href:t},r.querySelector(i)===null&&(t=r.createElement(`link`),np(t,`link`,e),Mt(t),r.head.appendChild(t)))}}function Em(e){xm.D(e),Tm(`dns-prefetch`,e,null)}function Dm(e,t){xm.C(e,t),Tm(`preconnect`,e,t)}function Om(e,t,n){xm.L(e,t,n);var r=wm;if(r&&e&&t){var i=`link[rel="preload"][as="`+Qt(t)+`"]`;t===`image`&&n&&n.imageSrcSet?(i+=`[imagesrcset="`+Qt(n.imageSrcSet)+`"]`,typeof n.imageSizes==`string`&&(i+=`[imagesizes="`+Qt(n.imageSizes)+`"]`)):i+=`[href="`+Qt(e)+`"]`;var a=i;switch(t){case`style`:a=Pm(e);break;case`script`:a=Rm(e)}if(!(vm.has(a)||(e=D({rel:`preload`,href:t===`image`&&n&&n.imageSrcSet?void 0:e,as:t},n),vm.set(a,e),r.querySelector(i)!==null||t===`style`&&r.querySelector(Fm(a))||t===`script`&&r.querySelector(zm(a))))){var o=r.createElement(`link`);np(o,`link`,e),t===`style`&&(o[Et]=!0,o.onload=o.onerror=function(){Nt(o)}),Mt(o),r.head.appendChild(o)}}}function km(e,t){xm.m(e,t);var n=wm;if(n&&e){var r=t&&typeof t.as==`string`?t.as:`script`,i=`link[rel="modulepreload"][as="`+Qt(r)+`"][href="`+Qt(e)+`"]`,a=i;switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:a=Rm(e)}if(!vm.has(a)&&(e=D({rel:`modulepreload`,href:e},t),vm.set(a,e),n.querySelector(i)===null)){switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:if(n.querySelector(zm(a)))return}r=n.createElement(`link`),np(r,`link`,e),Mt(r),n.head.appendChild(r)}}}function Am(e,t,n){xm.S(e,t,n);var r=wm;if(r&&e){var i=jt(r).hoistableStyles,a=Pm(e);t||=`default`;var o=i.get(a);if(!o){var s={loading:0,preload:null};if(o=r.querySelector(Fm(a)))s.loading=5;else{e=D({rel:`stylesheet`,href:e,"data-precedence":t},n),(n=vm.get(a))&&Hm(e,n);var c=o=r.createElement(`link`);Mt(c),np(c,`link`,e),c._p=new Promise(function(e,t){c.onload=e,c.onerror=t}),c.addEventListener(`load`,function(){s.loading|=1}),c.addEventListener(`error`,function(){s.loading|=2}),s.loading|=4,Vm(o,t,r)}o={type:`stylesheet`,instance:o,count:1,state:s},i.set(a,o)}}}function jm(e,t){xm.X(e,t);var n=wm;if(n&&e){var r=jt(n).hoistableScripts,i=Rm(e),a=r.get(i);a||(a=n.querySelector(zm(i)),a||(e=D({src:e,async:!0},t),(t=vm.get(i))&&Um(e,t),a=n.createElement(`script`),Mt(a),np(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function Mm(e,t){xm.M(e,t);var n=wm;if(n&&e){var r=jt(n).hoistableScripts,i=Rm(e),a=r.get(i);a||(a=n.querySelector(zm(i)),a||(e=D({src:e,async:!0,type:`module`},t),(t=vm.get(i))&&Um(e,t),a=n.createElement(`script`),Mt(a),np(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function Nm(e,t,n,r){var i=(i=ve.current)?bm(i):null;if(!i)throw Error(s(446));switch(e){case`meta`:case`title`:return null;case`style`:return typeof n.precedence==`string`&&typeof n.href==`string`?(n=Pm(n.href),t=jt(i).hoistableStyles,r=t.get(n),r||(r={type:`style`,instance:null,count:0,state:null},t.set(n,r)),r):{type:`void`,instance:null,count:0,state:null};case`link`:if(n.rel===`stylesheet`&&typeof n.href==`string`&&typeof n.precedence==`string`){e=Pm(n.href);var a=jt(i).hoistableStyles,o=a.get(e);if(o||(i=i.ownerDocument||i,o={type:`stylesheet`,instance:null,count:0,state:{loading:0,preload:null}},a.set(e,o),(a=i.querySelector(Fm(e)))?a._p||(o.instance=a,o.state.loading=5):(a=vm.get(e),a||(a={rel:`preload`,as:`style`,href:n.href,crossOrigin:n.crossOrigin,integrity:n.integrity,media:n.media,hrefLang:n.hrefLang,referrerPolicy:n.referrerPolicy},vm.set(e,a)),Lm(i,e,a,o.state))),t&&r===null)throw Error(s(528,``));return o}if(t&&r!==null)throw Error(s(529,``));return null;case`script`:return t=n.async,n=n.src,typeof n==`string`&&t&&typeof t!=`function`&&typeof t!=`symbol`?(n=Rm(n),t=jt(i).hoistableScripts,r=t.get(n),r||(r={type:`script`,instance:null,count:0,state:null},t.set(n,r)),r):{type:`void`,instance:null,count:0,state:null};default:throw Error(s(444,e))}}function Pm(e){return`href="`+Qt(e)+`"`}function Fm(e){return`link[rel="stylesheet"][`+e+`]`}function Im(e){return D({},e,{"data-precedence":e.precedence,precedence:null})}function Lm(e,t,n,r){if(t=e.querySelector(`link[rel="preload"][as="style"][`+t+`]`)){if(!0!==t[Et]){r.loading=1;return}}else t=e.createElement(`link`),t[Et]=!0,t.onload=t.onerror=Nt.bind(null,t),np(t,`link`,n),Mt(t),e.head.appendChild(t);r.preload=t,t.addEventListener(`load`,function(){return r.loading|=1}),t.addEventListener(`error`,function(){return r.loading|=2})}function Rm(e){return`[src="`+Qt(e)+`"]`}function zm(e){return`script[async]`+e}function Bm(e,t,n){if(t.count++,t.instance===null)switch(t.type){case`style`:var r=e.querySelector(`style[data-href~="`+Qt(n.href)+`"]`);if(r)return t.instance=r,Mt(r),r;var i=D({},n,{"data-href":n.href,"data-precedence":n.precedence,href:null,precedence:null});return r=(e.ownerDocument||e).createElement(`style`),Mt(r),np(r,`style`,i),Vm(r,n.precedence,e),t.instance=r;case`stylesheet`:i=Pm(n.href);var a=e.querySelector(Fm(i));if(a)return t.state.loading|=4,t.instance=a,Mt(a),a;r=Im(n),(i=vm.get(i))&&Hm(r,i),a=(e.ownerDocument||e).createElement(`link`),Mt(a);var o=a;return o._p=new Promise(function(e,t){o.onload=e,o.onerror=t}),np(a,`link`,r),t.state.loading|=4,Vm(a,n.precedence,e),t.instance=a;case`script`:return a=Rm(n.src),(i=e.querySelector(zm(a)))?(t.instance=i,Mt(i),i):(r=n,(i=vm.get(a))&&(r=D({},n),Um(r,i)),e=e.ownerDocument||e,i=e.createElement(`script`),Mt(i),np(i,`link`,r),e.head.appendChild(i),t.instance=i);case`void`:return null;default:throw Error(s(443,t.type))}else t.type===`stylesheet`&&!(t.state.loading&4)&&(r=t.instance,t.state.loading|=4,Vm(r,n.precedence,e));return t.instance}function Vm(e,t,n){for(var r=n.querySelectorAll(`link[rel="stylesheet"][data-precedence],style[data-precedence]`),i=r.length?r[r.length-1]:null,a=i,o=0;o title`):null)}function qm(e,t,n){if(n===1||t.itemProp!=null)return!1;switch(e){case`meta`:case`title`:return!0;case`style`:if(typeof t.precedence!=`string`||typeof t.href!=`string`||t.href===``)break;return!0;case`link`:if(typeof t.rel!=`string`||typeof t.href!=`string`||t.href===``||t.onLoad||t.onError)break;switch(t.rel){case`stylesheet`:return e=t.disabled,typeof t.precedence==`string`&&e==null;default:return!0}case`script`:if(t.async&&typeof t.async!=`function`&&typeof t.async!=`symbol`&&!t.onLoad&&!t.onError&&t.src&&typeof t.src==`string`)return!0}return!1}function Jm(e,t){return e===`img`&&t.src!=null&&t.src!==``&&t.onLoad==null&&t.loading!==`lazy`}function Ym(e){return!(e.type===`stylesheet`&&!(e.state.loading&3))}function Xm(e){return(e.width||100)*(e.height||100)*(typeof devicePixelRatio==`number`?devicePixelRatio:1)*.25}function Zm(e,t){typeof t.decode==`function`&&(e.imgCount++,t.complete||(e.imgBytes+=Xm(t),e.suspenseyImages.push(t)),e=rh.bind(e),t.decode().then(e,e))}function Qm(e,t,n,r){if(n.type===`stylesheet`&&(typeof r.media!=`string`||!1!==matchMedia(r.media).matches)&&!(n.state.loading&4)){if(n.instance===null){var i=Pm(r.href),a=t.querySelector(Fm(i));if(a){t=a._p,typeof t==`object`&&t&&typeof t.then==`function`&&(e.count++,e=nh.bind(e),t.then(e,e)),n.state.loading|=4,n.instance=a,Mt(a);return}a=t.ownerDocument||t,r=Im(r),(i=vm.get(i))&&Hm(r,i),a=a.createElement(`link`),Mt(a);var o=a;o._p=new Promise(function(e,t){o.onload=e,o.onerror=t}),np(a,`link`,r),n.instance=a}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(n,t),(t=n.state.preload)&&!(n.state.loading&3)&&(e.count++,n=nh.bind(e),t.addEventListener(`load`,n),t.addEventListener(`error`,n))}}var $m=0;function eh(e,t){return e.stylesheets&&e.count===0&&ah(e,e.stylesheets),0$m?50:800)+t);return e.unsuspend=n,function(){e.unsuspend=null,clearTimeout(r),clearTimeout(i)}}:null}function th(e){if(e.count===0&&(e.imgCount===0||!e.waitingForImages)){if(e.stylesheets)ah(e,e.stylesheets);else if(e.unsuspend){var t=e.unsuspend;e.unsuspend=null,t()}}}function nh(){this.count--,th(this)}function rh(){this.imgCount--,th(this)}var ih=null;function ah(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,ih=new Map,t.forEach(oh,e),ih=null,nh.call(e))}function oh(e,t){if(!(t.state.loading&4)){var n=ih.get(e);if(n)var r=n.get(null);else{n=new Map,ih.set(e,n);for(var i=e.querySelectorAll(`link[data-precedence],style[data-precedence]`),a=0;a{function n(){if(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<`u`&&typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE==`function`)try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=s()}))(),l=n(),u=``;function d(e){u=e}var f=class extends Error{code;status;result;constructor(e,t,n,r){super(t),this.code=e,this.status=n,this.result=r}};async function p(e,t){let n=await fetch(`/admin/api${e}`,{...t,credentials:`same-origin`,headers:{"Content-Type":`application/json; charset=utf-8`,...u?{"X-Iris-CSRF":u}:{},...t?.headers}});if(!n.ok){let e=await n.json().catch(()=>({})),t=e.error||{};throw[`login_required`,`setup_required`,`csrf_failed`].includes(t.code)&&dispatchEvent(new Event(`iris-auth`)),new f(t.code||`request_failed`,t.message||(t.fields?`请检查输入:${t.fields.map(e=>`${e.field.split(`.`).pop()}:${e.message}`).join(`;`)}`:`请求失败,请重试`),n.status,e.result)}return n}async function m(e,t){let n=await p(e,t);return{data:await n.json(),status:n.status,headers:n.headers}}async function h(e,t){let n=await p(e,t);if(n.headers.get(`Content-Type`)?.split(`;`)[0].trim()!==`application/zip`)throw new f(`invalid_download`,`没有收到 ZIP 备份,请刷新登录状态后重试`,n.status);return{blob:await n.blob(),headers:n.headers}}async function g(e,t){return(await m(e,t)).data}var _=(e,t)=>({method:e,...t===void 0?{}:{body:JSON.stringify(t)}}),v=e=>e instanceof f?e.status===410&&[`entry_profile_legacy_write_retired`,`entry_profile_publish_mode_retired`].includes(e.code)?`旧画像的整版编辑、回滚和候选审批已退役。请在入口画像页逐条管理画像记忆;旧版本仅供查看。`:e.message:`无法连接服务,请检查服务是否仍在运行`;function y(e,t=0){let[n,r]=(0,l.useState)(null),[i,a]=(0,l.useState)(``),[o,s]=(0,l.useState)(e!==null),[c,u]=(0,l.useState)(0),d=(0,l.useCallback)(()=>{s(!0),u(e=>e+1)},[]);return(0,l.useEffect)(()=>{r(null),a(``)},[e]),(0,l.useEffect)(()=>{if(s(e!==null),e===null)return;let n=new AbortController,i=!0,o,c=async()=>{try{let t=await g(e,{signal:n.signal});i&&(r(t),a(``))}catch(e){i&&!n.signal.aborted&&a(v(e))}finally{i&&s(!1)}i&&t&&(o=setTimeout(c,t))};return c(),()=>{i=!1,n.abort(),clearTimeout(o)}},[e,t,c]),{data:n,error:i,refresh:d,loading:o}}var b=e((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.fragment`);function r(e,n,r){var i=null;if(r!==void 0&&(i=``+r),n.key!==void 0&&(i=``+n.key),`key`in n)for(var a in r={},n)a!==`key`&&(r[a]=n[a]);else r=n;return n=r.ref,{$$typeof:t,type:e,key:i,ref:n===void 0?null:n,props:r}}e.Fragment=n,e.jsx=r,e.jsxs=r})),x=e(((e,t)=>{t.exports=b()}))(),S=e=>e?new Date(e).toLocaleString(`zh-CN`,{month:`numeric`,day:`numeric`,hour:`2-digit`,minute:`2-digit`}):`暂无记录`,C=e=>e==null?`—`:`${(e/1e3).toFixed(1)} 秒`,w=e=>e?new Date(e).toLocaleString(`zh-CN`):`暂无记录`;function T({total:e,offset:t,limit:n=30,change:r}){return e<=n&&t===0?null:(0,x.jsxs)(`div`,{className:`pagination`,children:[(0,x.jsx)(`button`,{className:`secondary`,disabled:t===0,onClick:()=>r(Math.max(0,t-n)),children:`上一页`}),(0,x.jsxs)(`span`,{children:[`第 `,Math.floor(t/n)+1,` 页 · 共 `,e,` 条`]}),(0,x.jsx)(`button`,{className:`secondary`,disabled:t+n>=e,onClick:()=>r(t+n),children:`下一页`})]})}var E=e=>({active:`有效`,forgotten:`已遗忘`,deleted:`已删除`})[e]||e,D=e=>({normal:`正常`,temporarily_unavailable:`暂时不可用`,invalid_key:`密钥无效`,configuration_error:`配置错误`,account_problem:`账户异常`,usage_limit:`达到今日用量上限`,rate_limited:`限流退避中`})[e]||e,O=e=>({pending:`已接收 · 待学习`,batched:`已接收 · 批次处理中`,learned:`学习已完成`,abandoned:`学习放弃 · 未记住`,refused:`内容拒绝 · 未记住`,filtered:`已过滤 · 不参与学习`})[e]||e;function k(e){return e?e.state===`succeeded`?e.result?.created?.length||e.result?.updated?.length?`学习成功 · 新增 ${e.result.created?.length||0} / 更新 ${e.result.updated?.length||0}`:`学习成功,未形成新记忆`:{running:`正在学习`,waiting:e.next_retry_at?`失败后等待重试`:`等待学习`,abandoned:`已放弃 · 未记住`,refused:`已拒绝 · 未记住`}[e.state]||e.state:`暂无批次`}function A({children:e,error:t=!1}){return(0,x.jsx)(`div`,{className:`notice ${t?`error`:``}`,role:t?`alert`:`status`,children:e})}function j({title:e,children:t}){return(0,x.jsxs)(`div`,{className:`empty`,children:[(0,x.jsx)(`span`,{className:`empty-mark`,"aria-hidden":!0,children:`✳`}),(0,x.jsx)(`h3`,{children:e}),t&&(0,x.jsx)(`p`,{children:t})]})}function M({children:e,tone:t=``}){return(0,x.jsx)(`span`,{className:`badge ${t}`,children:e})}function N({title:e,onClose:t,children:n,closeDisabled:r=!1}){let i=(0,l.useRef)(null),a=(0,l.useRef)(t);return a.current=r?()=>{}:t,(0,l.useEffect)(()=>{let e=document.activeElement;(i.current?.querySelector(`button,input,textarea,select`))?.focus();let t=e=>{if(e.key===`Escape`&&(e.preventDefault(),a.current()),e.key===`Tab`){let t=[...i.current?.querySelectorAll(`button:not(:disabled),a[href],input:not(:disabled),textarea:not(:disabled),select:not(:disabled),[tabindex="0"]`)||[]],n=t[0],r=t[t.length-1];e.shiftKey&&document.activeElement===n?(e.preventDefault(),r?.focus()):!e.shiftKey&&document.activeElement===r&&(e.preventDefault(),n?.focus())}},n=document.body.style.overflow;return document.body.style.overflow=`hidden`,document.addEventListener(`keydown`,t),()=>{document.body.style.overflow=n,document.removeEventListener(`keydown`,t),e?.focus()}},[]),(0,x.jsx)(`div`,{className:`overlay`,children:(0,x.jsxs)(`section`,{ref:i,className:`dialog`,role:`dialog`,"aria-modal":`true`,"aria-label":e,children:[(0,x.jsxs)(`div`,{className:`dialog-title`,children:[(0,x.jsx)(`h2`,{children:e}),(0,x.jsx)(`button`,{className:`icon-button`,"aria-label":`关闭详情`,disabled:r,onClick:t,children:`×`})]}),n]})})}function P({value:e}){return e?(0,x.jsx)(`time`,{dateTime:e,children:e.replace(`T`,` `).replace(/\.\d+(?=[+-]|Z$)/,``).replace(/([+-]\d{2}:\d{2}|Z)$/,` $1`)}):(0,x.jsx)(x.Fragment,{children:`暂无记录`})}var F={initial_setting:`初始设定`,periodic:`定期更新`,regenerate:`重新生成`,admin_edit:`管理员编辑`,rollback:`回滚`},I={current:`当前`,pending:`待确认`,rejected:`已拒绝`,superseded:`已被后续候选替代`,history:`历史已发布`},L={small:`小`,medium:`中`,large:`大`},ee={memory:`记忆依据`,admin:`手写`,initial_template:`初始模板`},te={modified:`记忆已修改`,forgotten:`记忆已遗忘`,deleted:`记忆已删除或清除`,no_longer_self_memory:`已不属于自我记忆`,sources_changed:`来源已变化`,daily_token_limit:`达到每日用量上限`,no_self_evidence:`暂无有效自我记忆依据`,not_due:`尚未满足定期更新条件`,evidence_changed:`依据已变化`,current_version_changed:`当前版本已变化`,interrupted:`服务中断,任务未完成`,worker_unavailable:`生成工作线程不可用`,unconfigured:`尚未配置生成模型`,unexpected_error:`生成时发生异常`,timeout:`模型调用超时`,invalid_output:`模型输出不符合要求`,paused:`模型用途已暂停`,usage_limit:`达到每日用量上限`,temporarily_unavailable:`模型暂时不可用`,configuration_error:`模型配置错误`,invalid_key:`模型密钥无效`,account_problem:`模型账户异常`,rate_limited:`模型限流`,"administrator rejected":`管理员拒绝采用`,"sentences must be an array":`句子列表格式无效`,"empty persona":`persona 正文为空`,"persona exceeds 800 characters":`persona 正文超过 800 字`,"residual memory or participant reference":`正文残留记忆或参与者编号`,"under 300 characters: concise evidence-bound text is allowed":`不足 300 字:允许依据有限时保持简短`,"initial template retains the pre-M3 length behavior":`初始模板沿用此前的长度规则`,"nonempty text required":`句子不能为空`,"one sentence per item required":`每项须为一句话`,"invalid administrator attribution":`手写归属无效`,"missing or unknown evidence":`缺少依据或依据未知`,"invalid model verdict":`模型判断格式无效`,"single-date/unknown-date evidence needs a scene qualifier":`单日或日期未知的依据需要场景限定`,"invalid change degree":`变化程度无效`,"model check must cover every sentence, in order":`模型检查须按顺序覆盖每句话`,"model check reason required":`模型检查缺少理由`};function ne(e){let t=e.match(/^sentence (\d+):\s*(.*)$/);return t?`第 ${t[1]} 句:${ne(t[2])}`:te[e]||e}var re=e=>e===`queued`||e===`running`;function ie(e,t){return re(e)?{queued:`等待生成`,generating:`正在生成候选`,checking:`正在检查候选`}[t]||`正在生成候选`:{current:`已发布 persona`,pending:`候选待确认,当前版本仍保留`,rejected:`候选被拒绝,当前版本仍保留`,skipped:`本次未生成候选`,conflict:`生成期间版本或依据发生变化,未发布`,failed:`生成失败,当前版本仍保留`}[e]||e}var ae={disputed:`争议`,insufficient_support:`依据不足`,superseded:`已被替代`},oe={pending:`待确认`,confirmed:`已确认`,cleared:`已清除`},se=[[`merge_enabled`,`合并重复记忆`],[`conflict_enabled`,`矛盾检查与建议`],[`dependency_enabled`,`派生依据复核与建议`],[`persona_enabled`,`定期更新 persona`],[`person_summary_enabled`,`定期更新人物摘要`],[`goal_review_enabled`,`目标依据复核`]];function ce(e){return{disabled:`本次设置已关闭`,model_items_disabled:`记忆模型整理项目均已关闭`,call_budget:`模型调用次数预算已用尽`,persona_busy:`已有 persona 任务正在运行`,checks_rejected:`persona 检查未通过,候选被拒绝`,revision_conflict:`对象修订已变化,跳过本次写入`,unsafe_write:`未通过写入保护校验`,invalid_response:`模型返回格式无效`,invalid_json:`模型返回的 JSON 无效`,temporary_unavailable:`模型暂时不可用`,cooldown:`尚未到定期更新时间`,no_changes:`没有需要更新的变化`,stale:`判断期间目标或依据已变化,等待重新复核`,lease_expired:`本次判断任务已超时,等待重新复核`,configuration_changed:`判断设置已变化,等待重新复核`,goal_closed:`目标已结束,取消待复核任务`,in_progress:`已有复核任务正在运行`,queue_full:`判断排队已满`,configuration:`模型尚未配置或配置无效`,budget:`预算已耗尽`,invalid:`模型输出未通过校验`,source_unavailable:`来源已不可用`,insufficient_new_memories:`新增自我记忆不足,尚未到更新条件`,too_soon:`距离上次更新尚不足一个周期`}[e]||ne(e)}function le({value:e,timezone:t,busy:n,save:r}){let[i,a]=(0,l.useState)(()=>({...e,person_summary_enabled:e.person_summary_enabled??!0,max_calls:String(e.max_calls)})),o=(0,l.useRef)(!1),[s,c]=(0,l.useState)(``),[u,d]=(0,l.useState)(!1);(0,l.useEffect)(()=>{o.current||a({...e,person_summary_enabled:e.person_summary_enabled??!0,max_calls:String(e.max_calls)})},[e]);function f(e,t){o.current=!0,d(!1),a(n=>({...n,[e]:t}))}async function p(e){if(e.preventDefault(),n)return;if(c(``),d(!1),!/^(?:[01][0-9]|2[0-3]):[0-5][0-9]$/.test(i.maintenance_time)){c(`整理运行时间须为 HH:MM,范围 00:00—23:59`);return}let t=Number(i.max_calls);if(!i.max_calls.trim()||!Number.isInteger(t)||t<0||t>50){c(`模型调用次数预算须为 0—50 的整数`);return}let s=await r({...i,max_calls:t});s&&(o.current=!1,a({...s,person_summary_enabled:s.person_summary_enabled??!0,max_calls:String(s.max_calls)}),d(!0))}return(0,x.jsxs)(`section`,{className:`panel settings-panel`,"aria-label":`梦境整理设置`,id:`consolidation-settings`,children:[(0,x.jsx)(`h2`,{children:`梦境整理`}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`整理不中断接收和学习。修改只影响之后接受的新运行,已接受的运行与续跑沿用其设置快照。`}),(0,x.jsx)(`form`,{onSubmit:p,noValidate:!0,children:(0,x.jsxs)(`fieldset`,{disabled:n,className:`lifecycle-fieldset`,children:[(0,x.jsxs)(`div`,{className:`form-grid`,children:[(0,x.jsxs)(`label`,{children:[`整理运行时间`,(0,x.jsx)(`input`,{"aria-label":`整理运行时间`,type:`text`,required:!0,maxLength:5,placeholder:`03:00`,value:i.maintenance_time,onChange:e=>f(`maintenance_time`,e.target.value)}),(0,x.jsxs)(`small`,{children:[`HH:MM · 角色时区 `,t||`未设置`,`,与每日记忆维护共用时间。`]})]}),(0,x.jsxs)(`label`,{children:[`每次整理的模型调用次数预算`,(0,x.jsx)(`input`,{"aria-label":`每次整理的模型调用次数预算`,type:`number`,min:0,max:50,step:1,required:!0,value:i.max_calls,onChange:e=>f(`max_calls`,e.target.value)}),(0,x.jsx)(`small`,{children:`0—50,包含重试、修正、persona 与人物摘要生成及检查。`})]})]}),se.map(([e,t])=>(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:i[e],onChange:t=>f(e,t.target.checked)}),t]},e)),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`预算为 0 时不调用模型,记忆生命周期维护与开启的目标依据复核仍会执行。persona 与人物摘要需满足各自更新条件且至少剩余 2 次调用名额。人物摘要开关只影响之后的整理,不关闭已发布摘要的宿主读取。`}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`矛盾和依赖复核只产生管理员可见的模型建议;目标依据复核不自动完成或放弃目标。`}),s&&(0,x.jsx)(A,{error:!0,children:s}),u&&(0,x.jsx)(A,{children:`梦境整理设置已保存`}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`primary`,children:`保存梦境整理设置`}),(0,x.jsx)(`button`,{type:`button`,onClick:()=>{o.current=!1,a({...e,person_summary_enabled:e.person_summary_enabled??!0,max_calls:String(e.max_calls)}),c(``),d(!1)},children:`还原整理设置`})]})]})}),(0,x.jsx)(`a`,{href:`#/status`,children:`查看整理报告或手动运行`})]})}function ue({value:e,busy:t,save:n}){let r=e=>({enabled:e.enabled,budget_seconds:String(e.budget_seconds),concurrency:String(e.concurrency),queue_limit:String(e.queue_limit)}),[i,a]=(0,l.useState)(()=>r(e)),o=(0,l.useRef)(!1),[s,c]=(0,l.useState)(``),[u,d]=(0,l.useState)(!1);(0,l.useEffect)(()=>{o.current||a(r(e))},[e]);function f(e,t){o.current=!0,d(!1),a(n=>({...n,[e]:t}))}async function p(e){if(e.preventDefault(),t)return;c(``),d(!1);let s=Number(i.budget_seconds),l=Number(i.concurrency),u=Number(i.queue_limit);if(!i.budget_seconds.trim()||!Number.isFinite(s)||s<=0||s>10){c(`目标去重判断预算须大于 0 且不超过 10 秒`);return}if(!i.concurrency.trim()||!Number.isInteger(l)||l<1||l>8){c(`目标去重判断并发须为 1—8 的整数`);return}if(!i.queue_limit.trim()||!Number.isInteger(u)||u<0||u>64){c(`目标去重判断排队上限须为 0—64 的整数`);return}let f=await n({enabled:i.enabled,budget_seconds:s,concurrency:l,queue_limit:u});f&&(o.current=!1,a(r(f)),d(!0))}return(0,x.jsxs)(`form`,{className:`judge-settings`,onSubmit:p,noValidate:!0,"aria-label":`目标去重判断设置`,children:[(0,x.jsx)(`h3`,{children:`目标判断开关与排队`}),(0,x.jsxs)(`fieldset`,{disabled:t,className:`lifecycle-fieldset`,children:[(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:i.enabled,onChange:e=>f(`enabled`,e.target.checked)}),`启用目标去重判断`]}),(0,x.jsxs)(`label`,{children:[`目标去重方法`,(0,x.jsx)(`input`,{"aria-label":`目标去重方法`,readOnly:!0,value:i.enabled?`C2(批量判断与可能重复提示)`:`A(确定性规则)`}),(0,x.jsx)(`small`,{children:`方法由后端固定;管理接口目前不提供方法切换。`})]}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`关闭后使用确定性规则。开启时若模型暂时不可用,先保留目标并等待复核;管理员创建的目标始终只标可能重复,不自动合并。清除独立模型配置只恢复沿用,不会关闭判断。`}),(0,x.jsxs)(`div`,{className:`form-grid`,children:[(0,x.jsxs)(`label`,{children:[`目标去重判断预算(秒)`,(0,x.jsx)(`input`,{type:`number`,"aria-label":`目标去重判断预算(秒)`,min:.01,max:10,step:`any`,required:!0,value:i.budget_seconds,onChange:e=>f(`budget_seconds`,e.target.value)}),(0,x.jsx)(`small`,{children:`大于 0 且不超过 10,含排队和模型调用。`})]}),(0,x.jsxs)(`label`,{children:[`目标去重判断并发`,(0,x.jsx)(`input`,{type:`number`,min:1,max:8,step:1,required:!0,value:i.concurrency,onChange:e=>f(`concurrency`,e.target.value)})]}),(0,x.jsxs)(`label`,{children:[`目标去重判断排队上限`,(0,x.jsx)(`input`,{type:`number`,min:0,max:64,step:1,required:!0,value:i.queue_limit,onChange:e=>f(`queue_limit`,e.target.value)})]})]}),s&&(0,x.jsx)(A,{error:!0,children:s}),u&&(0,x.jsx)(A,{children:`目标去重判断设置已保存`}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`primary`,children:`保存目标去重判断设置`}),(0,x.jsx)(`button`,{type:`button`,onClick:()=>{o.current=!1,a(r(e)),c(``),d(!1)},children:`还原目标判断设置`})]})]})]})}function de(){return(0,x.jsxs)(`details`,{className:`persona-guide panel`,children:[(0,x.jsx)(`summary`,{children:`persona 从哪里来?与当前状态、目标有什么区别?`}),(0,x.jsxs)(`figure`,{children:[(0,x.jsx)(`figcaption`,{children:`经历成为自我认知,经过提炼与检查后形成 persona。`}),(0,x.jsxs)(`ol`,{className:`persona-flow`,children:[(0,x.jsx)(`li`,{children:`初始背景 + 持续经历`}),(0,x.jsxs)(`li`,{children:[`自我认知`,(0,x.jsx)(`small`,{children:`有来源的自我记忆`})]}),(0,x.jsxs)(`li`,{children:[`结合生成目标 + 监管要求`,(0,x.jsx)(`small`,{children:`由管理员设定,不从记忆中改写`})]}),(0,x.jsxs)(`li`,{children:[`梦境整理中提炼与检查`,(0,x.jsx)(`small`,{children:`逐句依据与表达检查`})]}),(0,x.jsxs)(`li`,{children:[`persona`,(0,x.jsx)(`small`,{children:`按发布方式发布或等待确认`})]})]})]}),(0,x.jsxs)(`dl`,{className:`persona-distinction`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`当前状态`}),(0,x.jsx)(`dd`,{children:`现在在做什么、心情如何,由宿主报告,可能过时。`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`目标与询问`}),(0,x.jsx)(`dd`,{children:`未来要做或要问的事,跨入口共享;提醒被取走不代表目标完成。`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`persona`}),(0,x.jsx)(`dd`,{children:`相对稳定的自我表达,有版本与依据;不是当前心情,也不是待办清单。`})]})]}),(0,x.jsx)(`p`,{children:`宿主结合当前状态、目标、persona、相关记忆和本入口近期消息,组织上下文并决定说什么、做什么。`}),(0,x.jsx)(`p`,{className:`muted`,children:`“待更新”表示当前版本有失效依据;“待确认”表示已有候选等待管理员决定。两者可以同时出现。`})]})}function fe({value:e,busy:t,save:n}){let[r,i]=(0,l.useState)(e),[a,o]=(0,l.useState)(``),s=(0,l.useRef)(!1);return(0,l.useEffect)(()=>{s.current||i(e)},[e]),(0,x.jsxs)(`section`,{className:`panel settings-panel persona-settings`,children:[(0,x.jsx)(`h2`,{children:`persona 的生成与发布`}),(0,x.jsx)(`p`,{children:`生成目标和监管要求只能由管理员修改,学习和整理不能修改它们。保存只影响之后接受的任务;已接受的任务、已有候选和当前 persona 保持原设置。`}),(0,x.jsxs)(`form`,{noValidate:!0,onSubmit:async e=>{if(e.preventDefault(),t)return;let a=r.goal.trim(),c=r.rules.trim();if(!a||[...a].length>4e3){o(`生成目标须为 1—4000 字,不能只含空白`);return}if(!c||[...c].length>16e3){o(`监管要求须为 1—16000 字,不能只含空白`);return}o(``);let l=await n({goal:a,rules:c,publish_mode:r.publish_mode});l&&(s.current=!1,i(l))},children:[(0,x.jsxs)(`label`,{children:[`persona 发布方式`,(0,x.jsxs)(`select`,{disabled:t,value:r.publish_mode,onChange:e=>{s.current=!0,i({...r,publish_mode:e.target.value})},children:[(0,x.jsx)(`option`,{value:`small_medium_auto`,children:`小或中自动发布`}),(0,x.jsx)(`option`,{value:`all_auto`,children:`全部自动`}),(0,x.jsx)(`option`,{value:`all_manual`,children:`全部人工确认(默认)`})]})]}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`M3 的 persona 门槛尚未达到,默认采用“全部人工确认”:检查通过的候选也先由管理员确认,确认后才生效。可以改回“小或中自动发布”或“全部自动”。`}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`所有候选都要经过检查。“小或中自动发布”会自动发布检查通过的小、中变化,大变化等待确认。`}),(0,x.jsx)(A,{children:`自动候选删去或改动手写内容时按“大变化”处理。选择“全部自动”后,检查通过的大变化也会直接发布,包括删改手写内容;不会等待确认。`}),(0,x.jsxs)(`label`,{children:[`生成目标`,(0,x.jsx)(`textarea`,{rows:4,disabled:t,value:r.goal,onChange:e=>{s.current=!0,i({...r,goal:e.target.value})}})]}),(0,x.jsxs)(`label`,{children:[`监管要求`,(0,x.jsx)(`textarea`,{rows:6,disabled:t,value:r.rules,onChange:e=>{s.current=!0,i({...r,rules:e.target.value})}})]}),a&&(0,x.jsx)(A,{error:!0,children:a}),(0,x.jsx)(`button`,{className:`primary`,disabled:t,children:`保存 persona 设置`})]}),(0,x.jsx)(`p`,{children:(0,x.jsx)(`a`,{href:`#/persona`,children:`查看 persona 的依据、候选和版本历史`})}),(0,x.jsx)(de,{})]})}var R=[[`forget_threshold`,`遗忘阈值 F`,1,99],[`restore_threshold`,`恢复阈值 H`,2,100],[`feedback_increment`,`实际使用增幅`,0,100],[`confirmation_increment`,`再次确认增幅`,0,100],[`decay_amount`,`每次衰减幅度`,0,100],[`dependency_penalty`,`依据失效扣减`,0,100],[`auto_delete_days`,`遗忘后自动删除天数`,1,36500],[`upcoming_delete_days`,`即将删除窗口(天)`,1,36500],[`message_retention_days`,`消息保留天数`,1,36500]];function z(e){let t=Object.fromEntries(R.map(([t])=>[t,String(e[t])]));return{...e,...t}}function B({value:e,timezone:t,managedTime:n=!1}){let[r,i]=(0,l.useState)(()=>z(e)),a=(0,l.useRef)(!1),[o,s]=(0,l.useState)(!1),[c,u]=(0,l.useState)(``),[d,f]=(0,l.useState)(!1);(0,l.useEffect)(()=>{a.current||i(z(e))},[e]);function p(e,t){a.current=!0,f(!1),i(n=>({...n,[e]:t}))}async function m(e){if(e.preventDefault(),o)return;u(``),f(!1);for(let[e,t,n,i]of R){let a=Number(r[e]);if(!r[e].trim()||!Number.isInteger(a)||ai){u(`${t}须为 ${n}—${i} 的整数`);return}}if(Number(r.restore_threshold)<=Number(r.forget_threshold)){u(`恢复阈值 H 必须大于遗忘阈值 F`);return}if(!n&&!/^(?:[01][0-9]|2[0-3]):[0-5][0-9]$/.test(r.maintenance_time)){u(`维护时间须为 HH:MM 格式,范围 00:00—23:59`);return}let{maintenance_time:t,...c}={...r,...Object.fromEntries(R.map(([e])=>[e,Number(r[e])]))};s(!0);try{let e=await g(`/settings/lifecycle`,_(`PATCH`,n?c:{...c,maintenance_time:t}));i(z(e.lifecycle)),a.current=!1,f(!0)}catch(e){u(v(e))}finally{s(!1)}}return(0,x.jsxs)(`section`,{className:`panel settings-panel full-width`,children:[(0,x.jsx)(`h2`,{children:`记忆生命周期`}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`有效记忆低于 F 时遗忘,遗忘记忆达到 H 时恢复;两阈值之间保持原状态。置顶不自动恢复。`}),n&&(0,x.jsxs)(`p`,{className:`lifecycle-help`,children:[`每日运行时间 `,e.maintenance_time,`(`,t||`角色时区`,`),在梦境整理设置中修改。`]}),(0,x.jsx)(`form`,{onSubmit:m,noValidate:!0,children:(0,x.jsxs)(`fieldset`,{disabled:o,className:`lifecycle-fieldset`,children:[(0,x.jsxs)(`div`,{className:`lifecycle-settings-grid`,children:[R.map(([e,t,n,i])=>(0,x.jsxs)(`label`,{children:[t,(0,x.jsx)(`input`,{"aria-label":t,type:`number`,required:!0,min:n,max:i,step:1,value:r[e],onChange:t=>p(e,t.target.value)}),(0,x.jsxs)(`small`,{children:[n,`—`,i,`,整数`]})]},e)),!n&&(0,x.jsxs)(`label`,{children:[`维护时间`,(0,x.jsx)(`input`,{"aria-label":`维护时间`,required:!0,type:`text`,inputMode:`text`,placeholder:`03:00`,maxLength:5,value:r.maintenance_time,onChange:e=>p(`maintenance_time`,e.target.value)}),(0,x.jsxs)(`small`,{children:[`HH:MM · 角色时区 `,t||`未设置`]})]})]}),(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:r.auto_delete_enabled,onChange:e=>p(`auto_delete_enabled`,e.target.checked)}),`自动删除遗忘记忆`]}),(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:r.abandoned_retry_enabled,onChange:e=>p(`abandoned_retry_enabled`,e.target.checked)}),`自动重试已放弃批次`]}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`维护按实际执行次数衰减,遗忘和置顶记忆不衰减。依据失效时每个依据只扣一次,置顶期间暂缓扣减。自动重试仅处理角色时区前一天放弃的批次,每批最多一次;内容拒绝不自动重试。`}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`关闭自动删除后仍保留天数设置,“即将删除”列表为空。消息只有超过保留期、已结束学习且没有受保护的引用时才清理。新设置用于以后接受的维护,当前运行沿用接受时的设置。`}),c&&(0,x.jsx)(A,{error:!0,children:c}),d&&(0,x.jsx)(A,{children:`生命周期设置已保存`}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`primary`,children:o?`正在保存…`:`保存生命周期设置`}),(0,x.jsx)(`button`,{type:`button`,className:`secondary`,onClick:()=>{i(z(e)),a.current=!1,u(``),f(!1)},children:`还原为最近读取的设置`})]})]})})]})}var pe={person_summary_settings:`更新人物摘要设置`,person_summary_edit:`编辑发布人物摘要`,person_summary_confirm:`确认人物摘要候选`,person_summary_reject:`拒绝人物摘要候选`,person_summary_rollback:`回滚人物摘要`,person_summary_regenerate_requested:`请求重新生成人物摘要`,person_summary_generation_requested:`请求生成人物摘要`,person_summary_generation_published:`人物摘要生成并发布`,person_summary_generation_candidate:`人物摘要待确认`,person_summary_generation_rejected:`人物摘要检查未通过`,person_summary_generation_skipped:`跳过人物摘要生成`,person_summary_generation_interrupted:`人物摘要生成中断`,token_create:`创建宿主令牌`,token_revoke:`撤销宿主令牌`,token_limits_saved:`更新宿主令牌限流`,backup_export:`导出备份`,backup_import:`从备份导入`,consolidation_settings_saved:`更新梦境整理设置`,goal_dedup_judge_saved:`更新目标去重判断设置`,consolidation_merge:`整理合并记忆`,consolidation_conflict:`整理提出矛盾建议`,consolidation_dependency:`整理提出依赖复核建议`,consolidation_annotation_confirm:`确认整理建议`,consolidation_annotation_clear:`清除整理建议`,goal_basis_review:`目标依据复核`,goal_basis_clear:`清除目标依据标注`,persona_settings_saved:`更新 persona 设置`,persona_edit:`编辑发布 persona`,persona_confirm:`确认 persona 候选`,persona_reject:`拒绝 persona 候选`,persona_rollback:`回滚 persona`,persona_current:`发布 persona`,persona_pending:`persona 候选待确认`,persona_rejected:`persona 候选被拒绝`,persona_generation_requested:`请求生成 persona`,persona_generation_current:`persona 生成并发布`,persona_generation_pending:`persona 生成后待确认`,persona_generation_rejected:`persona 生成检查未通过`,persona_generation_skipped:`跳过 persona 生成`,persona_generation_conflict:`persona 生成遇到版本或依据冲突`,persona_generation_failed:`persona 生成失败`,persona_generation_interrupted:`persona 生成中断`,goal_dedup_judged:`目标去重判断结果`,goal_dedup_queued:`目标待去重复核`,goal_create:`创建目标`,goal_update:`更新目标`,goal_merge:`合并重复目标`,goal_duplicate_dismiss:`驳回目标重复`,settings_goals:`更新目标与提醒设置`,memory_adjust:`调整记忆`,memory_forget:`手动遗忘`,memory_bulk_forget:`批量遗忘记忆`,memory_bulk_delete:`批量删除记忆`,memory_bulk_purge:`批量彻底清除记忆`,memory_restore:`恢复记忆`,memory_purge:`彻底清除记忆`,memory_recreate:`按旧内容新建`,memory_revision:`人工修订记忆`,lifecycle_saved:`更新生命周期设置`,state_settings_saved:`更新当前状态设置`,maintenance_requested:`请求维护`,maintenance_completed:`维护完成`,batch_relearn:`重新学习批次`,batch_result:`批次结果`,learn_requested:`请求立即学习`,feedback:`使用反馈`,feedback_rejected:`使用反馈被拒绝`,learn_rejected:`立即学习请求被拒绝`,trial_media_uploaded:`上传试用图片`,trial_entry_created:`创建试用入口`,trial_speaker_created:`创建发言人`,trial_message_received:`试用消息接收`,trial_prepare:`试用回复准备`,trial_reply:`试用角色回复`,setup_password:`设置管理员密码`,setup_completed:`完成首次设置`,models_saved:`更新模型配置`,role_saved:`更新角色设置`,limits_saved:`更新用量与并发`,model_retry:`请求模型重试`,model_test:`测试模型连接`,recall_judge_saved:`更新召回判断设置`,entry_visibility:`更新入口记忆可见范围`,entry_settings_updated:`更新入口节奏与过滤`,subject_alias_added:`添加人物别名`,subject_alias_removed:`删除人物别名`,subject_link_denied:`否认人物联系`,subjects_merged:`确认并合并人物`,models_imported:`导入模型配置`,login:`管理员登录`,logout:`退出登录`},me={person_summary:`人物摘要`,local_cli:`本机命令行`,persona:`persona 更新`,consolidation:`梦境整理`,goal_dedup:`目标去重判断`,learning:`学习`,admin:`管理员`,host:`宿主`,system:`系统`,scheduler:`后台调度`,maintenance:`维护`,local_import:`本机导入`},he={person_summary:`人物摘要`,host_token:`宿主令牌`,backup:`备份`,persona:`persona 版本`,persona_attempt:`persona 生成任务`,goal:`目标`,memory:`记忆`,memory_bulk:`批量记忆操作`,batch:`批次`,entry:`入口`,subject:`人物`,subject_link:`人物联系`,model:`模型`,settings:`设置`,maintenance:`维护`,recall:`召回`,request:`请求`};function ge({initialQuery:e=``}){let t=new URLSearchParams(e),[n,r]=(0,l.useState)({time_from:``,time_to:``,action:``,actor:``,object_type:t.get(`object_type`)||``,object_id:t.get(`object_id`)||``}),i=e=>new URLSearchParams(Object.entries(e).filter(([,e])=>!!e)).toString(),[a,o]=(0,l.useState)(()=>i(n)),[s,c]=(0,l.useState)(0),[u,d]=(0,l.useState)(``),f=y(`/operations?${a}&limit=30&offset=${s}`),p=(e,t)=>r(n=>({...n,[e]:t}));function m(e){if(e.preventDefault(),n.time_from&&n.time_to&&n.time_from>n.time_to){d(`开始日期不能晚于结束日期`);return}d(``),c(0),o(i(n)),f.refresh()}return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{className:`page-heading`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`p`,{className:`eyebrow`,children:`每次变更,均有记录`}),(0,x.jsx)(`h1`,{children:`操作记录`}),(0,x.jsx)(`p`,{children:`查看管理员、宿主与系统保存的操作摘要。`})]})}),(0,x.jsx)(`section`,{className:`panel`,children:(0,x.jsxs)(`form`,{onSubmit:m,className:`memory-filters`,children:[(0,x.jsxs)(`div`,{className:`filter-grid operation-filters`,children:[(0,x.jsxs)(`label`,{children:[`开始日期`,(0,x.jsx)(`input`,{type:`date`,value:n.time_from,onChange:e=>p(`time_from`,e.target.value)})]}),(0,x.jsxs)(`label`,{children:[`结束日期`,(0,x.jsx)(`input`,{type:`date`,value:n.time_to,onChange:e=>p(`time_to`,e.target.value)})]}),(0,x.jsxs)(`label`,{children:[`操作类型`,(0,x.jsxs)(`select`,{value:n.action,onChange:e=>p(`action`,e.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`全部类型`}),Object.entries(pe).map(([e,t])=>(0,x.jsx)(`option`,{value:e,children:t},e))]})]}),(0,x.jsxs)(`label`,{children:[`操作者`,(0,x.jsxs)(`select`,{value:n.actor,onChange:e=>p(`actor`,e.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`全部操作者`}),Object.entries(me).map(([e,t])=>(0,x.jsx)(`option`,{value:e,children:t},e))]})]}),(0,x.jsxs)(`label`,{children:[`对象类型`,(0,x.jsxs)(`select`,{value:n.object_type,onChange:e=>p(`object_type`,e.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`全部对象`}),Object.entries(he).map(([e,t])=>(0,x.jsx)(`option`,{value:e,children:t},e))]})]}),(0,x.jsxs)(`label`,{children:[`对象标识`,(0,x.jsx)(`input`,{value:n.object_id,maxLength:200,placeholder:`如记忆编号 8`,onChange:e=>p(`object_id`,e.target.value)})]})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`日期筛选按角色时区解释,结束日期包含当天;记录时间按本机时区显示。`}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`primary`,children:`筛选记录`}),(0,x.jsx)(`button`,{type:`button`,className:`secondary`,onClick:f.refresh,children:`刷新记录`})]})]})}),(u||f.error)&&(0,x.jsx)(A,{error:!0,children:u||f.error}),(0,x.jsx)(`div`,{className:`list-heading`,children:(0,x.jsx)(`span`,{children:f.data?`共 ${f.data.total} 条`:`正在读取…`})}),f.data?.items.length===0&&(0,x.jsx)(j,{title:`没有符合条件的操作记录`}),(0,x.jsx)(`div`,{className:`learning-list`,children:f.data?.items.map(e=>(0,x.jsxs)(`article`,{className:`panel operation-card`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:pe[e.action]||e.action}),(0,x.jsxs)(`span`,{className:`muted`,children:[`记录 #`,e.id]})]}),(0,x.jsxs)(`p`,{children:[w(e.created_at),` · `,me[e.actor]||e.actor]}),e.object_type&&(0,x.jsxs)(`p`,{children:[`对象:`,he[e.object_type]||e.object_type,e.object_id===null?``:` · ${e.object_id}`]}),(0,x.jsxs)(`details`,{children:[(0,x.jsx)(`summary`,{children:`查看记录详情`}),(0,x.jsx)(`pre`,{className:`record-json`,children:JSON.stringify(e.details,null,2)})]})]},e.id))}),f.data&&(0,x.jsx)(T,{total:f.data.total,offset:s,change:c})]})}var V=[`chat`,`embedding`,`recall_judge`,`goal_dedup_judge`,`image_understanding`],H={chat:`对话模型`,embedding:`Embedding 模型`,recall_judge:`召回判断模型`,goal_dedup_judge:`目标去重判断模型`,image_understanding:`图片理解模型`},_e=()=>Intl.DateTimeFormat().resolvedOptions().timeZone||`Asia/Shanghai`,ve=e=>e.inherited?{enabled:!1}:{enabled:e.enabled,base_url:e.base_url,model:e.model,dimensions:e.dimensions,reasoning_effort:e.reasoning_effort,...e.vision===void 0?{}:{vision:e.vision},...e.clearKey?{api_key:``}:e.key?{api_key:e.key}:{}};function ye({value:e,change:t}){return(0,x.jsxs)(`div`,{className:`form-grid`,children:[(0,x.jsxs)(`label`,{children:[`角色名`,(0,x.jsx)(`input`,{required:!0,maxLength:100,value:e.name,onChange:n=>t({...e,name:n.target.value})})]}),(0,x.jsxs)(`label`,{children:[`时区`,(0,x.jsx)(`input`,{required:!0,value:e.timezone||``,placeholder:`Asia/Shanghai`,onChange:n=>t({...e,timezone:n.target.value})})]}),(0,x.jsxs)(`label`,{className:`full-width`,children:[`背景材料(可选)`,(0,x.jsx)(`textarea`,{maxLength:16e3,rows:4,value:e.background,onChange:n=>t({...e,background:n.target.value})}),(0,x.jsx)(`small`,{children:`保存为“设定”的自我记忆,不会当作亲身经历。`})]})]})}function be({kind:e,value:t,change:n,settings:r}){let i=H[e],a=r.model_source===`external`,o=r.presets.find(e=>e.id===`ark-glm`)?.reasoning_effort,[s,c]=(0,l.useState)(``),[u,d]=(0,l.useState)(!1),f=e===`recall_judge`||e===`goal_dedup_judge`,p=e===`image_understanding`,m=(f||p)&&t.inherited,h=m&&!r.models[e].inherited,y=m?r.models.chat.enabled&&!h:t.enabled,b=async()=>{d(!0),c(``);try{let n=await g(`/settings/models/${e}/test`,_(`POST`,a||m?{}:ve(t)));c(`${n.message} · ${n.duration_ms} ms`)}catch(e){c(v(e))}finally{d(!1)}};return(0,x.jsxs)(`div`,{className:`model-fields`,children:[f||p?(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,disabled:a,checked:p?t.enabled&&!t.inherited:!t.inherited,onChange:e=>{c(``),n({...t,inherited:!e.target.checked&&(!p||!!r.models.chat.vision),enabled:!p||e.target.checked})}}),`单独配置`,i]}):(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,disabled:a,checked:t.enabled,onChange:e=>n({...t,enabled:e.target.checked})}),`启用`,i]}),m?(0,x.jsxs)(`p`,{children:[p?`沿用已保存的对话模型接口、模型、密钥和推理档位。当前模型:`:`沿用已保存的对话模型接口、模型和密钥,推理档位 high。当前模型:`,r.models.chat.model||`未配置`,`。`]}):(0,x.jsxs)(`fieldset`,{disabled:a||!t.enabled,children:[e!==`embedding`&&e!==`image_understanding`&&(0,x.jsxs)(`label`,{children:[i,`服务商预设`,(0,x.jsxs)(`select`,{defaultValue:``,onChange:e=>{let i=r.presets.find(t=>t.id===e.target.value);i&&n({...t,base_url:i.base_url,model:i.model,reasoning_effort:i.reasoning_effort})},children:[(0,x.jsx)(`option`,{value:``,children:`自定义 OpenAI 兼容服务`}),r.presets.map(e=>(0,x.jsx)(`option`,{value:e.id,children:e.name},e.id))]})]}),(0,x.jsxs)(`label`,{children:[i,`接口地址`,(0,x.jsx)(`input`,{type:`url`,required:t.enabled,value:t.base_url,placeholder:`https://…/v1`,onChange:e=>n({...t,base_url:e.target.value})})]}),(0,x.jsxs)(`label`,{children:[i,`模型名`,(0,x.jsx)(`input`,{required:t.enabled,value:t.model,maxLength:200,onChange:e=>n({...t,model:e.target.value})})]}),(0,x.jsxs)(`label`,{children:[i,` API key`,(0,x.jsx)(`input`,{"aria-label":`${i} API key`,type:`password`,autoComplete:`new-password`,value:t.key||``,placeholder:t.key_set?`已设置;留空保留`:`未设置(本地服务可留空)`,onChange:e=>n({...t,key:e.target.value,clearKey:!1})}),(0,x.jsxs)(`small`,{children:[`密钥`,t.key_set?`已设置`:`未设置`,`,保存后不回显。`]})]}),t.key_set&&(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:t.clearKey||!1,onChange:e=>n({...t,clearKey:e.target.checked,key:``})}),`移除已保存的密钥`]}),e===`chat`&&(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:!!t.vision,onChange:e=>n({...t,vision:e.target.checked})}),`支持图片输入(vision)`,(0,x.jsx)(`small`,{children:`对话模型支持图片输入。开启后,图片理解未单独配置时沿用对话模型。学习时是否直接看原图,请在“用量与学习”中设置。`})]}),e===`embedding`?(0,x.jsxs)(`label`,{children:[i,`向量维度`,(0,x.jsx)(`input`,{type:`number`,min:1,max:65536,value:t.dimensions??``,onChange:e=>n({...t,dimensions:e.target.value?Number(e.target.value):null})}),(0,x.jsx)(`small`,{children:`可选;更换模型或维度后须重新标定召回。`})]}):(0,x.jsxs)(`label`,{children:[i,`推理档位`,(0,x.jsx)(`input`,{"aria-label":`${i}推理档位`,value:t.reasoning_effort||``,maxLength:50,placeholder:f?`留空使用 high`:`可选;留空不发送`,onChange:e=>n({...t,reasoning_effort:e.target.value||null})}),o&&e!==`image_understanding`&&(0,x.jsxs)(`small`,{children:[`火山方舟 GLM 预设使用 `,o,`。`]}),f&&(0,x.jsx)(`small`,{children:`判断档位留空时,后端使用 high。`})]})]}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{type:`button`,disabled:u||!y,onClick:()=>void b(),children:u?`正在测试…`:`测试${i}连接`}),s&&(0,x.jsx)(`span`,{role:`status`,children:s})]}),h&&(0,x.jsx)(`p`,{className:`muted`,children:`保存沿用设置后可测试连接。`})]})}function xe({done:e}){let t=y(`/settings`);return t.error?(0,x.jsxs)(A,{error:!0,children:[t.error,(0,x.jsx)(`button`,{onClick:t.refresh,children:`重新加载`})]}):t.data?(0,x.jsx)(Se,{settings:t.data,done:e}):(0,x.jsx)(`p`,{role:`status`,children:`正在读取设置…`})}function Se({settings:e,done:t}){let[n,r]=(0,l.useState)({...e.role,timezone:e.role.timezone||_e()}),[i,a]=(0,l.useState)(e.models),[o,s]=(0,l.useState)(!1),[c,u]=(0,l.useState)(``);return(0,x.jsxs)(`form`,{onSubmit:async r=>{r.preventDefault(),s(!0),u(``);try{if(e.model_source===`local`)for(let t of[`chat`,`embedding`])(i[t].enabled||e.models[t].enabled)&&await g(`/settings/models/${t}`,_(`PUT`,ve(i[t])));await g(`/setup/complete`,_(`POST`,n)),history.replaceState(null,``,`/#/trial`),t()}catch(e){u(v(e))}finally{s(!1)}},className:`setup-form`,children:[(0,x.jsxs)(`section`,{children:[(0,x.jsx)(`h2`,{children:`2 · 认识角色`}),(0,x.jsx)(ye,{value:n,change:e=>r({...e,timezone:e.timezone||_e()})})]}),(0,x.jsxs)(`section`,{children:[(0,x.jsx)(`h2`,{children:`3 · 配置模型`}),(0,x.jsx)(`p`,{children:`对话模型用于学习和试用回复,也可以稍后再配。Embedding 可选,未配置时使用全文检索。`}),e.model_source===`external`&&(0,x.jsx)(A,{children:`配置来自外部文件,只读;请在外部文件中修改。`}),[`chat`,`embedding`].map(t=>(0,x.jsxs)(`div`,{className:`setup-model`,children:[(0,x.jsx)(`h3`,{children:t===`chat`?`对话模型`:`Embedding 模型(可选)`}),(0,x.jsx)(be,{kind:t,value:i[t],change:e=>a({...i,[t]:e}),settings:e})]},t))]}),!i.chat.enabled&&(0,x.jsx)(A,{children:`未配置模型,暂不学习;完成设置后仍可接收消息。`}),c&&(0,x.jsx)(A,{error:!0,children:c}),(0,x.jsx)(`button`,{className:`primary`,disabled:o,children:o?`正在保存…`:`完成设置并开始试用`})]})}function Ce(){let e=y(`/settings`,2e3);return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{className:`page-heading`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`span`,{className:`eyebrow`,children:`管理`}),(0,x.jsx)(`h1`,{children:`设置`}),(0,x.jsx)(`p`,{children:`保存后对新的工作生效。`})]})}),e.error&&(0,x.jsx)(A,{error:!0,children:e.error}),e.data?(0,x.jsx)(we,{settings:e.data}):(0,x.jsx)(`p`,{children:`正在读取设置…`})]})}function we({settings:e}){let[t,n]=(0,l.useState)(e);(0,l.useEffect)(()=>n(e),[e]);let[r,i]=(0,l.useState)({...t.role,timezone:t.role.timezone||_e()}),[a,o]=(0,l.useState)(t.models),[s,c]=(0,l.useState)(t.daily_token_limit?.toString()||``),[u,d]=(0,l.useState)(t.learning_concurrency),[f,p]=(0,l.useState)(``),[m,h]=(0,l.useState)(``),[y,b]=(0,l.useState)(!1),[S,C]=(0,l.useState)(String(t.state.stale_after_minutes)),[w,T]=(0,l.useState)(t.native_image_learning===!0),E=(0,l.useRef)(!1),O=t.models.chat.enabled&&t.models.chat.vision===!0;(0,l.useEffect)(()=>{E.current||T(t.native_image_learning===!0)},[t.native_image_learning]);let k=(0,l.useRef)(!1),j=(0,l.useRef)(new Set);(0,l.useEffect)(()=>{k.current||C(String(t.state.stale_after_minutes))},[t.state.stale_after_minutes]);let[M,N]=(0,l.useState)(String(t.goals.default_reminder_minutes)),[P,F]=(0,l.useState)(t.goals.overdue_reminders),I=(0,l.useRef)(!1);(0,l.useEffect)(()=>{I.current||(N(String(t.goals.default_reminder_minutes)),F(t.goals.overdue_reminders))},[t.goals.default_reminder_minutes,t.goals.overdue_reminders]);let L=async(e,t,r)=>{if(!y){b(!0),p(``),h(``);try{let i=await g(e,_(t,r));n(i),e===`/settings/limits`&&(E.current=!1,T(i.native_image_learning===!0)),e===`/settings/state`&&(k.current=!1,C(String(i.state.stale_after_minutes))),e===`/settings/goals`&&(I.current=!1,N(String(i.goals.default_reminder_minutes)),F(i.goals.overdue_reminders));for(let t of V)e===`/settings/models/${t}`&&(j.current.delete(t),o(e=>Object.fromEntries(V.map(n=>[n,n===t||!j.current.has(n)?i.models[n]:e[n]]))));return h(`已保存`),i}catch(e){return p(v(e)),null}finally{b(!1)}}};return(0,x.jsxs)(`div`,{className:`settings-grid`,children:[f&&(0,x.jsx)(A,{error:!0,children:f}),m&&(0,x.jsx)(A,{children:m}),(0,x.jsxs)(`section`,{className:`panel settings-panel`,children:[(0,x.jsx)(`h2`,{children:`角色`}),(0,x.jsxs)(`form`,{onSubmit:e=>{e.preventDefault(),L(`/settings/role`,`PATCH`,r)},children:[(0,x.jsx)(ye,{value:r,change:e=>i({...e,timezone:e.timezone||_e()})}),(0,x.jsx)(`button`,{disabled:y,className:`primary`,children:`保存角色`})]})]}),t.model_source===`external`&&(0,x.jsx)(A,{children:`配置来自外部文件,只读;数据库模型配置和 secrets.json 不用于本次服务。`}),V.filter(e=>t.models[e]).map(e=>(0,x.jsxs)(`section`,{className:`panel settings-panel`,"aria-label":H[e],children:[(0,x.jsx)(`h2`,{children:H[e]}),(0,x.jsxs)(`p`,{children:[`当前状态:`,e===`image_understanding`&&!t.models[e].enabled?`未启用`:D(t.health[e]?.state||`configuration_error`)]}),e===`image_understanding`&&(0,x.jsxs)(`p`,{children:[t.models[e].inherited?`当前图片理解沿用对话模型。`:t.models[e].enabled?`当前图片理解使用独立配置。`:`当前图片理解未启用。`,`未单独配置且对话模型开启 vision 时会自动沿用;取消独立配置会恢复此规则。 测试连接会发送一张固定测试图片,健康状态与用量仍按图片理解用途记录。`]}),(0,x.jsxs)(`form`,{onSubmit:t=>{t.preventDefault(),L(`/settings/models/${e}`,`PUT`,ve(a[e]))},children:[(0,x.jsx)(be,{kind:e,value:a[e],change:t=>{j.current.add(e),o({...a,[e]:t})},settings:t}),t.model_source===`local`&&(0,x.jsxs)(`button`,{className:`primary`,disabled:y,children:[`保存`,H[e]]})]}),[`temporarily_unavailable`,`account_problem`].includes(t.health[e]?.state)&&(0,x.jsx)(`button`,{onClick:()=>void L(`/settings/models/${e}/retry`,`POST`,{}),children:`立即重试`}),e===`goal_dedup_judge`&&t.goal_dedup_judge&&(0,x.jsx)(ue,{value:t.goal_dedup_judge,busy:y,save:async e=>(await L(`/settings/goal-dedup-judge`,`PATCH`,e))?.goal_dedup_judge||null}),e===`recall_judge`&&(0,x.jsx)(Te,{value:t.recall_judge})]},e)),(0,x.jsxs)(`section`,{className:`panel settings-panel`,children:[(0,x.jsx)(`h2`,{children:`用量与学习`}),(0,x.jsxs)(`form`,{onSubmit:e=>{e.preventDefault(),L(`/settings/limits`,`PATCH`,{daily_token_limit:s?Number(s):null,learning_concurrency:u,native_image_learning:w})},children:[(0,x.jsxs)(`label`,{children:[`每日 token 上限`,(0,x.jsx)(`input`,{type:`number`,min:1,value:s,placeholder:`不限`,onChange:e=>c(e.target.value)})]}),(0,x.jsxs)(`label`,{children:[`学习并发`,(0,x.jsx)(`input`,{type:`number`,required:!0,min:1,max:32,value:u,onChange:e=>d(Number(e.target.value))})]}),(0,x.jsx)(`p`,{className:`muted`,children:`按角色时区每日恢复;在途调用和未报告的 token 可能使实际用量超过上限。`}),(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,"aria-describedby":`native-image-learning-help native-image-learning-availability`,checked:w,disabled:y||!O,onChange:e=>{E.current=!0,T(e.target.checked),h(``)}}),`学习时直接看原图`]}),(0,x.jsx)(`p`,{className:`lifecycle-help`,id:`native-image-learning-help`,children:`默认关闭。开启后,后续学习把原图交给对话模型;图片描述仍用于回复准备、检索与管理页。超限或不可用的图片沿用描述或占位。`}),(0,x.jsx)(`p`,{className:`lifecycle-help`,id:`native-image-learning-availability`,children:O?t.model_source===`external`?`这是运行设置,使用外部模型配置时也可以保存。`:`使用已保存的对话模型图片能力;保存后对后续学习生效。`:`${t.models.chat.enabled?`当前对话模型未启用图片输入(vision),此设置暂不生效。`:`当前对话模型未启用,无法直接看原图。`}${t.model_source===`external`?`请在外部模型配置中启用对话模型及 vision。`:`请先启用并保存对话模型的“支持图片输入(vision)”。`}`}),(0,x.jsx)(`button`,{className:`primary`,disabled:y,children:`保存用量与学习`})]})]}),(0,x.jsxs)(`section`,{className:`panel settings-panel`,children:[(0,x.jsx)(`h2`,{children:`当前状态`}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`宿主报告的活动与情绪供当前回复使用。超过设定分钟数未更新时,只标注“可能过时”,不会自动结束活动。`}),(0,x.jsxs)(`form`,{noValidate:!0,onSubmit:e=>{if(e.preventDefault(),y)return;let t=Number(S);if(!S.trim()||!Number.isInteger(t)||t<1||t>525600){h(``),p(`可能过时的分钟数须为 1—525600 的整数`);return}L(`/settings/state`,`PATCH`,{stale_after_minutes:t})},children:[(0,x.jsxs)(`label`,{children:[`可能过时的分钟数`,(0,x.jsx)(`input`,{"aria-label":`可能过时的分钟数`,type:`number`,required:!0,min:1,max:525600,step:1,disabled:y,value:S,onChange:e=>{k.current=!0,C(e.target.value),h(``)}}),(0,x.jsx)(`small`,{children:`1—525600 的整数,默认 30 分钟;严格超过此时长才标记。`})]}),(0,x.jsxs)(`p`,{className:`lifecycle-help`,children:[`保存后立即影响后续状态读取。`,(0,x.jsx)(`a`,{href:`#/state`,children:`查看当前状态`})]}),(0,x.jsx)(`button`,{className:`primary`,disabled:y,children:`保存当前状态设置`})]})]}),(0,x.jsxs)(`section`,{className:`panel settings-panel`,children:[(0,x.jsx)(`h2`,{children:`目标与提醒`}),(0,x.jsx)(`p`,{children:`未单独填写提前量的普通目标使用默认值。询问不安排提醒,过期不会自动放弃目标。`}),(0,x.jsxs)(`form`,{noValidate:!0,onSubmit:e=>{if(e.preventDefault(),y)return;let t=Number(M);if(!M.trim()||!Number.isInteger(t)||t<0||t>525600){h(``),p(`默认提醒提前量须为 0—525600 的整数`);return}L(`/settings/goals`,`PATCH`,{default_reminder_minutes:t,overdue_reminders:P})},children:[(0,x.jsxs)(`label`,{children:[`默认提醒提前量(分钟)`,(0,x.jsx)(`input`,{"aria-label":`默认提醒提前量(分钟)`,type:`number`,min:0,max:525600,step:1,required:!0,disabled:y,value:M,onChange:e=>{I.current=!0,N(e.target.value),h(``)}}),(0,x.jsx)(`small`,{children:`0—525600 的整数,默认 60 分钟;0 表示到期时提醒。`})]}),(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,disabled:y,checked:P,onChange:e=>{I.current=!0,F(e.target.checked),h(``)}}),`启用过期提醒`]}),(0,x.jsxs)(`p`,{className:`lifecycle-help`,children:[`过期提醒每日最多一次。`,(0,x.jsx)(`a`,{href:`#/state?tab=notifications`,children:`查看提醒`}),`;“已取走”只表示宿主拿到了。`]}),(0,x.jsx)(`button`,{className:`primary`,disabled:y,children:`保存目标与提醒设置`})]})]}),t.consolidation&&(0,x.jsx)(le,{value:t.consolidation,timezone:t.role.timezone,busy:y,save:async e=>(await L(`/settings/consolidation`,`PATCH`,e))?.consolidation||null}),(0,x.jsx)(fe,{value:t.persona,busy:y,save:async e=>(await L(`/settings/persona`,`PATCH`,e))?.persona||null}),(0,x.jsxs)(`section`,{className:`panel settings-panel`,children:[(0,x.jsx)(`h2`,{children:`最近操作`}),(0,x.jsx)(`a`,{className:`text-button`,href:`#/operations`,children:`查看全部操作记录`}),(0,x.jsx)(`ul`,{className:`operations`,children:t.operations.map(e=>(0,x.jsxs)(`li`,{children:[(0,x.jsx)(`span`,{children:pe[e.action]||e.action}),(0,x.jsxs)(`small`,{children:[new Date(e.created_at).toLocaleString(`zh-CN`),` ·`,` `,me[e.actor]||e.actor]})]},e.id))})]}),(0,x.jsx)(B,{managedTime:!!t.consolidation,value:t.lifecycle,timezone:t.role.timezone})]})}function Te({value:e}){let[t,n]=(0,l.useState)(e.enabled),[r,i]=(0,l.useState)(String(e.concurrency)),[a,o]=(0,l.useState)(String(e.queue_limit)),[s,c]=(0,l.useState)(!1),[u,d]=(0,l.useState)(``),[f,p]=(0,l.useState)(!1);async function m(e){if(e.preventDefault(),!s){if(p(!1),!r.trim()||!Number.isInteger(Number(r))||Number(r)<1||Number(r)>8){d(`召回判断并发须为 1—8 的整数`);return}if(!a.trim()||!Number.isInteger(Number(a))||Number(a)<0||Number(a)>64){d(`召回判断排队上限须为 0—64 的整数`);return}c(!0),d(``);try{await g(`/settings/recall-judge`,_(`PATCH`,{enabled:t,concurrency:Number(r),queue_limit:Number(a)})),p(!0)}catch(e){d(v(e))}finally{c(!1)}}}return(0,x.jsxs)(`form`,{className:`judge-settings`,onSubmit:m,noValidate:!0,children:[(0,x.jsx)(`h3`,{children:`判断开关与排队`}),(0,x.jsx)(`p`,{children:`每次回复准备最多判断 8 条相关记忆,总预算 10 秒(含排队)。判断失败或暂停时保留仍有效的原召回;人物要点不参与判断。`}),u&&(0,x.jsx)(A,{error:!0,children:u}),f&&(0,x.jsx)(A,{children:`召回判断设置已保存`}),(0,x.jsxs)(`fieldset`,{className:`lifecycle-fieldset`,disabled:s,children:[(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:t,onChange:e=>n(e.target.checked)}),`启用召回判断`]}),(0,x.jsx)(`p`,{className:`muted`,children:`关闭后保留基础召回。清除独立模型配置只会恢复沿用对话模型,不会关闭判断。`}),(0,x.jsxs)(`div`,{className:`form-grid`,children:[(0,x.jsxs)(`label`,{children:[`召回判断并发`,(0,x.jsx)(`input`,{type:`number`,min:1,max:8,step:1,required:!0,value:r,onChange:e=>i(e.target.value)})]}),(0,x.jsxs)(`label`,{children:[`召回判断排队上限`,(0,x.jsx)(`input`,{type:`number`,min:0,max:64,step:1,required:!0,value:a,onChange:e=>o(e.target.value)})]})]})]}),(0,x.jsx)(`button`,{className:`primary`,disabled:s,children:`保存召回判断设置`})]})}function Ee({children:e}){let[t,n]=(0,l.useState)(null),[r,i]=(0,l.useState)(``),a=(0,l.useCallback)(()=>{g(`/session`).then(e=>{d(e.csrf_token),n(e),i(``)}).catch(e=>i(v(e)))},[]);return(0,l.useEffect)(()=>(a(),addEventListener(`iris-auth`,a),()=>removeEventListener(`iris-auth`,a)),[a]),t?.configured&&t.authenticated?e(a):(0,x.jsxs)(`main`,{className:`access-page`,children:[(0,x.jsxs)(`div`,{className:`access-brand`,children:[(0,x.jsx)(`span`,{"aria-hidden":!0,children:`✳`}),` Iris `,(0,x.jsx)(`small`,{children:`相处与记忆`})]}),(0,x.jsxs)(`div`,{className:`panel access-card`,children:[(0,x.jsx)(`span`,{className:`eyebrow`,children:`仅本机管理`}),(0,x.jsx)(`h1`,{children:t?.configured?`管理员登录`:`首次设置`}),r&&(0,x.jsxs)(A,{error:!0,children:[r,(0,x.jsx)(`button`,{onClick:a,children:`重新连接`})]}),t?t.authenticated?(0,x.jsx)(xe,{done:a}):(0,x.jsx)(De,{creating:!t.admin_exists,configured:t.configured,setupCodeRequired:!!t.setup_code_required,done:a}):(0,x.jsx)(`p`,{children:`正在连接…`})]})]})}function De({creating:e,configured:t,setupCodeRequired:n,done:r}){let[i,a]=(0,l.useState)(``),[o,s]=(0,l.useState)(``),[c,u]=(0,l.useState)(``),[d,f]=(0,l.useState)(``),[p,m]=(0,l.useState)(!1);return(0,x.jsxs)(`form`,{className:`password-form`,onSubmit:async n=>{if(n.preventDefault(),e&&i!==o){f(`两次密码不一致`);return}m(!0),f(``);try{await g(e?`/setup/password`:`/login`,_(`POST`,{password:i,...e&&c?{setup_code:c}:{}})),a(``),s(``),u(``),t&&location.pathname!==`/`&&history.replaceState(null,``,`/#/trial`),r()}catch(e){f(v(e))}finally{m(!1)}},children:[(0,x.jsxs)(`p`,{children:[e?`1 · 先设置管理员密码,保护记忆与设置。`:`请输入管理员密码。`,!e&&!t&&`登录后继续完成首次设置。`]}),(0,x.jsxs)(`label`,{children:[`管理员密码`,(0,x.jsx)(`input`,{required:!0,type:`password`,"aria-label":`管理员密码`,minLength:8,maxLength:256,autoComplete:e?`new-password`:`current-password`,value:i,onChange:e=>a(e.target.value)}),(0,x.jsx)(`small`,{children:`至少 8 个字符。`})]}),e&&(0,x.jsxs)(`label`,{children:[`确认密码`,(0,x.jsx)(`input`,{required:!0,type:`password`,minLength:8,maxLength:256,autoComplete:`new-password`,value:o,onChange:e=>s(e.target.value)})]}),e&&n&&(0,x.jsxs)(`label`,{children:[`设置码`,(0,x.jsx)(`input`,{required:!0,type:`password`,"aria-label":`设置码`,maxLength:128,autoComplete:`off`,value:c,onChange:e=>u(e.target.value)}),(0,x.jsx)(`small`,{children:`从服务启动日志取得;仅首次设置使用。`})]}),d&&(0,x.jsx)(A,{error:!0,children:d}),(0,x.jsx)(`button`,{className:`primary`,disabled:p,children:p?`正在验证…`:e?`设置密码并继续`:`登录`})]})}function Oe({value:e}){return e.kind===`all`?(0,x.jsx)(`span`,{children:`全部入口`}):e.kind===`prefix`?(0,x.jsxs)(`span`,{children:[`入口前缀:`,(0,x.jsx)(`code`,{children:e.prefix})]}):(0,x.jsxs)(`span`,{children:[`入口列表:`,e.entries.map((e,t)=>(0,x.jsxs)(`span`,{children:[t>0&&`、`,(0,x.jsx)(`code`,{children:e})]},e))]})}function ke(){let e=y(`/tokens`,5e3),[t,n]=(0,l.useState)(!1),[r,i]=(0,l.useState)(null),[a,o]=(0,l.useState)(!1),[s,c]=(0,l.useState)(``),[u,d]=(0,l.useState)(``);return(0,x.jsxs)(`section`,{className:`panel access-panel`,"aria-label":`宿主令牌`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:`宿主令牌`}),(0,x.jsx)(`button`,{className:`primary`,onClick:()=>{d(``),n(!0)},children:`创建宿主令牌`})]}),(0,x.jsx)(`p`,{children:`每个宿主使用自己的令牌。入口范围控制该宿主可以操作哪些入口,不是记忆可见范围设置。`}),e.data&&(0,x.jsxs)(`p`,{className:`muted`,children:[`每令牌限流:每秒 `,e.data.rate_limits.rate_per_second,` 次,突发上限`,` `,e.data.rate_limits.burst,` 次。`]}),u&&(0,x.jsx)(A,{children:u}),e.error&&(0,x.jsxs)(A,{error:!0,children:[e.error,(0,x.jsx)(`button`,{onClick:e.refresh,children:`重试令牌列表`})]}),!e.data&&!e.error&&(0,x.jsx)(`p`,{children:`正在读取令牌…`}),e.data?.items.length===0&&(0,x.jsx)(j,{title:`尚未创建宿主令牌`,children:`创建令牌后,将它配置到同一台电脑上的宿主程序。`}),(0,x.jsx)(`div`,{className:`access-records`,children:e.data?.items.map(e=>(0,x.jsxs)(`article`,{className:`access-record`,"aria-label":`${e.host} · ${e.id}`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h3`,{children:e.host}),(0,x.jsx)(M,{tone:e.revoked_at?``:`green`,children:e.revoked_at?`已撤销`:`有效`})]}),(0,x.jsx)(`p`,{children:(0,x.jsx)(Oe,{value:e.scope})}),(0,x.jsxs)(`dl`,{className:`access-facts`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`创建时间`}),(0,x.jsx)(`dd`,{children:(0,x.jsx)(P,{value:e.created_at})})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`最近使用`}),(0,x.jsx)(`dd`,{children:e.last_used_at?(0,x.jsx)(P,{value:e.last_used_at}):`尚未使用`})]}),e.revoked_at&&(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`撤销时间`}),(0,x.jsx)(`dd`,{children:(0,x.jsx)(P,{value:e.revoked_at})})]})]}),(0,x.jsxs)(`p`,{className:`muted`,children:[`令牌 ID:`,(0,x.jsx)(`code`,{children:e.id})]}),!e.revoked_at&&(0,x.jsxs)(`button`,{className:`danger-button`,onClick:()=>{c(``),i(e)},children:[`撤销 `,e.host,` 的令牌`]})]},e.id))}),(0,x.jsx)(`p`,{children:(0,x.jsx)(`a`,{href:`#/operations?object_type=host_token`,children:`查看令牌操作记录`})}),t&&(0,x.jsx)(Ae,{close:()=>n(!1),created:e.refresh}),r&&(0,x.jsx)(N,{title:`撤销宿主令牌`,onClose:()=>i(null),closeDisabled:a,children:(0,x.jsxs)(`div`,{className:`access-dialog`,children:[(0,x.jsxs)(`p`,{children:[`即将撤销 `,(0,x.jsx)(`strong`,{children:r.host}),` 的令牌(`,r.id,`)。后续宿主请求立即失效,无法恢复此令牌;再次接入需要创建新令牌。`]}),s&&(0,x.jsx)(A,{error:!0,children:s}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{disabled:a,onClick:()=>i(null),children:`取消`}),(0,x.jsx)(`button`,{className:`danger-button`,disabled:a,onClick:async()=>{if(!a){o(!0),c(``);try{await g(`/tokens/${encodeURIComponent(r.id)}/revoke`,_(`POST`,{})),i(null),d(`令牌已撤销`),e.refresh()}catch(e){c(v(e))}finally{o(!1)}}},children:a?`正在撤销…`:`确认撤销`})]})]})})]})}function Ae({close:e,created:t}){let n=y(`/catalog`),[r,i]=(0,l.useState)(``),[a,o]=(0,l.useState)(`entries`),[s,c]=(0,l.useState)(``),[u,d]=(0,l.useState)(``),[f,p]=(0,l.useState)(!1),[m,h]=(0,l.useState)(``),[b,S]=(0,l.useState)(null),[C,w]=(0,l.useState)(``);return(0,x.jsx)(N,{title:b?`令牌已创建 · 仅显示这一次`:`创建宿主令牌`,onClose:e,closeDisabled:f,children:(0,x.jsx)(`div`,{className:`access-dialog`,children:b?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(A,{children:[`请现在复制并交给 `,b.host,` `,`保存。关闭此窗口、离开页面或刷新后,无法再次查看令牌原文;丢失后只能撤销并重新创建。`]}),(0,x.jsxs)(`label`,{children:[`新令牌原文`,(0,x.jsx)(`textarea`,{className:`token-secret`,readOnly:!0,rows:3,spellCheck:!1,autoComplete:`off`,value:b.token,onFocus:e=>e.target.select()})]}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{className:`primary`,onClick:async()=>{try{await navigator.clipboard.writeText(b.token),w(`已复制,请妥善保存`)}catch{w(`无法自动复制,请选择令牌原文并手动复制。`)}},children:`复制令牌`}),(0,x.jsx)(`button`,{onClick:e,children:`关闭并清除原文`})]}),C&&(0,x.jsx)(A,{children:C})]}):(0,x.jsx)(`form`,{noValidate:!0,onSubmit:async e=>{if(e.preventDefault(),f)return;let n=s.split(/\r?\n/).filter(e=>e!==``);if(!r.trim()||[...r.trim()].length>100){h(`宿主名称须为 1—100 字,不能只含空白`);return}if(a===`entries`&&(!n.length||n.length>1e3||new Set(n).size!==n.length||n.some(e=>!e.trim()||[...e].length>200||e.includes(`\0`)))){h(`请填写 1—1000 个不重复的入口 ID,每行一个,每个为 1—200 字,不能只含空白。`);return}if(a===`prefix`&&(!u.trim()||[...u].length>200||u.includes(`\0`))){h(`入口前缀须为 1—200 字,不能只含空白`);return}let i=a===`entries`?{kind:a,entries:n}:a===`prefix`?{kind:a,prefix:u}:{kind:a};p(!0),h(``);try{let e=await g(`/tokens`,_(`POST`,{host:r.trim(),scope:i}));S(e),t()}catch(e){h(`${v(e)}。如请求已提交但结果不明确,请刷新列表核对;若令牌已创建却未取得原文,请撤销后重新创建。`),t()}finally{p(!1)}},children:(0,x.jsxs)(`fieldset`,{disabled:f,children:[(0,x.jsxs)(`label`,{children:[`宿主名称`,(0,x.jsx)(`input`,{value:r,maxLength:100,onChange:e=>i(e.target.value),placeholder:`例如:本机聊天机器人`})]}),(0,x.jsxs)(`label`,{children:[`入口范围`,(0,x.jsxs)(`select`,{value:a,onChange:e=>o(e.target.value),children:[(0,x.jsx)(`option`,{value:`entries`,children:`入口列表`}),(0,x.jsx)(`option`,{value:`prefix`,children:`入口前缀`}),(0,x.jsx)(`option`,{value:`all`,children:`全部入口`})]})]}),a===`entries`&&(0,x.jsxs)(x.Fragment,{children:[!!n.data?.entries.length&&(0,x.jsxs)(`label`,{children:[`添加已有入口`,(0,x.jsxs)(`select`,{value:``,onChange:e=>{e.target.value&&!s.split(/\r?\n/).includes(e.target.value)&&c(s?`${s}\n${e.target.value}`:e.target.value)},children:[(0,x.jsx)(`option`,{value:``,children:`选择入口加入列表`}),n.data.entries.map(e=>(0,x.jsxs)(`option`,{value:e.id,children:[e.name,` · `,e.id]},e.id))]})]}),(0,x.jsxs)(`label`,{children:[`入口 ID 列表`,(0,x.jsx)(`textarea`,{rows:4,value:s,onChange:e=>c(e.target.value),placeholder:`group-a -private-a`})]}),n.error&&(0,x.jsx)(`p`,{className:`muted`,children:`已有入口暂时无法读取,仍可手动填写入口 ID。`})]}),a===`prefix`&&(0,x.jsxs)(`label`,{children:[`入口 ID 前缀`,(0,x.jsx)(`input`,{value:u,onChange:e=>d(e.target.value),maxLength:200,placeholder:`例如:astrbot:`})]}),(0,x.jsx)(`p`,{children:`列表和前缀按入口 ID 原字符匹配,区分大小写;前缀不是通配符。可以授权尚未创建的入口。范围创建后不可修改,需要调整时请新建令牌并撤销旧令牌。`}),a===`all`&&(0,x.jsx)(A,{children:`此令牌可访问全部现有及今后创建的入口。`}),m&&(0,x.jsx)(A,{error:!0,children:m}),(0,x.jsx)(`button`,{className:`primary`,disabled:f,children:f?`正在创建…`:`创建并显示令牌`})]})})})})}function je(e){return Number.isFinite(e)?e<1024?`${e} B`:e<1024**2?`${(e/1024).toFixed(1)} KiB`:`${(e/1024**2).toFixed(1)} MiB`:`未记录`}function Me(){let e=y(`/backups?limit=30`,5e3),[t,n]=(0,l.useState)(!1),[r,i]=(0,l.useState)(!1),[a,o]=(0,l.useState)(``),[s,c]=(0,l.useState)(null),u=(0,l.useRef)(null);return(0,l.useEffect)(()=>()=>u.current?.abort(),[]),(0,l.useEffect)(()=>()=>{s&&URL.revokeObjectURL(s.url)},[s]),(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`section`,{className:`panel access-panel`,"aria-label":`导出备份`,children:[(0,x.jsx)(`h2`,{children:`导出备份`}),(0,x.jsx)(`p`,{children:`服务运行时即可导出数据库与媒体的一致快照。备份包含原始消息和记忆,请妥善保存。`}),(0,x.jsxs)(`form`,{onSubmit:async n=>{if(n.preventDefault(),r)return;let a=new AbortController;u.current=a,i(!0),o(``),c(null);try{let{blob:e,headers:n}=await h(`/backups/export`,{..._(`POST`,{include_secrets:t}),signal:a.signal});if(a.signal.aborted)return;let r=n.get(`X-Iris-Backup-Includes-Secrets`)===`true`||t,i=n.get(`X-Iris-Backup-Id`),o=`iris-backup${i&&/^[a-f0-9]{32}$/.test(i)?`-${i}`:``}${r?`-with-secrets`:``}.zip`,s=URL.createObjectURL(e);c({url:s,filename:o,includesSecrets:r});let l=document.createElement(`a`);l.href=s,l.download=o,document.body.append(l),l.click(),l.remove()}catch(e){a.signal.aborted||o(v(e))}finally{a.signal.aborted||(i(!1),e.refresh())}},children:[(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:t,disabled:r,onChange:e=>n(e.target.checked),"aria-describedby":`backup-key-help`}),`包含模型密钥`]}),(0,x.jsx)(`p`,{id:`backup-key-help`,className:`muted`,children:`默认不包含模型密钥。选择包含时只导出本实例已保存的密钥,不包含外部模型配置文件或环境变量中的密钥。`}),t&&(0,x.jsxs)(A,{error:!0,children:[(0,x.jsx)(`strong`,{children:`包含模型密钥的 ZIP 不加密。`}),`请只保存到可信位置,不要分享或提交到代码仓库。`]}),(0,x.jsx)(`button`,{className:`primary`,disabled:r,children:r?`正在导出,请稍候…`:t?`导出并下载(含模型密钥)`:`导出并下载备份`})]}),a&&(0,x.jsxs)(A,{error:!0,children:[a,`。如未取得备份文件,请重新导出。`]}),s&&(0,x.jsxs)(A,{children:[`已生成备份并请求浏览器下载。若下载未开始,可`,(0,x.jsx)(`a`,{href:s.url,download:s.filename,children:`保存本次备份`}),`。`,s.includesSecrets&&(0,x.jsx)(`p`,{children:(0,x.jsx)(`strong`,{children:`本次备份含未加密的模型密钥,请勿分享。`})})]}),(0,x.jsx)(`h3`,{children:`最近的导出记录`}),(0,x.jsx)(`p`,{className:`muted`,children:`最多显示最近 30 次。记录不保留可再次下载的文件,需要时请重新导出。`}),e.error&&(0,x.jsxs)(A,{error:!0,children:[e.error,(0,x.jsx)(`button`,{onClick:e.refresh,children:`重试导出记录`})]}),!e.data&&!e.error&&(0,x.jsx)(`p`,{children:`正在读取导出记录…`}),e.data?.items.length===0&&(0,x.jsx)(j,{title:`还没有导出记录`}),(0,x.jsx)(`div`,{className:`access-records`,children:e.data?.items.map(e=>(0,x.jsxs)(`article`,{className:`access-record`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h4`,{children:(0,x.jsx)(P,{value:e.created_at})}),(0,x.jsx)(M,{tone:e.includes_model_secrets?`danger`:`green`,children:e.includes_model_secrets?`含模型密钥`:`不含模型密钥`})]}),(0,x.jsxs)(`p`,{children:[je(e.size),` · `,e.file_count??`未记录`,` 个文件 · `,e.media_included?`含媒体`:`无媒体`]}),(0,x.jsxs)(`p`,{children:[`格式版本 `,e.format_version??`未记录`,` · 迁移版本`,` `,e.migration_version??`未记录`]}),(0,x.jsxs)(`p`,{children:[(e.trigger||e.purpose)===`scheduled`?`定时`:(e.trigger||e.purpose)===`pre_import`?`导入前自动备份`:`手动导出`,` `,`·`,` `,e.actor===`admin`?`管理员`:e.actor===`local_cli`?`本机命令行`:e.actor===`scheduler`?`调度器`:e.actor]}),(0,x.jsxs)(`p`,{className:`muted`,children:[`备份 ID:`,(0,x.jsx)(`code`,{children:e.backup_id})]})]},e.backup_id))}),(0,x.jsx)(`p`,{children:(0,x.jsx)(`a`,{href:`#/operations?object_type=backup`,children:`查看导出与导入操作记录`})})]}),(0,x.jsxs)(`section`,{className:`panel access-panel`,"aria-label":`离线导入`,children:[(0,x.jsx)(`h2`,{children:`从备份导入`}),(0,x.jsx)(`p`,{children:`导入需要停止 Iris 服务,在本机命令行操作。先确认备份与目标数据目录,再按以下步骤恢复。`}),(0,x.jsxs)(`ol`,{className:`import-steps`,children:[(0,x.jsx)(`li`,{children:`停止 Iris 服务和其他配置命令。`}),(0,x.jsxs)(`li`,{children:[`将示例路径替换为自己的路径。导入到新目录:`,(0,x.jsx)(`pre`,{children:(0,x.jsx)(`code`,{children:`uv run iris --data-dir /path/to/new-data backup import /path/to/backup.zip`})})]}),(0,x.jsxs)(`li`,{children:[`覆盖已有实例时,确认目标后添加覆盖参数:`,(0,x.jsx)(`pre`,{children:(0,x.jsx)(`code`,{children:`uv run iris --data-dir /path/to/iris-data backup import /path/to/backup.zip --confirm-overwrite`})}),`覆盖前会在数据目录旁自动备份现有实例;备份失败不会覆盖。`]}),(0,x.jsx)(`li`,{children:`导入完成后按原方式启动服务,检查记忆、媒体与模型设置。`})]}),(0,x.jsx)(A,{children:`不含模型密钥的备份导入后,需要重新配置密钥,或继续使用原有外部配置;不会沿用目标目录原来的模型密钥。`}),(0,x.jsx)(`p`,{children:`覆盖前会单独保存目标实例原有的模型密钥,以便人工恢复;请私密保存该归档。它不会自动配给导入后的模型设置。`}),e.data?.import_instructions&&(0,x.jsxs)(`p`,{className:`muted`,children:[`服务提供的导入说明:`,e.data.import_instructions]})]})]})}function Ne(){let e=`http://127.0.0.1${location.port?`:${location.port}`:``}/api/v1`;return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{className:`page-heading`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`p`,{className:`eyebrow`,children:`接入与备份`}),(0,x.jsx)(`h1`,{children:`接入与数据`}),(0,x.jsx)(`p`,{children:`连接同一台电脑上的宿主,管理令牌与实例备份。`})]})}),(0,x.jsxs)(`section`,{className:`panel access-panel`,"aria-label":`接入说明`,children:[(0,x.jsx)(`h2`,{children:`把宿主连到 Iris`}),(0,x.jsxs)(`p`,{children:[`宿主程序与 Iris 在同一台电脑上运行。先创建令牌,在宿主配置中保存,再访问`,` `,(0,x.jsx)(`code`,{children:e}),`。端口与当前 Iris 服务一致。`]}),(0,x.jsxs)(`p`,{children:[`请求使用 `,(0,x.jsx)(`code`,{children:`Authorization: Bearer <令牌>`}),`。管理员登录会话不能代替宿主令牌;Iris 的宿主接口负责接收消息与准备回复,不生成对外回复。`]}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`a`,{href:`/docs`,target:`_blank`,rel:`noreferrer`,children:`打开接口文档`}),(0,x.jsx)(`a`,{href:`/openapi.json`,target:`_blank`,rel:`noreferrer`,children:`查看 OpenAPI 契约`})]})]}),(0,x.jsx)(ke,{}),(0,x.jsx)(`div`,{className:`access-data-grid`,children:(0,x.jsx)(Me,{})})]})}function Pe({value:e,openMemory:t}){return(0,x.jsxs)(`div`,{className:`trial-diagnostic`,"aria-label":`召回候选与判断分`,children:[(0,x.jsxs)(`p`,{className:`fine-print`,children:[`触发消息 #`,e.message_id,` · 准备于 `,w(e.prepared_at),(0,x.jsx)(`br`,{}),`召回记录 `,e.recall_id]}),!e.candidates.length&&(0,x.jsx)(`p`,{children:`本次没有额外召回候选。`}),e.candidates.map(e=>(0,x.jsxs)(`div`,{className:`entry-profile-evidence`,children:[(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>t(e.id),children:[`记忆 #`,e.id,` · 当时修订 `,e.revision]}),(0,x.jsxs)(`p`,{children:[e.reason===`person_highlight`?`人物要点(不参与判断)`:e.support==null?`判断分:未取得`:`判断分:${e.support} / 100`,` `,(0,x.jsx)(M,{children:{retained:`保留`,removed:`已去掉`,stale:`复核时失效`}[e.outcome]||e.outcome})]})]},e.id)),(0,x.jsx)(`p`,{className:`fine-print`,children:`以上是当次准备的诊断,链接打开记忆的当前详情;查看诊断不会再次召回或增加使用次数。`})]})}var Fe=[`image/png`,`image/jpeg`,`image/gif`,`image/webp`],Ie=e=>e>=1048576?`${(e/1048576).toFixed(1)} MiB`:`${Math.ceil(e/1024)} KiB`;function Le({media:e}){return e?.length?(0,x.jsx)(`div`,{className:`message-media`,children:e.map((e,t)=>(0,x.jsx)(Re,{item:e,number:t+1},e.id))}):null}function Re({item:e,number:t}){let[n,r]=(0,l.useState)(!1),i=e.kind===`image`&&Fe.includes(e.content_type),a=i&&e.understanding_source===`unprocessed`&&!!e.completed_at,o=i&&e.understanding_source===`unprocessed`&&!e.completed_at,s=e.kind===`audio`?`音频`:e.kind===`video`?`视频`:`文件`;return(0,x.jsxs)(`div`,{className:`media-card`,children:[(0,x.jsx)(`a`,{href:e.file_url,target:`_blank`,rel:`noopener noreferrer`,"aria-label":i?`查看图片 ${t} 原图`:`查看${s}附件 ${t}`,children:i?n?(0,x.jsx)(`span`,{children:`图片不可用或已清理`}):(0,x.jsx)(`img`,{src:e.file_url,alt:`图片 ${t}`,loading:`lazy`,onError:()=>r(!0)}):`${s}附件 ${t}`}),(0,x.jsxs)(`small`,{children:[e.content_type,` · `,Ie(e.size_bytes)]}),(0,x.jsx)(`div`,{children:(0,x.jsx)(M,{tone:a||e.understanding_source===`refused`?`danger`:``,children:e.understanding_source_label})}),a&&(0,x.jsx)(`strong`,{className:`danger-text`,children:`理解失败`}),o&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`strong`,{children:`等待理解/理解中`}),(0,x.jsx)(`small`,{children:`未启用或暂停时也会保持等待。`})]}),(0,x.jsx)(`p`,{className:`media-description`,children:e.understanding_text}),e.completed_at&&(0,x.jsxs)(`small`,{children:[`完成时间:`,w(e.completed_at)]})]})}var ze=10485760;function Be(e,t){return t.throwIfAborted(),new Promise((n,r)=>{let i=new FileReader,a=()=>i.abort();i.onload=()=>n(String(i.result).split(`,`,2)[1]),i.onerror=()=>r(new f(`image_read_failed`,`无法读取图片 ${e.name},请重新选择`,0)),i.onabort=()=>r(new DOMException(`Aborted`,`AbortError`)),i.onloadend=()=>t.removeEventListener(`abort`,a),t.addEventListener(`abort`,a,{once:!0}),i.readAsDataURL(e)})}function Ve(){let[e,t]=(0,l.useState)([]),n=(0,l.useRef)([]),r=(0,l.useRef)(new Map),i=e=>{n.current=e,t(e)};(0,l.useEffect)(()=>()=>{for(let e of n.current)URL.revokeObjectURL(e.url);r.current.clear()},[]);function a(e){if(n.current.length+e.length>100)throw new f(`too_many_images`,`每条消息最多发送 100 张图片`,0);for(let t of e){if(!Fe.includes(t.type))throw new f(`unsupported_media_type`,`${t.name}:仅支持 PNG、JPEG、GIF、WebP 图片`,0);if(t.size>ze)throw new f(`media_too_large`,`${t.name}:图片超过单文件 10 MiB 上限`,413);if(!t.size)throw new f(`empty_image`,`${t.name}:图片文件为空`,0)}i([...n.current,...e.map(e=>({file:e,key:crypto.randomUUID(),url:URL.createObjectURL(e)}))])}function o(e){let t=n.current.find(t=>t.key===e);t&&URL.revokeObjectURL(t.url),r.current.delete(e),i(n.current.filter(t=>t.key!==e))}function s(){for(let e of n.current)URL.revokeObjectURL(e.url);r.current.clear(),i([])}async function c(e,t){let i=[],a=n.current;for(let[n,o]of a.entries()){e.throwIfAborted();let s=r.current.get(o.key);if(!s){t(`正在上传图片 ${n+1}/${a.length}…`);let i=await Be(o.file,e);e.throwIfAborted();let c=await g(`/media`,{..._(`POST`,{content_type:o.file.type,data_base64:i}),signal:e});e.throwIfAborted(),s=c.id,r.current.set(o.key,s)}i.push(s)}return i}return{images:e,add:a,remove:o,clear:s,upload:c}}function He({images:e,busy:t,add:n,remove:r}){return(0,x.jsxs)(`div`,{className:`trial-images`,children:[(0,x.jsxs)(`label`,{children:[`选择图片`,(0,x.jsx)(`input`,{type:`file`,accept:Fe.join(`,`),multiple:!0,disabled:t,onChange:e=>{n(Array.from(e.target.files||[])),e.target.value=``}})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`也可在消息框粘贴图片。PNG/JPEG/GIF/WebP,每张最多 10 MiB,可只发送图片。`}),!!e.length&&(0,x.jsx)(`ul`,{className:`draft-images`,"aria-label":`待发送图片`,children:e.map(e=>(0,x.jsxs)(`li`,{children:[(0,x.jsx)(`img`,{src:e.url,alt:`待发送图片:${e.file.name}`}),(0,x.jsxs)(`span`,{children:[e.file.name,` · `,Ie(e.file.size)]}),(0,x.jsx)(`button`,{type:`button`,disabled:t,onClick:()=>r(e.key),"aria-label":`移除图片 ${e.file.name}`,children:`移除`})]},e.key))})]})}function Ue(){let e=y(`/persona`,2e3),t=e.data;return(0,x.jsxs)(`section`,{className:`persona-summary`,"aria-label":`试用 persona`,children:[e.error&&(0,x.jsxs)(A,{error:!0,children:[e.error,`。persona 可能尚未更新。`,(0,x.jsx)(`button`,{onClick:e.refresh,children:`重试 persona`})]}),t?.needs_update&&(0,x.jsxs)(`p`,{children:[(0,x.jsx)(M,{tone:`warning`,children:`待更新`}),` `,t.stale_basis_count,` `,`条依据已失效,当前版本仍在使用。`]}),t?.pending&&(0,x.jsxs)(A,{children:[(0,x.jsx)(M,{tone:`warning`,children:`待确认`}),` `,(0,x.jsx)(`strong`,{children:`1 个 persona 候选等待确认`}),(0,x.jsxs)(`p`,{children:[`候选 v`,t.pending.id,` 尚未生效,当前版本仍在使用。`]}),(0,x.jsx)(`a`,{href:`#/persona?tab=current&focus=pending`,children:`查看候选与差异`})]}),(0,x.jsxs)(`details`,{open:!0,children:[(0,x.jsxs)(`summary`,{children:[`当前 persona`,t?.current?` · v${t.current.id}`:``]}),(0,x.jsx)(`p`,{className:`persona-content`,children:t?t.current?.content||`暂无 persona 版本`:`正在读取 persona…`})]}),(0,x.jsx)(`a`,{href:`#/persona`,children:`查看 persona 与自我`})]})}function We(e,t){let n=t.find(t=>t.id===e);return n?`${n.name}(${e})`:e}function Ge(e,t){return e.visibility===`shared`?`全部入口共享(默认)`:e.visibility===`entry_only`?`仅本入口`:e.visibility===`entries`?`指定入口:${e.visible_in.map(e=>We(e,t)).join(`、`)}`:`未返回,请重新加载`}function Ke(e,t){return e?e.shared?`全部入口`:e.visible_in.length?e.visible_in.map(e=>We(e,t)).join(`、`):`仅管理员可见`:`未返回,请重新加载详情`}function qe({entry:e,entries:t,value:n,busy:r,setBusy:i,onSaved:a}){let[o,s]=(0,l.useState)(n.visibility),[c,u]=(0,l.useState)(n.visible_in.filter(t=>t!==e.id)),[d,f]=(0,l.useState)(``);async function p(t){if(t.preventDefault(),!r){i(!0),f(``);try{await g(`/entries/${encodeURIComponent(e.id)}/visibility`,_(`PATCH`,{visibility:o,visible_in:o===`entries`?c:[]})),a()}catch(e){f(v(e))}finally{i(!1)}}}return(0,x.jsxs)(`form`,{className:`entry-settings-form entry-visibility-form`,onSubmit:p,children:[(0,x.jsx)(`h3`,{children:`记忆可见范围`}),(0,x.jsx)(`p`,{className:`muted`,id:`entry-visibility-help`,children:`这是查询时生效的设置。修改后立即影响该入口来源的全部已有记忆,无需重新学习,可随时改回。 多个来源或派生依据的限制共同生效,最终范围可在记忆详情查看。`}),d&&(0,x.jsx)(A,{error:!0,children:d}),(0,x.jsxs)(`fieldset`,{className:`lifecycle-fieldset`,disabled:r,children:[(0,x.jsxs)(`label`,{children:[`记忆可见范围`,(0,x.jsxs)(`select`,{value:o,"aria-describedby":`entry-visibility-help`,onChange:e=>s(e.target.value),children:[(0,x.jsx)(`option`,{value:`shared`,children:`全部入口共享(默认)`}),(0,x.jsx)(`option`,{value:`entry_only`,children:`仅本入口`}),(0,x.jsx)(`option`,{value:`entries`,children:`指定入口`})]})]}),o===`entries`&&(0,x.jsxs)(`fieldset`,{className:`lifecycle-fieldset`,children:[(0,x.jsx)(`legend`,{children:`选择可见入口(可多选)`}),(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:!0,disabled:!0}),We(e.id,[e]),` · 本入口始终包含`]}),t.filter(t=>t.id!==e.id).map(e=>(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:c.includes(e.id),onChange:t=>{u(t.target.checked?[...c,e.id]:c.filter(t=>t!==e.id))}}),We(e.id,t)]},e.id)),t.every(t=>t.id===e.id)&&(0,x.jsx)(`p`,{className:`muted`,children:`暂无其他入口可选。`})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`可见范围与下方的节奏、过滤分别保存。`}),(0,x.jsx)(`button`,{className:`primary`,disabled:r,children:r?`正在保存…`:`保存可见范围`})]})]})}var Je={realtime:{name:`实时`,value:{count:4,idle_seconds:5,max_wait_seconds:60}},standard:{name:`标准`,value:{count:12,idle_seconds:600,max_wait_seconds:3600}},economy:{name:`省流`,value:{count:30,idle_seconds:1800,max_wait_seconds:14400}}};function Ye(e){if(typeof e==`string`&&Je[e])return Je[e].name;try{let t=typeof e==`string`?JSON.parse(e):e;return`自定义 · ${t.count} 条 / 空闲 ${t.idle_seconds} 秒 / 最长 ${t.max_wait_seconds} 秒`}catch{return`未知节奏`}}function Xe({value:e}){return e?(0,x.jsxs)(`div`,{className:`entry-filter-summary`,children:[(0,x.jsxs)(`p`,{children:[`最短字数:`,e.min_chars?`${e.min_chars} 字`:`不限制`]}),(0,x.jsxs)(`p`,{children:[`提及过滤:`,e.mention_only?`只学习提到角色的消息及前后各 ${e.context_messages} 条`:`关闭`]}),(0,x.jsxs)(`p`,{children:[`每小时批次上限:`,e.max_batches_per_hour||`不限制`]})]}):null}function Ze({value:e}){return e?(0,x.jsxs)(`div`,{className:`entry-queue-wait`,children:[e.reason&&(0,x.jsx)(`p`,{className:`queue-reason`,children:e.reason===`hourly_batch_limit`?`达到每小时批次上限,消息排队等待`:e.reason===`filter_context`?`等待提及窗口的后续消息或空闲定案`:e.reason}),e.reason===`hourly_batch_limit`&&e.retry_at&&(0,x.jsxs)(`p`,{children:[`最早释放额度:`,w(e.retry_at),`(不是完成时间)`]}),e.batches_last_hour!==null&&(0,x.jsxs)(`p`,{className:`muted`,children:[`滚动 60 分钟已组成 `,e.batches_last_hour,` / `,e.limit,` 个批次`]}),(0,x.jsxs)(`p`,{className:`muted`,children:[`待过滤定案 `,e.filter_waiting_count,` 条 · 已过滤`,` `,e.filtered_count,` 条`]})]}):null}function Qe({entry:e,entries:t,onClose:n,onSaved:r}){let i=y(`/entries/${encodeURIComponent(e.id)}/settings`),[a,o]=(0,l.useState)(!1);return(0,x.jsxs)(N,{title:`入口设置 · ${e.name}`,onClose:n,closeDisabled:a,children:[i.error&&(0,x.jsxs)(A,{error:!0,children:[i.error,(0,x.jsx)(`button`,{onClick:i.refresh,children:`重新加载`})]}),i.data?(0,x.jsxs)(x.Fragment,{children:[i.data.visibility?(0,x.jsx)(qe,{entry:e,entries:t,value:i.data,busy:a,setBusy:o,onSaved:r}):(0,x.jsxs)(A,{error:!0,children:[`未读到可见范围,请重新加载入口设置。`,(0,x.jsx)(`button`,{onClick:i.refresh,children:`重新加载`})]}),(0,x.jsx)($e,{entry:e,value:i.data,busy:a,setBusy:o,onSaved:r})]}):(0,x.jsx)(`p`,{role:`status`,children:`正在读取入口设置…`})]})}function $e({entry:e,value:t,busy:n,setBusy:r,onSaved:i}){let[a,o]=(0,l.useState)(typeof t.pace==`string`?t.pace:`custom`),s=typeof t.pace==`string`?Je[t.pace].value:t.pace,[c,u]=(0,l.useState)({count:String(s.count),idle_seconds:String(s.idle_seconds),max_wait_seconds:String(s.max_wait_seconds)}),[d,f]=(0,l.useState)({min_chars:String(t.filters.min_chars),mention_only:t.filters.mention_only,context_messages:String(t.filters.context_messages),max_batches_per_hour:String(t.filters.max_batches_per_hour)}),[p,m]=(0,l.useState)(``),h=[[`min_chars`,`最短字数`,32768],[`context_messages`,`前后各 K 条消息`,100],[`max_batches_per_hour`,`每小时最多批次`,1e3]],y=[[`count`,`触发条数`,1e3],[`idle_seconds`,`空闲秒数`,86400],[`max_wait_seconds`,`最长等待秒数`,604800]];async function b(t){if(t.preventDefault(),!n){for(let[e,t,n]of h){let r=Number(d[e]);if(!d[e].trim()||!Number.isInteger(r)||r<0||r>n){m(`${t}须为 0—${n} 的整数`);return}}if(a===`custom`)for(let[e,t,n]of y){let r=Number(c[e]);if(!c[e].trim()||!Number.isInteger(r)||r<1||r>n){m(`${t}须为 1—${n} 的整数`);return}}r(!0),m(``);try{await g(`/entries/${encodeURIComponent(e.id)}/settings`,_(`PATCH`,{pace:a===`custom`?{count:Number(c.count),idle_seconds:Number(c.idle_seconds),max_wait_seconds:Number(c.max_wait_seconds)}:a,filters:{min_chars:Number(d.min_chars),mention_only:d.mention_only,context_messages:Number(d.context_messages),max_batches_per_hour:Number(d.max_batches_per_hour)}})),i()}catch(e){m(v(e))}finally{r(!1)}}}return(0,x.jsxs)(`form`,{className:`entry-settings-form`,onSubmit:b,noValidate:!0,children:[p&&(0,x.jsx)(A,{error:!0,children:p}),(0,x.jsxs)(`fieldset`,{className:`lifecycle-fieldset`,disabled:n,children:[(0,x.jsxs)(`label`,{children:[`学习节奏`,(0,x.jsxs)(`select`,{value:a,onChange:e=>o(e.target.value),children:[Object.entries(Je).map(([e,t])=>(0,x.jsx)(`option`,{value:e,children:t.name},e)),(0,x.jsx)(`option`,{value:`custom`,children:`自定义`})]})]}),a===`custom`?(0,x.jsx)(`div`,{className:`form-grid`,children:y.map(([e,t,n])=>(0,x.jsxs)(`label`,{children:[t,(0,x.jsx)(`input`,{type:`number`,min:1,max:n,step:1,required:!0,value:c[e],onChange:t=>u({...c,[e]:t.target.value})})]},e))}):(0,x.jsxs)(`p`,{className:`muted`,children:[Je[a].value.count,` 条 / 空闲`,` `,Je[a].value.idle_seconds,` 秒 / 最长等待`,` `,Je[a].value.max_wait_seconds,` 秒`]}),(0,x.jsx)(`h3`,{children:`高流量入口过滤`}),(0,x.jsxs)(`label`,{children:[`最短字数`,(0,x.jsx)(`input`,{"aria-label":`最短字数`,"aria-describedby":`min-chars-help`,type:`number`,min:0,max:32768,step:1,required:!0,value:d.min_chars,onChange:e=>f({...d,min_chars:e.target.value})})]}),(0,x.jsx)(`small`,{id:`min-chars-help`,children:`0 表示关闭;按正文去掉首尾空白后的字符数计算。`}),(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:d.mention_only,onChange:e=>f({...d,mention_only:e.target.checked})}),`只学习提到角色的消息`]}),(0,x.jsx)(`p`,{className:`muted`,children:`正文中出现角色名或已确认的角色别名才算提及;引用内容、发送者名字和“记住”本身不算。`}),(0,x.jsxs)(`label`,{children:[`前后各 K 条消息`,(0,x.jsx)(`input`,{"aria-label":`前后各 K 条消息`,"aria-describedby":`context-help`,type:`number`,min:0,max:100,step:1,required:!0,disabled:!d.mention_only,value:d.context_messages,onChange:e=>f({...d,context_messages:e.target.value})})]}),(0,x.jsx)(`small`,{id:`context-help`,children:`0 表示仅学习提及消息;按本入口原始消息顺序计数,等待后续消息或空闲后定案。`}),(0,x.jsxs)(`label`,{children:[`每小时最多批次`,(0,x.jsx)(`input`,{"aria-label":`每小时最多批次`,"aria-describedby":`hourly-help`,type:`number`,min:0,max:1e3,step:1,required:!0,value:d.max_batches_per_hour,onChange:e=>f({...d,max_batches_per_hour:e.target.value})})]}),(0,x.jsx)(`small`,{id:`hourly-help`,children:`0 表示关闭;按滚动 60 分钟内新组成的批次计数。立即学习也受此上限及提及窗口限制。`}),(0,x.jsx)(A,{children:`设置立即作用于尚未冻结的待处理消息,已组成批次保持原样。被过滤的消息仍保存并可用于近期对话,但不会进入学习、不算积压或记忆缺口;放宽或关闭过滤不会重新学习这些消息。`})]}),(0,x.jsx)(`button`,{className:`primary`,disabled:n,children:n?`正在保存…`:`保存节奏与过滤`})]})}var et={no_candidates:`没有需要判断的相关候选`,host_disabled:`本次请求已关闭判断`,configuration_disabled:`设置中已关闭判断`,unconfigured:`未配置判断模型`,configuration_error:`模型配置错误`,configuration:`模型配置或响应无效`,configuration_changed:`调用期间模型配置发生变化`,invalid_key:`密钥无效`,authentication:`密钥无效`,account_problem:`模型账户异常`,account:`模型账户异常`,usage_limit:`达到每日 token 上限`,rate_limited:`服务商限流,正在退避`,temporarily_unavailable:`模型用途已暂停`,paused:`模型用途已暂停`,queue_full:`判断排队已满`,queue_timeout:`排队超时`,timeout:`超过判断总预算`,retryable:`模型连接暂时失败`,invalid_output:`判断输出格式无效`,content_rejection:`模型拒绝判断内容`};function tt({value:e}){return e?(0,x.jsxs)(`div`,{className:`judgment-summary`,"aria-label":`本次召回判断`,children:[(0,x.jsxs)(`p`,{children:[(0,x.jsx)(`strong`,{children:`召回判断:`}),(0,x.jsx)(M,{tone:e.status===`degraded`?`danger`:e.status===`applied`?`green`:``,children:{applied:`正常`,disabled:`已关闭`,degraded:`降级`}[e.status]||e.status})]}),e.reason&&(0,x.jsx)(`p`,{children:et[e.reason]||`判断原因:${e.reason}`}),(0,x.jsxs)(`p`,{children:[`被判断去掉 `,e.removed_memory_ids.length,` 条记忆`]}),!!e.stale_memory_ids?.length&&(0,x.jsxs)(`p`,{children:[`另有 `,e.stale_memory_ids.length,` 条记忆在复核时失效`]}),(0,x.jsxs)(`p`,{className:`muted`,children:[`耗时 `,C(e.duration_ms),` · 总预算 `,e.budget_seconds,` `,`秒(含排队)`]}),e.status===`degraded`&&(0,x.jsx)(`p`,{children:`本次保留仍有效的原召回。`})]}):(0,x.jsx)(`p`,{className:`fine-print`,children:`本次未返回召回判断状态。`})}function nt({value:e}){return e?(0,x.jsxs)(`div`,{className:`subject-annotations`,children:[e.possible_same_as.map(e=>(0,x.jsxs)(`p`,{children:[`可能是同一人:`,e.subjects.map(e=>e.name).join(`、`),` · 相信程度`,` `,e.belief,` / 100。`,(0,x.jsx)(`a`,{href:`#/people?id=${encodeURIComponent(e.subjects[0].id)}`,children:`核对人物联系`})]},e.link_id)),e.roleplay.map(e=>(0,x.jsxs)(`p`,{children:[`扮演关系(虚构):`,e.actor.name,` 扮演 `,e.character.name,` ·`,` `,e.worlds.map(e=>e??`场景未知`).join(`、`),` · 相信程度`,` `,e.belief,` / 100`]},e.link_id))]}):null}var rt={open:`未结束`,completed:`已完成`,abandoned:`已放弃`},it={normal:`普通目标`,question:`询问`},at={internal:`内部`,host:`宿主`,admin:`管理员`},ot={soon:`临近提醒`,due:`到期提醒`,overdue:`过期提醒`,immediate:`即时提醒`},st={pending:`待取走`,taken:`已取走`,cancelled:`已取消`},ct={created:`新建`,possible_duplicate:`可能重复,已分别保留`,merged:`已合并`,pending:`去重待复核,已保留`},lt=(e,t)=>{let n=t?.people.find(t=>t.id===e);return n?`${n.name}(${e})`:e},ut=(e,t)=>e?t?.entries.find(t=>t.id===e)?.name||e:`未指定`;function dt({goal:e}){return(0,x.jsxs)(`div`,{className:`detail-badges goal-badges`,children:[(0,x.jsx)(M,{children:it[e.kind]}),(0,x.jsx)(M,{children:rt[e.state]}),(0,x.jsx)(M,{children:at[e.origin]}),e.overdue?(0,x.jsx)(M,{tone:`danger`,children:`已过期`}):e.due_soon?(0,x.jsx)(M,{tone:`purple`,children:`临近截止`}):null,e.possible_duplicate&&(0,x.jsx)(M,{tone:`warning`,children:`可能重复`}),e.basis_needs_review&&(0,x.jsx)(M,{tone:`warning`,children:`依据可能不成立`}),e.merged_into&&(0,x.jsx)(M,{children:`已合并`})]})}function ft({goal:e}){return e.kind===`question`?(0,x.jsx)(x.Fragment,{children:`询问不设截止时间`}):e.deadline?e.deadline_unresolved?(0,x.jsxs)(`span`,{className:`danger-text`,children:[e.deadline,`(时间待明确,不安排提醒)`]}):(0,x.jsx)(P,{value:e.deadline}):(0,x.jsx)(x.Fragment,{children:`未设截止时间`})}function pt({goal:e,catalog:t}){return(0,x.jsxs)(`dl`,{className:`goal-facts`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`截止时间`}),(0,x.jsx)(`dd`,{children:(0,x.jsx)(ft,{goal:e})})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`提醒提前量`}),(0,x.jsx)(`dd`,{children:e.kind===`question`?`询问不安排提醒`:`${e.effective_reminder_minutes} 分钟${e.reminder_minutes===null?`(使用默认值)`:``}`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`涉及的人`}),(0,x.jsx)(`dd`,{children:e.people.map(e=>lt(e,t)).join(`、`)||`未指定`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`产生入口`}),(0,x.jsx)(`dd`,{children:ut(e.entry_id,t)})]})]})}function mt({receipt:e,openGoal:t}){return(0,x.jsxs)(`div`,{className:`notice`,role:`status`,children:[(0,x.jsxs)(`p`,{children:[`已创建目标 #`,e.submitted_id,` · `,ct[e.dedup.status]]}),(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>t(e.goal.id),children:[`查看目标 #`,e.goal.id]}),e.dedup.target_id&&e.dedup.target_id!==e.goal.id&&(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>t(e.dedup.target_id),children:[`查看可能重复的目标 #`,e.dedup.target_id]})]})}function ht({goal:e,locked:t,openMemory:n,clear:r}){return e.basis_annotations?.length?(0,x.jsxs)(`section`,{className:`panel goals-panel`,"aria-label":`目标依据复核`,children:[(0,x.jsx)(`h2`,{children:`依据可能不成立`}),(0,x.jsx)(`p`,{className:`goal-help`,children:`依据记忆已变化,请核对目标是否仍然成立;标注不会自动结束目标。`}),e.basis_annotations.map(i=>(0,x.jsxs)(`article`,{className:`goal-operation`,children:[(0,x.jsx)(`p`,{className:`report-text`,children:i.text}),(0,x.jsxs)(`p`,{children:[`依据修订 `,i.basis_revision,` · 观察到修订`,` `,i.observed_revision??`未知`]}),(0,x.jsxs)(`p`,{className:`muted`,children:[`复核时间:`,(0,x.jsx)(P,{value:i.created_at})]}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>n(i.memory_id),children:[`查看依据记忆 #`,i.memory_id]}),i.observed_merged_into!=null&&(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>n(i.observed_merged_into),children:[`已合并到记忆 #`,i.observed_merged_into]}),!e.merged_into&&(0,x.jsxs)(`button`,{disabled:t,onClick:()=>r(i),children:[`清除依据标注 #`,i.id]})]})]},i.id))]}):null}function gt({goal:e,openGoal:t}){let n=e.dedup_review;return(0,x.jsxs)(`section`,{className:`panel goals-panel`,"aria-label":`目标去重判断`,children:[(0,x.jsx)(`h2`,{children:`目标去重判断`}),n?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(M,{tone:n.state===`done`?`green`:`warning`,children:{pending:`待复核`,running:`复核中`,done:`已判断`,cancelled:`已取消`}[n.state]}),(0,x.jsxs)(`p`,{children:[`方法 `,n.method,` · 输入修订 `,n.input_revision,` · 尝试`,` `,n.attempts,` 次`]}),n.result.status&&(0,x.jsxs)(`p`,{children:[`判断结果:`,ct[n.result.status]||n.result.status]}),n.result.reason&&(0,x.jsx)(`p`,{children:ce(n.result.reason)}),n.result.target_id!=null&&(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>t(n.result.target_id),children:[`查看判断关联目标 #`,n.result.target_id]}),n.next_attempt_at&&(0,x.jsxs)(`p`,{children:[`下次复核:`,(0,x.jsx)(P,{value:n.next_attempt_at})]}),(0,x.jsxs)(`p`,{className:`muted`,children:[`最后更新:`,(0,x.jsx)(P,{value:n.updated_at})]}),[`pending`,`running`].includes(n.state)&&(0,x.jsx)(`p`,{className:`goal-help`,children:`已保留目标,等待模型复核;待复核不表示已经判定重复。`})]}):(0,x.jsx)(`p`,{className:`goal-help`,children:`没有异步复核任务记录。可能重复关系以当前目标标记为准。`}),(0,x.jsx)(`p`,{className:`goal-help`,children:`管理员手动创建的目标不会自动合并,判断为重复也只标记“可能重复”。`})]})}var _t=e=>{let t=new Date(e);if(!Number.isFinite(t.getTime()))return``;let n=e=>String(e).padStart(2,`0`);return`${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())}T${n(t.getHours())}:${n(t.getMinutes())}:${n(t.getSeconds())}`};function vt({goal:e,catalog:t,busy:n,locked:r=!1,submit:i,cancel:a}){let[o,s]=(0,l.useState)(e?.content||``),[c,u]=(0,l.useState)(e?.kind||`normal`),[d,f]=(0,l.useState)(e?`keep`:`none`),[p,m]=(0,l.useState)(``),[h,g]=(0,l.useState)(e?.deadline&&!e.deadline_unresolved?_t(e.deadline):``),[_,v]=(0,l.useState)(e?.reminder_minutes?.toString()??``),[y,b]=(0,l.useState)([]),[S,C]=(0,l.useState)(``),[w,T]=(0,l.useState)(``);function E(t){if(t.preventDefault(),n||r)return;if(T(``),!o.trim()||o.trim().length>4e3){T(`目标正文须为 1—4000 个字符且不为空白`);return}let a={content:o.trim()};if(c===`normal`){if(_.trim()&&(!Number.isInteger(Number(_))||Number(_)<0||Number(_)>525600)){T(`提醒提前量须为 0—525600 的整数,留空使用默认值`);return}if((!e||_!==(e.reminder_minutes?.toString()??``))&&(a.reminder_minutes=_.trim()?Number(_):null),d===`date`){if(!/^\d{4}-\d{2}-\d{2}$/.test(p)||!Number.isFinite(Date.parse(p))||new Date(p).toISOString().slice(0,10)!==p){T(`请选择有效的截止日期`);return}a.deadline=p}else if(d===`datetime`){let e=new Date(h);if(!h||!Number.isFinite(e.getTime())||_t(e.toISOString())!==(h.length===16?h+`:00`:h)){T(`请选择有效的截止时间`);return}a.deadline=e.toISOString()}else d===`none`&&(a.deadline=null)}else e||(a.deadline=null,a.reminder_minutes=null);if(!e){if(y.length>100){T(`涉及的人最多 100 位`);return}Object.assign(a,{kind:c,people:y,entry_id:S||null})}i(a)}return(0,x.jsxs)(`form`,{className:`goal-form`,onSubmit:E,noValidate:!0,children:[w&&(0,x.jsx)(A,{error:!0,children:w}),(0,x.jsxs)(`fieldset`,{className:`lifecycle-fieldset`,disabled:n||r,children:[!e&&(0,x.jsxs)(`label`,{children:[`创建类型`,(0,x.jsxs)(`select`,{value:c,onChange:e=>u(e.target.value),children:[(0,x.jsx)(`option`,{value:`normal`,children:`普通目标`}),(0,x.jsx)(`option`,{value:`question`,children:`询问`})]})]}),(0,x.jsxs)(`label`,{children:[`目标正文`,(0,x.jsx)(`textarea`,{required:!0,maxLength:4e3,rows:4,value:o,onChange:e=>s(e.target.value)})]}),c===`question`?(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`询问没有截止时间和提醒,由宿主决定何时询问。`}):(0,x.jsxs)(x.Fragment,{children:[e&&(0,x.jsxs)(`p`,{children:[`当前截止时间:`,(0,x.jsx)(ft,{goal:e})]}),(0,x.jsxs)(`div`,{className:`form-grid`,children:[(0,x.jsxs)(`label`,{children:[`截止方式`,(0,x.jsxs)(`select`,{value:d,onChange:e=>f(e.target.value),children:[e&&(0,x.jsx)(`option`,{value:`keep`,children:`保持当前截止时间`}),(0,x.jsx)(`option`,{value:`none`,children:`不设截止时间`}),(0,x.jsx)(`option`,{value:`date`,children:`指定日期`}),(0,x.jsx)(`option`,{value:`datetime`,children:`指定日期和时间`})]})]}),(0,x.jsxs)(`label`,{children:[`提醒提前量(分钟)`,(0,x.jsx)(`input`,{type:`number`,min:0,max:525600,step:1,value:_,placeholder:`留空使用默认值`,onChange:e=>v(e.target.value)})]}),d===`date`&&(0,x.jsxs)(`label`,{children:[`截止日期`,(0,x.jsx)(`input`,{"aria-label":`截止日期`,type:`date`,required:!0,value:p,onChange:e=>m(e.target.value)}),(0,x.jsx)(`small`,{children:`按角色时区当天 23:59:59 截止。`})]}),d===`datetime`&&(0,x.jsxs)(`label`,{children:[`截止日期和时间`,(0,x.jsx)(`input`,{"aria-label":`截止日期和时间`,type:`datetime-local`,step:1,required:!0,value:h,onChange:e=>g(e.target.value)}),(0,x.jsxs)(`small`,{children:[`按本机时区`,` `,Intl.DateTimeFormat().resolvedOptions().timeZone,` `,`输入;保存后按角色时区显示。`]})]})]}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`留空提前量使用默认值;0 表示到期时提醒。修改期限或提前量会更新尚未取走的提醒,已取走的记录保留。`})]}),!e&&(0,x.jsxs)(`div`,{className:`form-grid`,children:[(0,x.jsxs)(`label`,{children:[`涉及的人`,(0,x.jsx)(`select`,{"aria-label":`涉及的人`,multiple:!0,size:4,value:y,onChange:e=>b(Array.from(e.target.selectedOptions,e=>e.value)),children:t?.people.filter(e=>![`self`,`scene`].includes(e.id)&&![`self`,`scene`].includes(e.kind||``)).map(e=>(0,x.jsx)(`option`,{value:e.id,children:lt(e.id,t)},e.id))}),(0,x.jsx)(`small`,{children:`可多选,也可不指定。`})]}),(0,x.jsxs)(`label`,{children:[`记录产生入口`,(0,x.jsxs)(`select`,{"aria-label":`记录产生入口`,value:S,onChange:e=>C(e.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`不指定`}),t?.entries.map(e=>(0,x.jsxs)(`option`,{value:e.id,children:[e.name,` · `,e.id]},e.id))]}),(0,x.jsx)(`small`,{children:`仅记录产生位置,所有入口共享此目标。`})]})]}),!e&&(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`管理员创建的目标独立保留;发现相似项只标“可能重复”,由管理员明确合并或驳回。`}),(0,x.jsx)(`div`,{className:`actions`,children:(0,x.jsx)(`button`,{className:`primary`,children:n?`正在保存…`:e?`保存目标`:`创建`})})]}),(0,x.jsx)(`button`,{type:`button`,className:`secondary`,disabled:n,onClick:a,children:`取消`})]})}function yt({note:e,openGoal:t}){return(0,x.jsxs)(`article`,{className:`notification-card`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h3`,{children:ot[e.reminder_kind]}),(0,x.jsx)(M,{tone:e.status===`pending`?`purple`:``,children:st[e.status]})]}),(0,x.jsx)(`p`,{className:`goal-content`,children:e.content}),(0,x.jsxs)(`div`,{className:`goal-time-lines`,children:[(0,x.jsxs)(`p`,{children:[`发布时间:`,(0,x.jsx)(P,{value:e.published_at})]}),(0,x.jsxs)(`p`,{children:[`计划时间:`,(0,x.jsx)(P,{value:e.scheduled_at})]}),e.deadline_at&&(0,x.jsxs)(`p`,{children:[`发布时的截止时间:`,(0,x.jsx)(P,{value:e.deadline_at})]}),e.taken_at&&(0,x.jsxs)(`p`,{children:[`取走时间:`,(0,x.jsx)(P,{value:e.taken_at})]}),e.cancelled_at&&(0,x.jsxs)(`p`,{children:[`取消时间:`,(0,x.jsx)(P,{value:e.cancelled_at})]})]}),(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>t(e.goal_id),children:[`查看目标 #`,e.goal_id]})]})}function bt({goalId:e,openGoal:t}){let[n,r]=(0,l.useState)(e?``:`pending`),[i,a]=(0,l.useState)(0),o=new URLSearchParams({limit:`30`,offset:String(i)});n&&o.set(`status`,n),e&&o.set(`goal_id`,String(e));let s=y(`/notifications?${o}`,i===0?2e3:0);return(0,x.jsxs)(`section`,{className:`panel goals-panel`,"aria-label":`提醒列表`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:e?`该目标的提醒`:`提醒`}),(0,x.jsx)(`button`,{className:`text-button`,onClick:s.refresh,children:`刷新提醒`})]}),(0,x.jsx)(`p`,{className:`goal-help`,children:`“已取走”只表示宿主拿到了提醒,不代表已送达用户或目标完成。此处查看不会取走提醒。`}),(0,x.jsxs)(`label`,{className:`notification-filter`,children:[`提醒状态`,(0,x.jsxs)(`select`,{value:n,onChange:e=>{r(e.target.value),a(0)},children:[(0,x.jsx)(`option`,{value:``,children:`全部`}),Object.entries(st).map(([e,t])=>(0,x.jsx)(`option`,{value:e,children:t},e))]})]}),s.error&&(0,x.jsxs)(A,{error:!0,children:[s.error,`。`,s.data&&`以下为上次读取结果。`]}),!s.data&&!s.error&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取提醒…`}),s.data?.items.length===0&&(0,x.jsx)(j,{title:`当前范围没有提醒`,children:`有截止时间的普通目标会在临近、到期时产生提醒;询问不安排提醒。`}),s.data?.items.map(e=>(0,x.jsx)(yt,{note:e,openGoal:t},e.id)),s.data&&(0,x.jsx)(T,{total:s.data.total,offset:i,change:a})]})}var xt=`合并待核对(双方互有细节,不代表事实矛盾)`;function St({details:e,ids:t,openMemory:n,disabled:r=!1}){return(0,x.jsxs)(`div`,{className:`merge-detail-review`,children:[(0,x.jsx)(`p`,{children:`双方各有另一条没有的细节,未自动合并。采纳只确认建议,不执行合并,也不改正文和相信程度。`}),[`a`,`b`].map((i,a)=>(0,x.jsxs)(`div`,{children:[t[a]==null?(0,x.jsxs)(`strong`,{children:[`第 `,a+1,` 条记忆的独有细节`]}):(0,x.jsxs)(`button`,{disabled:r,className:`text-button`,onClick:()=>n(t[a]),children:[`记忆 #`,t[a],` 的独有细节`]}),e?.[i]?.length?(0,x.jsx)(`ul`,{children:e[i].map((e,t)=>(0,x.jsx)(`li`,{children:e},t))}):(0,x.jsx)(`p`,{className:`muted`,children:`未保存独有细节,请核对报告正文。`})]},i))]})}var Ct={relationship:`与我的关系`,fact:`稳定事实`,preference:`偏好与习惯`,recent:`近期重要事项`},wt={published:`已发布`,candidate:`待确认`,rejected:`已拒绝`,failed:`失败`,skipped:`已跳过`,conflict:`版本或依据冲突`,running:`生成中`};function Tt(e){return{memory_purged:`依据记忆已彻底清除`,memory_unavailable:`依据记忆已遗忘或删除`,visibility_changed:`依据不再满足全部入口共享条件`,no_longer_related:`依据不再与此人物相关`,memory_changed:`依据记忆已修订`,subject_changed:`人物资料或关联发生变化`,subject_merged:`人物已合并`,subject_unavailable:`此人物当前不可生成摘要`,subject_kind:`此类主体不生成人物摘要`,time_range_expired:`近期事项已到期`,purged:`因彻底清除而清空`,disabled:`人物摘要开关已关闭`,insufficient_memories:`相关全局有效记忆不足(至少需要 8 条)`,no_changes_since_attempt:`上次被拒或确定性失败后,尚无新依据`,not_due:`尚未达到更新条件`,generation_in_progress:`管理员生成中,本轮已跳过`,interrupted:`任务被中断,可以重试`,invalid_output:`模型输出格式无效`,invalid_check_output:`模型检查格式无效`,invalid_check_item:`逐条检查格式无效`,too_many_deleted:`检查累计删去超过一半的模型条目`,empty:`没有可保留的摘要内容`,too_many_items:`条目数超出预算`,too_long:`摘要字数超出预算`,token_budget:`摘要 token 超出预算`,invalid_item_or_references:`条目或引用依据无效`,missing_time_range:`近期事项缺少时间范围`,invalid_or_expired_time_range:`时间范围无效或已经到期`,unexpected_time_range:`非近期事项带有不适用的时间范围`,too_many_relationships:`与我的关系最多保留一条`,timeout:`模型请求超时,可以重试`,retryable:`模型暂时失败,可以重试`,temporary_unavailable:`模型暂时不可用,可以稍后重试`,paused:`模型用途已暂停`,usage_limit:`已达到每日用量上限`,call_budget:`剩余模型调用预算不足`,unconfigured:`模型尚未配置`,configuration:`模型配置无效`,account:`模型账户不可用`,refused:`模型拒绝处理`,unexpected_error:`生成过程中发生错误,可以重试`,superseded:`已被新候选或编辑取代`,administrator_rejected:`管理员拒绝`,evidence_changed:`依据已变化,请刷新后重试`,current_version_changed:`当前版本已变化,请刷新后重试`,settings_or_subject_changed:`设置或人物资料已变化,请刷新后重试`,settings_changed:`设置已变化,请刷新后重试`,candidate_changed:`候选已变化,请刷新后重试`}[e]||e}var Et=(e,t)=>`#/people?id=${encodeURIComponent(e)}${t?`&summary_version=${t}`:``}`;function Dt({basis:e,catalog:t,openMemory:n}){let r=y(e.memory?`/memories/${e.memory_id}`:null,5e3),i=r.data,a=[...new Set([i?.entry_id,...(i?.sources||[]).map(e=>e.message?.entry_id)].filter(e=>!!e))];return(0,x.jsxs)(`article`,{className:`persona-evidence`,children:[(0,x.jsxs)(`h4`,{children:[`记忆 #`,e.memory_id]}),(0,x.jsxs)(`p`,{className:`muted`,children:[`记录修订 `,e.revision,` ·`,` `,e.memory?`当前修订 ${e.memory.revision} · ${E(e.memory.lifecycle)}`:`当前记忆不可用`]}),(0,x.jsx)(`p`,{className:`persona-content`,children:e.content_at_revision??`该修订正文不可用`}),i&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{className:`muted`,children:[`当前记忆记录时间:`,(0,x.jsx)(P,{value:i.created_at}),`;事件时间:`,(0,x.jsx)(P,{value:i.event_time??null})]}),(0,x.jsxs)(`p`,{className:`muted`,children:[`当前来源入口类型:`,a.length?a.map(e=>{let n=t?.entries.find(t=>t.id===e);return n?`${{group:`群聊`,private:`私聊`}[n.kind]||n.kind} · ${n.name}`:`入口 ${e}(类型暂不可用)`}).join(`;`):i.sources.some(e=>e.kind===`initial_setting`)?`初始设定`:`未记录入口`]}),(0,x.jsx)(`small`,{children:`以上时间和入口来自当前记忆详情,不是该版本生成时的历史快照。`})]}),r.loading&&(0,x.jsx)(`p`,{children:`正在读取当前记忆元数据…`}),r.error&&(0,x.jsxs)(A,{error:!0,children:[r.error,(0,x.jsx)(`button`,{onClick:r.refresh,children:`重试记忆元数据`})]}),(0,x.jsxs)(`button`,{className:`text-button`,disabled:!e.memory,onClick:()=>n(e.memory_id),children:[`查看记忆 #`,e.memory_id]})]})}function Ot({sentence:e,index:t,catalog:n,openMemory:r}){let[i,a]=(0,l.useState)(!1),o=e.admin_written||e.origin===`admin`;return(0,x.jsxs)(`li`,{className:`persona-sentence`,children:[(0,x.jsxs)(`div`,{className:`persona-sentence-line`,children:[(0,x.jsxs)(`span`,{className:`muted`,children:[t+1,`.`]}),(0,x.jsx)(`p`,{children:e.text}),(0,x.jsx)(M,{tone:o?`warning`:``,children:o?`手写`:ee[e.origin]||e.origin})]}),(0,x.jsxs)(`button`,{className:`text-button`,"aria-expanded":i,onClick:()=>a(!i),children:[i?`收起`:`展开`,`第 `,t+1,` 句依据`]}),i&&(0,x.jsxs)(`div`,{className:`persona-basis`,children:[(0,x.jsxs)(`p`,{children:[`该句的依据日期:`,e.dates.length?e.dates.join(`、`):`未记录日期`,`(`,e.date_count,` 个日期)`,e.initial_setting&&` · 含初始设定`]}),e.basis.map(e=>(0,x.jsx)(Dt,{basis:e,catalog:n,openMemory:r},`${e.memory_id}-${e.revision}`)),!e.basis.length&&(0,x.jsx)(`p`,{className:`muted`,children:o?`管理员手写内容,没有记忆依据;手写标记不代表模型检查通过。`:`初始模板,没有逐句记忆依据。`})]})]})}var kt=e=>typeof e==`object`&&e&&!Array.isArray(e)?e:null;function At({value:e,index:t}){let n=kt(e);if(!n)return(0,x.jsxs)(`li`,{children:[`第 `,t+1,` 句:检查结果格式不完整`]});let r=(e,t,n)=>typeof e==`boolean`?e?t:n:`未报告`;return(0,x.jsxs)(`li`,{children:[`第 `,typeof n.index==`number`?n.index:t+1,` `,`句:依据支持 `,r(n.supported,`是`,`否`),`;虚构`,` `,r(n.fabricated,`是`,`否`),`;场景限定`,` `,r(n.scene_qualified,`是`,`否`),typeof n.reason==`string`&&(0,x.jsx)(`p`,{children:n.reason}),Array.isArray(n.violations)&&n.violations.some(e=>typeof e==`string`)&&(0,x.jsxs)(`p`,{children:[`违反要求:`,n.violations.filter(e=>typeof e==`string`).join(`;`)]})]})}function jt({version:e}){let{checks:t}=e,n=kt(t.model);return(0,x.jsxs)(`div`,{className:`persona-checks`,children:[(0,x.jsx)(`h3`,{children:`检查结果`}),(0,x.jsxs)(`p`,{children:[t.passed===!0?`综合检查通过`:t.passed===!1?`综合检查未通过`:`没有综合检查结论`,t.administrator_published&&` · 管理员直接发布`]}),(0,x.jsx)(`p`,{className:`muted`,children:`手写标记表示内容的来源,不代表模型检查通过。`}),(0,x.jsx)(`h4`,{children:`确定性检查`}),(0,x.jsx)(`p`,{children:t.deterministic?.passed===!0?`通过`:t.deterministic?.passed===!1?`未通过`:`没有确定性检查记录`}),!!t.deterministic?.errors?.length&&(0,x.jsx)(`ul`,{children:t.deterministic.errors.map((e,t)=>(0,x.jsx)(`li`,{children:ne(e)},t))}),!!t.deterministic?.warnings?.length&&(0,x.jsx)(`ul`,{className:`muted`,children:t.deterministic.warnings.map((e,t)=>(0,x.jsxs)(`li`,{children:[`提示:`,ne(e)]},t))}),(0,x.jsx)(`h4`,{children:`模型检查`}),t.model==null?(0,x.jsx)(`p`,{children:`未进行模型检查`}):n?(0,x.jsxs)(x.Fragment,{children:[typeof n.change_degree==`string`&&(0,x.jsxs)(`p`,{children:[`判断的变化程度:`,L[n.change_degree]||n.change_degree]}),typeof n.reason==`string`&&(0,x.jsx)(`p`,{children:n.reason}),Array.isArray(n.sentences)?(0,x.jsx)(`ul`,{children:n.sentences.map((e,t)=>(0,x.jsx)(At,{value:e,index:t},t))}):(0,x.jsx)(`p`,{children:`逐句检查结果格式不完整`})]}):(0,x.jsx)(`p`,{children:`模型检查结果格式不完整`}),!!t.model_errors?.length&&(0,x.jsx)(`ul`,{children:t.model_errors.map((e,t)=>(0,x.jsx)(`li`,{children:ne(e)},t))}),t.admin_content_removed_or_changed&&(0,x.jsx)(A,{children:`候选删去或改动了手写内容,变化程度按“大”处理。默认发布方式需要确认;“全部自动”模式会直接发布检查通过的候选。`})]})}function Mt({id:e,title:t,catalog:n,openMemory:r,onAction:i,locked:a=!1,currentID:o,history:s=!1}){let c=y(`/persona/versions/${e}`,5e3),l=c.data;return(0,x.jsxs)(`section`,{className:`panel persona-version`,"aria-label":t,children:[l&&(0,x.jsxs)(`h2`,{children:[t,` · v`,e]}),c.error&&(0,x.jsxs)(A,{error:!0,children:[c.error,(0,x.jsx)(`button`,{onClick:c.refresh,children:`重试版本详情`})]}),l?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`persona-meta`,children:[(0,x.jsx)(M,{tone:l.status===`pending`||l.status===`rejected`?`warning`:``,children:I[l.status]}),(0,x.jsx)(`span`,{children:F[l.source]||l.source}),(0,x.jsxs)(`span`,{children:[`变化程度:`,l.change_degree?L[l.change_degree]||l.change_degree:`未记录`]})]}),(0,x.jsxs)(`p`,{className:`muted`,children:[`生成时间:`,(0,x.jsx)(P,{value:l.generated_at}),` · 发布时间:`,(0,x.jsx)(P,{value:l.published_at})]}),(0,x.jsxs)(`p`,{className:`muted`,children:[l.base_version_id?`基于 v${l.base_version_id}`:`初始版本`,l.rollback_of&&` · 回滚自 v${l.rollback_of}`]}),(0,x.jsx)(`ol`,{className:`persona-sentences`,children:l.sentences.map((e,t)=>(0,x.jsx)(Ot,{sentence:e,index:t,catalog:n,openMemory:r},`${t}-${e.text}`))}),!l.sentences.length&&(0,x.jsx)(`p`,{className:`persona-content`,children:l.content}),!!l.rejection_reasons.length&&(0,x.jsxs)(`div`,{className:`notice error`,children:[(0,x.jsx)(`h3`,{children:`拒绝原因`}),(0,x.jsx)(`ul`,{children:l.rejection_reasons.map((e,t)=>(0,x.jsx)(`li`,{children:ne(e)},t))})]}),(0,x.jsx)(jt,{version:l}),l.settings&&(0,x.jsxs)(`details`,{children:[(0,x.jsx)(`summary`,{children:`本次候选接受时的设置`}),(0,x.jsxs)(`p`,{children:[`发布方式:`,{small_medium_auto:`小或中自动发布`,all_auto:`全部自动`,all_manual:`全部人工确认`}[l.settings.publish_mode]||l.settings.publish_mode]}),(0,x.jsx)(`h4`,{children:`生成目标`}),(0,x.jsx)(`p`,{className:`persona-content`,children:l.settings.goal}),(0,x.jsx)(`h4`,{children:`监管要求`}),(0,x.jsx)(`p`,{className:`persona-content`,children:l.settings.rules})]}),(0,x.jsxs)(`div`,{className:`persona-actions`,children:[i&&o&&l.status===`pending`&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`button`,{className:`primary`,disabled:a||!!c.error,onClick:()=>i(`confirm`,l),children:`确认发布候选`}),(0,x.jsx)(`button`,{disabled:a||!!c.error,onClick:()=>i(`reject`,l),children:`拒绝候选`})]}),i&&o&&s&&[`current`,`history`].includes(l.status)&&(0,x.jsx)(`button`,{disabled:a||!!c.error,onClick:()=>i(`rollback`,l),children:`回滚到此版本`}),(0,x.jsx)(`a`,{href:`#/operations?object_type=persona&object_id=${e}`,children:`查看版本操作记录`})]})]}):(0,x.jsx)(`p`,{children:`正在读取版本详情…`})]})}function Nt({sentences:e,start:t}){return e.length?(0,x.jsx)(`ol`,{className:`persona-diff-sentences`,start:t,children:e.map((e,t)=>(0,x.jsxs)(`li`,{children:[(0,x.jsx)(`p`,{children:e.text}),(0,x.jsxs)(`small`,{children:[ee[e.origin]||e.origin,` · 依据:`,e.basis.length?e.basis.map(e=>`#${e.memory_id} 修订 ${e.revision}`).join(`、`):`无`,` `,`· 日期:`,e.dates.join(`、`)||`未记录`,`(`,e.date_count,` 个日期)`,e.initial_setting&&` · 初始设定`]})]},t))}):(0,x.jsx)(`p`,{className:`muted`,children:`无句子`})}function Pt({before:e,after:t}){let n=y(`/persona/diff?before_version=${e}&after_version=${t}`);return(0,x.jsxs)(`section`,{className:`persona-diff`,"aria-label":`版本差异 v${e} 到 v${t}`,children:[(0,x.jsxs)(`h3`,{children:[`逐句差异:v`,e,` → v`,t]}),n.error&&(0,x.jsxs)(A,{error:!0,children:[n.error,(0,x.jsx)(`button`,{onClick:n.refresh,children:`重试版本对比`})]}),!n.data&&!n.error&&(0,x.jsx)(`p`,{children:`正在读取差异…`}),n.data?.changes.length===0&&(0,x.jsx)(`p`,{children:`这两个版本的句子与依据没有差异。`}),n.data?.changes.map((n,r)=>(0,x.jsxs)(`article`,{className:`persona-change persona-change-${n.kind}`,children:[(0,x.jsx)(`h4`,{children:{insert:`新增句子`,delete:`删除句子`,replace:`改写句子`,basis_changed:`正文相同,依据或归属变化`}[n.kind]}),(0,x.jsxs)(`div`,{className:`persona-diff-columns`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsxs)(`strong`,{children:[`之前 · v`,e]}),(0,x.jsx)(Nt,{sentences:n.before,start:n.before_start})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsxs)(`strong`,{children:[`之后 · v`,t]}),(0,x.jsx)(Nt,{sentences:n.after,start:n.after_start})]})]})]},r))]})}function Ft({value:e,openMemory:t}){return(0,x.jsxs)(`details`,{className:`source consolidation-excerpts`,children:[(0,x.jsx)(`summary`,{children:`查看来源摘录`}),(0,x.jsx)(`p`,{className:`fine-print`,children:`本次模型判断时的来源摘录;完整来源与前后文可在记忆详情查看。`}),!e?.length&&(0,x.jsx)(`p`,{children:`没有保存的来源摘录。`}),e?.map((e,n)=>(0,x.jsxs)(`div`,{children:[(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>t(e.memory_id),children:[`记忆 #`,e.memory_id]}),!e.sources.length&&(0,x.jsx)(`p`,{className:`quiet`,children:`没有可用的来源消息摘录。`}),e.sources.map(e=>(0,x.jsxs)(`article`,{className:`consolidation-excerpt`,children:[(0,x.jsxs)(`p`,{className:`muted`,children:[`消息 #`,e.id,` · `,e.entry_name||e.entry_id,` ·`,` `,{private:`私聊`,group:`群聊`,trial:`试用`}[e.entry_kind||``]||e.entry_kind,` `,`· `,e.sender_name||e.sender,` ·`,` `,(0,x.jsx)(P,{value:e.at||e.occurred_at||null})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:{message:`他人消息`,self_output:`角色输出`,action_result:`行动结果`,event:`事件`}[e.kind]||e.kind}),(0,x.jsx)(`blockquote`,{children:e.text}),e.quote_content&&(0,x.jsxs)(`div`,{className:`source-quote`,children:[(0,x.jsxs)(`small`,{children:[`原消息引用 `,e.quote_author||``]}),(0,x.jsx)(`blockquote`,{children:e.quote_content})]})]},e.id))]},`${e.memory_id}:${n}`))]})}function It({name:e,items:t,openMemory:n}){let[r,i]=(0,l.useState)(0);return(0,x.jsxs)(`section`,{className:`detail-section`,"aria-label":e,children:[(0,x.jsxs)(`h3`,{children:[e,` `,(0,x.jsx)(M,{children:t.length})]}),e.includes(`建议`)&&(0,x.jsx)(`p`,{className:`fine-print`,children:`仅管理员可见。采纳只记录确认,不改正文和相信程度;已确认的建议也不进入宿主召回。`}),!t.length&&(0,x.jsx)(`p`,{className:`quiet`,children:`本次暂无记录。`}),t.slice(r,r+30).map(e=>{let t=e.details;return(0,x.jsxs)(`article`,{className:`maintenance-item`,children:[e.outcome===`merged`?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`actions`,children:[t.absorbed_ids?.map(e=>(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>n(e),children:[`记忆 #`,e]},e)),(0,x.jsx)(`span`,{children:`并入`}),t.result_id!=null&&(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>n(t.result_id),children:[`记忆 #`,t.result_id]})]}),(0,x.jsx)(`p`,{children:`全部来源已归入保留记忆;被合并的记忆保留为占位。`}),(0,x.jsxs)(`p`,{children:[`来源消息:`,t.source_messages?.map(e=>`#${e}`).join(`、`)||`无消息来源`,` `,`· 重定向派生依据 `,t.redirected_dependencies??0,` 处`]})]}):(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(M,{tone:`warning`,children:`模型建议`}),` `,(0,x.jsx)(`span`,{children:t.suggestion_type===`merge_details`?xt:e.outcome===`conflicts`?`矛盾检查`:`依赖复核`}),t.suggestion_type===`merge_details`&&(0,x.jsx)(St,{details:t.unique_details,ids:t.before_memories?.slice(0,2).map(e=>e.id)||[],openMemory:n}),t.suggestions?.map(e=>(0,x.jsxs)(`div`,{className:`suggestion-summary`,children:[(0,x.jsxs)(`p`,{children:[(0,x.jsx)(M,{children:t.suggestion_type===`merge_details`?`合并待核对`:ae[e.kind]||e.kind}),` `,(0,x.jsx)(M,{children:oe[e.review_status]}),` 建议 #`,e.id]}),(0,x.jsx)(`p`,{children:e.text}),e.memory_id!=null&&(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>n(e.memory_id),children:[`查看记忆 #`,e.memory_id,` 的建议`]}),e.confirmed_at&&(0,x.jsxs)(`p`,{className:`muted`,children:[`管理员确认:`,(0,x.jsx)(P,{value:e.confirmed_at})]}),e.cleared_at&&(0,x.jsxs)(`p`,{className:`muted`,children:[`管理员清除:`,(0,x.jsx)(P,{value:e.cleared_at})]})]},e.id)),!t.suggestions?.length&&e.memory_id!=null&&(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>n(e.memory_id),children:[`查看记忆 #`,e.memory_id]})]}),t.report&&(0,x.jsx)(`p`,{className:`report-text`,children:t.report}),!!t.before_memories?.length&&(0,x.jsxs)(`details`,{className:`source`,children:[(0,x.jsx)(`summary`,{children:`涉及的记忆与修订快照`}),t.before_memories.map(e=>{let r=t.after_memories?.find(t=>t.id===e.id);return(0,x.jsxs)(`div`,{children:[(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>n(e.id),children:[`记忆 #`,e.id]}),(0,x.jsxs)(`span`,{children:[` `,`· 修订 `,e.revision,r&&` → ${r.revision}`]}),(0,x.jsx)(`p`,{className:`report-text`,children:e.content||`正文已不可用`}),r?.content!==e.content&&(0,x.jsxs)(`p`,{className:`report-text`,children:[`整理后:`,r?.content||`正文已不可用`]})]},e.id)})]}),(0,x.jsx)(Ft,{value:t.source_excerpts,openMemory:n}),(0,x.jsx)(`small`,{children:(0,x.jsx)(P,{value:e.created_at})})]},`${e.phase}:${e.item_key}`)}),(0,x.jsx)(T,{total:t.length,offset:r,change:i})]})}function Lt({data:e}){let[t,n]=(0,l.useState)(0),r=e.items.filter(e=>e.outcome===`goals_reviewed`);return!e.goal_review&&!r.length?null:(0,x.jsxs)(`section`,{className:`detail-section`,"aria-label":`目标复核结果`,children:[(0,x.jsx)(`h3`,{children:`目标复核结果`}),(0,x.jsx)(`p`,{children:e.goal_review?.enabled===!1?`未执行:${ce(e.goal_review.skip_reason||`disabled`)}`:`已检查 ${e.goal_review?.checked??0} 个目标,${r.length} 个目标的依据标注发生变化。`}),(0,x.jsx)(`p`,{className:`fine-print`,children:`复核只更新依据标注,不自动完成或放弃目标,也不改变提醒。`}),r.slice(t,t+30).map(e=>(0,x.jsxs)(`article`,{className:`maintenance-item`,children:[(0,x.jsxs)(`a`,{href:`#/state?tab=goals&id=${e.object_id}`,children:[`查看目标 #`,e.object_id]}),(0,x.jsxs)(`p`,{children:[`新增或重新启用标注:`,e.details.annotation_ids?.map(e=>`#${e}`).join(`、`)||`无`]}),(0,x.jsxs)(`p`,{children:[`结束的旧标注:`,e.details.ended_annotation_ids?.map(e=>`#${e}`).join(`、`)||`无`]}),(0,x.jsx)(`small`,{children:(0,x.jsx)(P,{value:e.created_at})})]},e.item_key)),(0,x.jsx)(T,{total:r.length,offset:t,change:n})]})}function Rt({data:e}){let[t,n]=(0,l.useState)(0),r=e.items.filter(e=>e.outcome===`person_summary`);return!r.length&&e.consolidation?.settings.person_summary_enabled==null?null:(0,x.jsxs)(`section`,{className:`detail-section`,"aria-label":`人物摘要处理结果`,children:[(0,x.jsxs)(`h3`,{children:[`人物摘要处理结果 `,(0,x.jsx)(M,{children:r.length})]}),e.consolidation?.settings.person_summary_enabled===!1&&(0,x.jsx)(`p`,{children:`本次运行已关闭人物摘要更新。`}),!r.length&&(0,x.jsx)(`p`,{children:`本次没有人物摘要处理记录。`}),r.slice(t,t+30).map(e=>(0,x.jsxs)(`article`,{className:`maintenance-item`,children:[(0,x.jsx)(`p`,{children:(0,x.jsx)(M,{children:wt[e.details.status||``]||e.details.status||`未记录结果`})}),e.details.subject_id?(0,x.jsxs)(`a`,{href:Et(e.details.subject_id,e.details.version),children:[`查看人物 `,e.details.subject_id,e.details.version?` 的摘要 v${e.details.version}`:` 的摘要与任务`]}):(0,x.jsx)(`p`,{children:`人物摘要步骤异常,未关联具体人物。`}),e.reason&&(0,x.jsx)(`p`,{children:Tt(e.reason)}),e.details.attempt_id!=null&&(0,x.jsxs)(`p`,{children:[`生成任务 #`,e.details.attempt_id]}),(0,x.jsx)(`small`,{children:(0,x.jsx)(P,{value:e.created_at})})]},e.item_key)),(0,x.jsx)(T,{total:r.length,offset:t,change:n})]})}function zt({data:e,openMemory:t}){let n=e.summary.model_calls,r=e.persona;return(0,x.jsxs)(x.Fragment,{children:[e.consolidation&&(0,x.jsxs)(`section`,{className:`detail-section`,"aria-label":`本次整理与模型用量`,children:[(0,x.jsx)(`h3`,{children:`本次整理与模型用量`}),(0,x.jsxs)(`p`,{children:[`后续待处理项目:`,e.consolidation.deferred,` 项`,e.consolidation.skip_reason&&` · ${ce(e.consolidation.skip_reason)}`]}),n&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{children:[`模型调用 `,n.count,` 次 · 输入 `,n.prompt_tokens??0,` `,`token · 输出 `,n.completion_tokens??0,` token · 总耗时`,` `,C(n.duration_ms??0)]}),(0,x.jsxs)(`p`,{className:`fine-print`,children:[n.unknown_usage_calls??0,` `,`次调用用量未知;用量为已知合计,包含实际重试、persona 及人物摘要调用。`]})]}),(0,x.jsxs)(`details`,{children:[(0,x.jsx)(`summary`,{children:`本次接受任务时的整理设置`}),(0,x.jsxs)(`p`,{children:[`模型调用次数预算:`,e.consolidation.settings.max_calls??`未记录`]}),se.map(([t,n])=>(0,x.jsxs)(`p`,{children:[n,`:`,e.consolidation?.settings[t]==null?`未记录`:e.consolidation.settings[t]?`开启`:`关闭`]},t)),(0,x.jsx)(`p`,{className:`fine-print`,children:`设置修改只影响之后接受的新运行。`})]})]}),(e.consolidation||e.items.some(e=>e.phase===`consolidation`))&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(It,{name:`记忆合并`,items:e.items.filter(e=>e.outcome===`merged`),openMemory:t}),(0,x.jsx)(It,{name:`整理建议(模型建议)`,items:e.items.filter(e=>[`conflicts`,`dependencies_reviewed`].includes(e.outcome)),openMemory:t})]}),r&&(0,x.jsxs)(`section`,{className:`detail-section`,"aria-label":`persona 变化`,children:[(0,x.jsx)(`h3`,{children:`persona 变化`}),(0,x.jsxs)(`p`,{children:[(0,x.jsx)(M,{tone:r.status===`published`?`green`:``,children:{published:`已发布`,pending:`待确认,当前版本保留`,rejected:`已拒绝,当前版本保留`,not_due:`尚未到更新条件`,skipped:`已跳过`,failed:`失败`,conflict:`版本或依据冲突`,running:`更新中`}[r.status]||r.status}),r.change_degree&&` · 变化程度:${L[r.change_degree]||r.change_degree}`]}),r.reason&&(0,x.jsx)(`p`,{children:ce(r.reason)}),r.version_id&&r.base_version_id?(0,x.jsxs)(`a`,{href:`#/persona?tab=history&version=${r.version_id}&before=${r.base_version_id}&after=${r.version_id}`,children:[`对比 persona v`,r.base_version_id,` → v`,r.version_id]}):(0,x.jsx)(`a`,{href:`#/persona?tab=attempts`,children:`查看 persona 生成记录`}),r.content&&(0,x.jsxs)(`details`,{children:[(0,x.jsx)(`summary`,{children:`查看候选正文与检查`}),(0,x.jsx)(`p`,{className:`persona-content`,children:r.content}),r.checks&&(0,x.jsx)(jt,{version:{checks:r.checks}})]})]}),(0,x.jsx)(Rt,{data:e}),(0,x.jsx)(Lt,{data:e})]})}function Bt({detail:e,busy:t,blocked:n,setBusy:r,saved:i,failed:a,openMemory:o,close:s}){let[c,u]=(0,l.useState)(null),d=t||n;async function f(){if(c&&!d){r(!0);try{i(await g(`/memories/${e.id}/annotations/${c.annotation.id}${c.kind===`confirm`?`/confirm`:``}`,_(c.kind===`confirm`?`POST`:`DELETE`,{expected_revision:c.revision}))),u(null)}catch(e){a(e)}finally{r(!1)}}}return(0,x.jsxs)(`section`,{className:`detail-section`,"aria-label":`整理建议`,children:[(0,x.jsxs)(`h3`,{children:[`整理建议 `,(0,x.jsx)(M,{children:`模型建议 · 仅管理员可见`})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`建议可能有误,请结合来源核对。未确认和已确认的建议都不会进入宿主召回。`}),!e.consolidation_annotations?.length&&(0,x.jsx)(`p`,{className:`quiet`,children:`暂无整理建议。`}),e.consolidation_annotations?.map(n=>(0,x.jsxs)(`article`,{className:`maintenance-item`,children:[(0,x.jsxs)(`div`,{className:`detail-badges`,children:[(0,x.jsx)(M,{tone:`warning`,children:n.report.suggestion_type===`merge_details`?xt:ae[n.kind]||n.kind}),(0,x.jsx)(M,{children:oe[n.review_status]}),n.modified_since_annotation&&(0,x.jsx)(M,{tone:`warning`,children:`标注后已修改`}),(0,x.jsxs)(`span`,{className:`muted`,children:[`建议 #`,n.id]})]}),n.report.suggestion_type===`merge_details`&&(0,x.jsx)(St,{details:n.report.unique_details,ids:n.report.detail_memory_ids||n.related_memory_ids,openMemory:o,disabled:t}),(0,x.jsx)(`p`,{className:`report-text`,children:n.text}),(0,x.jsxs)(`p`,{className:`muted`,children:[`标注时修订 `,n.memory_revision,` · `,(0,x.jsx)(P,{value:n.created_at})]}),n.confirmed_at&&(0,x.jsxs)(`p`,{children:[`管理员已确认 · `,(0,x.jsx)(P,{value:n.confirmed_at})]}),(0,x.jsxs)(`div`,{className:`actions`,children:[n.related_memory_ids.filter(t=>t!==e.id).map(e=>(0,x.jsxs)(`button`,{className:`text-button`,disabled:t,onClick:()=>o(e),children:[`相关记忆 #`,e]},e)),n.superseded_by!=null&&(0,x.jsxs)(`button`,{className:`text-button`,disabled:t,onClick:()=>o(n.superseded_by),children:[`建议的替代记忆 #`,n.superseded_by]})]}),n.report.reason&&(0,x.jsx)(`p`,{className:`report-text`,children:n.report.reason}),(0,x.jsx)(Ft,{value:n.report.source_excerpts,openMemory:o}),(0,x.jsxs)(`a`,{href:`#/status?run=${n.report.run_id}`,onClick:e=>{t?e.preventDefault():s()},children:[`查看整理报告 #`,n.report.run_id]}),(0,x.jsxs)(`div`,{className:`actions suggestion-actions`,children:[n.review_status===`pending`&&(0,x.jsxs)(`button`,{disabled:d||!!c,onClick:()=>u({kind:`confirm`,annotation:n,revision:e.revision}),children:[`采纳建议 #`,n.id]}),(0,x.jsxs)(`button`,{disabled:d||!!c,onClick:()=>u({kind:`clear`,annotation:n,revision:e.revision}),children:[`清除建议 #`,n.id]})]}),c?.annotation.id===n.id&&(0,x.jsxs)(`div`,{className:`delete-confirm`,role:`group`,"aria-label":`确认建议操作`,children:[(0,x.jsx)(`p`,{children:c.kind===`confirm`?n.report.suggestion_type===`merge_details`?`采纳只记录管理员确认,不执行合并,不改正文和相信程度;建议仍只对管理员可见。`:`采纳只记录管理员确认,不改正文和相信程度;建议仍只对管理员可见。`:`清除会撤下这条整理建议并保留操作记录,不改正文和相信程度。`}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`primary`,disabled:d,onClick:()=>void f(),children:c.kind===`confirm`?`确认采纳建议`:`确认清除建议`}),(0,x.jsx)(`button`,{disabled:t,onClick:()=>u(null),children:`取消建议操作`})]})]})]},n.id))]})}function Vt({notice:e}){return e?(0,x.jsx)(A,{children:e.message}):null}var U={memory_source:`仍是其他记忆的来源`,batch_segment:`等待或运行中的批次仍在使用`,goal_source:`仍是目标的来源`,subject_alias:`仍是主体别名的证据`,subject_link:`仍是主体联系的证据`,learning_request:`立即学习请求仍在使用`};function Ht({result:e}){return(0,x.jsxs)(`div`,{className:`lifecycle-stack`,children:[(0,x.jsxs)(A,{children:[`已彻底清除记忆 #`,e.memory_id]}),(0,x.jsx)(Vt,{notice:e.backup_notice}),(0,x.jsxs)(`section`,{children:[(0,x.jsx)(`h3`,{children:`已删除的来源消息`}),e.deleted_message_ids.length?(0,x.jsx)(`ul`,{children:e.deleted_message_ids.map(e=>(0,x.jsxs)(`li`,{children:[`消息 #`,e,` · 没有其他受保护的引用`]},e))}):(0,x.jsx)(`p`,{className:`quiet`,children:`没有删除来源消息。`})]}),(0,x.jsxs)(`section`,{children:[(0,x.jsx)(`h3`,{children:`被保留的来源消息及原因`}),e.retained_messages.length?(0,x.jsx)(`ul`,{children:e.retained_messages.map(e=>(0,x.jsxs)(`li`,{children:[`消息 #`,e.message_id,` ·`,` `,e.reasons.map(e=>U[e]||e).join(`;`)]},e.message_id))}):(0,x.jsx)(`p`,{className:`quiet`,children:`没有被保留的来源消息。`})]})]})}function Ut({detail:e,busy:t,blocked:n,setBusy:r,saved:i,failed:a,purged:o,recreated:s}){let[c,u]=(0,l.useState)(null),[d,f]=(0,l.useState)(!1),[p,m]=(0,l.useState)(``),[h,v]=(0,l.useState)(``),[y,b]=(0,l.useState)(``),[S,C]=(0,l.useState)(``),w=t||n,T=new Map;for(let t of e.revisions)T.set(t.revision_after,t.after);for(let t of e.revisions)T.set(t.revision_before,t.before);let E=T.get(Number(S));async function D(t,n={}){if(!w){r(!0);try{let r=`/memories/${e.id}/${t}`,a=_(t===`lifecycle`?`PATCH`:`POST`,{expected_revision:e.revision,...n});t===`purge`?o(await g(r,a)):t===`recreate`?s((await g(r,a)).id):i(await g(r,a)),u(null),f(!1)}catch(e){a(e)}finally{r(!1)}}}function O(t){if(t.preventDefault(),b(``),[p,h].some(e=>!e.trim()||!Number.isInteger(Number(e))||Number(e)<0||Number(e)>100)){b(`重要度和保留强度须为 0—100 的整数`);return}let n={};if(Number(p)!==e.importance&&(n.importance=Number(p)),Number(h)!==e.retention&&(n.retention=Number(h)),!Object.keys(n).length){u(null);return}D(`lifecycle`,n)}let k=()=>{u(null),f(!1),b(``)};return(0,x.jsxs)(`section`,{className:`detail-section lifecycle-stack`,"aria-label":`生命周期操作`,children:[(0,x.jsx)(`h3`,{children:`生命周期操作`}),!c&&(0,x.jsxs)(`div`,{className:`actions`,children:[e.lifecycle!==`deleted`&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`button`,{className:`secondary`,disabled:w,onClick:()=>void D(`lifecycle`,{pinned:!e.pinned}),children:e.pinned?`取消置顶`:`置顶记忆`}),e.lifecycle===`forgotten`?(0,x.jsx)(`button`,{className:`secondary`,disabled:w,onClick:()=>void D(`restore`),children:`恢复记忆`}):(0,x.jsx)(`button`,{className:`secondary`,disabled:w,onClick:()=>u(`forget`),children:`手动遗忘`}),(0,x.jsx)(`button`,{className:`secondary`,disabled:w,onClick:()=>{u(`scores`),m(String(e.importance)),v(String(e.retention))},children:`调整分数`})]}),(0,x.jsx)(`button`,{className:`secondary`,disabled:w||!T.size,onClick:()=>{C(``),u(`recreate`)},children:`按旧内容新建`}),(0,x.jsx)(`button`,{className:`text-button danger-text`,disabled:w,onClick:()=>u(`purge`),children:`彻底清除`})]}),!T.size&&(0,x.jsx)(`p`,{className:`fine-print`,children:`尚无历史修订可用于“按旧内容新建”。`}),!!e.pinned&&e.lifecycle!==`deleted`&&(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`置顶记忆不自动衰减、遗忘、扣减或删除。置顶不会自动恢复已遗忘的记忆。`}),c===`scores`&&(0,x.jsx)(`form`,{onSubmit:O,noValidate:!0,children:(0,x.jsxs)(`fieldset`,{className:`lifecycle-fieldset`,disabled:w,children:[(0,x.jsxs)(`div`,{className:`form-grid`,children:[(0,x.jsxs)(`label`,{children:[`调整重要度`,(0,x.jsx)(`input`,{type:`number`,min:0,max:100,step:1,required:!0,value:p,onChange:e=>m(e.target.value)})]}),(0,x.jsxs)(`label`,{children:[`调整保留强度`,(0,x.jsx)(`input`,{type:`number`,min:0,max:100,step:1,required:!0,value:h,onChange:e=>v(e.target.value)})]})]}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`保留强度调整会按当前阈值判断遗忘或恢复。`}),y&&(0,x.jsx)(A,{error:!0,children:y}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`primary`,children:`保存分数`}),(0,x.jsx)(`button`,{className:`secondary`,type:`button`,onClick:k,children:`取消调整`})]})]})}),c===`forget`&&(0,x.jsxs)(`div`,{className:`delete-confirm`,children:[(0,x.jsx)(`p`,{children:`确认手动遗忘?保留强度会降至遗忘阈值以下,并取消置顶;此后只参与深度召回。恢复时不会重新置顶。`}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`primary`,disabled:w,onClick:()=>void D(`forget`),children:`确认遗忘`}),(0,x.jsx)(`button`,{className:`secondary`,disabled:t,onClick:k,children:`取消遗忘`})]})]}),c===`purge`&&(0,x.jsxs)(`div`,{className:`purge-confirm`,children:[(0,x.jsx)(`h3`,{children:`彻底清除不可撤销`}),(0,x.jsx)(`p`,{children:`将删除记忆正文、修订历史,以及只被这条记忆引用且没有其他受保护引用的来源消息。其他引用仍需要的消息会保留,执行后显示消息标识与原因。`}),(0,x.jsx)(`p`,{children:`同时清空可关联的模型原始输出等正文副本。`}),(0,x.jsx)(Vt,{notice:e.purge_preview?.backup_notice}),(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:d,disabled:w,onChange:e=>f(e.target.checked)}),`我理解此操作不可撤销`]}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`danger-button`,disabled:w||!d,onClick:()=>void D(`purge`,{confirm:!0}),children:`再次确认并彻底清除`}),(0,x.jsx)(`button`,{className:`secondary`,disabled:t,onClick:k,children:`取消清除`})]})]}),c===`recreate`&&(0,x.jsxs)(`div`,{className:`lifecycle-stack`,children:[(0,x.jsxs)(`label`,{children:[`选择历史修订`,(0,x.jsxs)(`select`,{disabled:w,value:S,onChange:e=>C(e.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`请选择修订`}),[...T.keys()].sort((e,t)=>t-e).map(e=>(0,x.jsxs)(`option`,{value:e,children:[`修订 `,e]},e))]})]}),E&&(0,x.jsxs)(`div`,{className:`revision`,"data-testid":`revision-preview`,children:[(0,x.jsx)(`p`,{children:String(E.content??``)}),(0,x.jsxs)(`small`,{children:[`相信程度 `,String(E.belief??e.belief),` · 重要度`,` `,String(E.importance??e.importance)]})]}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`新建使用新标识,原记忆保持原状。正文和判断取所选修订,涉及人物、标签和来源沿用当前保存的关系;不继承置顶、遗忘时间或向量。`}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`primary`,disabled:w||!E,onClick:()=>void D(`recreate`,{source_revision:Number(S)}),children:`确认新建`}),(0,x.jsx)(`button`,{className:`secondary`,disabled:t,onClick:k,children:`取消新建`})]})]})]})}function Wt({version:e,openMemory:t,onChange:n}){let[r,i]=(0,l.useState)(0),a=y(`/memories/upcoming-deletion?limit=30&offset=${r}`),[o,s]=(0,l.useState)(null),[c,u]=(0,l.useState)(``),[d,p]=(0,l.useState)(``),[m,h]=(0,l.useState)(!1);(0,l.useEffect)(()=>{a.refresh()},[e,a.refresh]),(0,l.useEffect)(()=>{a.data&&r&&r>=a.data.total&&i(Math.max(0,Math.ceil(a.data.total/30)*30-30))},[a.data,r]);async function b(e){if(!(o!==null||m||a.loading||a.error)){s(e.id),u(``),p(``);try{await g(`/memories/${e.id}/restore`,_(`POST`,{expected_revision:e.revision})),p(`已恢复记忆 #${e.id}`),a.refresh(),n()}catch(e){e instanceof f&&(e.status===409||e.status===404)?(h(!0),u(`这条记忆已变化或已被删除,请刷新列表后再操作。`)):u(v(e))}finally{s(null)}}}return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:`即将删除`}),(0,x.jsx)(`button`,{className:`secondary`,disabled:o!==null,onClick:()=>{h(!1),u(``),a.refresh()},children:`刷新列表`})]}),(0,x.jsx)(`p`,{className:`learning-intro`,children:`包括遗忘期将满和已到期等待维护的记忆;置顶记忆不自动删除。到期后由维护执行删除,可以在此提前恢复。`}),(c||a.error)&&(0,x.jsx)(A,{error:!0,children:c||a.error}),d&&(0,x.jsx)(A,{children:d}),!a.data&&!a.error&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取即将删除的记忆…`}),a.data&&!a.data.enabled&&(0,x.jsxs)(A,{children:[`自动删除已关闭,当前没有即将删除的记忆。`,(0,x.jsx)(`a`,{href:`#/settings`,children:`前往生命周期设置`})]}),a.data?.enabled&&!a.data.items.length&&(0,x.jsx)(j,{title:`暂无即将删除的记忆`}),(0,x.jsx)(`div`,{className:`memory-grid`,children:a.data?.items.map(e=>(0,x.jsxs)(`article`,{className:`panel upcoming-card`,children:[(0,x.jsxs)(`div`,{className:`memory-card-top`,children:[(0,x.jsx)(M,{children:`已遗忘`}),(0,x.jsxs)(`span`,{className:`muted`,children:[`#`,e.id,` · 保留强度 `,e.retention]})]}),(0,x.jsx)(`button`,{className:`memory-preview`,onClick:()=>t(e.id),children:e.content}),(0,x.jsxs)(`p`,{children:[`遗忘时间:`,w(e.forgotten_at)]}),(0,x.jsxs)(`p`,{children:[`删除到期时间:`,w(e.delete_after)]}),(0,x.jsx)(`button`,{className:`secondary`,"aria-label":`恢复记忆 #${e.id}`,disabled:o!==null||m||a.loading||!!a.error,onClick:()=>void b(e),children:o===e.id?`正在恢复…`:`恢复记忆`})]},e.id))}),a.data&&(0,x.jsx)(T,{total:a.data.total,offset:r,change:i})]})}var Gt=[`事件`,`事实`,`偏好`,`关系`,`观点`,`计划`,`自我`,`其他`];function Kt({openMemory:e,version:t,onChange:n,initialQuery:r}){let[i,a]=(0,l.useState)(`all`);return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{className:`page-heading`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`p`,{className:`eyebrow`,children:`留下的经历,有迹可循`}),(0,x.jsx)(`h1`,{children:`记忆`}),(0,x.jsx)(`p`,{children:`查看内容、追溯来源,管理记忆的保留与遗忘。`})]})}),(0,x.jsxs)(`div`,{className:`learning-tabs`,"aria-label":`记忆视图`,children:[(0,x.jsx)(`button`,{"aria-pressed":i===`all`,onClick:()=>a(`all`),children:`记忆列表`}),(0,x.jsx)(`button`,{"aria-pressed":i===`upcoming`,onClick:()=>a(`upcoming`),children:`即将删除`})]}),i===`all`?(0,x.jsx)(qt,{openMemory:e,version:t,initialQuery:r}):(0,x.jsx)(Wt,{openMemory:e,version:t,onChange:n})]})}function qt({openMemory:e,version:t,initialQuery:n=``}){let r=y(`/catalog`),i=new URLSearchParams(n),[a,o]=(0,l.useState)({text:``,person_id:i.get(`person_id`)||``,kind:``,entry_id:``,time_from:``,time_to:``,lifecycle:i.get(`lifecycle`)===`all`?`all`:`active`,pinned:``,sort:`time`}),[s,c]=(0,l.useState)(()=>new URLSearchParams(Object.entries(a).filter(([,e])=>!!e)).toString()),[u,d]=(0,l.useState)(0),[f,p]=(0,l.useState)(``),m=y(`/memories?${s}&limit=30&offset=${u}`);(0,l.useEffect)(()=>{m.refresh()},[t,m.refresh]),(0,l.useEffect)(()=>{m.data&&u&&u>=m.data.total&&d(Math.max(0,Math.ceil(m.data.total/30)*30-30))},[m.data,u]);function h(e){if(e.preventDefault(),a.time_from&&a.time_to&&a.time_from>a.time_to){p(`开始日期不能晚于结束日期`);return}p(``),d(0),c(new URLSearchParams(Object.entries(a).filter(([,e])=>!!e)).toString()),m.refresh()}let g=(e,t)=>o({...a,[e]:t});return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`section`,{className:`panel`,children:(0,x.jsxs)(`form`,{className:`memory-filters`,onSubmit:h,children:[(0,x.jsxs)(`div`,{className:`search-row`,children:[(0,x.jsxs)(`label`,{className:`search-field`,children:[`搜索记忆`,(0,x.jsx)(`input`,{value:a.text,maxLength:1e3,placeholder:`输入正文或标签中的词…`,onChange:e=>g(`text`,e.target.value)})]}),(0,x.jsx)(`button`,{className:`primary`,type:`submit`,children:`搜索`})]}),(0,x.jsxs)(`div`,{className:`filter-grid`,children:[(0,x.jsxs)(`label`,{children:[`涉及的人`,(0,x.jsxs)(`select`,{value:a.person_id,onChange:e=>g(`person_id`,e.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`全部人物`}),r.data?.people.map(e=>(0,x.jsxs)(`option`,{value:e.id,children:[e.name,(r.data?.people.filter(t=>t.name===e.name).length||0)>1?` · ${e.id.slice(0,6)}`:``]},e.id))]})]}),(0,x.jsxs)(`label`,{children:[`记忆类型`,(0,x.jsxs)(`select`,{value:a.kind,onChange:e=>g(`kind`,e.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`全部类型`}),Gt.map(e=>(0,x.jsx)(`option`,{children:e},e))]})]}),(0,x.jsxs)(`label`,{children:[`出处入口`,(0,x.jsxs)(`select`,{value:a.entry_id,onChange:e=>g(`entry_id`,e.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`全部入口`}),r.data?.entries.map(e=>(0,x.jsx)(`option`,{value:e.id,children:e.name},e.id))]})]}),(0,x.jsxs)(`label`,{children:[`状态`,(0,x.jsxs)(`select`,{value:a.lifecycle,onChange:e=>g(`lifecycle`,e.target.value),children:[(0,x.jsx)(`option`,{value:`active`,children:`有效`}),(0,x.jsx)(`option`,{value:`forgotten`,children:`已遗忘`}),(0,x.jsx)(`option`,{value:`deleted`,children:`已删除(历史)`}),(0,x.jsx)(`option`,{value:`all`,children:`全部状态`})]})]}),(0,x.jsxs)(`label`,{children:[`置顶筛选`,(0,x.jsxs)(`select`,{"aria-label":`置顶筛选`,value:a.pinned,onChange:e=>g(`pinned`,e.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`全部`}),(0,x.jsx)(`option`,{value:`true`,children:`已置顶`}),(0,x.jsx)(`option`,{value:`false`,children:`未置顶`})]})]}),(0,x.jsxs)(`label`,{children:[`开始日期`,(0,x.jsx)(`input`,{type:`date`,value:a.time_from,onChange:e=>g(`time_from`,e.target.value)})]}),(0,x.jsxs)(`label`,{children:[`结束日期`,(0,x.jsx)(`input`,{type:`date`,value:a.time_to,onChange:e=>g(`time_to`,e.target.value)})]}),(0,x.jsxs)(`label`,{children:[`排序方式`,(0,x.jsxs)(`select`,{value:a.sort,onChange:e=>g(`sort`,e.target.value),children:[(0,x.jsx)(`option`,{value:`time`,children:`更新时间 · 从新到旧`}),(0,x.jsx)(`option`,{value:`relevance`,children:`文本相关度`}),(0,x.jsx)(`option`,{value:`retention`,children:`保留强度 · 从高到低`})]})]})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`日期按事件时间筛选;没有事件时间时使用创建时间。`})]})}),f&&(0,x.jsx)(A,{error:!0,children:f}),(m.error||r.error)&&(0,x.jsx)(A,{error:!0,children:m.error||r.error}),(0,x.jsxs)(`div`,{className:`list-heading`,children:[(0,x.jsx)(`span`,{children:m.data?`共 ${m.data.total} 条`:`正在读取…`}),(0,x.jsx)(`span`,{children:`浏览列表不会增加召回或使用次数`})]}),m.data?.items.length===0&&(0,x.jsx)(`section`,{className:`panel`,children:(0,x.jsx)(j,{title:`没有找到记忆`,children:`尝试换一个词,或调整筛选条件。`})}),(0,x.jsx)(`div`,{className:`memory-grid`,children:m.data?.items.map(t=>(0,x.jsxs)(`button`,{className:`memory-card panel`,onClick:()=>e(t.id),children:[(0,x.jsxs)(`div`,{className:`memory-card-top`,children:[(0,x.jsx)(M,{tone:`purple`,children:t.kind}),(0,x.jsx)(M,{tone:t.pinned?`purple`:``,children:t.pinned?`已置顶`:`未置顶`}),(0,x.jsxs)(`span`,{className:`muted`,children:[`#`,t.id,` · `,E(t.lifecycle)]})]}),(0,x.jsx)(`p`,{className:`memory-content`,children:t.content}),(0,x.jsx)(`div`,{className:`person-line`,children:t.about.map(e=>e.name).join(`、`)||`未标注涉及人物`}),(0,x.jsxs)(`div`,{className:`memory-card-bottom`,children:[(0,x.jsxs)(`span`,{children:[`相信 `,t.belief,` · 保留强度 `,t.retention]}),(0,x.jsx)(`time`,{children:S(t.updated_at)}),(0,x.jsx)(`span`,{"aria-hidden":!0,children:`↗`})]})]},t.id))}),m.data&&(0,x.jsx)(T,{total:m.data.total,offset:u,change:d})]})}function Jt({id:e,onClose:t,onChange:n,openMemory:r}){let i=y(`/memories/${e}`),a=y(`/catalog`),[o,s]=(0,l.useState)(null),[c,u]=(0,l.useState)(!1),[d,p]=(0,l.useState)(``),[m,h]=(0,l.useState)(!1),[b,C]=(0,l.useState)(``),[T,D]=(0,l.useState)(!1),[O,k]=(0,l.useState)(!1),[j,P]=(0,l.useState)(null),[F,I]=(0,l.useState)(0),L=j?null:o||i.data,ee=e=>{O||r(e)};function te(e){e instanceof f&&e.code===`revision_conflict`?(D(!0),C(`其他操作已更新了这条记忆。草稿暂时保留;请刷新并载入最新修订,再核对后操作。载入会替换当前草稿。`)):e instanceof f&&e.status===404?(D(!0),C(`这条记忆已删除或已彻底清除,请刷新或返回列表查看。`)):C(v(e))}async function ne(t){if(t.preventDefault(),!(!L||O||T)){k(!0),C(``);try{s(await g(`/memories/${e}`,_(`PATCH`,{expected_revision:L.revision,content:d}))),u(!1),D(!1),n()}catch(e){te(e)}finally{k(!1)}}}async function re(){if(!(!L||O||T)){k(!0),C(``);try{s(await g(`/memories/${e}`,_(`DELETE`,{expected_revision:L.revision}))),h(!1),I(e=>e+1),u(!1),n()}catch(e){te(e)}finally{k(!1)}}}async function ie(){k(!0);try{let t=await g(`/memories/${e}`);s(t),p(t.content),I(e=>e+1),D(!1),C(``),h(!1)}catch(e){te(e)}finally{k(!1)}}return(0,x.jsxs)(N,{title:`记忆 #${e}`,onClose:t,closeDisabled:O,children:[(b||i.error)&&(0,x.jsx)(A,{error:!0,children:b||i.error}),T&&(0,x.jsx)(`button`,{className:`secondary`,disabled:O,onClick:ie,children:`载入最新修订`}),j&&(0,x.jsx)(Ht,{result:j}),!L&&!j&&!i.error&&(0,x.jsx)(`p`,{className:`quiet`,children:`正在读取详情…`}),L&&(0,x.jsxs)(`div`,{className:`memory-detail`,children:[(0,x.jsxs)(`div`,{className:`detail-badges`,children:[(0,x.jsx)(M,{tone:`purple`,children:L.kind}),(0,x.jsx)(M,{children:L.stance}),(0,x.jsx)(M,{tone:L.lifecycle===`deleted`?`danger`:``,children:E(L.lifecycle)}),(0,x.jsx)(M,{tone:L.pinned?`purple`:``,children:L.pinned?`已置顶`:`未置顶`}),(0,x.jsxs)(`span`,{className:`muted`,children:[`修订 `,L.revision]})]}),L.merged_into!=null&&(0,x.jsxs)(A,{children:[(0,x.jsxs)(`button`,{className:`text-button`,disabled:O,onClick:()=>ee(L.merged_into),children:[`已合并到 #`,L.merged_into]}),(0,x.jsx)(`p`,{children:`全部来源已归入保留记忆;此处是原记忆占位,不能恢复为有效记忆。`})]}),L.lifecycle===`deleted`&&L.merged_into==null&&(0,x.jsx)(A,{children:`此标识已撤销,不再参与召回;来源和修订历史仍然保留。`}),c&&L.lifecycle!==`deleted`?(0,x.jsxs)(`form`,{onSubmit:ne,children:[(0,x.jsxs)(`label`,{children:[`记忆正文`,(0,x.jsx)(`textarea`,{value:d,maxLength:1e3,rows:5,onChange:e=>p(e.target.value)})]}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`primary`,disabled:O||T||!d.trim(),children:`保存修改`}),(0,x.jsx)(`button`,{type:`button`,className:`secondary`,disabled:O,onClick:()=>u(!1),children:`取消编辑`}),(0,x.jsxs)(`small`,{children:[d.length,` / 1000 字`]})]})]}):(0,x.jsx)(`p`,{className:`detail-content`,children:L.content}),(0,x.jsxs)(`div`,{className:`score-grid`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`strong`,{children:L.belief}),(0,x.jsx)(`span`,{children:`相信程度`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`strong`,{children:L.importance}),(0,x.jsx)(`span`,{children:`重要度`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`strong`,{children:L.retention}),(0,x.jsx)(`span`,{children:`保留强度`})]})]}),(0,x.jsx)(Ut,{detail:L,busy:O,blocked:T||c||m,setBusy:k,failed:te,saved:e=>{s(e),C(``),n()},purged:e=>{P(e),s(null),C(``),n()},recreated:e=>{n(),r(e)}},`${L.id}:${L.revision}:${F}`),(0,x.jsxs)(`dl`,{className:`metadata`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`记忆可见范围`}),(0,x.jsx)(`dd`,{children:Ke(L.visibility,a.data?.entries||[])})]}),L.lifecycle===`forgotten`&&(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`遗忘时间`}),(0,x.jsx)(`dd`,{children:w(L.forgotten_at)})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`说话人`}),(0,x.jsx)(`dd`,{children:L.speaker.name})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`涉及的人`}),(0,x.jsx)(`dd`,{children:L.about.map(e=>e.name).join(`、`)||`未标注`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`事件时间`}),(0,x.jsx)(`dd`,{children:L.event_time||`未标注`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`更新时间`}),(0,x.jsx)(`dd`,{children:S(L.updated_at)})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`被召回`}),(0,x.jsxs)(`dd`,{children:[L.recall_count,` 次`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`被使用`}),(0,x.jsxs)(`dd`,{children:[L.used_count,` 次`]})]})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`被召回不等于被使用;使用次数不代表内容可信度。`}),!!L.tags.length&&(0,x.jsx)(`div`,{className:`tag-list`,children:L.tags.map(e=>(0,x.jsxs)(M,{children:[`# `,e]},e))}),(0,x.jsx)(Bt,{detail:L,busy:O,blocked:T||c||m,setBusy:k,saved:e=>{s(e),C(``),n()},failed:te,openMemory:ee,close:t},`suggestions-${L.id}:${L.revision}:${F}`),(0,x.jsxs)(`section`,{className:`detail-section`,children:[(0,x.jsx)(`h3`,{children:`来源与前后文`}),L.sources.length?L.sources.map(e=>(0,x.jsx)(Yt,{source:e,openMemory:ee},e.id)):(0,x.jsx)(`p`,{className:`quiet`,children:`没有保存的来源消息。`})]}),(0,x.jsxs)(`section`,{className:`detail-section`,children:[(0,x.jsx)(`h3`,{children:`基于它形成的记忆`}),L.derived_memories.length?L.derived_memories.map(e=>(0,x.jsxs)(`button`,{className:`memory-preview`,disabled:O,onClick:()=>ee(e.id),children:[(0,x.jsxs)(`span`,{children:[`#`,e.id,` · `,e.content]}),(0,x.jsxs)(`small`,{children:[E(e.lifecycle),e.needs_review?` · 来源已变化,待复核`:``]})]},e.id)):(0,x.jsx)(`p`,{className:`quiet`,children:`暂无派生记忆。`})]}),(0,x.jsxs)(`details`,{className:`history`,children:[(0,x.jsxs)(`summary`,{children:[`修订历史 `,(0,x.jsx)(M,{children:L.revisions.length})]}),L.revisions.length?L.revisions.map(e=>(0,x.jsx)(Xt,{revision:e},e.id)):(0,x.jsx)(`p`,{className:`quiet`,children:`还没有修订记录。`})]}),(0,x.jsx)(`a`,{className:`operation-link`,href:`#/operations?object_type=memory&object_id=${e}`,onClick:e=>{O?e.preventDefault():t()},children:`查看此记忆的操作记录`}),L.lifecycle!==`deleted`&&(0,x.jsx)(`div`,{className:`detail-footer`,children:m?(0,x.jsxs)(`div`,{className:`delete-confirm`,children:[(0,x.jsx)(`p`,{children:`确认删除这条记忆?此标识将永久撤销,共享的来源消息与其他记忆保留。`}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`danger-button`,disabled:O||T,onClick:re,children:`确认删除`}),(0,x.jsx)(`button`,{className:`secondary`,disabled:O,onClick:()=>h(!1),children:`取消`})]})]}):(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`secondary`,disabled:O||T||c,onClick:()=>{u(!0),p(L.content),C(``)},children:`编辑正文`}),(0,x.jsx)(`button`,{className:`text-button danger-text`,disabled:O||T||c,onClick:()=>h(!0),children:`删除记忆`})]})})]})]})}function Yt({source:e,openMemory:t,initiallyOpen:n=!1,speakerNames:r={}}){return(0,x.jsxs)(`details`,{className:`source`,open:n||void 0,children:[(0,x.jsx)(`summary`,{children:e.kind===`message`?`来源消息 · ${e.message?.sender_name||`原文已不可用`}`:e.kind===`memory`?`来源记忆 #${e.memory?.id||``}`:`初始背景`}),e.message&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{className:`muted`,children:[e.message.entry_name||e.message.entry_id,` ·`,` `,S(e.message.occurred_at)]}),(0,x.jsx)(`blockquote`,{children:e.message.content}),e.message.quote_content&&(0,x.jsxs)(`blockquote`,{children:[`转引原话(原作者:`,r[e.message.quote_author_subject_id||``]||e.message.quote_author_subject_id||`未记录`,`):`,e.message.quote_content]}),(0,x.jsx)(Le,{media:e.message.media}),(0,x.jsxs)(`details`,{className:`source-context`,children:[(0,x.jsx)(`summary`,{children:`查看前后文`}),e.context?.map(t=>(0,x.jsxs)(`div`,{className:`context-message ${t.id===e.message_id?`highlight`:``}`,children:[(0,x.jsxs)(`small`,{children:[t.sender_name,` · `,S(t.occurred_at)]}),(0,x.jsx)(`p`,{children:t.content}),(0,x.jsx)(Le,{media:t.media})]},t.id))]})]}),e.memory&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`button`,{className:`memory-preview`,onClick:()=>t(e.memory.id),children:e.memory.content}),(0,x.jsxs)(`p`,{className:`fine-print`,children:[`依据修订 `,e.source_revision,` · `,E(e.memory.lifecycle),e.needs_review?` · 来源已变化,待复核`:``]})]}),e.kind===`initial_setting`&&(0,x.jsx)(`p`,{children:e.note||`角色初始背景材料`})]})}function Xt({revision:e}){return(0,x.jsxs)(`article`,{className:`revision`,children:[(0,x.jsxs)(`small`,{children:[S(e.created_at),` ·`,` `,{admin:`管理员`,learning:`学习`,maintenance:`维护`,entry_profile:`画像学习`}[e.actor]||e.actor,` `,`· 修订 `,e.revision_before,` → `,e.revision_after]}),(0,x.jsxs)(`p`,{children:[(0,x.jsx)(`span`,{className:`muted`,children:`修改前`}),` `,String(e.before.content||``)]}),(0,x.jsxs)(`p`,{className:`muted`,children:[`相信程度 `,String(e.before.belief??`—`),` →`,` `,String(e.after.belief??`—`),` · 重要度`,` `,String(e.before.importance??`—`),` →`,` `,String(e.after.importance??`—`)]}),(0,x.jsxs)(`p`,{children:[(0,x.jsx)(`span`,{className:`muted`,children:`修改后`}),` `,e.after.lifecycle===`deleted`?`已删除(撤销对象)`:String(e.after.content||``)]})]})}function Zt({goal:e,openMemory:t}){let[n,r]=(0,l.useState)(0),i=y(`/goals/${e.id}/sources?limit=30&offset=${n}`);return(0,x.jsxs)(`section`,{className:`panel goals-panel`,"aria-label":`来源消息`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:`来源消息`}),(0,x.jsx)(`button`,{className:`text-button`,onClick:i.refresh,children:`刷新来源消息`})]}),(0,x.jsx)(`p`,{className:`goal-help`,children:`前后文来自同一入口的相邻消息,只读查看不会成为新经历。`}),i.error&&(0,x.jsxs)(A,{error:!0,children:[i.error,(0,x.jsx)(`button`,{onClick:i.refresh,children:`重试来源消息`})]}),!i.data&&!i.error&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取来源消息…`}),i.data?.total===0&&(0,x.jsx)(`p`,{className:`goal-help`,children:`没有关联来源消息。宿主和管理员创建的目标可以没有对话依据。`}),i.data?.items.map(e=>(0,x.jsx)(`div`,{children:e.missing||!e.message?(0,x.jsxs)(`div`,{className:`source`,children:[(0,x.jsxs)(`p`,{children:[`来源消息 #`,e.message_id]}),(0,x.jsx)(`p`,{className:`goal-help`,children:e.notice||`来源消息已清理或不可用`})]}):(0,x.jsx)(Yt,{source:{id:e.id,kind:`message`,message_id:e.message_id,message:e.message,context:e.context},openMemory:t})},e.id)),i.data&&(0,x.jsx)(T,{total:i.data.total,offset:n,change:r})]})}var Qt={content:`正文`,deadline:`截止时间`,deadline_at:`截止时刻`,reminder_minutes:`提醒提前量`,state:`状态`,kind:`类型`,origin:`来源`,entry_id:`产生入口`,people:`涉及的人`,closed_at:`结束时间`,closed_by:`结束操作者`,merged_into:`合并到目标`,source_message_ids:`来源消息`,promise_memories:`承诺记忆及依据修订`,merged_goal_ids:`合并进来的目标`,duplicates:`可能重复关系`,basis_annotations:`依据复核标注`},$t={create:`创建目标`,update:`更新目标`,merge:`合并目标`,duplicate_dismiss:`驳回重复`,possible_duplicate:`标记可能重复`,basis_clear:`清除依据标注`,basis_review:`复核目标依据`,dedup:`目标去重判断`},en={"goal created":`创建目标`,"goal updated":`更新目标`,"goals merged":`合并目标`,"possible duplicate identified":`发现可能重复的目标`,"possible duplicate dismissed":`驳回可能重复关系`,"goal basis reviewed":`复核目标依据`,"basis warning cleared by administrator":`管理员清除依据标注`},tn={possible:`可能重复`,dismissed:`已驳回`,merged:`已合并`,active:`生效`,cleared:`已清除`,superseded:`已被新标注替代`,resolved:`依据已恢复或移除`};function nn({field:e,value:t,catalog:n}){return t===void 0?(0,x.jsx)(x.Fragment,{children:`未记录`}):t===null?(0,x.jsx)(x.Fragment,{children:e===`reminder_minutes`?`使用默认值`:`未设置`}):(e===`deadline`||e===`closed_at`)&&typeof t==`string`?(0,x.jsx)(P,{value:t}):e===`reminder_minutes`?(0,x.jsxs)(x.Fragment,{children:[String(t),` 分钟`]}):e===`people`&&Array.isArray(t)?(0,x.jsx)(x.Fragment,{children:t.map(e=>lt(String(e),n)).join(`、`)||`无`}):e===`entry_id`?(0,x.jsx)(x.Fragment,{children:ut(String(t),n)}):e===`state`?(0,x.jsx)(x.Fragment,{children:rt[t]||String(t)}):e===`kind`?(0,x.jsx)(x.Fragment,{children:it[t]||String(t)}):e===`origin`?(0,x.jsx)(x.Fragment,{children:at[t]||String(t)}):e===`closed_by`?(0,x.jsx)(x.Fragment,{children:me[String(t)]||String(t)}):Array.isArray(t)?(0,x.jsx)(x.Fragment,{children:t.map(e=>typeof e==`object`&&e&&`memory_id`in e?`记忆 #${e.memory_id}(依据修订 ${e.memory_revision})`:`#${e}`).join(`、`)||`无`}):typeof t==`object`?(0,x.jsx)(x.Fragment,{children:Object.entries(t).map(([e,t])=>`#${e}:${tn[String(t)]||String(t)}`).join(`;`)||`无`}):(0,x.jsx)(x.Fragment,{children:String(t)})}function rn({id:e,catalog:t}){let[n,r]=(0,l.useState)(0),[i,a]=(0,l.useState)(0),o=y(`/goals/${e}/revisions?limit=30&offset=${n}`),s=y(`/operations?object_type=goal&object_id=${e}&limit=30&offset=${i}`);return(0,x.jsxs)(`section`,{className:`panel goals-panel`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:`修订与操作记录`}),(0,x.jsx)(`button`,{className:`text-button`,onClick:()=>{o.refresh(),s.refresh()},children:`刷新目标记录`})]}),(0,x.jsxs)(`section`,{"aria-label":`修订历史`,children:[(0,x.jsx)(`h3`,{children:`修订历史`}),(0,x.jsx)(`p`,{className:`goal-help`,children:`每次仅展示发生变化的字段;依据标注和重复关系的变化也会留下修订。`}),o.error&&(0,x.jsxs)(A,{error:!0,children:[o.error,(0,x.jsx)(`button`,{onClick:o.refresh,children:`重试修订历史`})]}),!o.data&&!o.error&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取修订历史…`}),o.data?.history_status===`pre_migration_no_snapshot`&&(0,x.jsxs)(A,{children:[`迁移前无快照:截至修订 `,o.data.missing_through_revision,` `,`的历史值无法还原。`]}),o.data?.items.length===0&&(0,x.jsx)(`p`,{className:`goal-help`,children:`暂无修订快照。`}),o.data?.items.map(e=>(0,x.jsxs)(`article`,{className:`goal-operation`,children:[(0,x.jsxs)(`h4`,{children:[$t[e.action]||pe[`goal_${e.action}`]||e.action,` `,`·`,` `,e.revision_before==null?`新建`:`修订 ${e.revision_before}`,` `,`→ `,e.revision_after]}),(0,x.jsxs)(`p`,{children:[(0,x.jsx)(P,{value:e.created_at}),` ·`,` `,me[e.actor]||e.actor]}),(0,x.jsx)(`p`,{className:`report-text`,children:en[e.reason]||e.reason}),(0,x.jsx)(`dl`,{className:`revision-values`,children:Array.from(new Set([...Object.keys(e.before),...Object.keys(e.after)])).map(n=>(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:Qt[n]||n}),(0,x.jsxs)(`dd`,{children:[(0,x.jsx)(`span`,{className:`muted`,children:`修改前`}),(0,x.jsx)(`p`,{children:(0,x.jsx)(nn,{field:n,value:e.before[n],catalog:t})})]}),(0,x.jsxs)(`dd`,{children:[(0,x.jsx)(`span`,{className:`muted`,children:`修改后`}),(0,x.jsx)(`p`,{children:(0,x.jsx)(nn,{field:n,value:e.after[n],catalog:t})})]})]},n))})]},e.id)),o.data&&(0,x.jsx)(T,{total:o.data.total,offset:n,change:r})]}),(0,x.jsxs)(`details`,{className:`goal-operations`,children:[(0,x.jsx)(`summary`,{children:`操作记录`}),s.error&&(0,x.jsx)(A,{error:!0,children:s.error}),!s.data&&!s.error&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取操作记录…`}),s.data?.items.length===0&&(0,x.jsx)(`p`,{className:`goal-help`,children:`暂无操作记录。`}),s.data?.items.map(e=>(0,x.jsxs)(`article`,{className:`goal-operation`,children:[(0,x.jsx)(`h3`,{children:pe[e.action]||e.action}),(0,x.jsxs)(`p`,{children:[(0,x.jsx)(P,{value:e.created_at}),` ·`,` `,me[e.actor]||e.actor]}),typeof e.details.revision_before==`number`&&(0,x.jsxs)(`p`,{children:[`修改前修订 `,e.details.revision_before]}),Array.isArray(e.details.fields)&&(0,x.jsxs)(`p`,{children:[`修改字段:`,e.details.fields.map(e=>Qt[String(e)]||String(e)).join(`、`)]}),typeof e.details.merged_id==`number`&&(0,x.jsxs)(`p`,{children:[`合并进来的目标 #`,e.details.merged_id]}),typeof e.details.other_id==`number`&&(0,x.jsxs)(`p`,{children:[`驳回与目标 #`,e.details.other_id,` 的可能重复关系`]}),e.action===`goal_create`&&(0,x.jsx)(`p`,{children:`已创建目标。`})]},e.id)),s.data&&(0,x.jsx)(T,{total:s.data.total,offset:i,change:a})]}),(0,x.jsx)(`a`,{className:`text-button`,href:`#/operations?object_type=goal&object_id=${e}`,children:`查看完整操作记录`})]})}function an({goal:e,otherId:t,locked:n,catalog:r,openGoal:i,merge:a,dismiss:o}){let s=y(`/goals/${t}`);return(0,x.jsxs)(`article`,{className:`goal-duplicate`,children:[(0,x.jsxs)(`h3`,{children:[`可能重复的目标 #`,t]}),s.error&&(0,x.jsxs)(A,{error:!0,children:[s.error,(0,x.jsx)(`button`,{onClick:s.refresh,children:`重试读取重复目标`})]}),!s.data&&!s.error&&(0,x.jsx)(`p`,{children:`正在读取…`}),s.data&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`p`,{className:`goal-content`,children:s.data.content}),(0,x.jsx)(dt,{goal:s.data}),(0,x.jsx)(pt,{goal:s.data,catalog:r}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsxs)(`button`,{className:`secondary`,onClick:()=>i(t),children:[`查看目标 #`,t]}),(0,x.jsxs)(`button`,{disabled:n||s.loading||!!s.error||e.state!==`open`||s.data.state!==`open`||!!s.data.merged_into,onClick:()=>a(s.data),children:[`合并目标 #`,t]}),(0,x.jsxs)(`button`,{disabled:n||s.loading||!!s.error||!!s.data.merged_into,onClick:()=>o(s.data),children:[`驳回重复 #`,t]})]})]})]})}function on({id:e,catalog:t,openMemory:n,openGoal:r,onBack:i,onChange:a}){let[o,s]=(0,l.useState)(null),[c,u]=(0,l.useState)(null),[d,p]=(0,l.useState)(!1),[m,h]=(0,l.useState)(!1),[b,S]=(0,l.useState)(``),[C,w]=(0,l.useState)(``),T=y(`/goals/${e}`,o||c||m?0:2e3),D=T.data,O=d||m||T.loading||!!T.error;function k(){s(null),u(null),S(``),w(``),h(!1),T.refresh()}async function j(e,t,n=`PATCH`){if(!(d||m)){p(!0),S(``),w(``);try{let i=await g(e,_(n,t));s(null),u(null),T.refresh(),a(),e.endsWith(`/merge`)?(w(`已合并,以下为保留目标。`),r(i.id)):w(e.endsWith(`/dismiss`)?`已驳回可能重复关系`:`目标已更新`)}catch(e){S(v(e)),e instanceof f&&e.status===409&&(h(!0),u(null))}finally{p(!1)}}}return(0,x.jsxs)(`div`,{className:`goal-detail`,children:[(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`text-button`,disabled:d,onClick:i,children:`← 返回目标列表`}),(0,x.jsx)(`button`,{className:`secondary`,disabled:d,onClick:k,children:m?`载入最新目标`:`刷新目标详情`})]}),!c&&(b||T.error)&&(0,x.jsxs)(A,{error:!0,children:[b||T.error,m&&`。请载入最新目标后重新核对;重新加载会放弃当前编辑草稿。`]}),C&&(0,x.jsx)(A,{children:C}),!D&&!T.error&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取目标详情…`}),D&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`section`,{className:`panel goals-panel`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsxs)(`h2`,{children:[`目标 #`,D.id]}),(0,x.jsxs)(`span`,{className:`muted`,children:[`修订 `,D.revision]})]}),(0,x.jsx)(dt,{goal:D}),D.merged_into&&(0,x.jsxs)(A,{children:[`此目标已合并到 #`,D.merged_into,`,原记录与依据保留。`,(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>r(D.merged_into),children:[`查看保留目标 #`,D.merged_into]})]}),o?(0,x.jsx)(vt,{goal:o,catalog:t,busy:d,locked:m||!!T.error,cancel:()=>s(null),submit:t=>void j(`/goals/${e}`,{...t,expected_revision:o.revision})}):(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`p`,{className:`goal-content goal-detail-content`,children:D.content}),(0,x.jsx)(pt,{goal:D,catalog:t}),(0,x.jsxs)(`div`,{className:`goal-time-lines`,children:[(0,x.jsxs)(`p`,{children:[`创建时间:`,(0,x.jsx)(P,{value:D.created_at})]}),(0,x.jsxs)(`p`,{children:[`最后更新:`,(0,x.jsx)(P,{value:D.updated_at})]}),D.state!==`open`&&(0,x.jsxs)(`p`,{children:[`结束时间:`,(0,x.jsx)(P,{value:D.closed_at}),` ·`,` `,D.closed_by?me[D.closed_by]||D.closed_by:`操作者未知`]})]}),D.overdue&&(0,x.jsx)(`p`,{className:`goal-help`,children:`已过期只是标记,目标仍未结束。可修改截止时间,或明确完成、放弃。`}),!D.merged_into&&(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`secondary`,disabled:O,onClick:()=>{s(D),w(``)},children:`编辑目标`}),D.state===`open`&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`button`,{disabled:O,onClick:()=>u({kind:`completed`,goal:D}),children:`完成目标`}),(0,x.jsx)(`button`,{className:`danger-text`,disabled:O,onClick:()=>u({kind:`abandoned`,goal:D}),children:`放弃目标`})]})]})]})]}),(0,x.jsx)(ht,{goal:D,locked:O||!!o||!!c,openMemory:n,clear:e=>u({kind:`basis_clear`,goal:D,annotation:e})}),(0,x.jsx)(gt,{goal:D,openGoal:r}),!D.merged_into&&D.possible_duplicate_ids.length>0&&(0,x.jsxs)(`section`,{className:`panel goals-panel`,children:[(0,x.jsx)(`h2`,{children:`可能重复`}),(0,x.jsx)(`p`,{className:`goal-help`,children:`相似不代表同一件事。核对双方内容、人物和时间后,再决定合并或驳回。`}),D.possible_duplicate_ids.map(n=>(0,x.jsx)(an,{goal:D,otherId:n,locked:O||!!o,catalog:t,openGoal:r,merge:e=>u({kind:`merge`,goal:D,other:e}),dismiss:t=>void j(`/goals/${e}/duplicates/${t.id}/dismiss`,{expected_revision:D.revision,other_revision:t.revision},`POST`)},`${D.revision}-${n}`))]}),(0,x.jsx)(Zt,{goal:D,catalog:t,openMemory:n},`sources-${D.revision}`),(0,x.jsxs)(`section`,{className:`panel goals-panel`,children:[(0,x.jsx)(`h2`,{children:`同证据的承诺记忆`}),(0,x.jsx)(`p`,{className:`goal-help`,children:`与目标使用同一来源消息的角色记忆,保留当时依据修订。目标完成不会自动改写记忆。`}),!D.promise_memories.length&&(0,x.jsx)(`p`,{children:`暂无关联记忆。`}),D.promise_memories.map(e=>(0,x.jsxs)(`article`,{className:`goal-operation`,children:[(0,x.jsx)(`p`,{className:`goal-content`,children:e.content}),(0,x.jsxs)(`p`,{className:`muted`,children:[`依据修订 `,e.revision,` · 当前修订`,` `,e.current_revision,` · `,E(e.lifecycle),e.revision===e.current_revision?``:` · 依据已变化`]}),(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>n(e.id),children:[`查看记忆 #`,e.id]})]},e.id))]}),(0,x.jsxs)(`section`,{className:`panel goals-panel`,children:[(0,x.jsx)(`h2`,{children:`合并进来的目标`}),!D.merged_goals.length&&(0,x.jsx)(`p`,{className:`goal-help`,children:`暂无合并记录。`}),D.merged_goals.map(e=>(0,x.jsxs)(`article`,{className:`goal-operation`,children:[(0,x.jsx)(`p`,{className:`goal-content`,children:e.content}),(0,x.jsx)(pt,{goal:e,catalog:t}),(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>r(e.id),children:[`查看原目标 #`,e.id]})]},e.id))]}),(0,x.jsx)(bt,{goalId:D.id,openGoal:r}),(0,x.jsx)(`section`,{className:`panel goals-panel`,children:(0,x.jsxs)(`details`,{children:[(0,x.jsxs)(`summary`,{children:[`提醒计划 · `,D.reminder_plans.length,` 条`]}),(0,x.jsx)(`p`,{className:`goal-help`,children:`计划到点才发布提醒,尚未发布的计划不属于“待取走”提醒。`}),D.reminder_plans.map(e=>(0,x.jsxs)(`div`,{className:`goal-operation`,children:[(0,x.jsxs)(`p`,{children:[ot[e.reminder_kind],` ·`,` `,{scheduled:`待发布`,published:`已发布`,skipped:`已跳过`,cancelled:`已取消`}[e.status]||e.status]}),(0,x.jsx)(P,{value:e.scheduled_at})]},e.id))]})}),(0,x.jsx)(rn,{id:D.id,catalog:t},`operations-${D.revision}`)]}),c&&(0,x.jsxs)(N,{title:c.kind===`basis_clear`?`清除目标依据标注`:c.kind===`merge`?`确认合并目标`:c.kind===`completed`?`完成目标`:`放弃目标`,closeDisabled:d,onClose:()=>u(null),children:[b&&(0,x.jsx)(A,{error:!0,children:b}),c.kind===`basis_clear`?(0,x.jsxs)(`div`,{className:`goal-confirm`,children:[(0,x.jsx)(`p`,{children:c.annotation.text}),(0,x.jsx)(`p`,{children:`清除只撤下这次观察的标注并保留修订记录,不改变目标正文、状态、截止时间或提醒;依据再次变化时仍可能出现新标注。`}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`primary`,disabled:d||m,onClick:()=>void j(`/goals/${e}/basis-annotations/${c.annotation.id}`,{expected_revision:c.goal.revision},`DELETE`),children:`确认清除依据标注`}),(0,x.jsx)(`button`,{disabled:d,onClick:()=>u(null),children:`取消`})]})]}):c.kind===`merge`?(0,x.jsxs)(`div`,{className:`goal-confirm`,children:[(0,x.jsxs)(`p`,{children:[`保留较早的目标 #`,[c.goal,c.other].sort((e,t)=>Date.parse(e.created_at)-Date.parse(t.created_at)||e.id-t.id)[0].id,`,另一条保留为指向它的合并记录。`]}),(0,x.jsx)(`p`,{children:`来源与待取提醒归入保留目标,重复提醒可能取消;已取走的记录仍保留。保留目标的正文不自动拼接;明确截止时间补入空值,两方都设提前量时采用较大的分钟数。`}),[c.goal,c.other].map(e=>(0,x.jsxs)(`div`,{children:[(0,x.jsxs)(`h3`,{children:[`目标 #`,e.id,` · 修订 `,e.revision]}),(0,x.jsx)(`p`,{className:`goal-content`,children:e.content}),(0,x.jsx)(pt,{goal:e,catalog:t})]},e.id)),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`primary`,disabled:d||m,onClick:()=>void j(`/goals/${e}/duplicates/${c.other.id}/merge`,{expected_revision:c.goal.revision,other_revision:c.other.revision},`POST`),children:`确认合并`}),(0,x.jsx)(`button`,{className:`secondary`,disabled:d,onClick:()=>u(null),children:`取消`})]})]}):(0,x.jsxs)(`div`,{className:`goal-confirm`,children:[(0,x.jsx)(`p`,{children:c.goal.content}),(0,x.jsxs)(`p`,{children:[`确认`,c.kind===`completed`?`完成`:`放弃`,`后,尚未取走的提醒会取消,已取走的记录保留。这是明确改变目标状态。`]}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`primary`,disabled:d||m,onClick:()=>void j(`/goals/${e}`,{state:c.kind,expected_revision:c.goal.revision}),children:c.kind===`completed`?`确认完成`:`确认放弃`}),(0,x.jsx)(`button`,{className:`secondary`,disabled:d,onClick:()=>u(null),children:`取消`})]})]})]})]})}var sn={state:`open`,kind:``,overdue:``,due_soon:``,possible_duplicate:``,entry_id:``,deadline_from:``,deadline_to:``},cn=e=>new URLSearchParams(Object.entries(e).filter(([,e])=>e!==``)).toString();function ln({initialId:e=null,openMemory:t}){let n=y(`/catalog`),[r,i]=(0,l.useState)(e),[a,o]=(0,l.useState)(sn),[s,c]=(0,l.useState)(cn(sn)),[u,d]=(0,l.useState)(0),[f,p]=(0,l.useState)(``),[m,h]=(0,l.useState)(!1),[b,S]=(0,l.useState)(!1),[C,w]=(0,l.useState)(``),[E,D]=(0,l.useState)(null),O=y(r===null?`/goals?${s}&limit=30&offset=${u}`:null,u===0?2e3:0),k=(e,t)=>o(n=>({...n,[e]:t}));function M(e){if(e.preventDefault(),a.deadline_from&&a.deadline_to&&a.deadline_from>a.deadline_to){p(`开始日期不能晚于结束日期`);return}p(``),d(0),c(cn(a)),O.refresh()}async function P(e){if(!b){S(!0),w(``);try{let t=await g(`/goals`,_(`POST`,e));D(t),h(!1),O.refresh()}catch(e){w(v(e))}finally{S(!1)}}}return(0,x.jsxs)(`div`,{className:`goal-workspace`,children:[n.error&&(0,x.jsxs)(A,{error:!0,children:[`人物与入口名称读取失败:`,n.error,(0,x.jsx)(`button`,{className:`text-button`,onClick:n.refresh,children:`重试人物与入口`})]}),r===null?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`section`,{className:`panel goals-panel`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:`目标与询问`}),(0,x.jsx)(`button`,{className:`primary`,onClick:()=>{w(``),h(!0)},children:`创建目标或询问`})]}),(0,x.jsx)(`p`,{className:`goal-help`,children:`所有入口共享目标。管理员创建的目标不自动合并,相似项仅标为“可能重复”。已过期只是标记,需要明确完成或放弃。`}),(0,x.jsxs)(`form`,{className:`goal-filters`,onSubmit:M,children:[(0,x.jsxs)(`label`,{children:[`目标状态`,(0,x.jsxs)(`select`,{value:a.state,onChange:e=>k(`state`,e.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`全部状态`}),Object.entries(rt).map(([e,t])=>(0,x.jsx)(`option`,{value:e,children:t},e))]})]}),(0,x.jsxs)(`label`,{children:[`目标类型`,(0,x.jsxs)(`select`,{value:a.kind,onChange:e=>k(`kind`,e.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`全部类型`}),Object.entries(it).map(([e,t])=>(0,x.jsx)(`option`,{value:e,children:t},e))]})]}),[[`overdue`,`是否过期`],[`due_soon`,`是否临近`],[`possible_duplicate`,`是否可能重复`]].map(([e,t])=>(0,x.jsxs)(`label`,{children:[t,(0,x.jsxs)(`select`,{value:a[e],onChange:t=>k(e,t.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`全部`}),(0,x.jsx)(`option`,{value:`true`,children:`是`}),(0,x.jsx)(`option`,{value:`false`,children:`否`})]})]},e)),(0,x.jsxs)(`label`,{children:[`产生的入口`,(0,x.jsxs)(`select`,{value:a.entry_id,onChange:e=>k(`entry_id`,e.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`全部入口`}),n.data?.entries.map(e=>(0,x.jsx)(`option`,{value:e.id,children:e.name||e.id},e.id))]})]}),(0,x.jsxs)(`label`,{children:[`截止日期从`,(0,x.jsx)(`input`,{type:`date`,value:a.deadline_from,onChange:e=>k(`deadline_from`,e.target.value)})]}),(0,x.jsxs)(`label`,{children:[`截止日期至`,(0,x.jsx)(`input`,{type:`date`,value:a.deadline_to,onChange:e=>k(`deadline_to`,e.target.value)})]}),(0,x.jsx)(`p`,{className:`goal-help full-width`,children:`日期范围按角色时区解释,结束日期包含当天。临近范围包含已过期目标;选择“是否过期:否”可排除。`}),(0,x.jsxs)(`div`,{className:`actions full-width`,children:[(0,x.jsx)(`button`,{className:`primary`,children:`筛选目标`}),(0,x.jsx)(`button`,{type:`button`,className:`secondary`,onClick:O.refresh,children:`刷新目标`}),(0,x.jsx)(`button`,{type:`button`,className:`text-button`,onClick:()=>{o(sn),c(cn(sn)),d(0),p(``),O.refresh()},children:`重置筛选`})]})]})]}),E&&(0,x.jsx)(mt,{receipt:E,openGoal:i}),(f||O.error)&&(0,x.jsxs)(A,{error:!0,children:[f||O.error,O.error&&O.data&&`。以下为上次读取结果,可能尚未更新。`]}),(0,x.jsx)(`div`,{className:`list-heading`,children:(0,x.jsx)(`span`,{children:O.data?`共 ${O.data.total} 个目标与询问`:O.error?`目标暂不可读取`:`正在读取目标…`})}),O.data?.items.length===0&&(0,x.jsx)(j,{title:`当前范围没有目标或询问`,children:`可以创建目标,或在试用对话中让角色答应一件事,学习后在这里查看。`}),(0,x.jsx)(`div`,{className:`goal-grid`,children:O.data?.items.map(e=>(0,x.jsxs)(`article`,{className:`panel goals-panel`,children:[(0,x.jsx)(dt,{goal:e}),(0,x.jsx)(`h3`,{className:`goal-content`,children:e.content}),(0,x.jsx)(pt,{goal:e,catalog:n.data}),(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>i(e.id),children:[`查看目标 #`,e.id]})]},e.id))}),O.data&&(0,x.jsx)(T,{total:O.data.total,offset:u,change:d})]}):(0,x.jsx)(on,{id:r,catalog:n.data,openMemory:t,openGoal:i,onBack:()=>i(null),onChange:O.refresh},r),m&&(0,x.jsxs)(N,{title:`创建目标或询问`,onClose:()=>h(!1),closeDisabled:b,children:[(0,x.jsx)(`p`,{className:`goal-help`,children:`手动创建只会标记可能重复,保留每一条目标供你核对。`}),C&&(0,x.jsx)(A,{error:!0,children:C}),(0,x.jsx)(vt,{catalog:n.data,busy:b,submit:e=>void P(e),cancel:()=>h(!1)})]})]})}var un={host:`宿主提供`,first_report:`自首次报告起`},dn={start:`开始活动`,replace:`更换活动`,update:`更新状态`,heartbeat:`心跳`,end:`结束活动`},fn={activity:`活动`,mood:`情绪`,started_at:`开始时间`,start_time_basis:`开始时间依据`};function pn(e){let t=Math.max(0,Math.floor(e));return[[Math.floor(t/86400),`天`],[Math.floor(t/3600)%24,`小时`],[Math.floor(t/60)%60,`分钟`],[t%60,`秒`]].filter(([e])=>e!==0).map(([e,t])=>`${e} ${t}`).join(` `)||`0 秒`}function mn(e,t=!1){return e===null?`无`:typeof e==`boolean`?e?`是(true)`:`否(false)`:e===``?`空文本`:t&&typeof e==`string`?`“${e}”`:String(e)}function hn({state:e}){return(0,x.jsx)(x.Fragment,{children:e.mood===null?e.mood_updated_at?`已清空`:`未报告`:mn(e.mood)})}function gn({error:e,retained:t}){return e?(0,x.jsxs)(A,{error:!0,children:[`当前状态读取失败:`,e,`。`,t&&`以下为上次读取结果,可能尚未更新。`]}):null}function _n({state:e}){return(0,x.jsxs)(x.Fragment,{children:[e.possibly_stale&&(0,x.jsxs)(`div`,{className:`state-stale`,children:[(0,x.jsx)(M,{tone:`warning`,children:`可能过时`}),(0,x.jsxs)(`p`,{children:[`超过 `,e.stale_after_minutes,` `,`分钟未收到报告,保留宿主最后报告的活动。`]})]}),(0,x.jsxs)(`dl`,{className:`state-fields`,children:[(0,x.jsxs)(`div`,{className:`full-width`,children:[(0,x.jsx)(`dt`,{children:`当前活动`}),(0,x.jsx)(`dd`,{className:`state-activity`,children:e.activity}),(0,x.jsxs)(`dd`,{className:`state-field-time`,children:[`活动更新时间:`,(0,x.jsx)(P,{value:e.activity_updated_at})]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`情绪`}),(0,x.jsx)(`dd`,{children:(0,x.jsx)(hn,{state:e})}),(0,x.jsxs)(`dd`,{className:`state-field-time`,children:[`情绪更新时间:`,(0,x.jsx)(P,{value:e.mood_updated_at})]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`活动持续时长`}),(0,x.jsx)(`dd`,{children:pn(e.duration_seconds)})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`开始时间`}),(0,x.jsx)(`dd`,{children:(0,x.jsx)(P,{value:e.started_at})})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`开始时间依据`}),(0,x.jsx)(`dd`,{children:un[e.start_time_basis]})]}),(0,x.jsxs)(`div`,{className:`full-width`,children:[(0,x.jsx)(`dt`,{children:`最后更新时间`}),(0,x.jsx)(`dd`,{children:(0,x.jsx)(P,{value:e.updated_at})})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`最后报告宿主`}),(0,x.jsx)(`dd`,{children:e.host??`未知`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`最后报告入口`}),(0,x.jsx)(`dd`,{children:e.entry_id??`未知`})]})]}),(0,x.jsx)(`h3`,{children:`细节`}),Object.keys(e.details).length?(0,x.jsx)(`dl`,{className:`state-fields state-detail-fields`,children:Object.entries(e.details).map(([e,t])=>(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:e}),(0,x.jsx)(`dd`,{children:mn(t.value)}),(0,x.jsxs)(`dd`,{className:`state-field-time`,children:[`更新时间:`,(0,x.jsx)(P,{value:t.updated_at})]})]},e))}):(0,x.jsx)(`p`,{className:`quiet`,children:`暂无细节报告`})]})}function vn(){let e=y(`/state`,2e3),t=e.data;return(0,x.jsxs)(`div`,{className:`state-summary`,children:[(0,x.jsx)(gn,{error:e.error,retained:t!==null}),e.error&&(0,x.jsx)(`button`,{className:`text-button`,onClick:e.refresh,children:`重试当前状态`}),!t&&!e.error&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取当前状态…`}),t&&(t.activity?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`p`,{className:`state-summary-activity`,children:t.activity}),t.possibly_stale&&(0,x.jsx)(M,{tone:`warning`,children:`可能过时`}),(0,x.jsxs)(`dl`,{className:`state-summary-fields`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`情绪`}),(0,x.jsx)(`dd`,{children:(0,x.jsx)(hn,{state:t})})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`活动持续时长`}),(0,x.jsx)(`dd`,{children:pn(t.duration_seconds)})]})]}),t.start_time_basis===`first_report`&&(0,x.jsx)(`p`,{className:`muted`,children:`持续时长自首次报告起计算。`})]}):(0,x.jsx)(`p`,{className:`quiet`,children:`暂无宿主报告的当前活动`})),(0,x.jsx)(`a`,{className:`text-button`,href:`#/state`,children:`查看状态与报告历史`})]})}function yn({report:e}){let t=[...Object.entries(fn).flatMap(([t,n])=>{let r=e.changes[t];return r?[{key:t,label:n,...r}]:[]}),...Object.entries(e.changes.details||{}).map(([e,t])=>({key:`details.${e}`,label:`细节 · ${e}`,...t}))],n=(e,t)=>t===null?`无`:e===`started_at`?(0,x.jsx)(P,{value:String(t)}):e===`start_time_basis`?un[t]||String(t):mn(t,!0);return(0,x.jsxs)(`article`,{className:`state-report`,"aria-label":`报告 #${e.id}`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsxs)(`h3`,{children:[dn[e.action],` · `,e.action]}),(0,x.jsxs)(`span`,{className:`muted`,children:[`报告 #`,e.id,` · `,e.method]})]}),(0,x.jsx)(`p`,{className:`state-report-time`,children:(0,x.jsx)(P,{value:e.reported_at})}),(0,x.jsxs)(`dl`,{className:`state-report-source`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`宿主`}),(0,x.jsx)(`dd`,{children:e.host??`未知`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`入口`}),(0,x.jsx)(`dd`,{children:e.entry_id??`未知`})]})]}),t.length?(0,x.jsx)(`dl`,{className:`state-changes`,children:t.map(e=>(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:e.label}),(0,x.jsxs)(`dd`,{children:[(0,x.jsx)(`span`,{className:`muted`,children:`原值`}),(0,x.jsx)(`span`,{children:n(e.key,e.before)})]}),(0,x.jsxs)(`dd`,{children:[(0,x.jsx)(`span`,{className:`muted`,children:`现值`}),(0,x.jsx)(`span`,{children:n(e.key,e.after)})]})]},e.key))}):(0,x.jsx)(`p`,{className:`muted`,children:`无字段值变化,本次报告仍已记录。`})]})}function bn(){let e=y(`/state`,2e3),[t,n]=(0,l.useState)(0),r=y(`/state/reports?limit=30&offset=${t}`,t===0?2e3:0);return(0,x.jsx)(x.Fragment,{children:(0,x.jsxs)(`div`,{className:`state-page`,children:[(0,x.jsxs)(`section`,{className:`panel state-panel`,"aria-labelledby":`current-state-title`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{id:`current-state-title`,children:`当前状态`}),(0,x.jsx)(`button`,{className:`text-button`,disabled:e.loading,onClick:e.refresh,children:`刷新当前状态`})]}),(0,x.jsx)(`p`,{className:`state-help`,children:`活动持续时长与情绪、细节的更新时间分别记录。时间按角色时区显示,保留 UTC 偏移。`}),(0,x.jsx)(gn,{error:e.error,retained:e.data!==null}),!e.data&&!e.error&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取当前状态…`}),e.data&&(e.data.activity?(0,x.jsx)(_n,{state:e.data}):(0,x.jsx)(j,{title:`暂无宿主报告的当前活动`,children:`宿主开始活动后会显示在这里;结束活动后,报告历史仍会保留。`}))]}),(0,x.jsxs)(`section`,{className:`panel state-panel`,"aria-labelledby":`state-reports-title`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsxs)(`h2`,{id:`state-reports-title`,children:[`报告历史`,r.data?` · ${r.data.total} 条`:``]}),(0,x.jsx)(`button`,{className:`text-button`,disabled:r.loading,onClick:()=>t===0?r.refresh():n(0),children:`刷新报告历史`})]}),(0,x.jsxs)(`p`,{className:`state-help`,children:[`按报告顺序从新到旧排列,列出字段值的实际变化。心跳也会保留记录。`,t===0?`最新一页自动刷新。`:`较早报告暂停自动刷新;刷新历史可回到最新一页。`]}),r.error&&(0,x.jsxs)(A,{error:!0,children:[`报告历史读取失败:`,r.error,`。`,r.data&&`以下为上次读取的报告。`]}),!r.data&&!r.error&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取报告历史…`}),r.data?.items.length===0&&(0,x.jsx)(j,{title:`暂无报告历史`}),r.data?.items.map(e=>(0,x.jsx)(yn,{report:e},e.id)),r.data&&(0,x.jsx)(T,{total:r.data.total,offset:t,limit:30,change:n})]})]})})}function xn({initialQuery:e=``,openMemory:t=()=>{}}){let n=new URLSearchParams(e),r=Number(n.get(`id`)),[i,a]=(0,l.useState)(Number.isSafeInteger(r)&&r>0?r:null),o=n.get(`tab`),[s,c]=(0,l.useState)(o===`goals`||o===`notifications`?o:`state`);function u(e){a(e),c(`goals`)}return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{className:`page-heading`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`p`,{className:`eyebrow`,children:`此刻与接下来的事`}),(0,x.jsx)(`h1`,{children:`状态与目标`}),(0,x.jsx)(`p`,{children:`当前状态完全由宿主报告,管理员不能编辑。状态与目标由所有入口共享。`})]})}),(0,x.jsxs)(`nav`,{className:`learning-tabs`,"aria-label":`状态与目标分区`,children:[(0,x.jsx)(`button`,{"aria-pressed":s===`state`,onClick:()=>c(`state`),children:`当前状态`}),(0,x.jsx)(`button`,{"aria-pressed":s===`goals`,onClick:()=>{a(null),c(`goals`)},children:`目标与询问`}),(0,x.jsx)(`button`,{"aria-pressed":s===`notifications`,onClick:()=>c(`notifications`),children:`提醒`})]}),s===`state`?(0,x.jsx)(bn,{}):s===`goals`?(0,x.jsx)(ln,{initialId:i,openMemory:t},i):(0,x.jsx)(bt,{openGoal:u})]})}function Sn({goals:e,error:t=``}){let n=y(`/notifications?status=pending&limit=1&offset=0`,2e3),r=e?.filter(e=>e.state===`open`&&!e.merged_into).slice(0,10);return(0,x.jsxs)(`section`,{className:`panel trial-goals`,"aria-labelledby":`trial-goals-title`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{id:`trial-goals-title`,children:`未结束的目标与询问`}),(0,x.jsx)(M,{children:r?.length??`—`})]}),(0,x.jsx)(`p`,{className:`goal-help`,children:`角色答应一件事 → 学习形成目标 → 到点发布提醒。可在学习结束后点击目标查看来源;全部入口共享,优先展示临近、过期的目标,最多 10 个。`}),t&&(0,x.jsxs)(A,{error:!0,children:[`目标暂不可读取:`,t,`。`,r&&`以下为上次读取结果。`]}),!r&&!t&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取目标…`}),r?.length===0&&(0,x.jsx)(`p`,{className:`quiet`,children:`暂无未结束的目标或询问`}),r?.map(e=>(0,x.jsxs)(`a`,{className:`trial-goal-link`,href:`#/state?tab=goals&id=${e.id}`,children:[(0,x.jsx)(dt,{goal:e}),(0,x.jsx)(`p`,{className:`goal-content`,children:e.content}),(0,x.jsx)(`small`,{children:(0,x.jsx)(ft,{goal:e})}),(0,x.jsx)(`span`,{className:`text-button`,children:`查看目标与来源 ↗`})]},e.id)),n.error&&(0,x.jsxs)(`p`,{className:`danger-text`,children:[`提醒暂不可读取:`,n.error,(0,x.jsx)(`button`,{className:`text-button`,onClick:n.refresh,children:`重试提醒`})]}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`a`,{className:`text-button`,href:`#/state?tab=goals`,children:`查看全部目标与询问`}),(0,x.jsxs)(`a`,{className:`text-button`,href:`#/state?tab=notifications`,children:[`查看提醒`,n.data?.total===void 0?``:` · ${n.data.total} 条待取走`]})]}),(0,x.jsx)(`p`,{className:`goal-help`,children:`提醒被宿主取走不代表已送达或目标完成。这里的自动刷新不会取走提醒。`})]})}function Cn(e){let t=y(`/trial`),[n,r]=(0,l.useState)(``),[i,a]=(0,l.useState)(!1),[o,s]=(0,l.useState)(``),[c,u]=(0,l.useState)(`group`),[d,f]=(0,l.useState)(``),[p,m]=(0,l.useState)(!1),h=t.data?.entries||[],b=(0,l.useMemo)(()=>{if(!t.data)return null;let e=new Map;for(let n of t.data.speakers){let t=e.get(n.id);e.set(n.id,{...n,is_default:!!(n.is_default||t?.is_default)})}return{...t.data,speakers:[...e.values()]}},[t.data]);(0,l.useEffect)(()=>{!n&&h.length&&r(h[0].id)},[n,h]);async function S(n){n.preventDefault(),m(!0),f(``);try{let n=await g(`/trial/entries`,_(`POST`,{name:o,kind:c}));r(n.id),a(!1),s(``),t.refresh(),e.refreshStatus()}catch(e){f(v(e))}finally{m(!1)}}return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`page-heading`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`p`,{className:`eyebrow`,children:`在相处中,慢慢记住`}),(0,x.jsx)(`h1`,{children:`试用对话`}),(0,x.jsx)(`p`,{children:`聊一件小事,看看它如何成为记忆。`})]}),(0,x.jsx)(M,{tone:`purple`,children:h.find(e=>e.id===n)?`${Ye(h.find(e=>e.id===n).pace)}学习`:`试用入口`})]}),(t.error||d)&&(0,x.jsx)(A,{error:!0,children:t.error||d}),(0,x.jsxs)(`div`,{className:`entry-bar`,children:[(0,x.jsxs)(`label`,{children:[`当前入口`,(0,x.jsxs)(`select`,{"aria-label":`当前入口`,value:n,onChange:e=>r(e.target.value),children:[(0,x.jsx)(`option`,{value:``,disabled:!0,children:`选择试用入口`}),h.map(e=>(0,x.jsx)(`option`,{value:e.id,children:e.name},e.id))]})]}),(0,x.jsx)(`button`,{className:`secondary`,onClick:()=>a(!i),children:`+ 新建入口`}),(0,x.jsx)(`span`,{className:`muted entry-tip`,children:`记忆共同积累,近期消息各自保留`})]}),(i||t.data&&!h.length)&&(0,x.jsxs)(`form`,{className:`inline-form panel`,onSubmit:S,children:[(0,x.jsxs)(`label`,{children:[`入口名称`,(0,x.jsx)(`input`,{value:o,onChange:e=>s(e.target.value),placeholder:`如:试用群聊 A`,required:!0,maxLength:100})]}),(0,x.jsxs)(`label`,{children:[`入口类型`,(0,x.jsxs)(`select`,{value:c,onChange:e=>u(e.target.value),children:[(0,x.jsx)(`option`,{value:`group`,children:`群聊`}),(0,x.jsx)(`option`,{value:`private`,children:`私聊`})]})]}),(0,x.jsx)(`button`,{className:`primary`,disabled:p||!o.trim(),children:`创建入口`})]}),!t.data&&!t.error&&(0,x.jsx)(`p`,{className:`muted`,children:`正在读取试用入口…`}),n&&b&&(0,x.jsx)(wn,{entryId:n,catalog:b,refreshCatalog:t.refresh,...e},n)]})}function wn({entryId:e,catalog:t,refreshCatalog:n,status:r,openMemory:i,refreshStatus:a}){let o=y(`/trial/entries/${e}`,2e3),[s,c]=(0,l.useState)(t.speakers.find(e=>e.is_default)?.id||``);(0,l.useEffect)(()=>{s||c(t.speakers.find(e=>e.is_default)?.id||``)},[s,t.speakers]);let[u,d]=(0,l.useState)(!1),[p,m]=(0,l.useState)(``),[h,b]=(0,l.useState)(``),C=`iris.trial.replies.${e}`,[w,T]=(0,l.useState)(()=>{try{return window.localStorage.getItem(C)===`true`}catch{return!1}});function E(e){T(e);try{window.localStorage.setItem(C,String(e))}catch{}}let[D,N]=(0,l.useState)(!1),[P,F]=(0,l.useState)(``),[I,L]=(0,l.useState)(``),[ee,te]=(0,l.useState)(``),[ne,re]=(0,l.useState)(null),[ie,ae]=(0,l.useState)(null),[oe,se]=(0,l.useState)(null),[ce,le]=(0,l.useState)(``),[ue,de]=(0,l.useState)([]),[fe,R]=(0,l.useState)(null),[z,B]=(0,l.useState)(!1),[pe,me]=(0,l.useState)(null),he=Ve(),ge=(0,l.useRef)(null);(0,l.useEffect)(()=>()=>ge.current?.abort(),[]);function V(e){if(!D){L(``);try{he.add(e)}catch(e){L(v(e))}}}let H=o.data,_e=r?.entries.find(t=>t.entry_id===e),ve=[...new Map([...ue,...H?.messages||[]].map(e=>[e.id,e])).values()].sort((e,t)=>e.id-t.id),ye=(0,l.useRef)(null),be=(0,l.useRef)(!0),xe=ve.at(-1)?.id;(0,l.useEffect)(()=>{be.current&&ye.current&&(ye.current.scrollTop=ye.current.scrollHeight)},[xe]);async function Se(e){e.preventDefault(),L(``);try{let e=await g(`/trial/speakers`,_(`POST`,{name:p}));n(),c(e.id),d(!1),m(``)}catch(e){L(v(e))}}async function Ce(t,n){F(n?`角色正在回复…`:`正在准备回复材料…`),le(``),se(null),ae(null);try{if(n){re(t);let n=await g(`/trial/entries/${e}/reply`,_(`POST`,{message_id:t}));ae(n.prepared),se(n.diagnostic||null),n.reused&&le(n.diagnostic?`已复用回复 #${n.diagnostic.reply_message_id};以下诊断来自发布该回复时的准备。`:`已复用已发布回复;原诊断未记录或已按保留期限清理,无法还原当时的判断。`),re(null)}else ae(await g(`/trial/entries/${e}/prepare`,_(`POST`)))}catch(e){let t=e instanceof f&&e.code===`reply_failed`?e.result:void 0;throw t?.diagnostic?(se(t.diagnostic),le(`角色回复失败;以下为本次已经完成的回复准备诊断。`)):le(`本次回复准备结果未返回,无法展示召回判断状态。`),e}}async function we(t){if(t.preventDefault(),!h.trim()&&!he.images.length||D||!s)return;let n=new AbortController;ge.current=n,N(!0),L(``),te(``),ae(null),se(null),le(``),re(null),F(`正在发送…`);let r=he.images.map(e=>e.key).join(`,`),i=pe?.content===h&&pe.speaker===s&&pe.imageKeys===r?pe:{content:h,speaker:s,imageKeys:r,key:crypto.randomUUID()};me(i);try{let t=await he.upload(n.signal,F);n.signal.throwIfAborted(),F(`正在发送…`);let r=await g(`/trial/entries/${e}/messages`,{..._(`POST`,{speaker_id:s,content:h,dedupe_key:i.key,media_ids:t}),signal:n.signal});n.signal.throwIfAborted(),b(``),he.clear(),me(null),te(`消息已接收,学习结果请看右侧批次。`),o.refresh(),a(),await Ce(r.message_id,w)}catch(e){n.signal.aborted||L(v(e))}finally{n.signal.aborted||(N(!1),F(``),o.refresh(),a())}}async function Te(){if(ne){N(!0),L(``);try{await Ce(ne,!0)}catch(e){L(v(e))}finally{N(!1),F(``),o.refresh(),a()}}}async function Ee(){L(``);try{let t=await g(`/trial/entries/${e}/learn`,_(`POST`));te(t.paused?`已请求立即学习;模型暂停中,恢复后处理。`:`已请求立即学习,完成情况请看批次状态。`),a()}catch(e){L(v(e))}}async function De(){B(!0);try{let t=await g(`/trial/entries/${e}?before=${ve[0].id}`);de([...t.messages,...ue]),R(t.has_older)}catch(e){L(v(e))}finally{B(!1)}}return(0,x.jsxs)(`div`,{className:`trial-grid`,children:[(0,x.jsxs)(`section`,{className:`panel conversation`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:H?.entry.name||`正在读取对话…`}),(0,x.jsxs)(`span`,{className:`muted`,children:[H?.entry.kind===`private`?`私聊`:`群聊`,` · 图文试用`]})]}),(0,x.jsxs)(`span`,{className:`live-label`,children:[(0,x.jsx)(`i`,{}),` `,o.error?`连接中断`:H?`入口已就绪`:`正在连接`]})]}),(0,x.jsxs)(`div`,{className:`messages`,"aria-label":`对话记录`,ref:ye,onScroll:e=>{let t=e.currentTarget;be.current=t.scrollHeight-t.scrollTop-t.clientHeight<60},children:[(fe??H?.has_older)&&(0,x.jsx)(`button`,{className:`text-button older`,onClick:De,disabled:z,children:`查看更早消息`}),!ve.length&&(0,x.jsx)(j,{title:`从一句话开始`,children:`例如「我下周三去上海出差」。实时节奏会在短暂停顿后开始学习。`}),ve.map(e=>(0,x.jsxs)(`article`,{className:`message ${e.kind===`self_output`?`role`:`user`}`,children:[(0,x.jsxs)(`div`,{className:`message-meta`,children:[(0,x.jsx)(`strong`,{children:e.kind===`self_output`?t.role_name:e.sender_name}),(0,x.jsx)(`time`,{children:S(e.received_at)})]}),(0,x.jsxs)(`div`,{className:`bubble`,children:[e.content,(0,x.jsx)(Le,{media:e.media})]}),(0,x.jsxs)(`div`,{className:`message-state ${[`abandoned`,`refused`].includes(e.learning_state)?`danger-text`:``}`,children:[O(e.learning_state),e.batch_id&&` · 批次 #${e.batch_id}`,e.kind===`self_output`?` · 角色实际输出`:``]})]},e.id))]}),(0,x.jsxs)(`div`,{className:`composer`,children:[(I||o.error)&&(0,x.jsx)(A,{error:!0,children:I||o.error}),ee&&(0,x.jsx)(`p`,{className:`receipt`,role:`status`,children:ee}),ne&&!D&&(0,x.jsx)(`button`,{className:`secondary`,onClick:Te,children:`重试角色回复`}),u&&(0,x.jsxs)(`form`,{className:`inline-form compact`,onSubmit:Se,children:[(0,x.jsxs)(`label`,{children:[`虚拟发言人姓名`,(0,x.jsx)(`input`,{value:p,maxLength:100,required:!0,onChange:e=>m(e.target.value)})]}),(0,x.jsx)(`button`,{className:`secondary`,disabled:!p.trim(),children:`添加发言人`})]}),(0,x.jsxs)(`form`,{onSubmit:we,children:[(0,x.jsxs)(`div`,{className:`composer-controls`,children:[(0,x.jsxs)(`label`,{className:`speaker-label`,children:[`发言人`,(0,x.jsx)(`select`,{"aria-label":`发言人`,disabled:D,value:s,onChange:e=>c(e.target.value),children:t.speakers.map(e=>(0,x.jsxs)(`option`,{value:e.id,children:[e.name,t.speakers.filter(t=>t.name===e.name).length>1?` · ${e.id.slice(0,6)}`:``]},e.id))})]}),(0,x.jsx)(`button`,{type:`button`,className:`text-button`,onClick:()=>d(!u),children:`+ 添加`}),(0,x.jsxs)(`label`,{className:`switch`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:w,disabled:D,onChange:e=>E(e.target.checked)}),(0,x.jsx)(`span`,{children:`角色回复`})]})]}),(0,x.jsx)(`textarea`,{"aria-label":`消息内容`,placeholder:`说说正在发生的事…`,value:h,onChange:e=>b(e.target.value),onPaste:e=>{let t=Array.from(e.clipboardData.files);t.length&&(e.preventDefault(),V(t))},rows:3,disabled:D}),(0,x.jsx)(He,{images:he.images,busy:D,add:V,remove:he.remove}),(0,x.jsxs)(`div`,{className:`composer-bottom`,children:[(0,x.jsx)(`span`,{className:`muted`,children:P||`接收后自动排队学习`}),(0,x.jsxs)(`button`,{className:`primary`,disabled:D||!h.trim()&&!he.images.length||!s,"aria-label":`发送消息`,children:[D?`处理中…`:`发送`,` `,(0,x.jsx)(`span`,{"aria-hidden":!0,children:`↑`})]})]})]})]})]}),(0,x.jsxs)(`aside`,{className:`trial-aside`,"aria-label":`学习与回复上下文`,children:[(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:`学习动态`}),(0,x.jsx)(`button`,{className:`text-button`,onClick:Ee,children:`立即学习`})]}),(0,x.jsxs)(`div`,{className:`queue-summary`,children:[(0,x.jsx)(`strong`,{children:_e?.pending_count??`—`}),(0,x.jsx)(`span`,{children:`条待学习`}),(0,x.jsx)(M,{tone:_e?.current_batch?`purple`:``,children:_e?.current_batch?`批次 #${_e.current_batch.id}`:`等待新消息`})]}),_e?.current_batch&&(0,x.jsxs)(`p`,{className:`batch-state`,children:[k(_e.current_batch),_e.current_batch.next_retry_at&&(0,x.jsxs)(`small`,{children:[`下次尝试:`,S(_e.current_batch.next_retry_at)]})]}),_e?.latest_batch&&(0,x.jsxs)(`div`,{className:`batch-result`,children:[(0,x.jsxs)(`span`,{className:`muted`,children:[`最近结束 · #`,_e.latest_batch.id]}),(0,x.jsx)(`p`,{children:k(_e.latest_batch)}),_e.latest_batch.last_error&&(0,x.jsx)(`small`,{children:_e.latest_batch.last_error})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`学习成功也可能没有值得记住的内容。`}),(0,x.jsx)(Ze,{value:_e?.queue_wait})]}),(0,x.jsx)(Sn,{goals:H?.goals,error:o.error}),(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:`新形成与更新`}),(0,x.jsx)(M,{children:H?.recent_memories.length||0})]}),(0,x.jsx)(`p`,{className:`muted section-help`,children:`本入口最近 12 条,点击查看来源`}),H?.recent_memories.length?H.recent_memories.map(e=>(0,x.jsxs)(`button`,{className:`memory-preview`,onClick:()=>i(e.id),children:[(0,x.jsxs)(`span`,{className:`tiny-label`,children:[e.kind,` · #`,e.id]}),(0,x.jsx)(`span`,{children:e.content}),(0,x.jsxs)(`small`,{children:[S(e.updated_at),` `,(0,x.jsx)(`span`,{"aria-hidden":!0,children:`↗`})]})]},e.id)):(0,x.jsx)(`p`,{className:`quiet`,children:`暂时还没有形成记忆。`})]}),(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:`这次回复准备`}),(0,x.jsx)(`span`,{className:`muted`,children:ie?`${ie.memories.length} 条召回`:oe?`当次诊断`:ce?`未返回材料`:D?`准备中`:`等待发送`})]}),!ie&&!oe?(0,x.jsx)(`p`,{className:`quiet`,children:ce||(D?`正在准备回复材料…`:`发送消息后展示召回结果。`)}):(0,x.jsxs)(x.Fragment,{children:[ce&&(0,x.jsx)(A,{children:ce}),(0,x.jsx)(tt,{value:oe?.judgment||ie?.judgment}),oe&&(0,x.jsx)(Pe,{value:oe,openMemory:i}),ie?.memories.length===0&&(0,x.jsx)(`p`,{className:`quiet`,children:`没有额外召回记忆,近期原文仍在对话上下文中。`}),ie?.memories.map(e=>(0,x.jsxs)(`div`,{children:[(0,x.jsxs)(`button`,{className:`memory-preview`,onClick:()=>i(e.id),children:[(0,x.jsx)(M,{tone:`purple`,children:e.reason===`person_highlight`?`人物要点`:`与当前内容相关`}),(0,x.jsx)(`span`,{children:e.content})]}),(0,x.jsx)(nt,{value:e.subject_annotations})]},e.id)),(0,x.jsx)(`p`,{className:`fine-print`,children:`被召回不等于被使用,也不代表内容已证实。`}),ie?.hints.filter(e=>e.code!==`recall_judgment`).map((e,t)=>(0,x.jsx)(`p`,{className:`fine-print`,children:e.message},t))]})]}),(0,x.jsxs)(`section`,{className:`panel context-panel`,children:[(0,x.jsx)(`h2`,{children:`角色上下文`}),(0,x.jsx)(Ue,{}),(0,x.jsxs)(`details`,{open:!0,children:[(0,x.jsx)(`summary`,{children:`当前状态`}),(0,x.jsx)(vn,{})]})]})]})]})}function Tn({value:e}){return e?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`table`,{className:`image-usage`,children:[(0,x.jsx)(`caption`,{children:`图片理解用量`}),(0,x.jsx)(`thead`,{children:(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`th`,{scope:`col`,children:`指标`}),(0,x.jsx)(`th`,{scope:`col`,children:`今日`}),(0,x.jsx)(`th`,{scope:`col`,children:`本周`})]})}),(0,x.jsx)(`tbody`,{children:[[`调用次数`,e=>e.calls],[`token(输入+输出)`,e=>e.tokens.toLocaleString()],[`累计耗时`,e=>C(e.duration_ms)],[`失败调用`,e=>e.failures],[`其中被拒绝`,e=>e.refusals],[`超时调用`,e=>e.timeouts],[`未返回 token 用量的调用`,e=>e.calls_without_usage]].map(([t,n])=>(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`th`,{scope:`row`,children:t}),(0,x.jsx)(`td`,{children:n(e.today)}),(0,x.jsx)(`td`,{children:n(e.week)})]},t))})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`按角色时区统计,本周自周一开始。含重试、连接测试和恢复探测;未返回的 token 用量不作推算。`})]}):(0,x.jsx)(`p`,{children:`暂时无法读取图片用量。`})}var En={manual:`手动维护`,scheduled:`定时维护`,catchup:`启动补跑`},Dn={decay:`衰减与状态转换`,expiry:`到期删除`,dependency:`依据失效扣减`,messages:`消息清理`,retry:`批次重试`,consolidation:`模型整理`,persona:`persona 更新`,goals:`目标依据复核`},On={decayed:`衰减`,forgotten:`遗忘`,restored:`恢复`,deleted:`删除`,dependencies_weakened:`依据扣减`,messages_deleted:`清理消息`,batches_retried:`重试批次`,checked:`检查项目`,skipped:`跳过`,failed:`失败`,merged:`合并`,conflicts:`待核对建议(矛盾或合并)`,dependencies_reviewed:`依赖复核建议`,persona_published:`persona 已发布`,persona_pending:`persona 待确认`,person_summary:`人物摘要处理`,goals_reviewed:`目标依据标注变化`,model_calls:`模型调用`},kn={pinned:`已置顶`,revision_conflict:`修订冲突`,forgotten:`已遗忘`,deleted:`已删除`,no_longer_due:`尚未到期`,already_applied:`已经扣减`,dependency_removed:`依据关系已移除`,no_longer_eligible:`不再符合清理条件`,referenced:`仍有引用`,batch_state_changed:`批次状态已变化`,already_retried:`已自动重试过`,batch_date_changed:`批次日期已变化`,target_messages_cleared:`目标消息已清理`};function An({summary:e}){return(0,x.jsx)(`dl`,{className:`maintenance-counts`,children:Object.entries(e).map(([e,t])=>(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:On[e]||e}),(0,x.jsx)(`dd`,{children:t.count})]},e))})}function jn({run:e}){return(0,x.jsxs)(`div`,{className:`lifecycle-stack`,children:[(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(M,{tone:e.state===`completed`?`green`:`purple`,children:e.state===`completed`?`已完成`:`运行中`}),(0,x.jsx)(`span`,{children:En[e.trigger]||e.trigger}),(0,x.jsxs)(`span`,{className:`muted`,children:[`#`,e.id]})]}),(0,x.jsxs)(`p`,{children:[`开始:`,w(e.created_at),` · 完成:`,e.finished_at?w(e.finished_at):`尚未完成`]})]})}function Mn({openMemory:e,initialRun:t}){let n=y(`/maintenance?limit=1&offset=0`,5e3),[r,i]=(0,l.useState)(!1),[a,o]=(0,l.useState)(0),s=y(r?`/maintenance?limit=10&offset=${a}`:null,5e3),[c,u]=(0,l.useState)(t||null),[d,f]=(0,l.useState)(!1),[p,m]=(0,l.useState)(!1),[h,b]=(0,l.useState)(``),S=n.data?.items[0];(0,l.useEffect)(()=>{let e=()=>{let e=location.hash;if(e.split(`?`)[0]!==`#/status`)return;let t=Number(new URLSearchParams(e.split(`?`)[1]||``).get(`run`));Number.isSafeInteger(t)&&t>0&&u(t)};return addEventListener(`hashchange`,e),()=>removeEventListener(`hashchange`,e)},[]);async function C(){if(!p){m(!0),b(``);try{let e=await g(`/maintenance`,_(`POST`,{}));f(!1),u(e.run_id),n.refresh(),s.refresh()}catch(e){b(v(e))}finally{m(!1)}}}return(0,x.jsxs)(`section`,{className:`panel maintenance-panel`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:`梦境整理与记忆维护`}),(0,x.jsx)(`button`,{className:`secondary`,disabled:p,onClick:()=>f(!0),children:`手动维护`})]}),(h||n.error||s.error)&&(0,x.jsxs)(A,{error:!0,children:[h||n.error||s.error,(0,x.jsx)(`button`,{className:`text-button`,onClick:()=>{n.refresh(),s.refresh()},children:`刷新维护记录`})]}),d&&(0,x.jsxs)(`div`,{className:`delete-confirm`,children:[(0,x.jsx)(`p`,{children:`手动维护也计一次衰减,并执行遗忘、到期删除、消息清理和批次重试。还会按本次设置调用模型进行整理与 persona 与人物摘要更新,并复核目标依据。已有未完成的维护时继续该次运行。`}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`primary`,disabled:p,onClick:()=>void C(),children:p?`正在请求…`:`确认运行维护`}),(0,x.jsx)(`button`,{className:`secondary`,disabled:p,onClick:()=>f(!1),children:`取消维护`})]})]}),!n.data&&!n.error&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取维护记录…`}),n.data&&!S&&(0,x.jsx)(j,{title:`尚无维护记录`}),S&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`h3`,{className:`maintenance-subheading`,children:`最近一次维护`}),(0,x.jsx)(jn,{run:S}),Object.keys(S.summary).length?(0,x.jsx)(An,{summary:S.summary}):(0,x.jsx)(`p`,{className:`quiet`,children:`维护进行中,可在报告中查看当前数量。`}),(0,x.jsx)(`button`,{className:`text-button`,onClick:()=>u(S.id),children:`查看最近维护报告`})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`维护不中断接收和学习。报告逐项保留实际变化、模型建议和失败;检查及跳过数量按阶段和原因汇总。`}),(0,x.jsx)(`button`,{className:`text-button`,"aria-expanded":r,onClick:()=>i(e=>!e),children:`历史维护`}),r&&(0,x.jsxs)(`div`,{className:`lifecycle-stack`,children:[!s.data&&!s.error&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取历史维护…`}),s.data?.items.length===0&&(0,x.jsx)(`p`,{className:`quiet`,children:`没有历史维护。`}),s.data?.items.map(e=>(0,x.jsxs)(`div`,{className:`maintenance-history-row`,children:[(0,x.jsxs)(`span`,{children:[`#`,e.id,` · `,w(e.created_at),` ·`,` `,En[e.trigger]||e.trigger,` ·`,` `,e.state===`completed`?`已完成`:`运行中`]}),(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>u(e.id),children:[`查看报告 #`,e.id]})]},e.id)),s.data&&(0,x.jsx)(T,{total:s.data.total,limit:10,offset:a,change:o})]}),c!==null&&(0,x.jsx)(Nn,{id:c,close:()=>{u(null),t&&(location.hash=`#/status`)},openMemory:t=>{u(null),location.hash.startsWith(`#/status?`)&&window.history.replaceState(null,``,`#/status`),e(t)}},c)]})}function Nn({id:e,close:t,openMemory:n}){let[r,i]=(0,l.useState)(3e3),a=y(`/maintenance/${e}`,r),o=a.data;(0,l.useEffect)(()=>{o?.state===`completed`&&i(0)},[o?.state]);let s=o?[[`变化的记忆`,o.items.filter(e=>e.memory_id!=null&&e.outcome!==`failed`&&e.phase!==`consolidation`)],[`清理的消息`,o.items.filter(e=>e.outcome===`messages_deleted`)],[`重试的批次`,o.items.filter(e=>e.outcome===`batches_retried`)],[`失败项`,o.items.filter(e=>e.outcome===`failed`)]]:[];return(0,x.jsxs)(N,{title:`维护报告 #${e}`,onClose:t,children:[a.error&&(0,x.jsxs)(A,{error:!0,children:[a.error,(0,x.jsx)(`button`,{className:`text-button`,onClick:a.refresh,children:`重新读取报告`})]}),!o&&!a.error&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取维护报告…`}),o&&(0,x.jsxs)(`div`,{className:`lifecycle-stack`,children:[(0,x.jsx)(jn,{run:o}),(0,x.jsxs)(`p`,{className:`muted`,children:[`角色时区:`,o.timezone,` · 当前阶段:`,o.state===`completed`?`已结束`:Object.values(Dn)[o.phase]||`生成报告`]}),(0,x.jsx)(An,{summary:o.summary}),(0,x.jsxs)(`details`,{children:[(0,x.jsx)(`summary`,{children:`检查阶段与跳过原因`}),Object.entries(o.summary.checked?.by_phase||{}).map(([e,t])=>(0,x.jsxs)(`p`,{children:[Dn[e]||e,`:`,t]},e)),Object.entries(o.summary.skipped?.reasons||{}).map(([e,t])=>(0,x.jsxs)(`p`,{children:[kn[e]||ce(e),`:`,t]},e))]}),(0,x.jsx)(zt,{data:o,openMemory:n}),s.map(([t,r])=>(0,x.jsx)(Pn,{name:t,items:r,openMemory:n},`${e}:${t}`))]})]})}function Pn({name:e,items:t,openMemory:n}){let[r,i]=(0,l.useState)(0);return(0,x.jsxs)(`section`,{className:`detail-section`,"aria-label":e,children:[(0,x.jsxs)(`h3`,{children:[e,` `,(0,x.jsx)(M,{children:t.length})]}),!t.length&&(0,x.jsx)(`p`,{className:`quiet`,children:`暂无记录。`}),t.slice(r,r+30).map(e=>(0,x.jsxs)(`article`,{className:`maintenance-item`,children:[e.memory_id==null?(0,x.jsxs)(`strong`,{children:[e.phase===`messages`?`消息`:e.phase===`persona`?`persona 任务`:e.phase===`goals`?`目标`:`批次`,` `,`#`,e.object_id]}):(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>n(e.memory_id),children:[`记忆 #`,e.memory_id]}),(0,x.jsxs)(`p`,{children:[Dn[e.phase]||e.phase,` ·`,` `,On[e.outcome]||e.outcome]}),typeof e.details.before==`number`&&(0,x.jsxs)(`p`,{children:[`保留强度:`,e.details.before,` → `,e.details.after]}),e.details.transition&&(0,x.jsxs)(`p`,{children:[`状态变为:`,E(e.details.transition)]}),e.details.source_memory_id!==void 0&&(0,x.jsxs)(`p`,{children:[`失效依据:记忆 #`,e.details.source_memory_id]}),e.reason&&(0,x.jsx)(`p`,{className:`danger-text`,children:kn[e.reason]||ce(e.reason)}),(0,x.jsx)(`small`,{children:w(e.created_at)})]},`${e.phase}:${e.item_key}`)),(0,x.jsx)(T,{total:t.length,offset:r,change:i})]})}var Fn={learning:`学习`,learning_repair:`学习 JSON 修正`,trial_reply:`试用回复`,trial_reply_repair:`回复 JSON 修正`,embedding:`向量生成`,image_understanding:`图片理解`,retrieval_query:`召回查询`,health_probe:`健康探测`,recall_judge:`召回判断`,goal_dedup_judge:`目标去重判断`,consolidation_merge:`整理合并判断`,consolidation_merge_repair:`整理合并 JSON 修正`,consolidation_conflict:`整理矛盾建议`,consolidation_conflict_repair:`整理矛盾 JSON 修正`,consolidation_dependency:`整理依赖复核`,consolidation_dependency_repair:`整理依赖 JSON 修正`,persona_generate:`persona 生成`,persona_check:`persona 检查`,connection_check:`连接测试`};function In({data:e,openMemory:t,initialQuery:n=``}){let r=y(`/catalog`),i=y(`/settings`,5e3);if(!e)return(0,x.jsx)(j,{title:`正在读取运行状态`});let a=Number(new URLSearchParams(n).get(`run`)),o=e.learning_latency_24h,s=e.models.find(e=>e.purpose===`image_understanding`),c=e.models.filter(e=>e.result_category!==`success`),l=new Map(r.data?.entries.map(e=>[e.id,e.name]));return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`page-heading`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`p`,{className:`eyebrow`,children:`每一步,都看得见`}),(0,x.jsx)(`h1`,{children:`运行状态`}),(0,x.jsx)(`p`,{children:`服务、模型和学习队列的当前情况。`})]}),(0,x.jsx)(M,{tone:e.scheduler.running?`green`:`danger`,children:e.scheduler.running?`调度运行中`:`调度未运行`})]}),(0,x.jsxs)(`div`,{className:`stat-grid`,children:[(0,x.jsxs)(`section`,{className:`panel metric`,children:[(0,x.jsx)(`span`,{children:`待学习消息`}),(0,x.jsx)(`strong`,{children:e.entries.reduce((e,t)=>e+t.pending_count,0)}),(0,x.jsxs)(`small`,{children:[e.scheduler.max_concurrent,` 个学习批次可同时运行`]})]}),(0,x.jsxs)(`section`,{className:`panel metric`,children:[(0,x.jsx)(`span`,{children:`今日 token 用量`}),(0,x.jsx)(`strong`,{children:e.usage.today.tokens.toLocaleString()}),(0,x.jsxs)(`small`,{children:[e.usage.today.calls,` 次请求 ·`,` `,e.usage.today.reasoning_tokens.toLocaleString(),` 推理 token(包含在总量内)`]})]}),(0,x.jsxs)(`section`,{className:`panel metric`,children:[(0,x.jsx)(`span`,{children:`近 24 小时学习 P95`}),(0,x.jsx)(`strong`,{children:C(o.p95_ms)}),(0,x.jsxs)(`small`,{children:[o.count,` 次学习调用`]})]}),(0,x.jsxs)(`section`,{className:`panel metric`,children:[(0,x.jsx)(`span`,{children:`近 24 小时学习超时`}),(0,x.jsx)(`strong`,{children:o.timeouts}),(0,x.jsxs)(`small`,{children:[`共享学习总预算 `,(0,x.jsxs)(`b`,{children:[e.timeouts_seconds.learning,` 秒`]})]})]})]}),(0,x.jsx)(Mn,{openMemory:t,initialRun:Number.isSafeInteger(a)&&a>0?a:void 0}),(0,x.jsxs)(`div`,{className:`status-grid`,children:[(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:`模型用途`}),(0,x.jsx)(`span`,{className:`muted`,children:`实时健康状态`})]}),Object.entries(e.model_health).map(([t,n])=>(0,x.jsxs)(`div`,{className:`model-row`,children:[(0,x.jsxs)(`div`,{className:`model-title`,children:[(0,x.jsx)(`strong`,{children:H[t]||t}),(0,x.jsx)(M,{tone:n.state===`normal`?`green`:`danger`,children:D(n.state)})]}),(0,x.jsx)(`p`,{className:`muted`,children:t===`chat`?`用于学习与角色回复`:t===`recall_judge`?`判断相关候选能否回答当前请求`:t===`goal_dedup_judge`?`跨入口判断目标是否为同一件事`:t===`image_understanding`?`为没有宿主说明的图片补充理解;失败时使用占位继续学习`:`用于记忆向量与语义检索`}),t===`recall_judge`&&(0,x.jsxs)(x.Fragment,{children:[e.timeouts_seconds.recall_judge!=null&&(0,x.jsxs)(`p`,{children:[`总预算 `,e.timeouts_seconds.recall_judge,` 秒(含排队)`]}),i.error&&(0,x.jsxs)(`p`,{className:`muted`,children:[`判断开关状态暂时无法读取。`,(0,x.jsx)(`button`,{onClick:i.refresh,children:`重新读取`})]}),i.data?.recall_judge?.enabled===!1?(0,x.jsx)(`p`,{children:`召回判断已关闭,保留基础召回。`}):n.state!==`normal`&&(0,x.jsx)(`p`,{children:`召回判断暂停或退避时降级,保留仍有效的原召回。`}),n.retry_at&&(0,x.jsxs)(`p`,{children:[`退避截止:`,S(n.retry_at)]}),(0,x.jsx)(`a`,{href:`#/settings`,children:`管理召回判断设置`})]}),t===`goal_dedup_judge`&&(0,x.jsxs)(x.Fragment,{children:[i.error&&(0,x.jsxs)(`p`,{className:`muted`,children:[`判断设置暂时无法读取。`,(0,x.jsx)(`button`,{onClick:i.refresh,children:`重新读取`})]}),i.data?.goal_dedup_judge&&(0,x.jsxs)(`p`,{children:[`判断预算 `,i.data.goal_dedup_judge.budget_seconds,` `,`秒(含排队) · 并发`,` `,i.data.goal_dedup_judge.concurrency,` · 排队上限`,` `,i.data.goal_dedup_judge.queue_limit]}),i.data?.goal_dedup_judge?.enabled===!1?(0,x.jsx)(`p`,{children:`目标去重判断已关闭,使用确定性规则。`}):(0,x.jsx)(`p`,{children:`模型暂停、退避或判断失败时先保留目标,等待复核。管理员创建的目标不会自动合并。`}),n.retry_at&&(0,x.jsxs)(`p`,{children:[`退避截止:`,S(n.retry_at)]}),(0,x.jsx)(`a`,{href:`#/settings`,children:`管理目标去重判断设置`})]}),t===`image_understanding`&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{children:[n.inherited?`沿用对话模型`:`使用独立图片理解配置`,` · 健康状态按图片理解用途独立记录。`]}),n.timeout_seconds!=null&&(0,x.jsxs)(`p`,{children:[`整批图片理解预算 `,n.timeout_seconds,` 秒(含排队与重试)`]}),n.retry_at&&(0,x.jsxs)(`p`,{children:[`退避截止:`,S(n.retry_at)]}),(0,x.jsx)(`a`,{href:`#/settings`,children:`管理图片理解设置`})]}),n.last_error&&(0,x.jsxs)(`p`,{className:`error-summary`,children:[`最近错误:`,n.last_error]}),n.next_probe_at&&(0,x.jsxs)(`small`,{children:[`下次探测:`,S(n.next_probe_at)]})]},t)),!e.model_health.image_understanding&&i.data?.models?.image_understanding?.enabled===!1&&(0,x.jsx)(`p`,{children:`图片理解未启用,没有宿主说明的图片以“未理解”占位继续学习。`}),(e.model_health.image_understanding||s||e.usage.by_purpose?.image_understanding)&&(0,x.jsxs)(`div`,{className:`model-row`,children:[(0,x.jsx)(`h3`,{children:`图片理解调用与用量`}),(0,x.jsx)(Tn,{value:e.usage.by_purpose?.image_understanding}),s&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{children:[`最近调用:`,s.model,` ·`,` `,C(s.duration_ms),` ·`,` `,s.result_category===`success`?`成功`:`未成功`]}),(0,x.jsx)(`p`,{className:`muted`,children:S(s.created_at)})]})]})]}),(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsx)(`h2`,{children:`用量与学习`}),(0,x.jsxs)(`dl`,{className:`status-facts`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`每日 token 上限`}),(0,x.jsx)(`dd`,{children:e.budget.limit==null?`不限`:e.budget.limit.toLocaleString()})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`未报告 token 的调用`}),(0,x.jsxs)(`dd`,{children:[e.usage.today.calls_without_usage,` 次`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`学习耗时 P50 / 最大`}),(0,x.jsxs)(`dd`,{children:[C(o.p50_ms),` / `,C(o.max_ms)]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`缺少向量的记忆`}),(0,x.jsxs)(`dd`,{children:[e.missing_vectors,` 条`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`记忆缺口`}),(0,x.jsxs)(`dd`,{children:[e.memory_gap_count,` 段`]})]})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`今日按角色时区统计。服务商未报告的用量和在途调用不计入已知总量;未配置价格,暂不估算费用。`})]})]}),(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:`入口队列`}),(0,x.jsx)(`span`,{className:`muted`,children:`接收、学习和形成记忆分别记录`})]}),e.entries.length?(0,x.jsx)(`div`,{className:`table-scroll`,children:(0,x.jsxs)(`table`,{children:[(0,x.jsx)(`thead`,{children:(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`th`,{children:`入口`}),(0,x.jsx)(`th`,{children:`待学习`}),(0,x.jsx)(`th`,{children:`当前批次`}),(0,x.jsx)(`th`,{children:`过滤与等待`}),(0,x.jsx)(`th`,{children:`最近结束的批次`}),(0,x.jsx)(`th`,{children:`未记住的消息`})]})}),(0,x.jsx)(`tbody`,{children:e.entries.map(e=>(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`td`,{children:l.get(e.entry_id)||e.entry_id}),(0,x.jsx)(`td`,{children:e.pending_count}),(0,x.jsx)(`td`,{children:k(e.current_batch)}),(0,x.jsx)(`td`,{children:(0,x.jsx)(Ze,{value:e.queue_wait})}),(0,x.jsx)(`td`,{children:k(e.latest_batch)}),(0,x.jsx)(`td`,{children:e.gap_message_count||0})]},e.entry_id))})]})}):(0,x.jsx)(`p`,{className:`quiet`,children:`暂无入口。`})]}),(0,x.jsxs)(`div`,{className:`status-grid`,children:[(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsx)(`h2`,{children:`最近学习调用`}),e.learning_calls_24h.length?(0,x.jsx)(`div`,{className:`call-list`,children:e.learning_calls_24h.slice(0,12).map((e,t)=>(0,x.jsxs)(`div`,{className:`call`,children:[(0,x.jsxs)(`span`,{children:[`批次 #`,e.batch_id,` · `,Fn[e.purpose]||e.purpose]}),(0,x.jsx)(`strong`,{children:C(e.duration_ms)}),e.timed_out?(0,x.jsx)(M,{tone:`danger`,children:`超时`}):e.error_summary?(0,x.jsx)(M,{tone:`danger`,children:`失败`}):(0,x.jsx)(M,{tone:`green`,children:`调用完成`}),e.error_summary&&(0,x.jsx)(`small`,{children:e.error_summary})]},t))}):(0,x.jsx)(`p`,{className:`quiet`,children:`近 24 小时没有学习调用。`}),(0,x.jsx)(`p`,{className:`fine-print`,children:`模型调用完成不等于批次成功;JSON 校验和记忆写入结果请看批次。`})]}),(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsx)(`h2`,{children:`错误摘要`}),(0,x.jsx)(`p`,{className:`muted section-help`,children:`来自现有状态接口的最近用途错误与调度错误`}),e.scheduler.last_error&&(0,x.jsx)(A,{error:!0,children:e.scheduler.last_error}),c.map(e=>(0,x.jsxs)(`div`,{className:`error-entry`,children:[(0,x.jsxs)(`strong`,{children:[Fn[e.purpose]||e.purpose,` · `,e.model]}),(0,x.jsx)(`p`,{children:e.error_summary||e.result_category}),(0,x.jsx)(`small`,{children:S(e.created_at)})]},e.purpose)),!c.length&&!e.scheduler.last_error&&(0,x.jsx)(`p`,{className:`quiet`,children:`最近的用途调用没有错误。`})]})]})]})}var Ln=e=>e.execution_state===`split`||e.state===`split`,Rn=e=>({full:`完整`,target_only:`仅目标`})[e||``]||`未记录`;function zn(e,t){return Ln(e)?[`waiting`,`running`].includes(e.state)?`拆小重学中`:e.state===`succeeded`?`拆小重学已完成`:e.state===`split`?`历史请求被拒绝 · 已拆分`:`拆小重学结束 · 仍有缺口`:e.parent_batch_id&&[`waiting`,`running`].includes(e.state)?`拆小重学中`:e.state===`refused`&&(t===1||t===void 0&&e.parent_batch_id)?`该单消息的学习请求被拒绝`:e.relearning?`重新学习中`:k(e)}function Bn(e){return new Set([...e.attempts.flatMap(e=>e.calls.map(e=>e.id)),...e.unassigned_calls.map(e=>e.id)]).size}function Vn({batch:e}){let t=e.split;if(!t)return null;let n=t.waiting_messages+t.running_messages,r=t.refused_messages+t.abandoned_messages,i=n+r+t.succeeded_messages,a=e.state===`succeeded`&&n===0&&r===0&&t.gap_count===0;return(0,x.jsxs)(`div`,{className:`split-progress`,children:[(0,x.jsxs)(`div`,{className:`split-metrics`,"aria-label":`子树消息进度`,children:[(0,x.jsxs)(`span`,{children:[e.parent_batch_id?`本子树目标`:`原目标`,` `,i,` 条`]}),(0,x.jsxs)(`span`,{children:[`已成功 `,t.succeeded_messages,` 条`]}),(0,x.jsxs)(`span`,{children:[`仍在补学 `,n,` 条`]}),(0,x.jsxs)(`span`,{children:[`最终被拒绝 `,t.refused_messages,` 条`]}),(0,x.jsxs)(`span`,{children:[`最终失败 `,r,` 条`]}),(0,x.jsxs)(`span`,{children:[`剩余缺口 `,t.gap_count,` 处`]})]}),(0,x.jsxs)(`p`,{children:[`批次树节点 `,t.node_count,` 个`]}),(0,x.jsx)(`p`,{className:`muted`,children:`消息结果仅统计末端子批次;最终失败包含拒绝与尝试用尽。父批次的历史拒绝单独保留。`}),a&&(0,x.jsx)(`p`,{className:`split-complete`,children:`全部成功,无缺口`}),!a&&(0,x.jsx)(`p`,{children:`缺口在对应子批次成功后消失;每处缺口可能包含多条消息。`})]})}function Hn({batch:e,onOpen:t}){return e.parent_batch_id?(0,x.jsxs)(`div`,{className:`batch-links`,children:[e.root_batch_id&&(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>t(e.root_batch_id),"aria-label":`查看原始批次 #${e.root_batch_id}`,children:[`原始批次 #`,e.root_batch_id,` →`]}),e.parent_batch_id!==e.root_batch_id&&(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>t(e.parent_batch_id),"aria-label":`查看父批次 #${e.parent_batch_id}`,children:[`父批次 #`,e.parent_batch_id,` →`]}),(0,x.jsxs)(`span`,{children:[`路径 `,e.split_path]})]}):null}function Un(e){return e.count?`第 ${e.start+1}${e.count>1?`–${e.end}`:``} 条 · 共 ${e.count} 条`:`没有目标消息`}function Wn({id:e}){let t=y(`/batches/${e}/tree?limit=1&offset=0`,3e3),n=t.data?.items.find(t=>t.id===e);return(0,x.jsxs)(x.Fragment,{children:[t.error&&(0,x.jsxs)(A,{error:!0,children:[t.error,(0,x.jsx)(`button`,{onClick:t.refresh,children:`重试读取目标范围`})]}),n&&(0,x.jsxs)(`p`,{children:[`原始目标范围:`,Un(n.target_range)]})]})}function Gn({batch:e}){let t=Ln(e);return(0,x.jsxs)(`div`,{className:`batch-node-facts`,children:[(0,x.jsxs)(`p`,{children:[`上下文模式:`,Rn(e.context_mode)]}),t?(0,x.jsxs)(`p`,{children:[`拆分前已计 `,e.attempt_count??0,` 次尝试;执行已交给子批次。`]}):(0,x.jsxs)(`p`,{children:[`当前额度:已用 `,e.attempt_count??0,` / 4,剩余`,` `,e.attempts_remaining??Math.max(0,4-(e.attempt_count??0)),` `,`次`]}),e.state===`waiting`&&!t&&(0,x.jsx)(`p`,{children:`排队原因未提供;请结合入口和运行状态查看。`}),!t&&(0,x.jsxs)(`p`,{children:[`下次重试:`,e.next_retry_at?S(e.next_retry_at):`无定时时间`]})]})}function Kn({id:e}){let t=y(`/batches/${e}`,3e3);return(0,x.jsxs)(x.Fragment,{children:[t.error&&(0,x.jsxs)(A,{error:!0,children:[t.error,(0,x.jsx)(`button`,{onClick:t.refresh,children:`重试读取历史`})]}),t.data?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{children:[`历史尝试编号:`,t.data.attempts.length?t.data.attempts.map(e=>e.number).join(`、`):`暂无已完成尝试`]}),(0,x.jsxs)(`p`,{children:[`本节点实际模型调用 `,Bn(t.data),` 次`]}),(0,x.jsx)(`p`,{className:`muted`,children:`含学习与 JSON 修正请求及未归入尝试的调用;不等于本轮已用额度。`})]}):(0,x.jsx)(`p`,{children:`正在读取历史…`})]})}function qn({id:e}){let[t,n]=(0,l.useState)(!1);return(0,x.jsxs)(`details`,{className:`node-history`,onToggle:e=>n(e.currentTarget.open),children:[(0,x.jsxs)(`summary`,{children:[`历史尝试与调用 · #`,e]}),t&&(0,x.jsx)(Kn,{id:e})]})}function Jn({id:e,onOpen:t}){let[n,r]=(0,l.useState)(!1),[i,a]=(0,l.useState)(0),[o,s]=(0,l.useState)([]),c=y(n?`/batches/${e}/tree?limit=100&offset=${i}`:null,3e3),u=c.data;return(0,x.jsxs)(`div`,{className:`split-tree`,children:[(0,x.jsx)(`button`,{className:`secondary`,"aria-expanded":n,"aria-controls":`split-tree-${e}`,"aria-label":`${n?`收起`:`展开`}拆分树 #${e}`,onClick:()=>r(!n),children:n?`收起拆分树`:`展开拆分树`}),n&&(0,x.jsxs)(`section`,{id:`split-tree-${e}`,"aria-label":`拆分树 #${e}`,children:[(0,x.jsx)(`p`,{className:`muted`,children:`范围按原始批次的目标消息顺序,从第 1 条开始;路径中 0 为左支、1 为右支。节点可展开历史尝试,或进入详情查看消息与调用。`}),c.error&&(0,x.jsxs)(A,{error:!0,children:[c.error,(0,x.jsx)(`button`,{onClick:c.refresh,children:`重试读取拆分树`})]}),u?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{children:[`显示节点 `,u.total?u.offset+1:0,`–`,u.offset+u.items.length,` / `,u.total]}),(0,x.jsx)(`ol`,{className:`batch-tree-nodes`,children:u.items.filter(e=>!o.some(t=>e.split_path!==t&&e.split_path?.startsWith(t))).map(n=>{let r=Ln(n),i=n.split_path||``,a=n.target_range,c=o.includes(i);return(0,x.jsxs)(`li`,{className:`batch-tree-node`,style:{"--tree-depth":Math.min(i.length,3)},children:[(0,x.jsxs)(`div`,{className:`section-title`,children:[(0,x.jsxs)(`strong`,{children:[`#`,n.id,` · `,r?`拆分父批次`:`子批次`]}),(0,x.jsx)(M,{children:zn(n,a.count)})]}),(0,x.jsx)(`p`,{children:Un(a)}),(0,x.jsxs)(`p`,{children:[`路径 `,i||`根`]}),n.parent_batch_id&&(0,x.jsxs)(`button`,{className:`text-button`,"aria-label":`查看父批次 #${n.parent_batch_id}`,onClick:()=>t(n.parent_batch_id),children:[`父批次 #`,n.parent_batch_id,` →`]}),(0,x.jsx)(Gn,{batch:n}),n.gap&&(0,x.jsxs)(`p`,{children:[`仍有记忆缺口`,[`waiting`,`running`].includes(n.state)?` · 拆小重学中`:``]}),n.relearn_blocked_reason&&!r&&(0,x.jsx)(`p`,{children:n.relearn_blocked_reason}),(0,x.jsxs)(`div`,{className:`batch-links`,children:[r&&(0,x.jsx)(`button`,{className:`text-button`,"aria-expanded":!c,"aria-label":`${c?`展开`:`折叠`}子批次 #${n.id}`,onClick:()=>s(c?o.filter(e=>e!==i):[...o,i]),children:c?`展开子批次`:`折叠子批次`}),n.id!==e&&(0,x.jsxs)(`button`,{className:`text-button`,"aria-label":`查看批次 #${n.id}`,onClick:()=>t(n.id),children:[`查看详情`,n.can_relearn&&!r?` / 重新学习`:``,` `,`→`]})]}),(0,x.jsx)(qn,{id:n.id})]},n.id)})}),u.total>u.limit&&(0,x.jsxs)(`div`,{className:`learning-pagination tree-pagination`,children:[(0,x.jsx)(`button`,{disabled:u.offset===0,onClick:()=>{a(Math.max(0,u.offset-u.limit)),s([])},children:`上一页节点`}),(0,x.jsx)(`button`,{disabled:u.offset+u.items.length>=u.total,onClick:()=>{a(u.offset+u.limit),s([])},children:`下一页节点`})]}),(0,x.jsx)(`p`,{className:`muted`,children:`分页统计的是批次树节点;实际模型调用次数在各节点历史中单独显示。`})]}):(0,x.jsx)(`p`,{children:`正在读取拆分树…`})]})]})}var Yn={topic:`常聊话题`,saying:`群内说法`,rule:`明确群规`};function Xn({value:e}){return e.kind?(0,x.jsxs)(`div`,{className:`profile-item-content`,children:[(0,x.jsxs)(`p`,{children:[(0,x.jsx)(M,{children:Yn[e.kind]||e.kind}),` `,(0,x.jsx)(`strong`,{children:e.label})]}),e.meaning&&(0,x.jsxs)(`p`,{children:[`含义:`,e.meaning]}),e.quotes?.map((e,t)=>(0,x.jsxs)(`blockquote`,{children:[e.text,(0,x.jsxs)(`footer`,{children:[`消息 #`,e.message_id,` ·`,` `,e.field===`content`?`消息正文`:e.field===`quote`?`转引原话`:`原话归属未记录`,` `,`· 原作者:`,e.speaker_name||e.speaker||`未记录`]})]},t))]}):(0,x.jsx)(`p`,{className:`entry-profile-content`,children:e.text})}var Zn=e=>({small:`小`,medium:`中`,large:`大`})[e]||e,Qn=e=>({periodic:`定期更新`,regenerate:`重新生成`,edit:`管理员编辑`,rollback:`回滚`})[e]||e,$n=e=>({published:`已发布`,candidate:`待确认`,rejected:`被拒绝`,failed:`失败`,conflict:`版本冲突`,skipped:`已跳过`})[e]||e,er={message_cleaned:`原消息已清理`,message_changed:`原消息已变化`,memory_unavailable:`记忆已失效或删除`,memory_changed:`记忆已修改`,visibility_changed:`记忆可见范围已变化`,memory_sources_changed:`记忆来源已变化`,disabled:`本入口画像已关闭`,entry_kind:`私聊入口不生成画像`,daily_limit:`今天已经尝试过生成,请在下一个角色本地日期重试`,insufficient_messages:`首次生成需要最近 14 天至少 50 条消息`,no_evidence:`没有可用的本入口依据`,unconfigured:`尚未配置对话模型`,daily_token_limit:`达到今日 token 上限`,current_version_changed:`当前已发布版本已变化,结果未发布`,settings_changed:`画像设置已变化,结果未发布`,evidence_changed:`依据在生成期间发生变化,结果未发布`,interrupted:`服务中断,任务未完成`,unexpected_error:`生成失败,请查看运行状态`,timeout:`模型调用超时`,invalid_output:`模型输出格式无效,未发布`,invalid_sentence:`候选句格式无效`,too_many_deleted:`检查删除了超过 30% 的候选句`,too_short:`正文低于旧版摘要的最少字数要求`,too_long:`正文超过该版本的字数上限`,superseded:`已被新候选或编辑取代`,paused:`对话用途已暂停`,invalid_items:`候选条目列表格式无效`,invalid_item:`条目类型、名称或含义格式无效`,invalid_quotes:`每个模型条目需要 1—3 条引语`,invalid_quote:`引语格式无效或超过 100 字`,invalid_quote_reference:`引语消息编号不在本入口材料中`,quote_not_found:`引语不是消息正文或转引原话的连续片段`,invalid_evidence_reference:`含义引用的记忆依据无效`,duplicate_item:`条目重复`,account_identifier:`包含账号标识或长数字号段`,insufficient_topic_recurrence:`常聊话题缺少跨日期的独立消息正文依据`,too_many_items:`条目数超过 6 条(包含手写条目)`,token_budget:`超过画像的估算 token 预算`,empty:`检查后没有可保留内容`,administrator_rejected:`管理员拒绝`},tr=(e,t)=>e===`too_many_deleted`?t===2?`检查累计删除了超过 50% 的模型条目`:t===1?`检查删除了超过 30% 的候选句`:`检查删除比例超出该版本上限,请查看版本检查记录`:er[e]||e,nr=e=>e.memory_id?`记忆 #${e.memory_id} · 修订 ${e.revision}`:`消息 #${e.message_id}`,rr={evidence_budget_exceeded:`必要依据超出单次检查预算,暂不能完成这次检查`,basis_changed:`依据已变化,需要重新检查`,reject:`本次自动检查未通过`,invalid_output:`模型返回的检查结果格式无效,未据此准入`,timeout:`本次模型调用超时,已保留此前处理结果`,rule_scope_not_established:`尚未建立这条群规的适用范围依据`,bundle_rejected:`同组检查已有页面未通过,后续页已取消`,stale_check:`检查所用的正文或依据已变化,需要重新检查`,call_budget:`本轮调用额度已用完,剩余工作留待后续处理`,purged:`相关内容已彻底清除,本项停止处理`,merged_basis:`合并后的依据需要重新检查`,no_new_evidence:`没有新依据,本次跳过;不会重复增加保留强度。`,snapshot_changed:`依据或画像已变化,本次结果未写入。`},ir=e=>e.startsWith(`unbound_entities:`)?`相关对象缺少绑定依据:${e.slice(17).split(`,`).join(`、`)}`:rr[e]||tr(e),ar=e=>({manual:`人工条目`,candidate:`候选`,pending:`等待自动检查`,accepted:`已准入`,rejected:`检查未通过`})[e]||e;function or({base:e,openMemory:t}){let[n,r]=(0,l.useState)(0),i=y(`${e}/versions?limit=10&offset=${n}`),[a,o]=(0,l.useState)(null),s=(0,l.useRef)(null),c=y(a===null?null:`${e}/versions/${a}`),[u,d]=(0,l.useState)(`1`),[f,p]=(0,l.useState)(`2`),[m,h]=(0,l.useState)(null),g=y(m),_=e=>{o(e),requestAnimationFrame(()=>s.current?.scrollIntoView?.({behavior:`smooth`,block:`start`}))};return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`section`,{className:`entry-profile-section`,"aria-label":`历史(旧形式)`,children:[(0,x.jsx)(`h3`,{children:`历史(旧形式)`}),(0,x.jsx)(`p`,{className:`muted`,children:`旧版本只读,保留原有依据与检查记录;不能回滚,也不再确认或拒绝候选。这里的版本号与宿主投影版本无关。`}),i.error&&(0,x.jsxs)(A,{error:!0,children:[i.error,(0,x.jsx)(`button`,{onClick:i.refresh,children:`重试历史`})]}),i.data?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`ul`,{className:`entry-profile-history`,children:i.data.items.map(e=>(0,x.jsxs)(`li`,{children:[(0,x.jsxs)(`div`,{children:[(0,x.jsxs)(`strong`,{children:[`v`,e.version]}),` · `,$n(e.status),` ·`,` `,Qn(e.source),` · 变化`,Zn(e.change_degree),(0,x.jsx)(`p`,{className:`muted`,children:w(e.generated_at)})]}),(0,x.jsxs)(`button`,{className:`secondary`,onClick:()=>_(e.version),children:[`查看旧版 v`,e.version]})]},e.version))}),!i.data.items.length&&(0,x.jsx)(`p`,{children:`还没有版本记录。`}),(0,x.jsx)(T,{total:i.data.total,offset:n,limit:10,change:r})]}):(0,x.jsx)(`p`,{children:`正在读取历史…`}),(0,x.jsxs)(`form`,{className:`entry-profile-compare`,onSubmit:t=>{t.preventDefault(),h(`${e}/diff?before_version=${Number(u)}&after_version=${Number(f)}`),g.refresh()},children:[(0,x.jsxs)(`label`,{children:[`对比起始版本`,(0,x.jsx)(`input`,{type:`number`,required:!0,min:1,max:2**53-1,value:u,onChange:e=>d(e.target.value)})]}),(0,x.jsxs)(`label`,{children:[`对比目标版本`,(0,x.jsx)(`input`,{type:`number`,required:!0,min:1,max:2**53-1,value:f,onChange:e=>p(e.target.value)})]}),(0,x.jsx)(`button`,{children:`逐句对比`})]}),g.error&&(0,x.jsx)(A,{error:!0,children:g.error}),g.data&&(0,x.jsxs)(`div`,{"aria-label":`逐句差异`,children:[!g.data.changed&&(0,x.jsx)(`p`,{children:`两版内容与依据相同。`}),g.data.sentences.map((e,t)=>(0,x.jsxs)(`div`,{className:`entry-profile-diff ${e.op}`,children:[(0,x.jsx)(`strong`,{children:{equal:JSON.stringify(e.before)===JSON.stringify(e.after)?`保留`:`依据或手写标记变化`,replace:`改写`,insert:`新增`,delete:`删除`}[e.op]||e.op}),e.op===`equal`&&JSON.stringify(e.before)===JSON.stringify(e.after)?e.after.map((e,t)=>(0,x.jsx)(cr,{value:e},t)):(0,x.jsxs)(`div`,{className:`entry-profile-diff-columns`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h4`,{children:`起始版本`}),e.before.map((e,t)=>(0,x.jsx)(cr,{value:e},t))]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h4`,{children:`目标版本`}),e.after.map((e,t)=>(0,x.jsx)(cr,{value:e},t))]})]})]},t))]})]}),a!==null&&(0,x.jsxs)(`section`,{ref:s,className:`entry-profile-section`,"aria-label":`旧版详情`,children:[(0,x.jsxs)(`h3`,{children:[`旧版 v`,a,` 的依据与检查`]}),(0,x.jsx)(M,{children:`只读历史`}),c.error?(0,x.jsxs)(A,{error:!0,children:[c.error,(0,x.jsx)(`button`,{onClick:c.refresh,children:`重试版本详情`})]}):c.data?(0,x.jsx)(sr,{value:c.data,openMemory:t}):(0,x.jsx)(`p`,{children:`正在读取版本…`})]})]})}function sr({value:e,openMemory:t}){let n=e.checks,r=n.model,i=n.format_version||1,a=n.reason!==`invalid_output`&&r&&typeof r.reason==`string`&&Array.isArray(r.sentences)&&r.sentences.length===n.checked_sentences?.length&&r.sentences.every((e,t)=>e&&typeof e==`object`&&e.index===t+1&&typeof e.supported==`boolean`&&typeof e.scene_qualified==`boolean`&&typeof e.reason==`string`&&Array.isArray(e.violations)&&e.violations.every(e=>typeof e==`string`));return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{children:[$n(e.status),` · `,Qn(e.source),` · 变化`,Zn(e.change_degree),` · `,w(e.generated_at)]}),i===1&&(0,x.jsx)(M,{children:`旧版摘要`}),e.redacted&&(0,x.jsxs)(A,{children:[`此旧版本的相关内容已彻底清除。`,e.redaction_reason&&`原因:${e.redaction_reason}`]}),e.possibly_stale&&(0,x.jsx)(A,{children:`此版本依据可能过时。`}),(0,x.jsx)(`ol`,{className:`entry-profile-sentences`,children:e.sentences.map((e,n)=>(0,x.jsxs)(`li`,{children:[(0,x.jsx)(Xn,{value:e}),(0,x.jsx)(M,{children:e.admin_written?`管理员手写 · 受保护`:`模型生成`}),e.admin_written&&!e.basis.length&&(0,x.jsx)(`p`,{className:`muted`,children:`管理员直接提供,无模型依据。`}),e.basis.map((e,n)=>(0,x.jsxs)(`div`,{className:`entry-profile-evidence`,children:[e.memory_id?(0,x.jsx)(`button`,{className:`text-button`,onClick:()=>t(e.memory_id),children:nr(e)}):(0,x.jsx)(`strong`,{children:nr(e)}),e.evidence?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`p`,{children:e.evidence.content}),e.evidence.occurred_at&&(0,x.jsx)(`small`,{children:w(e.evidence.occurred_at)}),e.evidence.source_messages?.map(e=>(0,x.jsxs)(`blockquote`,{children:[e.content,(0,x.jsxs)(`footer`,{children:[`本入口原消息 #`,e.message_id,` ·`,` `,w(e.occurred_at)]})]},e.message_id))]}):(0,x.jsx)(`p`,{children:`此版本未保存来源摘录,可按依据编号核对历史。`}),e.memory&&(0,x.jsxs)(`small`,{children:[`当前修订 `,e.memory.revision,` ·`,` `,{active:`有效`,forgotten:`已遗忘`,deleted:`已删除`}[e.memory.lifecycle]||e.memory.lifecycle]})]},n))]},n))}),(0,x.jsxs)(`h4`,{children:[`检查结果:`,n.passed?`通过`:`未通过`]}),n.reason&&(0,x.jsx)(`p`,{children:tr(n.reason,i)}),n.quote_validation&&(0,x.jsxs)(`p`,{children:[`引用原话核对:`,n.quote_validation.passed,` /`,` `,n.quote_validation.total,` `,`条通过(含被删条目的引语;不代表语义支持)`]}),!!n.quote_validation_items?.length&&(0,x.jsxs)(`details`,{children:[(0,x.jsx)(`summary`,{children:`逐条引用核对`}),(0,x.jsx)(`ul`,{children:n.quote_validation_items.map(e=>(0,x.jsxs)(`li`,{children:[`候选第 `,e.index,` 项:`,e.passed,` / `,e.total,` 条原话通过`,e.quotes.filter(e=>!e.passed).map(e=>(0,x.jsxs)(`p`,{children:[`引语 `,e.index,`:`,tr(e.reason||`invalid_quote`,i)]},e.index))]},e.index))})]}),n.deterministic?.characters!=null&&(0,x.jsxs)(`p`,{children:[`正文 `,n.deterministic.characters,` 字 ·`,` `,n.deterministic.tokens??`未记录`,` 估算 token`]}),(0,x.jsxs)(`p`,{children:[`确定性检查:`,n.deterministic?.passed?`通过`:`存在删句或错误,见下方记录`]}),n.errors?.length?(0,x.jsx)(`ul`,{children:n.errors.map((e,t)=>(0,x.jsx)(`li`,{children:tr(e,i)},t))}):null,a&&r?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{children:[`模型判断:`,r.reason]}),(0,x.jsx)(`ol`,{children:r.sentences.map((e,t)=>(0,x.jsxs)(`li`,{children:[(0,x.jsx)(`p`,{children:n.checked_sentences?.[t]?.text}),(0,x.jsxs)(`p`,{children:[`依据`,e.supported?`支持`:`不支持`,` · 场景限定`,e.scene_qualified?`通过`:`未通过`,` ·`,` `,n.checked_sentences?.[t]?.meaning&&typeof e.meaning_supported==`boolean`?`含义${e.meaning_supported?`有依据`:`无依据,已移除`} · `:``,e.violations.length?e.violations.join(`、`):`未发现禁止内容`]}),(0,x.jsx)(`p`,{children:e.reason})]},e.index))})]}):(0,x.jsx)(`p`,{children:r?`模型检查输出格式无效,本版未通过检查。`:n.admin_edit?`管理员编辑只做确定性检查。`:`本版未执行模型检查。`}),!!n.removed_meanings?.length&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`h4`,{children:`已删含义记录`}),(0,x.jsx)(`p`,{children:`说法本身可以保留;没有含义不表示生成失败。`}),(0,x.jsx)(`ul`,{children:n.removed_meanings.map((e,t)=>(0,x.jsxs)(`li`,{children:[`候选第 `,e.index,` 项:`,e.meaning,(0,x.jsx)(`p`,{children:tr(e.reason,i)})]},t))})]}),!!n.admin_warnings?.length&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`h4`,{children:`手写条目检查提醒`}),(0,x.jsx)(`ul`,{children:n.admin_warnings.map((e,t)=>(0,x.jsxs)(`li`,{children:[`第 `,e.index,` 项:`,e.result.violations.join(`、`),` ·`,` `,e.result.reason]},t))})]}),!!n.deleted_sentences?.length&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`h4`,{children:i===2?`已删条目记录`:`已删句记录`}),(0,x.jsx)(`ul`,{children:n.deleted_sentences.map((e,t)=>(0,x.jsxs)(`li`,{children:[(0,x.jsx)(`p`,{children:typeof e.sentence?.text==`string`?e.sentence.text:`候选第 ${e.index} 项`}),(0,x.jsxs)(`p`,{children:[e.stage===`deterministic`?`引用与格式核对:`:e.stage===`model`?`模型检查:`:``,tr(e.reason,i)]})]},t))})]})]})}function cr({value:e}){return(0,x.jsxs)(`div`,{children:[(0,x.jsx)(Xn,{value:e}),(0,x.jsxs)(`small`,{children:[e.author===`admin`?`管理员手写`:`模型生成`,e.basis?.length?` · ${e.basis.map(nr).join(`;`)}`:``]})]})}var lr={topic:`话题`,saying:`说法`,rule:`群规`},ur=e=>e?lr[e]:`管理员说明`;function dr({entry:e,blocked:t,busy:n,write:r,cancel:i,created:a}){let[o,s]=(0,l.useState)(`rule`),[c,u]=(0,l.useState)(``),[d,f]=(0,l.useState)(``);return(0,x.jsxs)(`form`,{className:`profile-memory-card`,"aria-label":`人工新建画像记忆`,onSubmit:async n=>{if(n.preventDefault(),!(t||!c.trim()||Array.from(c).length>1e3)){f(``);try{await r(`/memories`,`POST`,{kind:`入口画像`,owner_entry_id:e.id,category:o,content:c}),a()}catch(e){f(v(e))}}},children:[(0,x.jsx)(`h4`,{children:`人工新建画像记忆`}),(0,x.jsxs)(`p`,{children:[`仅用于入口“`,e.name,`”。人工内容无需模型依据。`]}),d&&(0,x.jsx)(A,{error:!0,children:d}),(0,x.jsxs)(`label`,{children:[`子类`,(0,x.jsxs)(`select`,{"aria-label":`子类`,value:o||``,disabled:n,onChange:e=>s(e.target.value||null),children:[Object.entries(lr).map(([e,t])=>(0,x.jsx)(`option`,{value:e,children:t},e)),(0,x.jsx)(`option`,{value:``,children:`管理员说明`})]})]}),(0,x.jsxs)(`label`,{children:[`新画像正文`,(0,x.jsx)(`textarea`,{"aria-label":`新画像正文`,rows:4,maxLength:1e3,value:c,disabled:n,onChange:e=>u(e.target.value)})]}),(0,x.jsxs)(`p`,{className:`fine-print`,children:[Array.from(c).length,` / 1000 字`]}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{disabled:t||!c.trim()||Array.from(c).length>1e3,children:`创建画像记忆`}),(0,x.jsx)(`button`,{type:`button`,className:`secondary`,disabled:n,onClick:i,children:`取消新建`})]})]})}function fr({id:e,revision:t,message:n,openMemory:r,speakerNames:i,pendingSources:a}){let o=y(`/memories/${e}`),s=(0,l.useRef)(null);return(0,l.useEffect)(()=>{o.refresh()},[t,o.refresh]),(0,l.useEffect)(()=>{o.data&&n!==null&&(s.current?.scrollIntoView?.({behavior:`smooth`,block:`start`}),s.current?.focus({preventScroll:!0}))},[o.data,n]),(0,x.jsxs)(`div`,{className:`profile-memory-evidence`,children:[o.error&&(0,x.jsxs)(A,{error:!0,children:[o.error,(0,x.jsx)(`button`,{onClick:o.refresh,children:`重试来源与修订`})]}),o.data?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`h4`,{children:`来源消息与前后文`}),!o.data.sources.length&&(0,x.jsx)(`p`,{children:`没有保存的来源消息。`}),o.data.sources.map(e=>(0,x.jsxs)(`section`,{ref:e.message_id===n?s:null,tabIndex:-1,className:e.message_id===n?`profile-source-target`:``,"aria-label":e.message_id?`来源消息 #${e.message_id}`:`来源 #${e.id}`,children:[e.message_id&&(0,x.jsxs)(`h5`,{children:[`消息 #`,e.message_id]}),a.some(t=>t.message.position===e.message_id)&&(0,x.jsx)(A,{children:`该消息含待审引文,请以上方已审/待审分区为准`}),(0,x.jsx)(Yt,{source:e,openMemory:r,initiallyOpen:e.message_id===n,speakerNames:i},`${e.id}:${e.message_id===n}`)]},e.id)),n!==null&&!o.data.sources.some(e=>e.message_id===n)&&(0,x.jsx)(A,{children:`该来源已变化或不可用,请刷新画像核对。`}),(0,x.jsxs)(`h4`,{children:[`修订历史 · `,o.data.revisions.length]}),o.data.revisions.length?o.data.revisions.map(e=>(0,x.jsx)(Xt,{revision:e},e.id)):(0,x.jsx)(`p`,{children:`还没有修订记录。`})]}):!o.error&&(0,x.jsx)(`p`,{children:`正在读取来源与修订…`})]})}function pr({memory:e,speakerNames:t,displayed:n,blocked:r,busy:i,write:a,refresh:o,openMemory:s}){let[c,u]=(0,l.useState)(null),[d,p]=(0,l.useState)(null),[m,h]=(0,l.useState)(!1),[g,_]=(0,l.useState)(``),[y,b]=(0,l.useState)(``),[S,C]=(0,l.useState)(!1),[T,D]=(0,l.useState)(null),O=!!c&&c.revision!==e.revision,k=e.lifecycle===`deleted`;function j(e){e instanceof f&&e.status===409?(h(!0),_(`这条画像记忆已变化,草稿已保留。请核对最新正文与修订后继续。`)):e instanceof f&&e.status===404?(h(!0),_(`这条画像记忆已不可用,草稿已保留。请复制需要保留的内容后关闭。`)):_(v(e))}async function N(t,n,i,o){if(!r){_(``),b(``);try{await a(`/memories/${e.memory_id}${n}`,t,i),u(null),p(null),h(!1),b(o)}catch(e){j(e)}}}return(0,x.jsxs)(`article`,{id:`profile-memory-${e.memory_id}`,className:`profile-memory-card`,"aria-label":`画像记忆 #${e.memory_id}`,children:[(0,x.jsxs)(`div`,{className:`detail-badges`,children:[(0,x.jsx)(M,{tone:`purple`,children:ur(e.category)}),(0,x.jsx)(M,{children:e.author===`admin`?`人工`:`模型`}),(0,x.jsx)(M,{children:ar(e.admission_state)}),e.manual_protected&&(0,x.jsx)(M,{children:`人工保护`}),(0,x.jsx)(M,{tone:k?`danger`:``,children:E(e.lifecycle)}),(0,x.jsxs)(`span`,{className:`muted`,children:[`#`,e.memory_id,` · 修订 `,e.revision]})]}),(0,x.jsx)(`p`,{className:`entry-profile-content`,children:e.body}),e.admission_state===`candidate`&&(0,x.jsx)(A,{children:`还在等待更多独立讨论,暂不给宿主看`}),e.admission_state===`pending`&&(0,x.jsx)(A,{children:`正在排队或自动检查,全部检查页通过前暂不给宿主看。`}),e.admission_state===`rejected`&&(0,x.jsx)(A,{children:`自动检查未通过,暂不给宿主看;后续由系统继续处理新依据。`}),e.admission_reason&&(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`p`,{children:ir(e.admission_reason)}),e.admission_state===`manual`&&(0,x.jsx)(`p`,{className:`fine-print`,children:`这是自动依据检查记录,不影响人工正文的使用。`}),e.admission_state===`accepted`&&(0,x.jsx)(`p`,{className:`fine-print`,children:`后续检查记录不代表已准入正文被撤下,是否展示请看宿主投影。`})]}),(0,x.jsxs)(`dl`,{className:`profile-memory-metadata`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`保留强度`}),(0,x.jsxs)(`dd`,{children:[e.retention,e.pinned?` · 已置顶`:``]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`最近确认时间`}),(0,x.jsx)(`dd`,{children:e.last_confirmed_at?w(e.last_confirmed_at):`暂无确认记录`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`独立日期`}),(0,x.jsxs)(`dd`,{children:[e.independent_days,` 天`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`独立依据`}),(0,x.jsxs)(`dd`,{children:[e.independent_uses,` 次`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`宿主投影`}),(0,x.jsx)(`dd`,{children:n?`已加入`:e.usable?`当前未加入`:`当前不可用`})]})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`独立日期按角色时区统计;独立依据已排除转引、复述等重复讨论,不等于消息总数。`}),(0,x.jsxs)(`div`,{"aria-label":`依据原话`,children:[(0,x.jsxs)(`h4`,{children:[`已审依据 · `,e.sources.length,` 条`]}),e.sources.map((e,n)=>(0,x.jsxs)(`blockquote`,{children:[(0,x.jsx)(`p`,{children:e.excerpt}),(0,x.jsxs)(`footer`,{children:[e.field===`quote`?`转引原话`:`消息正文`,` · 原作者:`,t[e.speaker]||e.speaker,` ·`,` `,w(e.message.occurred_at)]}),(0,x.jsxs)(`button`,{className:`text-button`,disabled:i,onClick:()=>{D(e.message.position),C(!0)},children:[`跳转来源消息 #`,e.message.position]})]},`${e.ref}:${n}`)),!e.sources.length&&(0,x.jsx)(`p`,{className:`muted`,children:e.author===`admin`?`管理员手写,无需模型依据。`:`当前没有可用的绑定原话,可在来源与修订历史中核对。`})]}),!!e.pending_sources.length&&(0,x.jsxs)(`section`,{"aria-label":`待审来源`,className:`profile-pending-sources`,children:[(0,x.jsxs)(`h4`,{children:[`待审来源 · `,e.pending_sources.length,` 条`]}),(0,x.jsxs)(`p`,{className:`fine-print`,children:[`这些引文尚未完成自动准入检查,不作为已审依据。`,e.admission_state===`manual`?`人工正文照常可用,无需等待这些引文。`:`通过检查后才可能成为可展示画像的依据。`]}),e.pending_sources.map((e,n)=>(0,x.jsxs)(`blockquote`,{children:[(0,x.jsx)(`p`,{children:e.excerpt}),(0,x.jsxs)(`footer`,{children:[e.field===`quote`?`转引原话`:`消息正文`,` · 原作者:`,t[e.speaker]||e.speaker,` ·`,` `,w(e.message.occurred_at)]}),(0,x.jsxs)(`button`,{className:`text-button`,disabled:i,onClick:()=>{D(e.message.position),C(!0)},children:[`跳转来源消息 #`,e.message.position]})]},`${e.ref}:${n}`))]}),g&&(0,x.jsxs)(A,{error:!0,children:[g,(0,x.jsx)(`button`,{className:`text-button`,disabled:i,onClick:()=>{o(),!c&&d===null&&(h(!1),_(``))},children:`刷新画像记忆`})]}),y&&(0,x.jsx)(A,{children:y}),c&&(0,x.jsxs)(`form`,{onSubmit:e=>{e.preventDefault(),!r&&!m&&!O&&!k&&c.content.trim()&&N(`PATCH`,``,{expected_revision:c.revision,content:c.content},`修改已保存。`)},children:[(0,x.jsxs)(`label`,{children:[`画像正文`,(0,x.jsx)(`textarea`,{"aria-label":`画像正文`,value:c.content,disabled:i,rows:4,maxLength:1e3,onChange:e=>u({...c,content:e.target.value})})]}),(0,x.jsxs)(`p`,{className:`fine-print`,children:[`草稿基于修订 `,c.revision,` · `,Array.from(c.content).length,` / 1000 字`]}),(O||m)&&(0,x.jsxs)(A,{children:[`草稿未被替换。上方显示当前修订 `,e.revision,` `,`的正文,请核对后继续。`,(0,x.jsx)(`button`,{type:`button`,disabled:r||k||m&&!O,onClick:()=>{u({...c,revision:e.revision}),h(!1),_(``)},children:`已核对最新修订,保留草稿继续`})]}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{disabled:r||m||O||k||!c.content.trim()||Array.from(c.content).length>1e3,children:`保存修改`}),(0,x.jsx)(`button`,{className:`secondary`,type:`button`,disabled:i,onClick:()=>{u(null),h(!1),_(``)},children:`取消编辑`})]})]}),d!==null&&(0,x.jsxs)(`div`,{className:`delete-confirm`,children:[(0,x.jsx)(`p`,{children:`确认删除这条画像记忆?该标识将永久撤销,不能恢复;来源和修订历史保留。`}),d!==e.revision&&(0,x.jsx)(A,{children:`这条记忆已变化,请取消并核对最新正文后重新操作。`}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{className:`danger-button`,disabled:r||m||k||d!==e.revision,onClick:()=>void N(`DELETE`,``,{expected_revision:d},`画像记忆已删除,历史仍保留。`),children:`确认删除`}),(0,x.jsx)(`button`,{className:`secondary`,disabled:i,onClick:()=>{p(null),h(!1),_(``)},children:`取消删除`})]})]}),k&&(0,x.jsx)(`p`,{className:`muted`,children:`已删除的记忆标识不可恢复。需要重新手写时,请使用人工新建。`}),(0,x.jsxs)(`div`,{className:`button-row`,children:[!k&&(0,x.jsx)(`button`,{className:`secondary`,disabled:r||!!c||d!==null,onClick:()=>{u({content:e.body,revision:e.revision}),h(!1),_(``),b(``)},children:`编辑`}),!k&&(0,x.jsx)(`button`,{className:`text-button danger-text`,disabled:r||!!c||d!==null,onClick:()=>{p(e.revision),h(!1),_(``),b(``)},children:`删除`}),e.lifecycle===`forgotten`&&(0,x.jsx)(`button`,{className:`secondary`,disabled:r||!!c||d!==null||m,onClick:()=>void N(`POST`,`/restore`,{expected_revision:e.revision},`画像记忆已恢复。`),children:`恢复`}),(0,x.jsx)(`button`,{className:`text-button`,"aria-expanded":S,disabled:i,onClick:()=>{C(!S),D(null)},children:S?`收起来源与修订历史`:`来源与修订历史`}),(0,x.jsx)(`button`,{className:`text-button`,disabled:i||!!c,onClick:()=>s(e.memory_id),children:`打开记忆详情`})]}),S&&(0,x.jsx)(fr,{id:e.memory_id,speakerNames:t,revision:e.revision,pendingSources:e.pending_sources,message:T,openMemory:s})]})}function mr({progress:e}){return e?(0,x.jsxs)(`section`,{"aria-label":`当前入口进度与积压`,children:[(0,x.jsx)(`h4`,{children:`当前入口进度与积压`}),(0,x.jsxs)(`dl`,{className:`profile-progress-grid`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`已完成观察分块`}),(0,x.jsxs)(`dd`,{children:[e.completed_chunks,` / `,e.observation_chunks,` 块`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`待检查`}),(0,x.jsxs)(`dd`,{children:[e.pending_checks,` 页`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`检查失败`}),(0,x.jsxs)(`dd`,{children:[e.failed_checks,` 页`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`检查未通过`}),(0,x.jsxs)(`dd`,{children:[e.rejected_checks,` 页`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`未准入画像`}),(0,x.jsxs)(`dd`,{children:[e.waiting_candidates,` 条`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`待扫描`}),(0,x.jsxs)(`dd`,{children:[e.unscanned_messages,` 条消息`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`观察缺口`}),(0,x.jsxs)(`dd`,{children:[e.observation_gaps,` 块`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`最早积压时间`}),(0,x.jsx)(`dd`,{children:e.oldest_pending_at?w(e.oldest_pending_at):`无`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`已排队至`}),(0,x.jsxs)(`dd`,{children:[`消息 #`,e.scan_cursor]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`已连续完成至`}),(0,x.jsxs)(`dd`,{children:[`消息 #`,e.applied_cursor]})]})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`页数和记忆条目数分别统计;未准入不等于失败。消息编号表示处理位置,不是发生时间;连续完成位置不会越过观察缺口。`})]}):null}function hr(e){return e.state===`applied`?e.kind===`admit`?`本页通过`:`已完成`:e.state===`rejected`?e.kind===`admit`?`本页未通过`:`未通过`:{queued:`排队中`,running:`处理中`,failed:`本次失败`,cancelled:`已取消`,deferred:`稍后重试`}[e.state]||e.state}function gr({work:e}){return e?.length?(0,x.jsxs)(`details`,{className:`history profile-work-list`,children:[(0,x.jsxs)(`summary`,{children:[`本次任务分块与检查 · `,e.length,` 项`]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`每页单独检查;全部页通过后才可能准入,还需核对最终正文与依据。宿主是否能看到,以每条画像的投影状态为准。`}),e.map(e=>(0,x.jsxs)(`article`,{"aria-label":`工作项 #${e.id}`,className:`profile-work-card`,children:[(0,x.jsxs)(`div`,{className:`detail-badges`,children:[(0,x.jsx)(`strong`,{children:e.kind===`observe`?`观察消息分块`:`画像准入检查`}),(0,x.jsx)(M,{tone:e.state===`failed`||e.state===`rejected`?`danger`:``,children:hr(e)}),(0,x.jsxs)(`span`,{className:`muted`,children:[`工作项 #`,e.id]})]}),e.memory_id!=null&&(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>document.getElementById(`profile-memory-${e.memory_id}`)?.scrollIntoView?.({behavior:`smooth`,block:`start`}),children:[`画像记忆 #`,e.memory_id]}),e.kind===`admit`&&(0,x.jsx)(`p`,{children:e.check_page!=null&&e.check_pages!=null?`检查第 ${e.check_page} / ${e.check_pages} 页`:`检查页码未记录`}),e.kind===`admit`&&e.state===`applied`&&(0,x.jsx)(`p`,{className:`fine-print`,children:`全部页通过后才可能准入,本页通过不代表整条已展示。`}),(0,x.jsxs)(`dl`,{className:`profile-work-metadata`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`所属日期(角色时区)`}),(0,x.jsx)(`dd`,{children:e.local_day||`未记录`})]}),e.kind===`observe`&&(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`消息编号范围`}),(0,x.jsxs)(`dd`,{children:[`#`,e.cursor_before,` 之后至 #`,e.cursor_after]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`执行次数`}),(0,x.jsxs)(`dd`,{children:[e.attempts,` 次`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`下次重试`}),(0,x.jsx)(`dd`,{children:e.retry_at?w(e.retry_at):`未安排`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`入队时间`}),(0,x.jsx)(`dd`,{children:w(e.created_at)})]}),e.finished_at&&(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`结束时间`}),(0,x.jsx)(`dd`,{children:w(e.finished_at)})]})]}),e.reason&&(0,x.jsx)(`p`,{children:ir(e.reason)})]},e.id))]}):null}function _r({base:e,initial:t,settled:n,progress:r}){let[i,a]=(0,l.useState)(t.state===`running`),o=y(`${e}/attempts/${t.id}`,i?1500:0),s=(0,l.useRef)(!1);(0,l.useEffect)(()=>{o.data&&o.data.state!==`running`&&!s.current&&(s.current=!0,a(!1),n(o.data))},[o.data,n]);let c=i&&o.data||t;return(0,x.jsxs)(`section`,{className:`entry-profile-task`,"aria-label":`画像更新任务`,children:[(0,x.jsxs)(`h3`,{children:[`更新任务 #`,c.id]}),o.error&&(0,x.jsxs)(A,{error:!0,children:[o.error,(0,x.jsx)(`button`,{onClick:o.refresh,children:`重试任务状态`})]}),(0,x.jsx)(`p`,{role:`status`,children:c.state===`running`?c.stage===`checking`?`正在检查画像条目…`:`正在观察消息分块…`:c.state===`published`?`本轮已提交处理结果,仍以逐条准入状态为准。`:$n(c.state)}),c.reason&&(0,x.jsx)(`p`,{children:ir(c.reason)}),(0,x.jsxs)(`p`,{className:`fine-print`,children:[`开始:`,w(c.started_at),c.finished_at&&` · 结束:${w(c.finished_at)}`]}),(0,x.jsx)(mr,{progress:c.progress||r}),(0,x.jsx)(gr,{work:c.work}),c.version!=null&&(0,x.jsxs)(`p`,{children:[`任务完成时的宿主投影版本:v`,c.version]})]})}function vr({entry:e,onClose:t,openMemory:n}){let r=`/entries/${encodeURIComponent(e.id)}/profile`,i=y(r,5e3),a=y(`/catalog`),o=Object.fromEntries((a.data?.people||[]).map(e=>[e.id,e.name])),[s,c]=(0,l.useState)(!1),[u,d]=(0,l.useState)(``),[p,m]=(0,l.useState)(``),[h,b]=(0,l.useState)(!1),[S,C]=(0,l.useState)(null),[T,E]=(0,l.useState)(null),D=(0,l.useRef)(!1),O=(0,l.useRef)(!0);(0,l.useEffect)(()=>(O.current=!0,()=>{O.current=!1}),[]);let k=async(e,t,n)=>{if(D.current)throw new f(`busy`,`正在保存,请稍候。`,409);D.current=!0,c(!0),d(``),m(``);try{return await g(e,_(t,n))}finally{D.current=!1,O.current&&(c(!1),i.refresh())}},j=(0,l.useCallback)(e=>{E(e),i.refresh()},[i.refresh]),P=i.data,F=P?.latest_attempt&&(!T||P.latest_attempt.id>T.id||P.latest_attempt.id===T.id&&(T.state===`running`||P.latest_attempt.state!==`running`))?P.latest_attempt:T||P?.latest_attempt,I=s||i.loading||!!i.error,L=F?.state===`running`,ee=e=>{s||(t(),n(e))};async function te(){if(S&&!I)try{await k(`${r}/settings`,`PATCH`,S),C(null),m(`画像设置已保存。`)}catch(e){d(e instanceof f&&e.status===409?`画像已变化,设置草稿已保留;请核对最新投影后重新确认。`:v(e))}}async function ne(){if(!(!P||I||L))try{let e=await k(`${r}/regenerate`,`POST`,{expected_version:P.settings.current_version});E(e.attempt),m(`更新请求已提交,可关闭面板后再查看任务结果。`)}catch(e){d(v(e))}}return(0,x.jsx)(N,{title:`入口画像 · ${e.name}`,onClose:t,closeDisabled:s,children:(0,x.jsxs)(`div`,{className:`entry-profile`,children:[(0,x.jsx)(`p`,{className:`muted`,children:`每条画像都是本入口的记忆,自动更新。手写内容按人工记忆保护。`}),(i.error||u)&&(0,x.jsxs)(A,{error:!0,children:[u||i.error,(0,x.jsx)(`button`,{className:`text-button`,disabled:s,onClick:i.refresh,children:`刷新画像`})]}),p&&(0,x.jsx)(A,{children:p}),P?P.supported?P.mode===`memory`?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`section`,{className:`entry-profile-section`,"aria-label":`画像设置`,children:[(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(M,{children:P.settings.enabled?`已开启`:`已关闭`}),(0,x.jsx)(`span`,{children:`自动更新,无需确认候选`})]}),!P.global_enabled&&(0,x.jsx)(A,{children:`全局画像开关已关闭,当前不会生成或加入回复准备。`}),S?(0,x.jsxs)(`form`,{onSubmit:e=>{e.preventDefault(),te()},children:[(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:S.enabled,disabled:s,onChange:e=>C({...S,enabled:e.target.checked})}),`启用本入口画像`]}),S.expected_version!==P.settings.current_version&&(0,x.jsxs)(A,{children:[`投影已更新为 v`,P.settings.current_version,`,请先核对下方预览。`,(0,x.jsx)(`button`,{type:`button`,disabled:I,onClick:()=>C({...S,expected_version:P.settings.current_version}),children:`已核对,保留设置草稿`})]}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{disabled:I||S.expected_version!==P.settings.current_version,children:`保存画像设置`}),(0,x.jsx)(`button`,{type:`button`,className:`secondary`,disabled:s,onClick:()=>C(null),children:`取消设置`})]})]}):(0,x.jsx)(`button`,{className:`secondary`,disabled:I,onClick:()=>C({enabled:P.settings.enabled,expected_version:P.settings.current_version}),children:`修改画像设置`})]}),(0,x.jsxs)(`section`,{className:`entry-profile-section`,"aria-label":`宿主投影预览`,children:[(0,x.jsxs)(`h3`,{children:[`宿主投影预览 · v`,P.settings.current_version]}),(0,x.jsx)(`p`,{className:`muted`,children:`以下为回复准备提供的原文;宿主传入已知记忆时会排除相应条目。投影版本独立于每条记忆的修订号。`}),P.projection?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`p`,{className:`entry-profile-content profile-projection`,children:P.projection.text}),(0,x.jsxs)(`p`,{className:`fine-print`,children:[`version:`,P.projection.version,` · 更新于`,` `,w(P.projection.generated_at)]}),(0,x.jsx)(`div`,{className:`button-row`,children:P.projection.memory_ids.map(e=>(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>document.getElementById(`profile-memory-${e}`)?.scrollIntoView?.({behavior:`smooth`,block:`start`}),children:[`画像记忆 #`,e]},e))}),P.projection.possibly_stale&&(0,x.jsx)(A,{children:`投影可能过时:还有未处理消息、观察缺口、待检查或待重建的内容。`})]}):(0,x.jsx)(`p`,{children:`当前不向宿主提供画像(entry_profile 为 null)。`}),!!P.diagnostics.omitted_memory_ids?.length&&(0,x.jsxs)(A,{children:[`受展示预算限制,以下记忆未加入投影:`,P.diagnostics.omitted_memory_ids.map(e=>(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>document.getElementById(`profile-memory-${e}`)?.scrollIntoView?.({behavior:`smooth`,block:`start`}),children:[`#`,e]},e)),(0,x.jsx)(`p`,{children:`这些记忆仍然保留;人工内容不会因展示预算被隐藏。`})]}),P.rebuild_pending&&(0,x.jsx)(A,{children:`画像正在等待新任务重建或继续处理消息。`})]}),(0,x.jsxs)(`section`,{className:`entry-profile-section`,"aria-label":`每日增量进度`,children:[(0,x.jsx)(`h3`,{children:`每日增量进度`}),(0,x.jsx)(`p`,{className:`muted`,children:`自动任务按角色时区处理已结束日期;立即运行也处理当日尾块。准入由系统自动检查,无需审批。`}),(0,x.jsx)(`button`,{disabled:I||L||!P.settings.enabled||!P.global_enabled,onClick:()=>void ne(),children:`立即运行`}),(0,x.jsx)(`p`,{className:`fine-print`,children:`继续处理新消息和排队的检查;没有新依据时不会重复确认。`}),!F&&(0,x.jsx)(mr,{progress:P.progress}),F&&(0,x.jsx)(_r,{base:r,initial:F,settled:j,progress:P.progress},F.id)]}),(0,x.jsxs)(`section`,{className:`entry-profile-section`,"aria-label":`画像记忆`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsxs)(`h3`,{children:[`画像记忆 · `,P.memories.length,` 条`]}),(0,x.jsx)(`button`,{disabled:I||h,onClick:()=>b(!0),children:`人工新建`})]}),h&&(0,x.jsx)(dr,{entry:e,blocked:I,busy:s,write:k,cancel:()=>b(!1),created:()=>{b(!1),m(`已创建本入口的画像记忆。`)}}),!P.memories.length&&(0,x.jsx)(`p`,{children:`暂无画像记忆。可手写补充,也可等待新消息形成画像。`}),(0,x.jsx)(`div`,{className:`profile-memory-list`,children:P.memories.map(e=>(0,x.jsx)(pr,{memory:e,speakerNames:o,displayed:!!P.projection?.memory_ids.includes(e.memory_id),blocked:I,busy:s,write:k,refresh:i.refresh,openMemory:ee},e.memory_id))})]})]}):(0,x.jsx)(A,{children:`入口画像尚未切换为记忆形式,请更新服务后刷新。旧版历史仍可只读查看。`}):(0,x.jsx)(A,{children:`私聊入口不生成入口画像。`}):(0,x.jsx)(`p`,{role:`status`,children:`正在读取入口画像…`}),P?.supported&&(0,x.jsxs)(x.Fragment,{children:[!!P.migration?.length&&(0,x.jsxs)(`details`,{className:`history`,children:[(0,x.jsx)(`summary`,{children:`旧画像迁移记录`}),(0,x.jsx)(`ul`,{children:P.migration.map(e=>(0,x.jsxs)(`li`,{children:[`旧版 v`,e.legacy_version,` · 原条目序号`,` `,e.sentence_index,`:`,{manual_imported:`已转为人工画像记忆`,manual_unclassified:`已转为管理员说明`,model_rebuild_pending:`原模型条目待按依据重建`,cleared_history:`原内容已清空`}[e.disposition]||e.disposition,e.memory_id!=null&&(0,x.jsxs)(`button`,{className:`text-button`,disabled:s,onClick:()=>ee(e.memory_id),children:[`查看记忆 #`,e.memory_id]})]},`${e.legacy_version}:${e.sentence_index}`))})]}),(0,x.jsx)(or,{base:r,openMemory:ee})]})]})})}var yr={forget:`遗忘`,delete:`删除`,purge:`彻底清除`},br={memory_source:`仍是其他记忆的来源`,batch_segment:`等待或运行中的批次仍在使用`,goal_source:`仍是目标的来源`,subject_alias:`仍是主体别名的证据`,subject_link:`仍是主体联系的证据`,learning_request:`立即学习请求仍在使用`};function xr({scope:e,name:t,onClose:n,onChanged:r}){let[i,a]=(0,l.useState)(`forget`),[o,s]=(0,l.useState)(!1),[c,u]=(0,l.useState)(null),[d,p]=(0,l.useState)(null),[m,h]=(0,l.useState)(!1),[y,b]=(0,l.useState)(``),[S,C]=(0,l.useState)(!1),[w,T]=(0,l.useState)(!1),D=d?.status===`completed`,O=()=>{u(null),b(``),C(!1),T(!1)};async function k(){h(!0),O();try{u(await g(`/memories/bulk/preview`,_(`POST`,{...e,action:i,include_pinned:o})))}catch(e){b(v(e))}finally{h(!1)}}async function j(){if(c&&!m&&c.applicable_count&&(i!==`purge`||w)){h(!0),b(``);try{p(await g(`/memories/bulk/apply`,_(`POST`,{snapshot_token:c.snapshot_token,action:i,confirm:i===`purge`&&w}))),u(null),C(!1),r()}catch(e){e instanceof f&&e.status===409?(O(),e.result&&(p(e.result),r()),b(e.message)):b(`${v(e)}。执行结果尚未确认,可使用当前预览重试;若服务已重启,请先查看操作记录。`)}finally{h(!1)}}}return(0,x.jsx)(N,{title:`批量遗忘/删除`,onClose:n,closeDisabled:m,children:(0,x.jsxs)(`div`,{className:`lifecycle-stack bulk-memory`,children:[(0,x.jsxs)(`p`,{children:[(0,x.jsx)(`strong`,{children:t}),` ·`,` `,`subject_id`in e?`人物 ${e.subject_id}`:`入口 ${e.entry_id}`]}),(0,x.jsx)(`p`,{className:`muted`,children:`subject_id`in e?`范围:说话人或涉及人物为此人的记忆。`:`范围:至少一条直接来源消息属于此入口的记忆。`}),y&&(0,x.jsx)(A,{error:!0,children:y}),d&&(0,x.jsxs)(`section`,{"aria-label":`批量操作结果`,children:[(0,x.jsx)(A,{error:!D,children:D?`已批量${yr[i]} ${d.count} 条记忆。`:`操作未全部完成,已处理 ${d.count} 条记忆。`}),(0,x.jsx)(Vt,{notice:d.backup_notice}),d.skipped_count>0&&(0,x.jsxs)(`p`,{children:[`跳过已删除的 `,d.skipped_count,` 条记忆。`]}),(0,x.jsxs)(`details`,{children:[(0,x.jsxs)(`summary`,{children:[`已处理记忆 ID(`,d.memory_ids.length,` 条)`]}),(0,x.jsx)(`p`,{className:`bulk-ids`,children:d.memory_ids.map(e=>`#${e}`).join(`、`)||`无`})]}),i===`purge`&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{children:[`已删除来源消息 `,d.deleted_message_ids.length,` 条;保留`,` `,d.retained_messages.length,` 条。`]}),(0,x.jsxs)(`details`,{children:[(0,x.jsx)(`summary`,{children:`来源消息处理明细`}),(0,x.jsxs)(`p`,{className:`bulk-ids`,children:[`已删除:`,d.deleted_message_ids.map(e=>`#${e}`).join(`、`)||`无`]}),d.retained_messages.map(e=>(0,x.jsxs)(`p`,{children:[`消息 #`,e.message_id,`:`,e.reasons.map(e=>br[e]||e).join(`;`)]},e.message_id))]})]})]}),!D&&(0,x.jsxs)(x.Fragment,{children:[!S&&(0,x.jsxs)(`fieldset`,{disabled:m,className:`bulk-options`,children:[(0,x.jsxs)(`label`,{children:[`目标操作`,(0,x.jsxs)(`select`,{value:i,onChange:e=>{a(e.target.value),O()},children:[(0,x.jsx)(`option`,{value:`forget`,children:`遗忘(可恢复)`}),(0,x.jsx)(`option`,{value:`delete`,children:`删除(撤销对象)`}),(0,x.jsx)(`option`,{value:`purge`,children:`彻底清除(不可撤销)`})]})]}),(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:o,onChange:e=>{s(e.target.checked),O()}}),`包含置顶记忆`]}),(0,x.jsx)(`p`,{children:i===`forget`?`遗忘会降低保留强度并取消置顶;仍可深度召回及恢复。`:i===`delete`?`删除会撤销记忆对象,保留来源与历史;普通和深度召回均不再返回。`:`彻底清除会清除正文、修订历史,以及没有其他受保护引用的来源消息。`}),(0,x.jsx)(`button`,{className:`secondary`,onClick:()=>void k(),children:m?`正在处理…`:`预览范围`})]}),c&&(0,x.jsxs)(`section`,{"aria-label":`批量操作预览`,children:[(0,x.jsxs)(`h3`,{children:[`范围内 `,c.total,` 条,本次处理 `,c.applicable_count,` `,`条`]}),(0,x.jsxs)(`p`,{children:[`有效 `,c.counts.active,` · 遗忘 `,c.counts.forgotten,` `,`· 已删除 `,c.counts.deleted]}),(0,x.jsxs)(`p`,{children:[`包含置顶 `,c.pinned_count,` 条;排除置顶`,` `,c.excluded_pinned_count,` 条。`]}),(0,x.jsx)(`p`,{className:`muted`,children:`已删除对象只参加彻底清除。预览有效期 15 分钟,记忆变化后需重新预览。`}),(0,x.jsx)(`ul`,{className:`bulk-examples`,children:c.examples.map(e=>(0,x.jsxs)(`li`,{children:[(0,x.jsxs)(`span`,{className:`muted`,children:[`#`,e.id,` · `,E(e.lifecycle),e.pinned?` · 置顶`:``]}),(0,x.jsx)(`p`,{children:e.content})]},e.id))}),i===`purge`&&(0,x.jsx)(Vt,{notice:c.backup_notice}),S?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(A,{error:!0,children:[`即将彻底清除 `,c.applicable_count,` `,`条记忆,此操作不可撤销。同时清空可关联的模型原始输出等正文副本。`]}),(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,disabled:m,checked:w,onChange:e=>T(e.target.checked)}),`我理解此操作不可撤销`]}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{className:`danger-button`,disabled:m||!w,onClick:()=>void j(),children:`再次确认并彻底清除`}),(0,x.jsx)(`button`,{className:`secondary`,disabled:m,onClick:()=>{C(!1),T(!1)},children:`返回预览`})]})]}):(0,x.jsxs)(`button`,{className:`danger-button`,disabled:m||!c.applicable_count,onClick:()=>i===`purge`?C(!0):void j(),children:[`确认批量`,yr[i]]})]})]}),m&&(0,x.jsx)(`p`,{role:`status`,children:`正在处理,请等待结果…`}),!m&&(0,x.jsx)(`a`,{href:`#/operations?object_type=memory_bulk`,onClick:n,children:`查看批量操作记录`}),D&&(0,x.jsx)(`button`,{className:`primary`,onClick:n,children:`完成`})]})})}var Sr=e=>({group:`群聊`,private:`私聊`,live:`直播`})[e]||e,Cr=e=>({message:`消息`,self_output:`角色实际输出`,action_result:`行动结果`,event:`场景事件`})[e]||e,wr=e=>({attempts_exhausted:`尝试用尽,未学习`,content_rejection:`内容拒绝,未学习`,interrupted:`学习中断`})[e]||e,Tr=e=>typeof e==`string`?e:JSON.stringify(e,null,2);function Er({openMemory:e}){let[t,n]=(0,l.useState)(`entries`),[r,i]=(0,l.useState)(null),[a,o]=(0,l.useState)(null),[s,c]=(0,l.useState)(null),[u,d]=(0,l.useState)(null),[f,p]=(0,l.useState)(``),[m,h]=(0,l.useState)({entry_id:``,time_from:``,time_to:``}),[g,_]=(0,l.useState)(m),[v,b]=(0,l.useState)(0),C=y(`/entries`,5e3),w=new URLSearchParams({limit:`30`,offset:String(v)});for(let[e,t]of Object.entries(g))t&&w.set(e,t);let T=y(t===`batches`&&r===null?`/batches?${w}`:null,3e3),E=y(t===`gaps`&&r===null?`/memory-gaps?${w}`:null,3e3),D=t===`batches`?T:E,O=()=>{C.refresh(),T.refresh(),E.refresh()};function k(e){n(e),i(null),b(0)}function N(e){let t={entry_id:e,time_from:``,time_to:``};h(t),_(t),k(`batches`)}return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{className:`page-heading`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`p`,{className:`eyebrow`,children:`从消息到记忆`}),(0,x.jsx)(`h1`,{children:`入口与学习`}),(0,x.jsx)(`p`,{children:`查看每个入口的学习进度,追溯批次结果与尚未记住的消息。`})]})}),(0,x.jsx)(`div`,{className:`learning-tabs`,role:`group`,"aria-label":`入口与学习视图`,children:[[`entries`,`入口列表`],[`batches`,`学习批次`],[`gaps`,`记忆缺口`]].map(([e,n])=>(0,x.jsx)(`button`,{"aria-pressed":t===e,onClick:()=>k(e),children:n},e))}),C.error&&(0,x.jsxs)(A,{error:!0,children:[C.error,(0,x.jsx)(`button`,{onClick:C.refresh,children:`重试`})]}),f&&(0,x.jsx)(A,{children:f}),a&&(0,x.jsx)(xr,{scope:{entry_id:a.id},name:a.name,onClose:()=>o(null),onChanged:O}),u&&(0,x.jsx)(vr,{entry:u,onClose:()=>d(null),openMemory:e},u.id),s&&(0,x.jsx)(Qe,{entry:s,entries:C.data?.items||[],onClose:()=>c(null),onSaved:()=>{c(null),p(`入口设置已保存`),O()}}),r===null?t===`entries`?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`p`,{className:`learning-intro`,children:`已接收的消息可能仍在等待学习;批次结束后,也可能没有形成记忆。`}),C.data?C.data.items.length?(0,x.jsx)(`div`,{className:`entry-grid`,children:C.data.items.map(e=>(0,x.jsxs)(`article`,{className:`panel learning-entry`,children:[(0,x.jsxs)(`div`,{className:`section-title`,children:[(0,x.jsx)(`h2`,{children:e.name}),(0,x.jsx)(M,{children:Sr(e.kind)})]}),(0,x.jsx)(`p`,{className:`muted`,children:e.platform===`iris-trial`?`试用入口`:`宿主入口 · ${e.platform}`}),(0,x.jsxs)(`div`,{className:`learning-entry-meta`,children:[(0,x.jsx)(M,{children:Ye(e.pace)}),(0,x.jsxs)(`strong`,{children:[`待学习 `,e.pending_count,` 条`]})]}),(0,x.jsxs)(`p`,{className:`entry-filter-summary`,children:[`记忆可见范围:`,Ge(e,C.data?.items||[])]}),(0,x.jsx)(Xe,{value:e.filters}),(0,x.jsx)(Ze,{value:e.queue_wait}),(0,x.jsxs)(`p`,{children:[`最近批次`,e.latest_batch?` #${e.latest_batch.id}`:``]}),(0,x.jsx)(`p`,{children:e.latest_batch?zn(e.latest_batch):`暂无批次`}),e.current_batch&&e.current_batch.id!==e.latest_batch?.id&&(0,x.jsxs)(`p`,{children:[`当前处理 #`,e.current_batch.id,` ·`,` `,zn(e.current_batch)]}),(0,x.jsx)(`button`,{className:`secondary`,"aria-label":`修改入口设置 · ${e.name}`,onClick:()=>{p(``),c(e)},children:`修改入口设置`}),(0,x.jsx)(`button`,{className:`secondary`,"aria-label":`入口画像 · ${e.name}`,onClick:()=>d(e),children:`入口画像`}),(0,x.jsx)(`button`,{className:`secondary`,"aria-label":`批量遗忘/删除 · ${e.name}`,onClick:()=>o(e),children:`批量遗忘/删除`}),(0,x.jsx)(`button`,{className:`text-button`,"aria-label":`查看批次 · ${e.name}`,onClick:()=>N(e.id),children:`查看批次 →`})]},e.id))}):(0,x.jsx)(j,{title:`还没有入口`,children:`可在试用对话页创建入口,或由宿主发送消息。`}):(0,x.jsx)(`p`,{children:`正在读取入口…`})]}):(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`p`,{className:`learning-intro`,children:t===`gaps`?`放弃或内容拒绝的批次留下记忆缺口。重新学习成功后才会消失;模型暂停期间的普通积压不算缺口。`:`批次保留冻结的三段消息。成功可以形成零条记忆;失败重试和放弃、拒绝会分别显示。`}),(0,x.jsxs)(`form`,{className:`learning-filters`,onSubmit:e=>{e.preventDefault(),_({...m}),b(0)},children:[(0,x.jsxs)(`label`,{children:[`筛选入口`,(0,x.jsxs)(`select`,{value:m.entry_id,onChange:e=>h({...m,entry_id:e.target.value}),children:[(0,x.jsx)(`option`,{value:``,children:`全部入口`}),C.data?.items.map(e=>(0,x.jsx)(`option`,{value:e.id,children:e.name},e.id))]})]}),(0,x.jsxs)(`label`,{children:[`开始日期`,(0,x.jsx)(`input`,{type:`date`,value:m.time_from,onChange:e=>h({...m,time_from:e.target.value})})]}),(0,x.jsxs)(`label`,{children:[`结束日期`,(0,x.jsx)(`input`,{type:`date`,value:m.time_to,min:m.time_from||void 0,onChange:e=>h({...m,time_to:e.target.value})})]}),(0,x.jsx)(`button`,{className:`secondary`,type:`submit`,children:`筛选`})]}),(0,x.jsxs)(`p`,{className:`muted learning-date-help`,children:[`日期按角色时区;`,t===`gaps`?`显示与日期范围重叠的消息区间。`:`按批次组成时间筛选。`]}),D.error&&(0,x.jsxs)(A,{error:!0,children:[D.error,(0,x.jsx)(`button`,{onClick:D.refresh,children:`重试`})]}),t===`batches`&&T.data?.entry_waits?.filter(e=>e.queue_wait.reason).map(e=>(0,x.jsxs)(`div`,{className:`panel`,children:[(0,x.jsxs)(`strong`,{children:[C.data?.items.find(t=>t.id===e.entry_id)?.name||e.entry_id,` `,`· 当前入口等待`]}),(0,x.jsx)(Ze,{value:e.queue_wait})]},e.entry_id)),D.data?(0,x.jsxs)(x.Fragment,{children:[D.data.total===0?(0,x.jsx)(j,{title:t===`gaps`?`当前范围没有记忆缺口`:`当前范围没有批次`}):(0,x.jsx)(`div`,{className:`learning-list`,children:t===`batches`?T.data?.items.map(e=>(0,x.jsxs)(`article`,{className:`panel learning-batch-card`,children:[(0,x.jsxs)(`div`,{className:`learning-row`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsxs)(`strong`,{children:[`#`,e.id,` · `,e.entry_name]}),(0,x.jsx)(`p`,{children:zn(e)}),(0,x.jsxs)(`small`,{children:[S(e.created_at),` ·`,` `,Ln(e)?`拆分前`:`本轮`,`已计`,` `,e.attempt_count,` 次尝试`]})]}),(0,x.jsx)(`button`,{className:`text-button`,"aria-label":`查看批次 #${e.id}`,onClick:()=>i(e.id),children:`查看详情 →`})]}),(0,x.jsx)(Hn,{batch:e,onOpen:i}),Ln(e)&&(0,x.jsxs)(`div`,{className:`learning-batch-tree`,children:[(0,x.jsx)(Vn,{batch:e}),(0,x.jsx)(Jn,{id:e.id,onOpen:i})]})]},e.id)):E.data?.items.map(e=>(0,x.jsxs)(`article`,{className:`panel learning-row`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsxs)(`strong`,{children:[e.entry_name,` · 批次 #`,e.batch_id]}),(0,x.jsxs)(`p`,{children:[S(e.started_at),` — `,S(e.ended_at)]}),(0,x.jsx)(`p`,{children:wr(e.reason)}),e.relearning&&(0,x.jsx)(M,{children:`重新学习中`})]}),(0,x.jsx)(`button`,{className:`text-button`,"aria-label":`查看批次 #${e.batch_id}`,onClick:()=>i(e.batch_id),children:`查看详情 →`})]},e.batch_id))}),(0,x.jsxs)(`div`,{className:`learning-pagination`,children:[(0,x.jsxs)(`span`,{children:[`共 `,D.data.total,` `,t===`batches`?`个批次节点(含子批次)`:`处缺口`]}),(0,x.jsx)(`button`,{disabled:v===0,onClick:()=>b(Math.max(0,v-30)),children:`上一页`}),(0,x.jsx)(`button`,{disabled:v+30>=D.data.total,onClick:()=>b(v+30),children:`下一页`})]})]}):(0,x.jsx)(`p`,{children:`正在读取…`})]}):(0,x.jsx)(kr,{id:r,openMemory:e,onBack:()=>i(null),onRelearn:O,onOpen:i},r)]})}function Dr({calls:e}){return e.length?(0,x.jsx)(`div`,{className:`learning-calls`,children:e.map(e=>(0,x.jsxs)(`div`,{children:[(0,x.jsxs)(`strong`,{children:[e.purpose===`learning_repair`?`JSON 修正请求`:`学习请求`,` `,`· `,e.model]}),(0,x.jsxs)(`dl`,{children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`请求结果`}),(0,x.jsxs)(`dd`,{children:[e.result_category===`success`?`已返回正文`:e.result_category,e.timed_out?` · 超时`:``]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`耗时`}),(0,x.jsx)(`dd`,{children:C(e.duration_ms)})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`结束原因(finish_reason)`}),(0,x.jsx)(`dd`,{children:e.finish_reason||`未提供`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`推理档位`}),(0,x.jsx)(`dd`,{children:e.reasoning_effort||`未记录 / 服务商默认`})]})]}),e.error_summary&&(0,x.jsx)(`p`,{children:e.error_summary})]},e.id))}):(0,x.jsx)(`p`,{className:`muted`,children:`没有可关联的调用记录;结束原因与推理档位未知。`})}function Or({label:e,value:t}){return t==null?(0,x.jsxs)(`p`,{className:`muted`,children:[e,`:没有记录`]}):(0,x.jsxs)(`details`,{className:`learning-output`,children:[(0,x.jsx)(`summary`,{children:e}),(0,x.jsx)(`pre`,{children:t||`(空正文)`})]})}function kr({id:e,onBack:t,openMemory:n,onRelearn:r,onOpen:i}){let a=y(`/batches/${e}`,3e3),[o,s]=(0,l.useState)(!1),[c,u]=(0,l.useState)(``),[d,f]=(0,l.useState)(``),p=a.data;async function m(){if(!o&&p?.can_relearn&&!Ln(p)&&[`abandoned`,`refused`].includes(p.state)){s(!0),f(``),u(``);try{await g(`/batches/${e}/relearn`,_(`POST`,{})),u(`已重新排队,尚未记住。模型恢复且本入口在途批次结束后开始学习。`),r()}catch(e){f(v(e))}finally{s(!1),a.refresh()}}}return(0,x.jsxs)(`section`,{"aria-label":`批次 #${e}`,className:`batch-detail`,children:[(0,x.jsx)(`button`,{className:`text-button`,onClick:t,children:`← 返回列表`}),(a.error||d)&&(0,x.jsx)(A,{error:!0,children:d||a.error}),c&&(0,x.jsx)(A,{children:c}),p?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`panel batch-overview`,children:[(0,x.jsxs)(`div`,{className:`section-title`,children:[(0,x.jsxs)(`h2`,{children:[`批次 #`,e,` · `,p.entry.name]}),(0,x.jsx)(M,{children:zn(p,p.segments.target.length)})]}),(0,x.jsx)(Hn,{batch:p,onOpen:i}),(0,x.jsxs)(`p`,{className:`muted`,children:[`组成于 `,S(p.created_at),p.finished_at?` · 结束于 ${S(p.finished_at)}`:``,` `,`· `,Ln(p)?`拆分前`:`本轮`,`已计`,` `,p.attempt_count,` / 4 次尝试`]}),p.parent_batch_id&&(0,x.jsx)(Wn,{id:e}),(0,x.jsx)(Gn,{batch:p}),Ln(p)&&(0,x.jsx)(Vn,{batch:p}),!Ln(p)&&p.gap&&(0,x.jsx)(`p`,{children:`仍有记忆缺口;成功学习后才会消失。`}),p.last_error&&(0,x.jsxs)(`p`,{children:[Ln(p)?`子批次最近错误`:`最近错误`,`:`,p.last_error]}),p.relearn_blocked_reason&&!Ln(p)&&(0,x.jsx)(`p`,{children:p.relearn_blocked_reason}),p.can_relearn&&!Ln(p)&&[`abandoned`,`refused`].includes(p.state)&&(0,x.jsxs)(`div`,{className:`relearn-action`,children:[(0,x.jsx)(`button`,{className:`primary`,disabled:o,onClick:m,children:o?`正在提交…`:`重新学习`}),(0,x.jsx)(`p`,{children:`保留原批次范围和历史记录,重新获得 4 次尝试;成功前缺口持续存在。`})]}),p.state===`succeeded`&&!p.memories.length&&(0,x.jsx)(`p`,{children:`本批已学习,形成或更新了 0 条记忆。这是正常的成功结果。`}),!Ln(p)&&p.state!==`succeeded`&&(0,x.jsx)(`p`,{children:`尚未成功学习,不能把这些消息当作已经记住。`})]}),Ln(p)&&(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsx)(`h2`,{children:`子批次结果`}),(0,x.jsx)(`p`,{children:`本节点的历史请求曾被拒绝,已拆分交给子批次。请进入失败子批次详情重新学习。`}),(0,x.jsx)(Jn,{id:e,onOpen:i})]}),(0,x.jsxs)(`section`,{children:[(0,x.jsx)(`h2`,{children:Ln(p)?`拆分前冻结的三段消息`:`三段消息`}),(0,x.jsxs)(`details`,{className:`panel`,children:[(0,x.jsx)(`summary`,{children:`组成批次时的入口设置`}),p.entry_settings?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{children:[`学习节奏:`,Ye(p.entry_settings.pace)]}),(0,x.jsx)(Xe,{value:p.entry_settings.filters})]}):(0,x.jsx)(`p`,{children:`该批次没有保存入口设置快照。`})]}),(0,x.jsx)(`p`,{className:`muted`,children:`三段范围已冻结;历史与后续只帮助理解,只有目标段可以形成记忆。这里保留消息原文。`}),p.context_mode===`target_only`&&(0,x.jsx)(`p`,{className:`notice`,children:`当前仅目标模式:下方历史段与后续段保留供追溯,不会作为可选前后文发送;仍保留目标引用、附件及既有相关记忆等材料。`}),(0,x.jsx)(`div`,{className:`batch-segments`,children:[[`history`,`历史段`,`只帮助理解`],[`target`,`目标段`,`只从这里学习`],[`future`,`后续段`,`以后再学习`]].map(([e,t,n])=>(0,x.jsxs)(`section`,{className:`panel segment segment-${e}`,children:[(0,x.jsxs)(`div`,{className:`section-title`,children:[(0,x.jsxs)(`h3`,{children:[t,` · `,p.segments[e].length,` 条`]}),(0,x.jsx)(`small`,{children:n})]}),!p.segments[e].length&&(0,x.jsx)(`p`,{className:`muted`,children:`本段为空`}),p.segments[e].map(e=>(0,x.jsx)(`article`,{className:`batch-message`,children:e.missing?(0,x.jsxs)(`p`,{children:[`消息 #`,e.id,` 已不可用`]}):(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`strong`,{children:e.sender_name||e.sender_subject_id}),` `,(0,x.jsx)(M,{children:Cr(e.kind)})]}),(0,x.jsxs)(`small`,{children:[`#`,e.id,` · `,S(e.occurred_at),e.scene_identity?` · ${e.scene_identity}`:``]}),e.content.length>600?(0,x.jsxs)(`details`,{children:[(0,x.jsxs)(`summary`,{children:[e.content.slice(0,120),`…(展开原文)`]}),(0,x.jsx)(`p`,{className:`message-body`,children:e.content})]}):(0,x.jsx)(`p`,{className:`message-body`,children:e.content}),(0,x.jsx)(Le,{media:e.media}),e.quote_content&&(0,x.jsxs)(`blockquote`,{children:[e.quote_author_name||`引用`,`:`,e.quote_content]}),(0,x.jsx)(`small`,{children:O(e.learning_state)})]})},e.id))]},e))})]}),(0,x.jsxs)(`section`,{children:[(0,x.jsx)(`h2`,{children:Ln(p)?`本节点历史尝试(拆分前)`:`每次尝试`}),Ln(p)&&(0,x.jsx)(`p`,{children:`以下只记录本节点拆分前的请求;这些历史拒绝不等于子批次最终失败。`}),(0,x.jsxs)(`p`,{children:[`本节点实际模型调用 `,Bn(p),` 次`]}),(0,x.jsx)(`p`,{className:`muted`,children:`含学习、JSON 修正和未归入尝试的调用;不包含子批次调用,不等于树节点数或尝试额度。`}),(0,x.jsx)(`p`,{className:`muted`,children:`历次尝试持续编号;服务暂停时的失败记录不一定扣除尝试额度。模型返回正文不代表已经写入记忆。`}),!p.attempts.length&&(0,x.jsx)(j,{title:p.state===`running`?`本次尝试仍在进行`:`尚无已完成的尝试`}),p.attempts.map(e=>(0,x.jsxs)(`article`,{className:`panel batch-attempt`,children:[(0,x.jsxs)(`div`,{className:`section-title`,children:[(0,x.jsxs)(`h3`,{children:[`第 `,e.number,` 次尝试`]}),(0,x.jsx)(M,{children:e.parse_status===`failed`?`失败 · 未写入`:`学习成功`})]}),(0,x.jsxs)(`p`,{children:[S(e.started_at),` — `,S(e.finished_at),` · 总耗时 `,C(e.duration_ms)]}),(0,x.jsxs)(`p`,{children:[`解析结果:`,{direct:`直接解析`,repaired:`修正后解析`,failed:`失败`}[e.parse_status]||e.parse_status]}),(0,x.jsxs)(`p`,{children:[`本次上下文模式:`,Rn(e.context_mode)]}),e.error&&(0,x.jsxs)(`p`,{children:[`诊断:`,e.error]}),(0,x.jsx)(Dr,{calls:e.calls}),(0,x.jsx)(Or,{label:`模型原始正文`,value:e.raw_output}),(0,x.jsx)(Or,{label:`JSON 修正后的正文`,value:e.repair_output})]},e.id)),!!p.unassigned_calls.length&&(0,x.jsxs)(`details`,{className:`panel batch-attempt`,children:[(0,x.jsxs)(`summary`,{children:[`尚未归入已完成尝试的调用 · `,p.unassigned_calls.length,` 条`]}),(0,x.jsx)(Dr,{calls:p.unassigned_calls})]})]}),(0,x.jsxs)(`div`,{className:`batch-results`,children:[(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsxs)(`h2`,{children:[`规整记录 · `,p.result.normalizations?.length||0,` 条`]}),!p.result.normalizations?.length&&(0,x.jsx)(`p`,{className:`muted`,children:`没有规整记录。`}),p.result.normalizations?.map((e,t)=>(0,x.jsxs)(`article`,{className:`result-item`,children:[(0,x.jsx)(`strong`,{children:e.field}),(0,x.jsx)(`p`,{children:e.reason}),(0,x.jsxs)(`small`,{children:[e.section,e.index==null?``:` · 第 ${e.index+1} 项`]}),(0,x.jsxs)(`pre`,{children:[Tr(e.before),` → `,Tr(e.after)]})]},t))]}),(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsxs)(`h2`,{children:[`被丢弃的条目 · `,p.result.dropped?.length||0,` 条`]}),!p.result.dropped?.length&&(0,x.jsx)(`p`,{className:`muted`,children:`没有已记录的丢弃条目;批次失败时请查看原始输出和错误。`}),p.result.dropped?.map((e,t)=>(0,x.jsxs)(`article`,{className:`result-item`,children:[(0,x.jsx)(`strong`,{children:e.reason}),(0,x.jsx)(`small`,{children:e.section}),(0,x.jsx)(`pre`,{children:Tr(e.item)})]},t))]})]}),(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsxs)(`h2`,{children:[Ln(p)?`成功子批次的记忆结果`:`记忆结果`,` ·`,` `,p.memories.length,` 条`]}),(0,x.jsx)(`p`,{className:`muted`,children:`下列正文为记忆当前版本;详情中可查看修订历史。`}),!p.memories.length&&(0,x.jsx)(`p`,{children:p.state===`succeeded`?`本批没有新增、更新或确认记忆。`:`尚无成功写入的记忆。`}),p.memories.map(e=>(0,x.jsxs)(`div`,{className:`learning-row`,children:[(0,x.jsx)(M,{children:{created:`新增`,updated:`更新`,confirmed:`再次确认`}[e.change]||e.change}),e.missing?(0,x.jsxs)(`span`,{children:[`记忆 #`,e.id,` 已不可用`]}):(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>n(e.id),children:[`#`,e.id,` · `,e.content]}),(0,x.jsxs)(`small`,{children:[E(e.lifecycle),` · 修订 `,e.revision]})]},`${e.change}-${e.id}`))]})]}):(0,x.jsx)(`p`,{children:`正在读取批次…`})]})}function Ar(e){if(!e||typeof e!=`object`)return null;let t=e;return typeof t.reason!=`string`||!Array.isArray(t.items)||!t.items.every(e=>{if(!e||typeof e!=`object`)return!1;let t=e;return Number.isInteger(t.index)&&typeof t.supported==`boolean`&&typeof t.scene_qualified==`boolean`&&typeof t.reason==`string`&&Array.isArray(t.violations)&&t.violations.every(e=>typeof e==`string`)})?null:t}function jr(e){if(!e||typeof e!=`object`)return`原条目格式无效或未保存`;let t=e.text;return typeof t==`string`?t:`原条目格式无效或未保存`}function Mr({value:e,openMemory:t}){return e.length?(0,x.jsxs)(A,{children:[(0,x.jsx)(`strong`,{children:`可能过时`}),(0,x.jsx)(`ul`,{children:e.map((e,n)=>(0,x.jsxs)(`li`,{children:[e.memory_id!=null&&(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>t(e.memory_id),children:[`记忆 #`,e.memory_id]}),e.revision!=null&&`(依据修订 ${e.revision})`,e.sentence_index!=null&&`第 ${e.sentence_index+1} 条:`,Tt(e.reason||``)]},n))})]}):null}function Nr({item:e,openMemory:t}){return(0,x.jsxs)(`div`,{className:`summary-item`,children:[(0,x.jsxs)(`p`,{children:[e.kind&&(0,x.jsx)(M,{children:Ct[e.kind]||e.kind}),` `,(0,x.jsx)(M,{children:e.admin_written||e.author===`admin`?`管理员手写`:`模型生成`})]}),(0,x.jsx)(`p`,{className:`entry-profile-content`,children:e.body||e.text}),e.time_range&&(0,x.jsxs)(`p`,{children:[`时间范围:`,e.time_range]}),e.valid_until&&(0,x.jsxs)(`p`,{children:[`有效至:`,e.valid_until]}),e.expires_at&&(0,x.jsxs)(`p`,{children:[`到期时间:`,w(e.expires_at)]}),(0,x.jsxs)(`details`,{className:`source`,children:[(0,x.jsxs)(`summary`,{children:[`记忆依据 · `,e.basis.length,` 条`]}),!e.basis.length&&(0,x.jsx)(`p`,{children:`此条没有模型记忆依据;管理员手写内容由管理员负责核对。`}),e.basis.map((e,n)=>(0,x.jsxs)(`div`,{className:`entry-profile-evidence`,children:[(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>t(e.memory_id),children:[`记忆 #`,e.memory_id]}),` `,`· 依据修订 `,e.revision,e.evidence?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`p`,{className:`entry-profile-content`,children:e.evidence.content}),(0,x.jsxs)(`small`,{children:[`依据快照 ·`,` `,w(e.evidence.event_time||e.evidence.created_at),e.evidence.truncated&&` · 摘录已截短`]})]}):(0,x.jsx)(`p`,{className:`muted`,children:`没有保存的依据正文快照。`}),e.memory?(0,x.jsxs)(`details`,{children:[(0,x.jsxs)(`summary`,{children:[`当前记忆 · 修订 `,e.memory.revision]}),(0,x.jsx)(`p`,{children:e.memory.content})]}):(0,x.jsx)(`p`,{className:`muted`,children:`当前记忆已不可用。`})]},n))]})]})}function Pr({value:e}){return(0,x.jsxs)(`p`,{className:`muted`,children:[`v`,e.version,` · `,wt[e.status]||e.status,` ·`,` `,{periodic:`定期更新`,regenerate:`管理员重新生成`,edit:`管理员编辑`,rollback:`回滚`}[e.source]||e.source,` `,`· 生成于 `,w(e.generated_at),` · 变化程度:`,{small:`小`,medium:`中`,large:`大`}[e.change_degree]||e.change_degree]})}function Fr({value:e,openMemory:t}){let n=e.checks,r=Ar(n.model);return e.cleared_at?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(Pr,{value:e}),(0,x.jsxs)(A,{children:[`因彻底清除而清空 · `,w(e.cleared_at),`。此版本不能回滚。`]})]}):(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(Pr,{value:e}),e.invalidated_reason&&(0,x.jsxs)(A,{children:[Tt(e.invalidated_reason),`,此版本不可回滚。`]}),(0,x.jsx)(Mr,{value:e.stale_basis,openMemory:t}),e.sentences.map((e,n)=>(0,x.jsx)(Nr,{item:e,openMemory:t},n)),!e.sentences.length&&(0,x.jsx)(`p`,{children:`此版本没有摘要条目。`}),(0,x.jsxs)(`details`,{className:`source`,children:[(0,x.jsx)(`summary`,{children:`检查与删条记录`}),(0,x.jsxs)(`p`,{children:[`检查结果:`,n.passed?`通过`:`未通过`,n.admin_edit&&`(管理员编辑,未调用模型检查)`]}),n.reason&&(0,x.jsx)(`p`,{children:Tt(n.reason)}),n.errors?.map((e,t)=>(0,x.jsx)(`p`,{children:Tt(e)},t)),n.deterministic&&(0,x.jsxs)(`p`,{children:[`规则检查:`,n.deterministic.passed?`通过`:`未通过`,n.deterministic.characters!=null&&` · ${n.deterministic.characters} 字`,n.deterministic.tokens!=null&&` · ${n.deterministic.tokens} token`]}),r?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{children:[`模型检查:`,r.reason]}),r.items.map((e,t)=>(0,x.jsxs)(`div`,{className:`entry-profile-evidence`,children:[(0,x.jsxs)(`strong`,{children:[`检查条目 `,e.index]}),(0,x.jsx)(`p`,{children:n.checked_sentences?.[t]?.text}),(0,x.jsxs)(`p`,{children:[`依据支持:`,e.supported?`是`:`否`,` · 场景限定:`,e.scene_qualified?`充分`:`不足`]}),(0,x.jsx)(`p`,{children:e.reason}),!!e.violations.length&&(0,x.jsxs)(`p`,{children:[`问题:`,e.violations.join(`、`)]})]},e.index))]}):(0,x.jsx)(`p`,{children:n.model==null?`没有模型检查记录。`:`模型检查记录格式无效,无法逐条展示。`}),!!n.deleted_sentences?.length&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`h4`,{children:`已删条目`}),n.deleted_sentences.map((e,t)=>(0,x.jsxs)(`div`,{children:[(0,x.jsxs)(`p`,{children:[`第 `,e.index,` 条 ·`,` `,e.stage===`references`?`引用核对`:`模型检查`]}),(0,x.jsx)(`p`,{children:e.sentence?.text||jr(e.item)}),(0,x.jsx)(`p`,{children:Tt(e.reason)}),!!e.violations?.length&&(0,x.jsx)(`p`,{children:e.violations.join(`、`)})]},t))]}),n.admin_warnings?.map((e,t)=>(0,x.jsxs)(A,{children:[`手写条目 `,e.index,` 的检查提醒:`,e.reason,` ·`,` `,e.violations.join(`、`)]},t)),n.rollback_from!=null&&(0,x.jsxs)(`p`,{children:[`从 v`,n.rollback_from,` 回滚新建。`]})]})]})}function Ir(e){let t=Array.from(e),n=0,r=0,i=0;for(;ie.kind).map(e=>e.text))].sort((e,t)=>t.length-e.length),r=0,i=0;if(n.length){let t=RegExp(`^(?:`+n.map(e=>e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)).join(`|`)+`)`,`gm`);for(let n of e.matchAll(t))r+=Ir(e.slice(i,n.index))+1,i=n.index+n[0].length}r+=Ir(e.slice(i));let a=Array.from(e),o=a.filter(e=>/[\u4e00-\u9fff]/u.test(e)).length;return{items:r,characters:a.length,tokens:Math.max(1,o+Math.floor((a.length-o+2)/3))}}function Rr({base:e,initial:t,onSettled:n,view:r}){let[i,a]=(0,l.useState)(t.state===`running`),o=y(`${e}/attempts/${t.id}`,i?1500:0),s=(0,l.useRef)(!1);(0,l.useEffect)(()=>{o.data&&o.data.state!==`running`&&!s.current&&(s.current=!0,a(!1),n())},[o.data,n]);let c=o.data||t;return(0,x.jsxs)(`section`,{className:`entry-profile-section`,"aria-label":`摘要生成任务`,children:[(0,x.jsxs)(`h3`,{children:[`生成任务 #`,c.id]}),o.error&&(0,x.jsxs)(A,{error:!0,children:[o.error,(0,x.jsx)(`button`,{onClick:o.refresh,children:`重试任务状态`})]}),(0,x.jsx)(`p`,{role:`status`,children:c.state===`running`?c.stage===`checking`?`正在检查候选…`:`正在生成候选…`:wt[c.state]||c.state}),c.reason&&(0,x.jsx)(`p`,{children:Tt(c.reason)}),(0,x.jsxs)(`p`,{className:`fine-print`,children:[`开始:`,w(c.started_at),c.finished_at&&` · 结束:${w(c.finished_at)}`]}),c.state===`rejected`&&(0,x.jsx)(`p`,{children:`当前发布版保持不变。确定性拒绝后自动整理等待新依据;管理员仍可主动重新生成。`}),c.cleared_at&&(0,x.jsx)(`p`,{children:`任务关联内容因彻底清除而清空。`}),c.version!=null&&(0,x.jsxs)(`button`,{onClick:()=>r(c.version),children:[`查看任务版本 v`,c.version]})]})}function zr({subjectId:e,initialVersion:t,openMemory:n}){let r=`/people/${encodeURIComponent(e)}/summary`,i=y(r,5e3),[a,o]=(0,l.useState)(0),[s,c]=(0,l.useState)(t||null),u=y(`${r}/versions?limit=10&offset=${a}`),d=y(i.data?.current?`${r}/versions/${i.data.current.version}`:null),p=y(s?`${r}/versions/${s}`:null),[h,g]=(0,l.useState)(null),b=y(h),[S,C]=(0,l.useState)(`1`),[E,D]=(0,l.useState)(`2`),[O,k]=(0,l.useState)(null),[j,P]=(0,l.useState)(null),[F,I]=(0,l.useState)(null),[L,ee]=(0,l.useState)(``),[te,ne]=(0,l.useState)(null),[re,ie]=(0,l.useState)(!1),[ae,oe]=(0,l.useState)(``),[se,ce]=(0,l.useState)(``),[le,ue]=(0,l.useState)(!1),de=(0,l.useRef)(!1),fe=(0,l.useRef)(!0);(0,l.useEffect)(()=>(fe.current=!0,()=>{fe.current=!1}),[]);let R=(0,l.useCallback)(()=>{i.refresh(),u.refresh(),d.refresh(),p.refresh(),b.refresh()},[i.refresh,u.refresh,d.refresh,p.refresh,b.refresh]),z=i.data,B=z?.settings.current_version??0,pe=JSON.stringify(z?.stale_basis||[]);(0,l.useEffect)(()=>{u.refresh(),d.refresh(),p.refresh()},[B,z?.current?.cleared_at,pe,z?.pending?.version,z?.latest_attempt?.state,u.refresh,d.refresh,p.refresh]);let me=e=>{c(e),oe(``)},he=z?.latest_attempt,ge=he&&(!te||he.id>=te.id)?he:te,V=ge?.state===`running`,H=re||i.loading||!!i.error||le,_e=!z?.current||d.data?.version===B&&!d.loading&&!d.error,ve=Lr(O?.content||``,O?.original),ye=z?.edit_limits||{max_items:5,max_chars:200,max_tokens:250},be=!O?.content.trim()||ve.characters>ye.max_chars||ve.tokens>ye.max_tokens||ve.items>ye.max_items;async function xe(e,t,n,i){if(de.current)return!1;de.current=!0,ie(!0),oe(``),ce(``);try{let a=await m(r+e,_(t,n));return fe.current&&(e===`/regenerate`&&a.status===202&&a.data.attempt&&ne(a.data.attempt),ce(i),I(null),R()),!0}catch(e){if(fe.current){let t=e instanceof f&&e.status===409;ue(t),oe(t?`当前摘要、设置、依据或生成任务已变化。已刷新版本;请核对后再操作,编辑草稿已保留。`:v(e)),t&&I(null),R()}return!1}finally{de.current=!1,fe.current&&ie(!1)}}let Se=(e,t)=>{C(String(e)),D(String(t)),g(`${r}/diff?before_version=${e}&after_version=${t}`)};return(0,x.jsxs)(`section`,{className:`panel person-summary`,"aria-label":`人物摘要`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:`人物摘要`}),(0,x.jsx)(`button`,{disabled:re,onClick:R,children:`刷新人物摘要`})]}),(0,x.jsx)(`p`,{className:`muted`,children:`从与此人物相关、全部入口共享的有效记忆提炼。查看与轮询不会召回或增加使用次数。`}),(i.error||ae)&&(0,x.jsx)(A,{error:!0,children:ae||i.error}),se&&(0,x.jsx)(A,{children:se}),z?(0,x.jsxs)(x.Fragment,{children:[!z.supported&&(0,x.jsx)(A,{children:`此主体类型或已合并人物不支持摘要写操作,可查阅已有历史。`}),!z.global_enabled&&(0,x.jsx)(A,{children:`全局人物摘要开关已关闭,不会生成或加入回复准备。`}),le&&(0,x.jsx)(`button`,{disabled:re||i.loading||!!i.error||!_e,onClick:()=>{ue(!1),oe(``),k(e=>e?{...e,expected_version:B,original:d.data?.sentences||[]}:null),P(e=>e?{...e,expected_version:B}:null)},children:`已核对最新版本,继续操作`}),(0,x.jsxs)(`p`,{children:[(0,x.jsx)(M,{children:z.settings.enabled?`此人摘要已开启`:`此人摘要已关闭`}),` `,`·`,` `,z.settings.publish_mode===`all_manual`?`全部人工确认`:`检查通过自动发布`,` `,`·`,` `,(0,x.jsxs)(M,{tone:z.pending_count?`amber`:``,children:[`待确认 `,z.pending_count]})]}),z.supported&&(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{disabled:H||!_e,onClick:()=>k({content:z.current?.content||``,expected_version:B,original:d.data?.sentences||[]}),children:`编辑摘要`}),(0,x.jsx)(`button`,{disabled:H,onClick:()=>P({enabled:z.settings.enabled,publish_mode:z.settings.publish_mode,expected_version:B}),children:`人物摘要设置`}),(0,x.jsx)(`button`,{disabled:H||V||!z.global_enabled||!z.settings.enabled,onClick:()=>void xe(`/regenerate`,`POST`,{expected_version:B},`已接受重新生成,请查看任务进度。`),children:V?`摘要生成中…`:`重新生成摘要`})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`重新生成至少需要 8 条相关全局有效记忆,并受开关、版本检查与模型预算限制。`}),j&&(0,x.jsxs)(`form`,{className:`entry-profile-section`,"aria-label":`人物摘要设置`,onSubmit:async e=>{e.preventDefault(),!(H||j.expected_version!==B)&&await xe(`/settings`,`PATCH`,j,`人物摘要设置已保存`)&&P(null)},children:[(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,disabled:re,checked:j.enabled,onChange:e=>P({...j,enabled:e.target.checked})}),`启用此人的摘要`]}),(0,x.jsxs)(`label`,{children:[`摘要发布方式`,(0,x.jsxs)(`select`,{disabled:re,value:j.publish_mode,onChange:e=>P({...j,publish_mode:e.target.value}),children:[(0,x.jsx)(`option`,{value:`check_auto`,children:`检查通过自动发布`}),(0,x.jsx)(`option`,{value:`all_manual`,children:`全部人工确认`})]})]}),(0,x.jsx)(`p`,{children:`关闭后保留历史;发布方式只影响之后的候选,不会发布已有待确认版本。`}),j.expected_version!==B&&(0,x.jsx)(A,{children:`设置基于旧版本,请取消后重新打开设置。`}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{disabled:H||j.expected_version!==B,children:`保存人物摘要设置`}),(0,x.jsx)(`button`,{type:`button`,disabled:re,onClick:()=>P(null),children:`取消设置`})]})]}),O&&(0,x.jsxs)(`form`,{className:`entry-profile-section`,"aria-label":`编辑人物摘要`,onSubmit:async e=>{e.preventDefault(),!(H||be||O.expected_version!==B)&&await xe(``,`PUT`,{content:O.content,expected_version:O.expected_version},`摘要编辑已发布`)&&k(null)},children:[(0,x.jsx)(`h3`,{children:`编辑并直接发布`}),(0,x.jsx)(`p`,{children:`新增或改动条目标为管理员手写,之后生成会保留;未改条目保留原依据。按句号或换行分条。`}),(0,x.jsxs)(`label`,{children:[`人物摘要正文`,(0,x.jsx)(`textarea`,{rows:6,disabled:re,value:O.content,onChange:e=>k({...O,content:e.target.value})})]}),(0,x.jsxs)(`p`,{children:[ve.items,` / `,ye.max_items,` 条 · `,ve.characters,` /`,` `,ye.max_chars,` 字 · `,ve.tokens,` / `,ye.max_tokens,` `,`估算 token(无最低字数) · 基于 v`,O.expected_version]}),O.expected_version!==B&&(0,x.jsxs)(A,{children:[`当前版本已变化,草稿已保留。请核对最新摘要后更新草稿版本。`,(0,x.jsx)(`button`,{type:`button`,disabled:!_e||H,onClick:()=>k({...O,expected_version:B,original:d.data?.sentences||[]}),children:`更新草稿版本`})]}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{disabled:H||be||O.expected_version!==B,children:`发布摘要编辑`}),(0,x.jsx)(`button`,{type:`button`,disabled:re,onClick:()=>k(null),children:`取消编辑摘要`})]})]}),(0,x.jsxs)(`section`,{className:`entry-profile-section`,"aria-label":`当前人物摘要`,children:[(0,x.jsx)(`h3`,{children:`当前摘要`}),z.current?d.error?(0,x.jsxs)(A,{error:!0,children:[d.error,(0,x.jsx)(`button`,{onClick:d.refresh,children:`重试当前摘要`})]}):!d.data||d.data.version!==B?(0,x.jsx)(`p`,{children:`正在读取当前摘要…`}):(0,x.jsx)(Fr,{value:d.data,openMemory:n}):(0,x.jsx)(`p`,{children:`尚无已发布的人物摘要。`}),!d.data&&(0,x.jsx)(Mr,{value:z.stale_basis,openMemory:n})]}),z.pending&&(0,x.jsxs)(`section`,{className:`entry-profile-section`,"aria-label":`待确认人物摘要`,children:[(0,x.jsxs)(`h3`,{children:[`待确认候选 · v`,z.pending.version]}),(0,x.jsx)(`p`,{className:`entry-profile-content`,children:z.pending.content}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsxs)(`button`,{onClick:()=>me(z.pending.version),children:[`审阅候选 v`,z.pending.version]}),z.current&&(0,x.jsx)(`button`,{onClick:()=>Se(B,z.pending.version),children:`对比当前与候选`})]})]}),ge&&(0,x.jsx)(Rr,{base:r,initial:ge,onSettled:R,view:me},ge.id),(0,x.jsxs)(`section`,{className:`entry-profile-section`,"aria-label":`人物摘要历史`,children:[(0,x.jsx)(`h3`,{children:`版本历史`}),u.error&&(0,x.jsxs)(A,{error:!0,children:[u.error,(0,x.jsx)(`button`,{onClick:u.refresh,children:`重试摘要历史`})]}),u.data?.items.map(e=>(0,x.jsxs)(`div`,{className:`entry-profile-evidence`,children:[(0,x.jsxs)(`button`,{onClick:()=>me(e.version),children:[`查看摘要 v`,e.version]}),` `,(0,x.jsx)(M,{children:e.is_current?`当前版本`:wt[e.status]||e.status}),e.cleared_at&&(0,x.jsx)(M,{tone:`warning`,children:`因彻底清除而清空`}),(0,x.jsx)(`p`,{children:w(e.generated_at)})]},e.version)),u.data&&!u.data.total&&(0,x.jsx)(`p`,{children:`暂无历史版本。`}),u.data&&(0,x.jsx)(T,{total:u.data.total,offset:a,change:o,limit:10})]}),s!=null&&(0,x.jsxs)(`section`,{className:`entry-profile-section`,"aria-label":`人物摘要版本详情`,children:[(0,x.jsxs)(`h3`,{children:[`摘要 v`,s,` 的依据与检查`]}),p.error?(0,x.jsxs)(A,{error:!0,children:[p.error,(0,x.jsx)(`button`,{onClick:p.refresh,children:`重试摘要版本`})]}):p.data?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(Fr,{value:p.data,openMemory:n}),z.supported&&p.data.status===`candidate`&&(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsxs)(`button`,{disabled:H||!!p.data.cleared_at||!p.data.checks.passed,onClick:()=>I({kind:`confirm`,version:s,expected_version:B}),children:[`确认发布摘要 v`,s]}),(0,x.jsxs)(`button`,{disabled:H,onClick:()=>{ee(``),I({kind:`reject`,version:s,expected_version:B})},children:[`拒绝摘要 v`,s]})]}),z.supported&&p.data.status===`published`&&!p.data.is_current&&(0,x.jsxs)(`button`,{disabled:H||!!p.data.cleared_at||!!p.data.invalidated_reason||!p.data.content.trim(),onClick:()=>I({kind:`rollback`,version:s,expected_version:B}),children:[`回滚到摘要 v`,s]})]}):(0,x.jsx)(`p`,{children:`正在读取版本…`})]}),(0,x.jsxs)(`section`,{className:`entry-profile-section`,"aria-label":`摘要版本对比`,children:[(0,x.jsx)(`h3`,{children:`任意两版对比`}),(0,x.jsxs)(`form`,{className:`button-row`,onSubmit:e=>{e.preventDefault(),Number.isSafeInteger(+S)&&+S>0&&Number.isSafeInteger(+E)&&+E>0&&Se(+S,+E)},children:[(0,x.jsxs)(`label`,{children:[`较早版本`,(0,x.jsx)(`input`,{type:`number`,min:1,required:!0,value:S,onChange:e=>C(e.target.value)})]}),(0,x.jsxs)(`label`,{children:[`较晚版本`,(0,x.jsx)(`input`,{type:`number`,min:1,required:!0,value:E,onChange:e=>D(e.target.value)})]}),(0,x.jsx)(`button`,{children:`对比摘要版本`})]}),b.error&&(0,x.jsxs)(A,{error:!0,children:[b.error,(0,x.jsx)(`button`,{onClick:b.refresh,children:`重试摘要对比`})]}),b.data&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{children:[`v`,b.data.before,` → v`,b.data.after,!b.data.changed&&` · 条目没有变化`]}),b.data.sentences.map((e,t)=>(0,x.jsxs)(`div`,{className:`persona-diff-row`,children:[(0,x.jsx)(`strong`,{children:{equal:`保留`,replace:`修改`,insert:`新增`,delete:`删除`}[e.op]||e.op}),(0,x.jsxs)(`div`,{className:`persona-diff-columns`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`small`,{children:`之前`}),e.before.map((e,t)=>(0,x.jsx)(`p`,{className:`entry-profile-content`,children:e.text},t))]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`small`,{children:`之后`}),e.after.map((e,t)=>(0,x.jsx)(`p`,{className:`entry-profile-content`,children:e.text},t))]})]})]},t))]})]}),(0,x.jsx)(`a`,{href:`#/operations?object_type=person_summary&object_id=${encodeURIComponent(e)}`,children:`查看人物摘要操作记录`}),F&&(0,x.jsxs)(N,{title:F.kind===`confirm`?`确认发布人物摘要`:F.kind===`reject`?`拒绝人物摘要`:`回滚人物摘要`,onClose:()=>I(null),closeDisabled:re,children:[(0,x.jsx)(`p`,{children:F.kind===`rollback`?`将复制 v${F.version},新建并发布一个版本;历史版本保持原记录。`:F.kind===`confirm`?`将发布候选 v${F.version},替换当前摘要。`:`将拒绝候选 v${F.version},保留当前发布版。`}),F.kind===`reject`&&(0,x.jsxs)(`label`,{children:[`拒绝摘要原因`,(0,x.jsx)(`input`,{maxLength:1e3,value:L,onChange:e=>ee(e.target.value),disabled:re})]}),(0,x.jsx)(`p`,{children:`请核对条目、依据和检查记录后再次确认。`}),ae&&(0,x.jsx)(A,{error:!0,children:ae}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{disabled:re,onClick:()=>I(null),children:`取消操作`}),(0,x.jsxs)(`button`,{className:`primary`,disabled:H||F.expected_version!==B,onClick:()=>void xe(`/versions/${F.version}/${F.kind}`,`POST`,{expected_version:F.expected_version,...F.kind===`reject`?{reason:L.trim()||`管理员拒绝`}:{}},F.kind===`rollback`?`已新建并发布回滚版本`:F.kind===`confirm`?`候选已确认发布`:`候选已拒绝`),children:[`确认`,F.kind===`rollback`?`回滚`:F.kind===`confirm`?`发布`:`拒绝`]})]})]})]}):(0,x.jsx)(`p`,{role:`status`,children:`正在读取人物摘要…`})]})}function Br({initialQuery:e=``,onChange:t,openMemory:n=()=>{}}){let r=new URLSearchParams(e),[i,a]=(0,l.useState)(r.get(`id`)),[o,s]=(0,l.useState)(``),[c,u]=(0,l.useState)({text:``,pending_only:r.get(`pending_only`)===`true`,include_merged:!1}),[d,f]=(0,l.useState)(c),[p,m]=(0,l.useState)(0),h=new URLSearchParams({text:d.text,pending_only:String(d.pending_only),include_merged:String(d.include_merged),limit:`30`,offset:String(p)}),g=y(i?null:`/people?${h}`,5e3);return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`page-heading`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`p`,{className:`eyebrow`,children:`名字背后的人`}),(0,x.jsx)(`h1`,{children:`人物`}),(0,x.jsx)(`p`,{children:`核对身份与证据,再决定是否为同一个人。`})]}),(0,x.jsx)(`a`,{className:`button`,href:`#/people-graph`,children:`人物关系图 →`})]}),o&&(0,x.jsx)(A,{children:o}),i?(0,x.jsx)(Hr,{id:i,summaryVersion:i===r.get(`id`)&&Number(r.get(`summary_version`))||void 0,openMemory:n,openPerson:a,onBack:()=>a(null),onChange:()=>{g.refresh(),t()},onMerged:e=>{s(`已确认联系并完成人物合并,以下为保留人物的资料。`),a(e)}},i):(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`form`,{className:`panel people-filters`,onSubmit:e=>{e.preventDefault(),f({...c}),m(0),g.refresh()},children:[(0,x.jsxs)(`label`,{children:[`搜索名字或别名`,(0,x.jsx)(`input`,{maxLength:100,value:c.text,onChange:e=>u({...c,text:e.target.value})})]}),(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:c.pending_only,onChange:e=>u({...c,pending_only:e.target.checked})}),`只看待确认`]}),(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:c.include_merged,onChange:e=>u({...c,include_merged:e.target.checked})}),`包含已合并人物`]}),(0,x.jsx)(`button`,{className:`primary`,children:`搜索人物`})]}),g.error&&(0,x.jsxs)(A,{error:!0,children:[g.error,(0,x.jsx)(`button`,{onClick:g.refresh,children:`重新加载`})]}),g.data?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{className:`muted`,children:[`共 `,g.data.total,` 位人物`]}),!g.data.items.length&&(0,x.jsx)(j,{title:`当前范围没有人物`}),(0,x.jsx)(`div`,{className:`entry-grid`,children:g.data.items.map(e=>(0,x.jsxs)(`article`,{className:`panel person-card`,children:[(0,x.jsx)(`h2`,{children:e.name}),(0,x.jsxs)(`small`,{className:`muted`,children:[`人物标识:`,e.id]}),!!e.pending_links&&(0,x.jsx)(`p`,{children:(0,x.jsxs)(M,{tone:`purple`,children:[`可能是同一人 · `,e.pending_links,` 条待确认`]})}),e.merged_into&&(0,x.jsx)(`p`,{children:(0,x.jsx)(M,{children:`已合并`})}),(0,x.jsxs)(`p`,{children:[`别名:`,e.aliases.map(e=>e.alias).join(`、`)||`暂无`]}),(0,x.jsxs)(`p`,{children:[`相关记忆 `,e.memory_count,` 条`]}),(0,x.jsx)(`button`,{className:`text-button`,onClick:()=>a(e.id),"aria-label":`查看人物 ${e.name}`,children:`查看人物 →`})]},e.id))}),(0,x.jsx)(T,{total:g.data.total,offset:p,change:m})]}):(0,x.jsx)(`p`,{role:`status`,children:`正在读取人物…`})]})]})}function Vr({messages:e}){return(0,x.jsxs)(`details`,{className:`person-evidence`,open:!0,children:[(0,x.jsxs)(`summary`,{children:[`证据消息 · `,e.length,` 条`]}),!e.length&&(0,x.jsx)(`p`,{className:`muted`,children:`没有可展示的证据消息。`}),e.map(e=>(0,x.jsxs)(`blockquote`,{children:[(0,x.jsxs)(`small`,{children:[e.sender_name||e.sender_subject_id,` ·`,` `,e.entry_name||e.entry_id,` · #`,e.id,` ·`,` `,w(e.occurred_at||e.received_at)]}),(0,x.jsx)(`p`,{children:e.content}),e.quote_content&&(0,x.jsxs)(`div`,{className:`evidence-quote`,children:[(0,x.jsxs)(`small`,{children:[`引用`,e.quote_author_subject_id?` · 作者标识 ${e.quote_author_subject_id}`:``]}),(0,x.jsx)(`p`,{children:e.quote_content})]})]},e.id))]})}function Hr({id:e,summaryVersion:t,openMemory:n,openPerson:r,onBack:i,onChange:a,onMerged:o}){let s=y(`/people/${encodeURIComponent(e)}`),[c,u]=(0,l.useState)(!1),[d,p]=(0,l.useState)(``),[m,h]=(0,l.useState)(null),[b,S]=(0,l.useState)(``),[C,w]=(0,l.useState)(``),[T,D]=(0,l.useState)(!1),[O,k]=(0,l.useState)(!1),j=s.data,P=T||O||s.loading||!!s.error,F=()=>{h(null),S(``),k(!1),s.refresh()},I=e=>{let t=e instanceof f&&e.status===409;k(t),S(t?`资料或联系已变化,请刷新人物资料后重新核对。`:v(e))},L=e=>{h(null),w(e),S(``),s.refresh(),a()};async function ee(t){if(t.preventDefault(),!j||P)return;let n=d.trim();if(!n||Array.from(n).length>100){S(`别名需为 1 至 100 个字符`);return}if(n.toLocaleLowerCase()===j.name.trim().toLocaleLowerCase()){S(`别名不能与人物名字相同`);return}D(!0),S(``),w(``);try{await g(`/people/${encodeURIComponent(e)}/aliases`,_(`POST`,{alias:n,expected_revision:j.revision})),p(``),L(`已添加别名`)}catch(e){I(e)}finally{D(!1)}}async function te(){if(j&&m&&m.kind!==`merge`&&!P){D(!0),S(``),w(``);try{m.kind===`deny`?await g(`/people/links/${m.link.id}/deny`,_(`POST`,{expected_revision:m.link.revision})):await g(`/people/${encodeURIComponent(e)}/aliases/${m.alias.id}`,_(`DELETE`,{expected_revision:j.revision})),L(m.kind===`deny`?`联系已否认,后续学习不会重新提出这对人物的同一人联系。`:`已删除别名,后续学习不会自动加回。必要时可手动添加。`)}catch(e){I(e)}finally{D(!1)}}}return(0,x.jsxs)(`section`,{className:`person-detail`,children:[(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{className:`text-button`,onClick:i,children:`← 返回人物列表`}),(0,x.jsx)(`button`,{disabled:T||s.loading,onClick:F,children:`刷新人物资料`})]}),(s.error||b)&&!m&&(0,x.jsx)(A,{error:!0,children:b||s.error}),C&&(0,x.jsx)(A,{children:C}),j?(0,x.jsxs)(x.Fragment,{children:[c&&(0,x.jsx)(xr,{scope:{subject_id:j.id},name:j.name,onClose:()=>u(!1),onChanged:()=>{s.refresh(),a()}}),(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsx)(`h2`,{children:j.name}),!j.merged_into&&(0,x.jsx)(`button`,{className:`secondary`,disabled:P,onClick:()=>u(!0),children:`批量遗忘/删除`}),(0,x.jsxs)(`p`,{className:`muted`,children:[`人物标识:`,j.id,` · 资料修订 `,j.revision]}),j.merged_into&&(0,x.jsxs)(A,{children:[`此人物已合并,原标识保留用于追溯。`,(0,x.jsx)(`button`,{onClick:()=>r(j.canonical_id),children:`查看合并后的人物`})]}),(0,x.jsx)(zr,{subjectId:e,initialVersion:t,openMemory:n}),(0,x.jsx)(`h3`,{children:`平台身份`}),!j.platform_identities.length&&(0,x.jsx)(`p`,{className:`muted`,children:`暂无平台身份。`}),j.platform_identities.map(e=>(0,x.jsxs)(`dl`,{className:`identity-facts`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`平台`}),(0,x.jsx)(`dd`,{children:e.platform===`iris-trial`?`试用`:e.platform})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`账号`}),(0,x.jsx)(`dd`,{children:e.account_id})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`显示名`}),(0,x.jsx)(`dd`,{children:e.display_name})]})]},`${e.platform}:${e.account_id}`)),(0,x.jsxs)(`h3`,{children:[`相关记忆 · `,j.memory_count,` 条`]}),(0,x.jsx)(`p`,{children:Object.entries(j.memory_counts).map(([e,t])=>`${E(e)} ${t} 条`).join(` · `)||`暂无相关记忆`}),(0,x.jsx)(`a`,{href:`#/memories?${new URLSearchParams({person_id:j.canonical_id,lifecycle:`all`})}`,children:`查看关于此人的记忆`})]}),(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsx)(`h3`,{children:`别名`}),!j.aliases.length&&(0,x.jsx)(`p`,{className:`muted`,children:`暂无别名。`}),(0,x.jsx)(`ul`,{className:`alias-list`,children:j.aliases.map(e=>(0,x.jsxs)(`li`,{children:[(0,x.jsx)(`span`,{children:e.alias}),!!e.evidence_message_ids.length&&(0,x.jsxs)(`small`,{className:`muted`,children:[`证据消息`,` `,e.evidence_message_ids.map(e=>`#${e}`).join(`、`)]}),!j.merged_into&&(0,x.jsx)(`button`,{disabled:P,className:`text-button danger-text`,"aria-label":`删除别名 ${e.alias}`,onClick:()=>{S(``),h({kind:`alias`,alias:e})},children:`删除`})]},e.id))}),!j.merged_into&&(0,x.jsxs)(`form`,{className:`inline-form`,onSubmit:ee,noValidate:!0,children:[(0,x.jsxs)(`label`,{children:[`新别名`,(0,x.jsx)(`input`,{value:d,maxLength:100,disabled:P,onChange:e=>p(e.target.value)})]}),(0,x.jsx)(`button`,{disabled:P,className:`secondary`,children:`添加别名`})]})]}),(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsx)(`h3`,{children:`可能是同一人`}),!j.same_as.length&&(0,x.jsx)(`p`,{className:`muted`,children:`暂无身份联系。`}),j.same_as.map(t=>(0,x.jsxs)(`article`,{className:`person-link`,children:[(0,x.jsx)(`h4`,{children:t.subjects.map(e=>e.name).join(` ↔ `)}),(0,x.jsxs)(`p`,{children:[(0,x.jsx)(M,{tone:t.status===`possible`?`purple`:``,children:t.status===`possible`?`待确认`:t.status===`denied`?`已否认`:`已确认`}),` `,`相信程度 `,t.belief,` / 100`]}),(0,x.jsx)(`div`,{className:`button-row`,children:t.subjects.filter(t=>t.id!==e).map(e=>(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>r(e.id),children:[`查看 `,e.name,` 的资料`]},e.id))}),(0,x.jsx)(Vr,{messages:t.evidence_messages}),t.status===`possible`&&!j.merged_into&&(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{disabled:P,className:`primary`,onClick:()=>{S(``),h({kind:`merge`,link:t})},children:`确认并合并`}),(0,x.jsx)(`button`,{disabled:P,onClick:()=>{S(``),h({kind:`deny`,link:t})},children:`否认联系`})]})]},t.id))]}),(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsx)(`h3`,{children:`扮演关系`}),!j.roleplay.length&&(0,x.jsx)(`p`,{className:`muted`,children:`暂无扮演关系。`}),j.roleplay.map(e=>(0,x.jsxs)(`article`,{className:`person-link`,children:[(0,x.jsxs)(`h4`,{children:[e.actor.name,` 扮演 `,e.character.name]}),(0,x.jsxs)(`p`,{children:[(0,x.jsx)(M,{children:`虚构角色`}),` · 相信程度 `,e.belief,` / 100`]}),(0,x.jsxs)(`p`,{children:[`所属场景:`,e.worlds.map(e=>e??`场景未知`).join(`、`)]}),(0,x.jsx)(`p`,{className:`muted`,children:`扮演关系不代表同一人,角色经历不归入现实人物。`}),(0,x.jsx)(Vr,{messages:e.evidence_messages})]},e.id))]}),m?.kind===`merge`?(0,x.jsx)(Ur,{link:m.link,initialTarget:e,onClose:()=>h(null),onRefresh:F,onSuccess:e=>{L(``),o(e)}}):m&&(0,x.jsxs)(N,{title:m.kind===`deny`?`否认人物联系`:`删除别名`,onClose:()=>h(null),closeDisabled:T,children:[m.kind===`deny`?(0,x.jsxs)(`p`,{children:[`否认 `,m.link.subjects.map(e=>e.name).join(`与`),` `,`是同一人。否认后,后续学习不会改回待确认,也不会再次提出这对人物的同一人联系。`]}):(0,x.jsxs)(`p`,{children:[`删除别名“`,m.alias.alias,`”及其别名证据记录,后续学习不会自动加回。管理员仍可手动添加。`]}),b&&(0,x.jsxs)(A,{error:!0,children:[b,O&&(0,x.jsx)(`button`,{onClick:F,children:`刷新人物资料`})]}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{onClick:()=>h(null),disabled:T,children:`取消`}),(0,x.jsx)(`button`,{className:`danger-button`,disabled:P,onClick:te,children:m.kind===`deny`?`确认否认`:`确认删除别名`})]})]})]}):(0,x.jsx)(`p`,{role:`status`,children:`正在读取人物资料…`})]})}function Ur({link:e,initialTarget:t,onClose:n,onRefresh:r,onSuccess:i}){let a=y(`/people/${encodeURIComponent(e.subjects[0].id)}`),o=y(`/people/${encodeURIComponent(e.subjects[1].id)}`),[s,c]=(0,l.useState)(t),[u,d]=(0,l.useState)(!1),[p,m]=(0,l.useState)(!1),[h,b]=(0,l.useState)(!1),[S,C]=(0,l.useState)(``),w=a.data&&o.data?[a.data,o.data]:null,T=w?.find(e=>e.id===s),E=w?.find(e=>e.id!==s),D=!!a.error||!!o.error||a.loading||o.loading||w?.some(e=>!!e.merged_into);async function O(){if(T&&E&&!p&&!h&&!D&&u){m(!0),C(``);try{i((await g(`/people/links/${e.id}/confirm`,_(`POST`,{target_id:T.id,expected_revision:e.revision,expected_source_revision:E.revision,expected_target_revision:T.revision}))).target_id)}catch(e){let t=e instanceof f&&e.status===409;b(t),C(t?`资料或联系已变化,请刷新人物资料后重新核对。`:v(e))}finally{m(!1)}}}return(0,x.jsxs)(N,{title:`确认并合并人物`,onClose:n,closeDisabled:p,children:[(S||a.error||o.error)&&(0,x.jsxs)(A,{error:!0,children:[S||a.error||o.error,(0,x.jsx)(`button`,{disabled:p,onClick:r,children:`刷新人物资料`})]}),w?(0,x.jsxs)(x.Fragment,{children:[w.some(e=>e.merged_into)&&(0,x.jsxs)(A,{error:!0,children:[`人物已合并,请刷新后核对。`,(0,x.jsx)(`button`,{onClick:r,children:`刷新人物资料`})]}),(0,x.jsxs)(`fieldset`,{className:`lifecycle-fieldset`,disabled:p||h||!!D,children:[(0,x.jsxs)(`label`,{children:[`保留的人物`,(0,x.jsx)(`select`,{value:s,onChange:e=>{c(e.target.value),d(!1)},children:w.map(e=>(0,x.jsxs)(`option`,{value:e.id,children:[e.name,` · `,e.id]},e.id))})]}),(0,x.jsxs)(`div`,{className:`purge-confirm`,children:[(0,x.jsxs)(`strong`,{children:[`将“`,E?.name,`”合并到“`,T?.name,`”`]}),(0,x.jsx)(`p`,{children:`平台身份、有效别名、记忆的涉及人和说话人、人物联系及从属人物会转到保留方。被合并方的名字成为别名,原人物保留为合并占位。`}),(0,x.jsx)(`p`,{children:`记忆正文、修订号与分数保持原值。联系冲突时否认优先。M2 不提供撤销合并,请先核对双方账号与证据。`}),(0,x.jsxs)(`p`,{children:[E?.name,`:`,E?.platform_identities.length,` `,`个平台身份,`,E?.memory_count,` 条相关记忆。`]}),(0,x.jsxs)(`p`,{children:[T?.name,`:`,T?.platform_identities.length,` 个平台身份,`,T?.memory_count,` 条相关记忆。`]}),w.map(e=>(0,x.jsxs)(`div`,{className:`merge-identity`,children:[(0,x.jsxs)(`strong`,{children:[e.name,` · `,e.id]}),(0,x.jsxs)(`p`,{children:[`账号:`,e.platform_identities.map(e=>`${e.platform} / ${e.account_id}`).join(`;`)||`未绑定平台账号`]}),(0,x.jsxs)(`p`,{children:[`别名:`,e.aliases.map(e=>e.alias).join(`、`)||`暂无`]})]},e.id)),(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:u,onChange:e=>d(e.target.checked)}),`我已核对身份,理解合并后无法在界面撤销`]})]})]}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{disabled:p,onClick:n,children:`取消`}),(0,x.jsx)(`button`,{className:`danger-button`,disabled:p||h||!!D||!u,onClick:O,children:p?`正在合并…`:`确认合并`})]})]}):(0,x.jsx)(`p`,{role:`status`,children:`正在核对双方资料…`})]})}var Wr=e=>JSON.stringify([e.source,e.target]),Gr=e=>`${e.links.some(e=>e.kind===`same_as`)?`可能同一人`:e.links.some(e=>e.kind===`roleplay`)?`扮演`:e.relationship_count?`关系`:`共现`} · ${e.memory_count}`;function Kr(e,t=900){let n=t<560,r=n?48:88,i=n?104:180,a=n?110:135,o=n?24:36,s=n?64:80,c=Math.max(1,Math.ceil(Math.sqrt(e*(n?1:1.7)))),l=Math.max(260,t,e>12?r*2+(c-1)*i:0),u=Math.min(c,Math.max(1,Math.floor((l-r*2)/i)+1)),d=Math.max(1,Math.ceil(e/u));return{width:l,height:Math.max(e<=3?220:n?330:400,o+s+(d-1)*a),compact:n,marginX:r,top:o,bottom:s,rows:d}}function qr(e,t,n=900){if(!e.length)return{};let r=Kr(e.length,n),i=e.map((t,n)=>({x:200*Math.cos(n*2*Math.PI/e.length),y:200*Math.sin(n*2*Math.PI/e.length)})),a=new Map(e.map((e,t)=>[e.id,t]));for(let e=0;e<90;e++){let n=i.map(e=>({x:-e.x*.009,y:-e.y*.009}));for(let e=0;e{e.x+=Math.max(-r,Math.min(r,n[t].x)),e.y+=Math.max(-r,Math.min(r,n[t].y))})}let o=[];for(let t=0;te.x),c=i.map(e=>e.y),l=Math.min(...s),u=Math.min(...c),d=Math.max(...s)-l,f=Math.max(...c)-u;return Object.fromEntries(e.map((e,t)=>{let n=d>.001?r.marginX+(i[t].x-l)/d*(r.width-r.marginX*2):r.width/2,a=f>.001?r.top+(i[t].y-u)/f*(r.height-r.top-r.bottom):(r.top+r.height-r.bottom)/2,s=0;for(let e=1;ee.leftt.left&&e.topt.top;function Yr(e,t,n,r){let i=e.map(e=>{let t=n[e.id];return{left:t.x-(r.compact?48:84),right:t.x+(r.compact?48:84),top:t.y-(r.compact?22:33),bottom:t.y+(r.compact?57:70)}}),a={};for(let e of t){let t=n[e.source],o=n[e.target],s=o.x-t.x,c=o.y-t.y,l=Math.max(1,Math.hypot(s,c)),u=r.compact?11:12,d=Array.from(Gr(e)).reduce((e,t)=>e+u*(t.charCodeAt(0)>255?1:.65),12),f=u+10,p=!1;for(let n of[.5,.35,.65,.2,.8]){for(let o of[-16,16,-32,32,-48,48]){let u={x:t.x+s*n-c/l*o,y:t.y+c*n+s/l*o},m={left:u.x-d/2,right:u.x+d/2,top:u.y-f/2,bottom:u.y+f/2};if(!(m.left<4||m.right>r.width-4||m.top<4||m.bottom>r.height-4||i.some(e=>Jr(m,e)))){a[Wr(e)]=u,i.push(m),p=!0;break}}if(p)break}}return a}var Xr=(e,t)=>Array.from(e).length>t?Array.from(e).slice(0,t).join(``)+`…`:e,Zr=e=>`#/memories?person_id=${encodeURIComponent(e)}&lifecycle=active`,Qr=e=>new URLSearchParams(Object.entries(e).filter(([,e])=>e)).toString();function $r({edge:e}){return(0,x.jsxs)(`span`,{className:`graph-kinds`,children:[e.memory_count>0&&(0,x.jsxs)(M,{children:[`共同涉及 `,e.memory_count]}),e.relationship_count>0&&(0,x.jsxs)(M,{tone:`purple`,children:[`关系记忆 `,e.relationship_count]}),e.links.some(e=>e.kind===`same_as`)&&(0,x.jsx)(M,{tone:`purple`,children:`可能同一人 · 未确认`}),e.links.some(e=>e.kind===`roleplay`)&&(0,x.jsx)(M,{children:`扮演 · 虚构角色`})]})}function ei({data:e,onEdge:t}){let n=(0,l.useRef)(null),[r,i]=(0,l.useState)(900),[a,o]=(0,l.useState)(null),[s,c]=(0,l.useState)(null),u=(0,l.useId)();(0,l.useEffect)(()=>{let e=n.current;if(!e)return;let t=()=>{let t=Math.floor(e.getBoundingClientRect().width);t>0&&i(t)};if(t(),typeof ResizeObserver>`u`)return;let r=new ResizeObserver(t);return r.observe(e),()=>r.disconnect()},[]);let d=(0,l.useMemo)(()=>Kr(e.nodes.length,r),[e.nodes.length,r]),f=(0,l.useMemo)(()=>qr(e.nodes,e.edges,r),[e,r]),p=(0,l.useMemo)(()=>Yr(e.nodes,e.edges,f,d),[e,f,d]),m=new Map(e.nodes.map(e=>[e.id,e.name])),h=e.edges.find(e=>Wr(e)===(s||a));return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{ref:n,className:`graph-scroll`,tabIndex:0,"aria-label":`关系图画布,可横向滚动`,children:(0,x.jsxs)(`svg`,{viewBox:`0 0 ${d.width} ${d.height}`,style:{minWidth:d.width},role:`group`,"aria-label":`人物关系图`,className:`people-graph-svg${d.compact?` compact`:``}`,children:[(0,x.jsx)(`title`,{children:`人物关系图`}),(0,x.jsx)(`desc`,{children:`点击节点打开人物的全部有效记忆,点击连线查看依据。悬停或聚焦连线查看摘要,也可使用画布下方的人物和连线列表。`}),e.edges.map(e=>{let n=f[e.source],r=f[e.target],i=`查看${m.get(e.source)}与${m.get(e.target)}的连线依据`,a=Wr(e),s=p[a],l=e.links.some(e=>e.kind===`same_as`)?`possible`:e.links.length?`roleplay`:e.relationship_count?`relationship`:`cooccurrence`;return(0,x.jsxs)(`g`,{className:`graph-edge ${l}`,role:`button`,tabIndex:0,"aria-label":i,"aria-describedby":h===e?u:void 0,onMouseEnter:()=>o(a),onMouseLeave:()=>o(null),onFocus:()=>c(a),onBlur:()=>c(null),onClick:()=>t(e),onKeyDown:n=>{(n.key===`Enter`||n.key===` `)&&(n.preventDefault(),t(e))},children:[(0,x.jsxs)(`title`,{children:[i,`;`,e.memory_count,` 条共同涉及记忆`]}),(0,x.jsx)(`line`,{x1:n.x,y1:n.y,x2:r.x,y2:r.y,className:`graph-edge-hit`}),(0,x.jsx)(`line`,{x1:n.x,y1:n.y,x2:r.x,y2:r.y,strokeWidth:Math.min(7,1.5+Math.log2(1+e.memory_count))}),s&&(0,x.jsx)(`text`,{x:s.x,y:s.y,textAnchor:`middle`,dominantBaseline:`middle`,children:Gr(e)})]},a)}),e.nodes.map(e=>(0,x.jsxs)(`a`,{href:Zr(e.id),"aria-label":`查看${e.name}的有效记忆`,className:`graph-node ${e.kind===`self`?`self`:``}`,children:[(0,x.jsxs)(`title`,{children:[e.name,`;别名:`,e.aliases.join(`、`)||`暂无`,`;`,e.account_count,` 个账号;`,e.memory_count,` 条有效记忆`]}),(0,x.jsx)(`circle`,{cx:f[e.id].x,cy:f[e.id].y,r:d.compact?14:Math.min(27,18+Math.log2(1+e.memory_count))}),(0,x.jsx)(`text`,{x:f[e.id].x,y:f[e.id].y+5,textAnchor:`middle`,className:`graph-node-mark`,children:e.kind===`self`?`我`:Array.from(e.name)[0]}),(0,x.jsx)(`rect`,{className:`graph-node-label-background`,x:f[e.id].x-(d.compact?44:78),y:f[e.id].y+(d.compact?20:30),width:d.compact?88:156,height:d.compact?33:38,rx:`4`}),(0,x.jsx)(`text`,{x:f[e.id].x,y:f[e.id].y+(d.compact?32:44),textAnchor:`middle`,children:Xr(e.name,d.compact?6:10)}),(0,x.jsxs)(`text`,{x:f[e.id].x,y:f[e.id].y+(d.compact?48:63),textAnchor:`middle`,className:`graph-node-count`,children:[e.memory_count,` 条记忆`]})]},e.id))]})}),(0,x.jsx)(`div`,{className:`graph-preview`,children:h?(0,x.jsxs)(`div`,{id:u,role:`tooltip`,children:[(0,x.jsxs)(`strong`,{children:[m.get(h.source),` · `,m.get(h.target)]}),(0,x.jsxs)(`p`,{children:[Gr(h),`(数字为共同涉及的有效记忆数)`]}),h.relationship_summaries.map(e=>(0,x.jsx)(`p`,{children:e.summary},e.id)),!h.relationship_summaries.length&&(0,x.jsx)(`p`,{children:`点击连线查看联系记录与支撑记忆。`})]}):(0,x.jsx)(`p`,{children:`悬停或用键盘聚焦连线可查看摘要;数字为共同涉及的有效记忆数。拥挤处省略标签,完整内容见下方列表。`})})]})}function ti({edge:e,names:t,entryId:n,onClose:r,openMemory:i}){let[a,o]=(0,l.useState)(0),s=y(`/people-graph/edge?${Qr({source_id:e.source,target_id:e.target,entry_id:n,limit:`30`,offset:String(a)})}`);return(0,x.jsxs)(N,{title:`连线依据:${t.get(e.source)} · ${t.get(e.target)}`,onClose:r,children:[(0,x.jsx)(`p`,{children:`这里只显示当前仍有效的记忆。身份/扮演联系来自独立联系记录;同来源记忆不等于确认身份,也不把角色经历归给扮演者。`}),s.error&&(0,x.jsxs)(A,{error:!0,children:[s.error,(0,x.jsx)(`button`,{onClick:s.refresh,children:`重新读取依据`})]}),s.loading&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取连线依据…`}),s.data&&(0,x.jsxs)(x.Fragment,{children:[s.data.links.map(e=>(0,x.jsxs)(`article`,{className:`graph-link-record`,children:[(0,x.jsx)(`h3`,{children:e.kind===`same_as`?`可能同一人 · 未确认`:`扮演 · 虚构角色`}),(0,x.jsxs)(`p`,{children:[t.get(e.source),` `,e.kind===`roleplay`?`→`:`↔`,` `,t.get(e.target),` · 相信程度 `,e.belief]}),e.kind===`roleplay`&&(0,x.jsxs)(`p`,{children:[`场景:`,e.worlds.map(e=>e||`场景未记录`).join(`、`)]}),(0,x.jsxs)(`p`,{children:[`联系 #`,e.id,` · `,e.evidence_message_count,` 条来源消息`]}),(0,x.jsx)(`a`,{href:`#/people?id=${encodeURIComponent(e.source)}`,onClick:r,children:`到人物详情核对联系与消息`})]},e.id)),(0,x.jsxs)(`p`,{children:[`共 `,s.data.total,` 条支撑/同来源记忆`]}),!s.data.items.length&&(0,x.jsx)(j,{title:`没有可展示的有效支撑记忆`,children:`联系记录可能只有来源消息;遗忘、删除或清除的记忆不会在这里显示。`}),(0,x.jsx)(`div`,{className:`graph-evidence-list`,children:s.data.items.map(e=>(0,x.jsxs)(`article`,{children:[(0,x.jsxs)(`p`,{children:[(0,x.jsx)(M,{children:e.kind}),` #`,e.id,` · 修订`,` `,e.revision]}),(0,x.jsx)(`p`,{className:`memory-content`,children:e.content}),(0,x.jsxs)(`p`,{children:[e.cooccurrence&&(0,x.jsx)(M,{children:`共同涉及两人`}),` `,e.link_evidence&&(0,x.jsx)(M,{children:`同来源联系证据`})]}),(0,x.jsxs)(`button`,{onClick:()=>{r(),i(e.id)},children:[`查看记忆 #`,e.id]})]},e.id))}),(0,x.jsx)(T,{total:s.data.total,offset:a,change:o})]})]})}function ni({initialQuery:e=``,openMemory:t}){let n=new URLSearchParams(e),[r,i]=(0,l.useState)({entry_id:n.get(`entry_id`)||``,person_id:n.get(`person_id`)||``,hops:`1`,min_memories:`1`,node_limit:`60`,edge_limit:`100`}),[a,o]=(0,l.useState)(r),[s,c]=(0,l.useState)(null),u=y(`/catalog`),d=y(`/people-graph?${Qr(a)}`),f=new Map(d.data?.nodes.map(e=>[e.id,e.name])||[]),p=e=>{c(null),o({...e}),Qr(e)===Qr(a)&&d.refresh()};return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`page-heading`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`p`,{className:`eyebrow`,children:`从已有经历看人物联系`}),(0,x.jsx)(`h1`,{children:`人物关系图`}),(0,x.jsx)(`p`,{children:`点击人物查看记忆,点击连线追溯依据。`})]}),(0,x.jsx)(`a`,{href:`#/people`,className:`button`,children:`返回人物列表`})]}),(0,x.jsxs)(`form`,{className:`panel graph-filters`,onSubmit:e=>{e.preventDefault(),p(r)},children:[(0,x.jsxs)(`label`,{children:[`来源入口`,(0,x.jsxs)(`select`,{value:r.entry_id,onChange:e=>i({...r,entry_id:e.target.value}),children:[(0,x.jsx)(`option`,{value:``,children:`全部入口`}),u.data?.entries.map(e=>(0,x.jsx)(`option`,{value:e.id,children:e.name},e.id))]})]}),(0,x.jsxs)(`label`,{children:[`聚焦人物`,(0,x.jsxs)(`select`,{value:r.person_id,onChange:e=>i({...r,person_id:e.target.value}),children:[(0,x.jsx)(`option`,{value:``,children:`所有人物`}),u.data?.people.filter(e=>e.id!==`scene`).map(e=>(0,x.jsxs)(`option`,{value:e.id,children:[e.name,e.id===`self`?`(角色)`:``,` · `,e.id]},e.id))]})]}),(0,x.jsxs)(`label`,{children:[`范围`,(0,x.jsxs)(`select`,{value:r.hops,disabled:!r.person_id,onChange:e=>i({...r,hops:e.target.value}),children:[(0,x.jsx)(`option`,{value:`1`,children:`一跳联系`}),(0,x.jsx)(`option`,{value:`2`,children:`两跳联系`})]})]}),(0,x.jsxs)(`label`,{children:[`共现最少记忆数`,(0,x.jsx)(`input`,{type:`number`,min:`1`,max:`1000000`,required:!0,value:r.min_memories,onChange:e=>i({...r,min_memories:e.target.value})})]}),(0,x.jsxs)(`label`,{children:[`节点上限`,(0,x.jsx)(`input`,{type:`number`,min:`2`,max:`100`,required:!0,value:r.node_limit,onChange:e=>i({...r,node_limit:e.target.value})})]}),(0,x.jsxs)(`label`,{children:[`连线上限`,(0,x.jsx)(`input`,{type:`number`,min:`1`,max:`200`,required:!0,value:r.edge_limit,onChange:e=>i({...r,edge_limit:e.target.value})})]}),(0,x.jsx)(`button`,{className:`primary`,disabled:d.loading,children:`生成关系图`})]}),u.error&&(0,x.jsxs)(A,{error:!0,children:[`筛选目录:`,u.error,(0,x.jsx)(`button`,{onClick:u.refresh,children:`重新读取目录`})]}),(0,x.jsxs)(`details`,{className:`panel graph-explanation`,children:[(0,x.jsx)(`summary`,{children:`数据口径与图例`}),(0,x.jsx)(`p`,{children:`只统计 active 且未彻底清除的记忆。共现按同一记忆的 about 涉及人两两计数,每条只算一次;共现不等于关系事实。“关系”类记忆另外显示正文摘要。`}),(0,x.jsx)(`p`,{children:`入口筛选只认至少一条直接来源消息在该入口的记忆,不沿派生依据扩大范围。身份/扮演联系按其来源消息筛选,可没有支撑记忆;共现阈值不隐藏这些独立联系。`}),(0,x.jsx)(`p`,{children:`节点记忆数包括作为涉及人或说话人的有效记忆,别名与账号数为当前主体资料。self 显示为角色节点,scene 不作为人物;已合并主体只显示保留人物。点击人物打开其全部入口的有效记忆列表。`}),(0,x.jsx)(`p`,{children:`线条越粗,共同涉及记忆越多;紫色为关系记忆,虚线为可能同一人,绿色为扮演。位置和距离只用于排布,没有关系强弱含义。图中读数不调用模型,不产生召回或使用记录。`})]}),d.error&&(0,x.jsxs)(A,{error:!0,children:[d.error,(0,x.jsx)(`button`,{onClick:d.refresh,children:`重新读取关系图`})]}),d.loading&&(0,x.jsx)(`p`,{role:`status`,children:`正在生成只读关系图…`}),d.data&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{"aria-live":`polite`,children:[`当前显示 `,d.data.nodes.length,` 个节点、`,d.data.edges.length,` `,`条连线。`]}),d.data.truncated&&(0,x.jsxs)(A,{children:[`筛选后共有 `,d.data.total_nodes,` 个节点、`,d.data.total_edges,` `,`条连线,超过显示上限。按共同涉及记忆数从高到低保留,关系记忆数和主体标识用于同权重排序;聚焦人物优先保留。可缩小入口或聚焦范围后重新查看。`]}),d.data.nodes.length?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`section`,{className:`panel graph-panel`,"aria-label":`关系图与图例`,children:[(0,x.jsxs)(`div`,{className:`graph-legend`,children:[(0,x.jsx)(`span`,{children:`实线:共现`}),(0,x.jsx)(`span`,{children:`紫色:关系记忆`}),(0,x.jsx)(`span`,{children:`虚线:可能同一人`}),(0,x.jsx)(`span`,{children:`绿色:扮演`})]}),(0,x.jsx)(ei,{data:d.data,onEdge:c}),(0,x.jsx)(`p`,{className:`muted`,children:`窄屏可横向滚动画布。下方列表提供相同的跳转和证据操作。`})]}),(0,x.jsxs)(`section`,{"aria-label":`图中人物`,children:[(0,x.jsx)(`h2`,{children:`图中人物`}),(0,x.jsx)(`div`,{className:`graph-node-list`,children:d.data.nodes.map(e=>(0,x.jsxs)(`article`,{className:`panel`,children:[(0,x.jsxs)(`h3`,{children:[(0,x.jsx)(`a`,{href:Zr(e.id),"aria-label":`查看${e.name}的有效记忆`,children:e.name}),` `,e.kind===`self`&&(0,x.jsx)(M,{children:`角色`})]}),(0,x.jsx)(`small`,{className:`muted`,children:e.id}),(0,x.jsxs)(`p`,{children:[`别名:`,e.aliases.join(`、`)||`暂无`]}),(0,x.jsxs)(`p`,{children:[e.account_count,` 个账号 · `,e.memory_count,` `,`条有效记忆`]}),(0,x.jsx)(`button`,{className:`text-button`,"aria-label":`聚焦${e.name}`,onClick:()=>{let t={...r,person_id:e.id};i(t),p(t)},children:`以此人为中心`})]},e.id))})]}),(0,x.jsxs)(`section`,{"aria-label":`图中连线`,children:[(0,x.jsx)(`h2`,{children:`图中连线`}),!d.data.edges.length&&(0,x.jsx)(`p`,{className:`muted`,children:`当前阈值和范围没有连线。`}),(0,x.jsx)(`div`,{className:`graph-edge-list`,children:d.data.edges.map(e=>(0,x.jsxs)(`article`,{className:`panel`,children:[(0,x.jsxs)(`h3`,{children:[f.get(e.source),` · `,f.get(e.target)]}),(0,x.jsx)($r,{edge:e}),(0,x.jsxs)(`p`,{children:[e.memory_count,` 条共同涉及记忆`]}),e.relationship_summaries.map(e=>(0,x.jsxs)(`p`,{children:[`关系记忆 #`,e.id,`:`,e.summary]},e.id)),e.relationship_count>e.relationship_summaries.length&&(0,x.jsx)(`small`,{children:`更多关系正文见连线依据。`}),(0,x.jsx)(`button`,{onClick:()=>c(e),"aria-label":`查看${f.get(e.source)}与${f.get(e.target)}的连线依据`,children:`查看连线依据`})]},JSON.stringify([e.source,e.target])))})]})]}):(0,x.jsx)(j,{title:`当前范围没有人物关系数据`,children:`可以改选入口或人物;遗忘、删除和清除的记忆不参与关系图。`})]}),s&&(0,x.jsx)(ti,{edge:s,names:f,entryId:a.entry_id,onClose:()=>c(null),openMemory:t},JSON.stringify([s.source,s.target,a.entry_id]))]})}function ri({initialVersion:e,initialComparison:t,currentID:n,catalog:r,openMemory:i,onAction:a,locked:o}){let[s,c]=(0,l.useState)(e),[u,d]=(0,l.useState)({status:``,source:``}),[f,p]=(0,l.useState)(``),[m,h]=(0,l.useState)(0),g=y(`/persona/versions?${f}limit=30&offset=${m}`,5e3),[_,v]=(0,l.useState)(t?.before.toString()||``),[b,S]=(0,l.useState)(t?.after.toString()||n?.toString()||``),[C,w]=(0,l.useState)(``),[E,D]=(0,l.useState)(t||null),[O,k]=(0,l.useState)(0);return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`section`,{className:`panel persona-history`,children:[(0,x.jsx)(`h2`,{children:`版本历史`}),(0,x.jsx)(`p`,{children:`可选择任意两个版本逐句对比。只有已经发布过的版本可以回滚;回滚会新建版本。`}),(0,x.jsxs)(`form`,{className:`persona-filters`,onSubmit:e=>{e.preventDefault();let t=new URLSearchParams;u.status&&t.set(`status`,u.status),u.source&&t.set(`source`,u.source),p(t.size?`${t}&`:``),h(0),g.refresh()},children:[(0,x.jsxs)(`label`,{children:[`版本状态`,(0,x.jsxs)(`select`,{value:u.status,onChange:e=>d({...u,status:e.target.value}),children:[(0,x.jsx)(`option`,{value:``,children:`全部状态`}),Object.entries(I).map(([e,t])=>(0,x.jsx)(`option`,{value:e,children:t},e))]})]}),(0,x.jsxs)(`label`,{children:[`版本来源`,(0,x.jsxs)(`select`,{value:u.source,onChange:e=>d({...u,source:e.target.value}),children:[(0,x.jsx)(`option`,{value:``,children:`全部来源`}),Object.entries(F).map(([e,t])=>(0,x.jsx)(`option`,{value:e,children:t},e))]})]}),(0,x.jsx)(`button`,{children:`筛选版本`})]}),g.error&&(0,x.jsxs)(A,{error:!0,children:[g.error,(0,x.jsx)(`button`,{onClick:g.refresh,children:`重试版本列表`})]}),g.loading&&(0,x.jsx)(`p`,{children:`正在读取版本…`}),g.data?.items.map(e=>(0,x.jsxs)(`article`,{className:`persona-history-row`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsxs)(`strong`,{children:[`v`,e.id]}),` `,(0,x.jsx)(M,{children:I[e.status]}),` ·`,` `,F[e.source],` · 变化`,` `,e.change_degree?L[e.change_degree]:`未记录`,(0,x.jsx)(`p`,{className:`muted`,children:(0,x.jsx)(P,{value:e.generated_at})}),(0,x.jsx)(`p`,{className:`persona-content`,children:e.content})]}),(0,x.jsxs)(`div`,{className:`persona-actions`,children:[(0,x.jsxs)(`button`,{onClick:()=>c(e.id),children:[`查看版本 v`,e.id]}),(0,x.jsxs)(`button`,{onClick:()=>v(String(e.id)),children:[`v`,e.id,` 作为对比前版`]}),(0,x.jsxs)(`button`,{onClick:()=>S(String(e.id)),children:[`v`,e.id,` 作为对比后版`]})]})]},e.id)),g.data?.total===0&&(0,x.jsx)(j,{title:`没有符合筛选的版本`}),g.data&&(0,x.jsx)(T,{total:g.data.total,offset:m,change:h})]}),(0,x.jsxs)(`section`,{className:`panel persona-comparison`,children:[(0,x.jsx)(`h2`,{children:`对比任意版本`}),(0,x.jsx)(`p`,{children:`从列表选择,或输入版本 ID;可以跨页选择,也可以查看被拒绝的候选。`}),(0,x.jsxs)(`form`,{noValidate:!0,className:`persona-filters`,onSubmit:e=>{if(e.preventDefault(),!/^\d+$/.test(_)||!/^\d+$/.test(b)||!Number.isSafeInteger(Number(_))||!Number.isSafeInteger(Number(b))||Number(_)<1||Number(b)<1){w(`请输入有效的正整数版本 ID`);return}w(``),D({before:Number(_),after:Number(b)}),k(e=>e+1)},children:[(0,x.jsxs)(`label`,{children:[`对比前版本 ID`,(0,x.jsx)(`input`,{type:`number`,min:1,step:1,value:_,onChange:e=>v(e.target.value)})]}),(0,x.jsxs)(`label`,{children:[`对比后版本 ID`,(0,x.jsx)(`input`,{type:`number`,min:1,step:1,value:b,onChange:e=>S(e.target.value)})]}),(0,x.jsx)(`button`,{children:`对比版本`})]}),C&&(0,x.jsx)(A,{error:!0,children:C}),E&&(0,x.jsx)(Pt,{...E},O)]}),s&&(0,x.jsx)(Mt,{id:s,title:`版本详情`,catalog:r,openMemory:i,onAction:a,locked:o,currentID:n,history:!0},s)]})}function ii({openMemory:e}){let[t,n]=(0,l.useState)(0),r=y(`/persona/self-memories?limit=30&offset=${t}`);return(0,x.jsxs)(`section`,{className:`panel persona-memories`,children:[(0,x.jsx)(`h2`,{children:`自我记忆`}),(0,x.jsx)(`p`,{children:`有效的自我设定与经历是 persona 的材料;打开或翻页不会触发召回。`}),r.error&&(0,x.jsxs)(A,{error:!0,children:[r.error,(0,x.jsx)(`button`,{onClick:r.refresh,children:`重试自我记忆`})]}),r.loading&&(0,x.jsx)(`p`,{children:`正在读取自我记忆…`}),r.data?.items.map(t=>(0,x.jsxs)(`article`,{className:`persona-history-row`,children:[(0,x.jsx)(`p`,{className:`persona-content`,children:t.content}),(0,x.jsxs)(`p`,{className:`muted`,children:[`#`,t.id,` · 修订 `,t.revision,` · `,t.stance,` ·`,` `,E(t.lifecycle),` · `,(0,x.jsx)(P,{value:t.created_at})]}),(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>e(t.id),children:[`查看自我记忆 #`,t.id]})]},t.id)),r.data?.total===0&&(0,x.jsx)(j,{title:`暂无有效自我记忆`,children:`在持续对话中积累经历,或在设置中完善初始背景。`}),r.data&&(0,x.jsx)(T,{total:r.data.total,offset:t,change:n})]})}function ai(){let[e,t]=(0,l.useState)(0),n=y(`/persona/attempts?limit=30&offset=${e}`,2e3);return(0,x.jsxs)(`section`,{className:`panel persona-attempts`,children:[(0,x.jsx)(`h2`,{children:`生成记录`}),(0,x.jsx)(`p`,{children:`包括未生成版本的跳过、冲突与失败;生成被拒绝不改变当前 persona。`}),n.error&&(0,x.jsxs)(A,{error:!0,children:[n.error,(0,x.jsx)(`button`,{onClick:n.refresh,children:`重试生成记录`})]}),n.loading&&(0,x.jsx)(`p`,{children:`正在读取生成记录…`}),n.data?.items.map(e=>(0,x.jsxs)(`article`,{className:`persona-history-row`,children:[(0,x.jsxs)(`h3`,{children:[`任务 #`,e.id,` · `,ie(e.state,e.stage)]}),(0,x.jsxs)(`p`,{children:[F[e.source]||e.source,` · 基于 v`,e.base_version_id]}),(0,x.jsxs)(`p`,{className:`muted`,children:[`接受:`,(0,x.jsx)(P,{value:e.created_at}),` · 结束:`,(0,x.jsx)(P,{value:e.finished_at})]}),e.reason&&(0,x.jsx)(`p`,{children:ne(e.reason)}),e.version_id&&(0,x.jsxs)(`a`,{href:`#/persona?tab=history&version=${e.version_id}`,children:[`查看版本 v`,e.version_id]}),(0,x.jsx)(`p`,{children:(0,x.jsx)(`a`,{href:`#/operations?object_type=persona_attempt&object_id=${e.id}`,children:`查看任务操作记录`})})]},e.id)),n.data?.total===0&&(0,x.jsx)(j,{title:`暂无生成任务`}),n.data&&(0,x.jsx)(T,{total:n.data.total,offset:e,change:t})]})}function oi({initial:e,path:t,onFinish:n}){let[r,i]=(0,l.useState)(e),[a,o]=(0,l.useState)(``),[s,c]=(0,l.useState)(0),u=(0,l.useRef)(n);u.current=n;let d=re(e.state);(0,l.useEffect)(()=>{if(!d){i(e),o(``);return}let n=new AbortController,r=!0,a,s=async()=>{let c=!0;try{let a=await g(t||`/persona/attempts/${e.id}`,{signal:n.signal});if(!r)return;i(a),o(``),re(a.state)||(c=!1,u.current(a))}catch(e){r&&!n.signal.aborted&&o(v(e))}r&&c&&(a=setTimeout(s,2e3))};return s(),()=>{r=!1,n.abort(),clearTimeout(a)}},[e.id,d,t,s]);let f=y(r.state===`rejected`&&r.version_id?`/persona/versions/${r.version_id}`:null);return(0,x.jsxs)(`section`,{className:`panel persona-task`,"aria-label":`最近生成任务`,children:[(0,x.jsxs)(`h2`,{children:[`生成任务 #`,r.id]}),(0,x.jsxs)(`p`,{role:`status`,children:[ie(r.state,r.stage),r.state===`current`&&r.version_id?` · v${r.version_id}`:``]}),re(r.state)&&(0,x.jsx)(`p`,{children:`请求已接受,尚未发布。页面会持续查询生成与检查结果;离开后任务仍在服务端运行。`}),r.reason&&(0,x.jsx)(A,{error:r.state===`failed`||r.state===`conflict`,children:ne(r.reason)}),(0,x.jsxs)(`p`,{className:`muted`,children:[`基于 v`,r.base_version_id,` · 接受时间:`,(0,x.jsx)(P,{value:r.created_at}),r.finished_at&&(0,x.jsxs)(x.Fragment,{children:[` `,`· 结束时间:`,(0,x.jsx)(P,{value:r.finished_at})]})]}),a&&(0,x.jsxs)(A,{error:!0,children:[a,`。任务结果尚未获知,将继续查询。`,(0,x.jsx)(`button`,{onClick:()=>c(e=>e+1),children:`立即查询任务`})]}),f.error&&(0,x.jsxs)(A,{error:!0,children:[f.error,(0,x.jsx)(`button`,{onClick:f.refresh,children:`重试拒绝原因`})]}),f.data&&(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h3`,{children:`拒绝原因`}),f.data.rejection_reasons.length?(0,x.jsx)(`ul`,{children:f.data.rejection_reasons.map((e,t)=>(0,x.jsx)(`li`,{children:ne(e)},t))}):(0,x.jsx)(`p`,{children:`未记录拒绝原因,请查看版本检查结果。`})]}),r.version_id&&(0,x.jsxs)(`a`,{href:`#/persona?tab=history&version=${r.version_id}`,children:[`查看结果版本 v`,r.version_id]}),(0,x.jsx)(`p`,{children:(0,x.jsx)(`a`,{href:`#/operations?object_type=persona_attempt&object_id=${r.id}`,children:`查看生成操作记录`})})]})}var si={edit:`编辑并发布 persona`,confirm:`确认发布候选`,reject:`拒绝候选`,rollback:`回滚 persona`},ci={edit:`发布编辑`,confirm:`确认发布`,reject:`确认拒绝`,rollback:`确认回滚`},li={current:`当前与候选`,history:`版本历史`,memories:`自我记忆`,attempts:`生成记录`};function ui({openMemory:e,initialQuery:t=``}){let n=new URLSearchParams(t),r=Number(n.get(`version`)),[i,a]=(0,l.useState)(n.get(`focus`)===`pending`),o=(0,l.useRef)(null),[s,c]=(0,l.useState)(Object.hasOwn(li,n.get(`tab`)||``)?n.get(`tab`):`current`),u=y(`/persona`,2e3),d=y(`/catalog`),[p,h]=(0,l.useState)(null),[b,S]=(0,l.useState)(``),[C,w]=(0,l.useState)(``),[T,E]=(0,l.useState)(``),[D,O]=(0,l.useState)(``),[k,P]=(0,l.useState)(!1),[F,I]=(0,l.useState)(!1),[L,ee]=(0,l.useState)(0),[te,ie]=(0,l.useState)(null),ae=u.data,oe=ae?.current,se=ae?.pending;(0,l.useEffect)(()=>{i&&s===`current`&&se&&o.current&&(o.current.focus(),o.current.scrollIntoView?.({block:`start`}),a(!1))},[i,s,se]);let ce=ae?.latest_attempt,le=ce&&(!te||ce.id>te.attempt.id||ce.id===te.attempt.id&&re(te.attempt.state)&&!re(ce.state))?{attempt:ce,path:te?.attempt.id===ce.id?te.path:void 0}:te,ue=k||F||!!u.error||u.loading;function fe(e,t){oe&&!ue&&(h({kind:e,version:t,expectedVersion:oe.id}),S(t.content),w(``),E(``),O(``))}function R(){h(null),I(!1),E(``),O(``),u.refresh(),ee(e=>e+1)}function z(e){E(v(e)),e instanceof f&&e.code===`persona_conflict`&&I(!0)}async function B(){if(p&&!ue){if(p.kind===`edit`&&(!b.trim()||[...b].length>800)){E(`persona 正文须为 1—800 字,不能只含空白`);return}if(p.kind===`reject`&&[...C.trim()].length>1e3){E(`拒绝原因不能超过 1000 字`);return}P(!0),E(``);try{let e={expected_version:p.expectedVersion,...p.kind===`edit`?{content:b}:p.kind===`reject`&&C.trim()?{reason:C.trim()}:{}},t=await g(p.kind===`edit`?`/persona`:`/persona/versions/${p.version.id}/${p.kind}`,_(p.kind===`edit`?`PUT`:`POST`,e));O(p.kind===`reject`?`已拒绝候选 v${t.id},当前版本仍保留。`:`已发布 persona v${t.id}${p.kind===`rollback`?`,回滚自 v${p.version.id}`:``}。`),h(null),c(`current`),u.refresh(),ee(e=>e+1)}catch(e){z(e)}finally{P(!1)}}}async function pe(){if(!(!oe||ue||re(le?.attempt.state))){P(!0),E(``),O(``);try{let e=await m(`/persona/regenerate`,_(`POST`,{expected_version:oe.id}));if(e.status!==202||!e.data.accepted)throw new f(`invalid_response`,`生成请求返回了意外结果,请刷新查看任务记录;不要重复提交。`,e.status);let t=e.data.attempt,n=e.headers.get(`Location`),r=n===`/admin/api/persona/attempts/${t.id}`?n.slice(10):`/persona/attempts/${t.id}`;ie({attempt:t,path:r}),u.refresh()}catch(e){z(e),u.refresh()}finally{P(!1)}}}let me=(0,x.jsx)(`button`,{disabled:k,onClick:R,children:`重新加载当前版本`});return(0,x.jsxs)(`div`,{className:`persona-page`,children:[(0,x.jsxs)(`div`,{className:`page-heading`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`span`,{className:`eyebrow`,children:`自我与未来`}),(0,x.jsx)(`h1`,{children:`persona 与自我`}),(0,x.jsx)(`p`,{children:`从持续经历中认识自己,逐句查看变化的依据。`})]}),(0,x.jsxs)(`div`,{className:`persona-actions`,children:[(0,x.jsx)(`button`,{disabled:k,onClick:u.refresh,children:`刷新 persona`}),oe&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`button`,{disabled:ue,onClick:()=>fe(`edit`,oe),children:`编辑并发布`}),(0,x.jsx)(`button`,{className:`primary`,disabled:ue||re(le?.attempt.state),onClick:()=>void pe(),children:`重新生成`})]})]})]}),u.error&&(0,x.jsxs)(A,{error:!0,children:[u.error,`。数据可能尚未更新,写操作暂不可用。`]}),d.error&&(0,x.jsxs)(A,{error:!0,children:[`入口类型暂不可用。`,d.error,(0,x.jsx)(`button`,{onClick:d.refresh,children:`重试入口信息`})]}),!p&&T&&(0,x.jsxs)(A,{error:!0,children:[T,F&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`p`,{children:`请重新加载后核对当前版本,再决定是否操作。`}),me]})]}),D&&(0,x.jsx)(A,{children:D}),ae?.needs_update&&(0,x.jsxs)(`section`,{className:`notice persona-stale`,"aria-label":`失效依据`,children:[(0,x.jsxs)(`h2`,{children:[(0,x.jsx)(M,{tone:`warning`,children:`待更新`}),` `,ae.stale_basis_count,` `,`条依据失效`]}),(0,x.jsx)(`p`,{children:`当前 persona 仍在使用。重新生成会重新提炼与检查;失效依据不等于已有待确认候选。`}),(0,x.jsx)(`ul`,{children:ae.stale_basis.map((t,n)=>(0,x.jsxs)(`li`,{children:[`记忆 #`,t.memory_id,` · 记录修订 `,t.expected_revision,` ·`,` `,t.current_revision==null?`当前不可用`:`当前修订 ${t.current_revision}`,`:`,ne(t.reason),t.memory&&(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>e(t.memory_id),children:[`查看失效依据 #`,t.memory_id]})]},`${t.memory_id}-${n}`))})]}),se&&(0,x.jsxs)(A,{children:[(0,x.jsx)(M,{tone:`warning`,children:`待确认`}),` 候选 v`,se.id,` `,`等待决定,当前版本仍在使用。`,(0,x.jsx)(`button`,{className:`text-button`,onClick:()=>{c(`current`),a(!0)},children:`查看候选与差异`})]}),ae&&!se&&n.get(`focus`)===`pending`&&(0,x.jsx)(A,{children:`当前没有待确认的 persona 候选。`}),le&&(0,x.jsx)(oi,{initial:le.attempt,path:le.path,onFinish:e=>{ie({attempt:e,path:le.path}),u.refresh(),ee(e=>e+1)}},le.attempt.id),(0,x.jsx)(de,{}),(0,x.jsx)(`div`,{className:`tabs persona-tabs`,role:`tablist`,"aria-label":`persona 内容`,children:Object.entries(li).map(([e,t])=>(0,x.jsx)(`button`,{id:`persona-tab-${e}`,role:`tab`,"aria-selected":s===e,tabIndex:s===e?0:-1,onKeyDown:t=>{let n=Object.keys(li),r=n.indexOf(e),i=t.key===`ArrowRight`?(r+1)%n.length:t.key===`ArrowLeft`?(r+n.length-1)%n.length:t.key===`Home`?0:t.key===`End`?n.length-1:null;i!==null&&(t.preventDefault(),c(n[i]),document.getElementById(`persona-tab-${n[i]}`)?.focus())},"aria-controls":`persona-tab-panel`,className:s===e?`active`:``,onClick:()=>c(e),children:t},e))}),(0,x.jsxs)(`div`,{role:`tabpanel`,id:`persona-tab-panel`,"aria-labelledby":`persona-tab-${s}`,children:[s===`current`&&(0,x.jsxs)(x.Fragment,{children:[!ae&&!u.error&&(0,x.jsx)(`p`,{children:`正在读取 persona…`}),ae&&!oe&&(0,x.jsx)(j,{title:`暂无 persona 版本`,children:`请先在设置中完成角色初始设定。`}),oe&&(0,x.jsx)(Mt,{id:oe.id,title:`当前 persona`,catalog:d.data,openMemory:e},`current-${oe.id}-${L}`),se&&(0,x.jsxs)(`div`,{ref:o,role:`region`,"aria-label":`待确认候选与差异`,tabIndex:-1,children:[(0,x.jsx)(Mt,{id:se.id,title:`待确认候选`,catalog:d.data,openMemory:e,onAction:fe,currentID:oe?.id,locked:ue},`pending-${se.id}-${L}`),oe&&(0,x.jsx)(`div`,{className:`panel`,children:(0,x.jsx)(Pt,{before:oe.id,after:se.id},`${oe.id}-${se.id}-${L}`)})]})]}),s===`history`&&(0,x.jsx)(ri,{initialComparison:(()=>{let e=Number(n.get(`before`)),t=Number(n.get(`after`));return Number.isSafeInteger(e)&&e>0&&Number.isSafeInteger(t)&&t>0?{before:e,after:t}:void 0})(),initialVersion:Number.isSafeInteger(r)&&r>0?r:void 0,currentID:oe?.id,catalog:d.data,openMemory:e,onAction:fe,locked:ue}),s===`memories`&&(0,x.jsx)(ii,{openMemory:e}),s===`attempts`&&(0,x.jsx)(ai,{})]}),p&&(0,x.jsx)(N,{title:si[p.kind],closeDisabled:k,onClose:()=>h(null),children:(0,x.jsxs)(`form`,{noValidate:!0,className:`persona-action-form`,onSubmit:e=>{e.preventDefault(),B()},children:[p.kind===`edit`?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{children:[`发布会替换当前 v`,p.expectedVersion,` `,`并新建版本;新增或改动的句子会标为手写。待确认候选会被替代。`]}),(0,x.jsx)(`p`,{children:`之后的自动候选若删去手写内容,按“大变化”处理:默认方式需人工确认;“全部自动”模式下,检查通过仍会直接发布。`}),(0,x.jsxs)(`label`,{children:[`persona 正文`,(0,x.jsx)(`textarea`,{rows:9,disabled:k,value:b,onChange:e=>S(e.target.value)})]}),(0,x.jsxs)(`small`,{children:[[...b].length,` / 800 字`]})]}):p.kind===`confirm`?(0,x.jsxs)(`p`,{children:[`发布候选 v`,p.version.id,` 会替换当前 v`,p.expectedVersion,`。旧版本保留在历史中,可在之后回滚;服务会再次核对版本和依据。`]}):p.kind===`reject`?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{children:[`拒绝候选 v`,p.version.id,`,保留当前 v`,p.expectedVersion,`。拒绝记录与原因会保存;采用新候选需要再次生成。`]}),(0,x.jsxs)(`label`,{children:[`拒绝原因(可选)`,(0,x.jsx)(`textarea`,{rows:3,maxLength:1e3,disabled:k,value:C,onChange:e=>w(e.target.value)})]})]}):(0,x.jsxs)(`p`,{children:[`使用 v`,p.version.id,` 的正文与依据新建一个版本,替换当前 v`,p.expectedVersion,`;历史版本保持不变。待确认候选会被替代,旧依据失效时新版本仍会标为待更新。`]}),T&&(0,x.jsxs)(A,{error:!0,children:[T,F&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`p`,{children:`重新加载会放弃本次未保存草稿。可先复制草稿,再核对最新版本。`}),(0,x.jsx)(`button`,{type:`button`,onClick:R,children:`重新加载当前版本`})]})]}),(0,x.jsxs)(`div`,{className:`persona-actions`,children:[(0,x.jsx)(`button`,{type:`button`,disabled:k,onClick:()=>h(null),children:`取消`}),(0,x.jsx)(`button`,{className:`primary`,disabled:ue,children:k?`正在提交…`:ci[p.kind]})]})]})})]})}var di=[{id:`trial`,name:`试用对话`,icon:`chat`},{id:`memories`,name:`记忆`,icon:`memory`},{id:`people`,name:`人物`,icon:`people`},{id:`learning`,name:`入口与学习`,icon:`learning`},{id:`persona`,name:`persona 与自我`,icon:`people`},{id:`state`,name:`状态与目标`,icon:`state`},{id:`status`,name:`运行状态`,icon:`status`},{id:`operations`,name:`操作记录`,icon:`memory`},{id:`connections`,name:`接入与数据`,icon:`learning`},{id:`settings`,name:`设置`,icon:`settings`}];function fi({name:e}){return(0,x.jsx)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`1.7`,strokeLinecap:`round`,strokeLinejoin:`round`,"aria-hidden":!0,children:e===`chat`?(0,x.jsx)(`path`,{d:`M20 11.5a8 8 0 0 1-8 8H5l-3 2 1.5-5A8 8 0 1 1 20 11.5ZM7 10h8M7 14h5`}):e===`people`?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`circle`,{cx:`9`,cy:`7`,r:`3`}),(0,x.jsx)(`path`,{d:`M3 21v-3a6 6 0 0 1 12 0v3M16 4a3 3 0 0 1 0 6M18 14a5 5 0 0 1 3 4v3`})]}):e===`learning`?(0,x.jsx)(x.Fragment,{children:(0,x.jsx)(`path`,{d:`M4 4h16v5H4zM4 14h7v6H4zM16 14h4v6h-4M8 9v5M18 9v5`})}):e===`state`?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`circle`,{cx:`12`,cy:`12`,r:`9`}),(0,x.jsx)(`path`,{d:`M12 7v5l3 2`})]}):e===`memory`?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`rect`,{x:`5`,y:`3`,width:`14`,height:`18`,rx:`3`}),(0,x.jsx)(`path`,{d:`M9 8h6M9 12h6M9 16h3`})]}):(0,x.jsx)(x.Fragment,{children:(0,x.jsx)(`path`,{d:`M3 13h4l3-7 4 13 3-7h4`})})})}function pi(){return(0,x.jsx)(Ee,{children:e=>(0,x.jsx)(mi,{refreshSession:e})})}function mi({refreshSession:e}){let[t,n]=(0,l.useState)(location.hash.slice(2)||`trial`),[r,i]=(0,l.useState)(null),[a,o]=(0,l.useState)(0),s=y(`/status`,2e3),c=y(`/people?pending_only=true&limit=1&offset=0`,5e3),u=t.split(`?`)[0],d=()=>{o(e=>e+1),s.refresh()};(0,l.useEffect)(()=>{let e=()=>{n(location.hash.slice(2)||`trial`),i(null)};return addEventListener(`hashchange`,e),()=>removeEventListener(`hashchange`,e)},[]);let f=(0,l.useCallback)(e=>i(e),[]),p=(0,l.useCallback)(()=>i(null),[]),m=s.data?.model_health.chat;return(0,x.jsxs)(`div`,{className:`app`,children:[(0,x.jsx)(`a`,{className:`skip-link`,href:`#main`,onClick:e=>{e.preventDefault(),document.getElementById(`main`)?.focus()},children:`跳到主内容`}),(0,x.jsxs)(`header`,{className:`app-header`,children:[(0,x.jsxs)(`a`,{href:`#/trial`,className:`brand`,"aria-label":`Iris 首页`,children:[(0,x.jsx)(`span`,{className:`brand-symbol`,"aria-hidden":!0,children:`✳`}),(0,x.jsxs)(`span`,{children:[`Iris`,(0,x.jsx)(`small`,{children:`相处与记忆`})]})]}),(0,x.jsx)(`nav`,{"aria-label":`主导航`,children:di.map(e=>(0,x.jsxs)(`a`,{href:`#/${e.id}`,"aria-current":u===e.id||u===`people-graph`&&e.id===`people`?`page`:void 0,children:[(0,x.jsx)(fi,{name:e.icon}),e.name,e.id===`people`&&!!c.data?.total&&(0,x.jsx)(`span`,{className:`nav-dot`,"aria-label":`有待确认的人物联系`})]},e.id))}),(0,x.jsx)(`button`,{className:`text-button logout-button`,onClick:async()=>{await g(`/logout`,_(`POST`,{})),e()},children:`退出登录`}),(0,x.jsxs)(`span`,{className:`local-badge`,children:[(0,x.jsx)(`span`,{"aria-hidden":!0,children:`◉`}),` 仅本机`]})]}),(0,x.jsx)(`main`,{id:`main`,tabIndex:-1,children:(0,x.jsxs)(`div`,{className:`content-wrap`,children:[!!c.data?.total&&u===`trial`&&(0,x.jsxs)(A,{children:[c.data.total,` 位人物有待确认的“可能是同一人”联系。`,(0,x.jsx)(`a`,{href:`#/people?pending_only=true`,children:`查看待确认联系`})]}),c.error&&u===`trial`&&(0,x.jsxs)(A,{error:!0,children:[`人物联系提示暂时无法更新。`,(0,x.jsx)(`button`,{onClick:c.refresh,children:`重试人物提示`})]}),s.error&&(0,x.jsxs)(A,{error:!0,children:[s.error,`。以下数据可能尚未更新。`,(0,x.jsx)(`button`,{className:`text-button`,onClick:s.refresh,children:`重新连接`})]}),m&&m.state!==`normal`&&(0,x.jsxs)(A,{error:!0,children:[`对话模型:`,D(m.state),`。`,m.last_error?.includes(`未配置`)?`未配置模型,暂不学习。`:`学习已暂停。`,`消息仍可接收。`,(0,x.jsx)(`a`,{href:`#/status`,children:`查看运行状态`})]}),u===`settings`?(0,x.jsx)(Ce,{}):u===`memories`?(0,x.jsx)(Kt,{initialQuery:t.split(`?`)[1],version:a,openMemory:f,onChange:d},t):u===`people-graph`?(0,x.jsx)(ni,{initialQuery:t.split(`?`)[1],openMemory:f},t):u===`people`?(0,x.jsx)(Br,{openMemory:f,initialQuery:t.split(`?`)[1],onChange:()=>{c.refresh(),d()}},t):u===`operations`?(0,x.jsx)(ge,{initialQuery:t.split(`?`)[1]},t):u===`learning`?(0,x.jsx)(Er,{openMemory:f}):u===`state`?(0,x.jsx)(xn,{initialQuery:t.split(`?`)[1],openMemory:f},t):u===`persona`?(0,x.jsx)(ui,{initialQuery:t.split(`?`)[1],openMemory:f},t):u===`connections`?(0,x.jsx)(Ne,{}):u===`status`?(0,x.jsx)(In,{initialQuery:t.split(`?`)[1]||``,data:s.data,openMemory:f},t):(0,x.jsx)(Cn,{status:s.data,openMemory:f,refreshStatus:s.refresh})]})}),(0,x.jsx)(`footer`,{className:`app-footer`,children:`Iris · 记忆有来源,相处有连续`}),r!==null&&(0,x.jsx)(Jt,{id:r,onClose:p,openMemory:f,onChange:d},r)]})}(0,c.createRoot)(document.getElementById(`root`)).render((0,x.jsx)(l.StrictMode,{children:(0,x.jsx)(pi,{})})); \ No newline at end of file diff --git a/src/iris/web/assets/index-CxPLpCWk.js b/src/iris/web/assets/index-CxPLpCWk.js new file mode 100644 index 00000000..9f26ccb9 --- /dev/null +++ b/src/iris/web/assets/index-CxPLpCWk.js @@ -0,0 +1,11 @@ +var e=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports);(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var t=e((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`react.fragment`),i=Symbol.for(`react.strict_mode`),a=Symbol.for(`react.profiler`),o=Symbol.for(`react.consumer`),s=Symbol.for(`react.context`),c=Symbol.for(`react.forward_ref`),l=Symbol.for(`react.suspense`),u=Symbol.for(`react.memo`),d=Symbol.for(`react.lazy`),f=Symbol.for(`react.activity`),p=Symbol.for(`react.view_transition`),m=Symbol.iterator;function h(e){return typeof e!=`object`||!e?null:(e=m&&e[m]||e[`@@iterator`],typeof e==`function`?e:null)}var g={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},_=Object.assign,v={};function y(e,t,n){this.props=e,this.context=t,this.refs=v,this.updater=n||g}y.prototype.isReactComponent={},y.prototype.setState=function(e,t){if(typeof e!=`object`&&typeof e!=`function`&&e!=null)throw Error(`takes an object of state variables to update or a function which returns an object of state variables.`);this.updater.enqueueSetState(this,e,t,`setState`)},y.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,`forceUpdate`)};function b(){}b.prototype=y.prototype;function x(e,t,n){this.props=e,this.context=t,this.refs=v,this.updater=n||g}var S=x.prototype=new b;S.constructor=x,_(S,y.prototype),S.isPureReactComponent=!0;var C=Array.isArray;function w(){}var T={H:null,A:null,T:null,S:null},E=Object.prototype.hasOwnProperty;function D(e,n,r){var i=r.ref;return{$$typeof:t,type:e,key:n,ref:i===void 0?null:i,props:r}}function O(e,t){return D(e.type,t,e.props)}function k(e){return typeof e==`object`&&!!e&&e.$$typeof===t}function A(e){var t={"=":`=0`,":":`=2`};return`$`+e.replace(/[=:]/g,function(e){return t[e]})}var j=/\/+/g;function M(e,t){return typeof e==`object`&&e&&e.key!=null?A(``+e.key):t.toString(36)}function ee(e){switch(e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason;default:switch(typeof e.status==`string`?e.then(w,w):(e.status=`pending`,e.then(function(t){e.status===`pending`&&(e.status=`fulfilled`,e.value=t)},function(t){e.status===`pending`&&(e.status=`rejected`,e.reason=t)})),e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason}}throw e}function N(e,r,i,a,o){var s=typeof e;(s===`undefined`||s===`boolean`)&&(e=null);var c=!1;if(e===null)c=!0;else switch(s){case`bigint`:case`string`:case`number`:c=!0;break;case`object`:switch(e.$$typeof){case t:case n:c=!0;break;case d:return c=e._init,N(c(e._payload),r,i,a,o)}}if(c)return o=o(e),c=a===``?`.`+M(e,0):a,C(o)?(i=``,c!=null&&(i=c.replace(j,`$&/`)+`/`),N(o,r,i,``,function(e){return e})):o!=null&&(k(o)&&(o=O(o,i+(o.key==null||e&&e.key===o.key?``:(``+o.key).replace(j,`$&/`)+`/`)+c)),r.push(o)),1;c=0;var l=a===``?`.`:a+`:`;if(C(e))for(var u=0;u{n.exports=t()})),r=e((e=>{function t(e,t){var n=e.length;e.push(t);a:for(;0>>1,a=e[r];if(0>>1;ri(c,n))li(u,c)?(e[r]=u,e[l]=n,r=l):(e[r]=c,e[s]=n,r=s);else if(li(u,n))e[r]=u,e[l]=n,r=l;else break a}}return t}function i(e,t){var n=e.sortIndex-t.sortIndex;return n===0?e.id-t.id:n}if(e.unstable_now=void 0,typeof performance==`object`&&typeof performance.now==`function`){var a=performance;e.unstable_now=function(){return a.now()}}else{var o=Date,s=o.now();e.unstable_now=function(){return o.now()-s}}var c=[],l=[],u=1,d=null,f=3,p=!1,m=!1,h=!1,g=!1,_=typeof setTimeout==`function`?setTimeout:null,v=typeof clearTimeout==`function`?clearTimeout:null,y=typeof setImmediate<`u`?setImmediate:null;function b(e){for(var i=n(l);i!==null;){if(i.callback===null)r(l);else if(i.startTime<=e)r(l),i.sortIndex=i.expirationTime,t(c,i);else break;i=n(l)}}function x(e){if(h=!1,b(e),!m){if(n(c)!==null)m=!0,S||(S=!0,O());else{var t=n(l);t!==null&&j(x,t.startTime-e)}}}var S=!1,C=-1,w=5,T=-1;function E(){return g?!0:!(e.unstable_now()-Tt&&E());){var o=d.callback;if(typeof o==`function`){d.callback=null,f=d.priorityLevel;var s=o(d.expirationTime<=t);if(t=e.unstable_now(),typeof s==`function`){d.callback=s,b(t),i=!0;break b}d===n(c)&&r(c),b(t)}else r(c);d=n(c)}if(d!==null)i=!0;else{var u=n(l);u!==null&&j(x,u.startTime-t),i=!1}}break a}finally{d=null,f=a,p=!1}i=void 0}}finally{i?O():S=!1}}}var O;if(typeof y==`function`)O=function(){y(D)};else if(typeof MessageChannel<`u`){var k=new MessageChannel,A=k.port2;k.port1.onmessage=D,O=function(){A.postMessage(null)}}else O=function(){_(D,0)};function j(t,n){C=_(function(){t(e.unstable_now())},n)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(e){e.callback=null},e.unstable_forceFrameRate=function(e){0>e||125o?(r.sortIndex=a,t(l,r),n(c)===null&&r===n(l)&&(h?(v(C),C=-1):h=!0,j(x,a-o))):(r.sortIndex=s,t(c,r),m||p||(m=!0,S||(S=!0,O()))),r},e.unstable_shouldYield=E,e.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}})),i=e(((e,t)=>{t.exports=r()})),a=e((e=>{var t=n();function r(e){var t=`https://react.dev/errors/`+e;if(1{function n(){if(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<`u`&&typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE==`function`)try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=a()})),s=e((e=>{var t=i(),r=n(),a=o();function s(e){var t=`https://react.dev/errors/`+e;if(1pe||(e.current=fe[pe],fe[pe]=null,pe--)}function H(e,t){pe++,fe[pe]=e.current,e.current=t}var U=me(null),ge=me(null),_e=me(null),ve=me(null);function ye(e,t){switch(H(_e,t),H(ge,e),H(U,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?up(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=up(t),e=dp(t,e);else switch(e){case`svg`:e=1;break;case`math`:e=2;break;default:e=0}}he(U),H(U,e)}function be(){he(U),he(ge),he(_e)}function xe(e){var t=e.memoizedState;t!==null&&(sh._currentValue=t.memoizedState,H(ve,e)),t=U.current;var n=dp(t,e.type);t!==n&&(H(ge,e),H(U,n))}function Se(e){ge.current===e&&(he(U),he(ge)),ve.current===e&&(he(ve),sh._currentValue=V)}var Ce,we;function Te(e){if(Ce===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);Ce=t&&t[1]||``,we=-1)`:-1i||c[r]!==l[i]){var u=` +`+c[r].replace(` at new `,` at `);return e.displayName&&u.includes(``)&&(u=u.replace(``,e.displayName)),u}while(1<=r&&0<=i);break}}}finally{Ee=!1,Error.prepareStackTrace=n}return(n=e?e.displayName||e.name:``)?Te(n):``}function Oe(e,t){switch(e.tag){case 26:case 27:case 5:return Te(e.type);case 16:return Te(`Lazy`);case 13:return e.child!==t&&t!==null?Te(`Suspense Fallback`):Te(`Suspense`);case 19:return Te(`SuspenseList`);case 0:case 15:return De(e.type,!1);case 11:return De(e.type.render,!1);case 1:return De(e.type,!0);case 31:return Te(`Activity`);case 30:return Te(`ViewTransition`);default:return``}}function ke(e){try{var t=``,n=null;do t+=Oe(e,n),n=e,e=e.return;while(e);return t}catch(e){return` +Error generating stack: `+e.message+` +`+e.stack}}var Ae=Object.prototype.hasOwnProperty,je=t.unstable_scheduleCallback,Me=t.unstable_cancelCallback,Ne=t.unstable_shouldYield,Pe=t.unstable_requestPaint,Fe=t.unstable_now,Ie=t.unstable_getCurrentPriorityLevel,Le=t.unstable_ImmediatePriority,Re=t.unstable_UserBlockingPriority,ze=t.unstable_NormalPriority,Be=t.unstable_LowPriority,Ve=t.unstable_IdlePriority,He=t.log,Ue=t.unstable_setDisableYieldValue,We=null,Ge=null;function Ke(e){if(typeof He==`function`&&Ue(e),Ge&&typeof Ge.setStrictMode==`function`)try{Ge.setStrictMode(We,e)}catch{}}var qe=Math.clz32?Math.clz32:Xe,Je=Math.log,Ye=Math.LN2;function Xe(e){return e>>>=0,e===0?32:31-(Je(e)/Ye|0)|0}var Ze=256,Qe=262144,$e=4194304;function et(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&-e;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function tt(e,t,n){var r=e.pendingLanes;if(r===0)return 0;var i=0,a=e.suspendedLanes,o=e.pingedLanes;e=e.warmLanes;var s=r&134217727;return s===0?(s=r&~a,s===0?o===0?n||(n=r&~e,n!==0&&(i=et(n))):i=et(o):i=et(s)):(r=s&~a,r===0?(o&=s,o===0?n||(n=s&~e,n!==0&&(i=et(n))):i=et(o)):i=et(r)),i===0?0:t!==0&&t!==i&&(t&a)===0&&(a=i&-i,n=t&-t,a>=n||a===32&&n&4194048)?t:i}function nt(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function rt(e,t){t&8&&(t|=t&32);var n=e.entangledLanes;if(n!==0)for(e=e.entanglements,n&=t;0n;n++)t.push(e);return t}function st(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function ct(e,t,n,r,i,a){var o=e.pendingLanes;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=n,e.entangledLanes&=n,e.errorRecoveryDisabledLanes&=n,e.shellSuspendCounter=0;var s=e.entanglements,c=e.expirationTimes,l=e.hiddenUpdates;for(n=o&~n;0=sr),ur=` `,dr=!1;function fr(e,t){switch(e){case`keyup`:return ar.indexOf(t.keyCode)!==-1;case`keydown`:return t.keyCode!==229;case`keypress`:case`mousedown`:case`focusout`:return!0;default:return!1}}function pr(e){return e=e.detail,typeof e==`object`&&`data`in e?e.data:null}var mr=!1;function hr(e,t){switch(e){case`compositionend`:return pr(t);case`keypress`:return t.which===32?(dr=!0,ur):null;case`textInput`:return e=t.data,e===ur&&dr?null:e;default:return null}}function gr(e,t){if(mr)return e===`compositionend`||!or&&fr(e,t)?(e=On(),Dn=En=Tn=null,mr=!1,e):null;switch(e){case`paste`:return null;case`keypress`:if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}a:{for(;n;){if(n.nextSibling){n=n.nextSibling;break a}n=n.parentNode}n=void 0}n=zr(n)}}function Vr(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?Vr(e,t.parentNode):`contains`in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Hr(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=Rr(e.document);t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href==`string`}catch{n=!1}if(n)e=t.contentWindow;else break;t=Rr(e.document)}return t}function Ur(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t===`input`&&(e.type===`text`||e.type===`search`||e.type===`tel`||e.type===`url`||e.type===`password`)||t===`textarea`||e.contentEditable===`true`)}var Wr=Sn&&`documentMode`in document&&11>=document.documentMode,Gr=null,Kr=null,qr=null,Jr=!1;function Yr(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;Jr||Gr==null||Gr!==Rr(r)||(r=Gr,`selectionStart`in r&&Ur(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),qr&&Lr(qr,r)||(qr=r,r=qf(Kr,`onSelect`),0>=o,i-=o,Gi=1<<32-qe(t)+i|n<h?(g=d,d=null):g=d.sibling;var _=p(i,d,s[h],c);if(_===null){d===null&&(d=g);break}e&&d&&_.alternate===null&&t(i,d),o=a(_,o,h),u===null?l=_:u.sibling=_,u=_,d=g}if(h===s.length)return n(i,d),G&&qi(i,h),l;if(d===null){for(;hg?(_=h,h=null):_=h.sibling;var y=p(i,h,v.value,l);if(y===null){h===null&&(h=_);break}e&&h&&y.alternate===null&&t(i,h),o=a(y,o,g),d===null?u=y:d.sibling=y,d=y,h=_}if(v.done)return n(i,h),G&&qi(i,g),u;if(h===null){for(;!v.done;g++,v=c.next())v=f(i,v.value,l),v!==null&&(o=a(v,o,g),d===null?u=v:d.sibling=v,d=v);return G&&qi(i,g),u}for(h=r(h);!v.done;g++,v=c.next())v=m(h,i,g,v.value,l),v!==null&&(e&&(_=v.alternate,_!==null&&h.delete(_.key===null?g:_.key)),o=a(v,o,g),d===null?u=v:d.sibling=v,d=v);return e&&h.forEach(function(e){return t(i,e)}),G&&qi(i,g),u}function _(e,r,a,c){if(typeof a==`object`&&a&&a.type===j&&a.key===null&&a.props.ref===void 0&&(a=a.props.children),typeof a==`object`&&a){switch(a.$$typeof){case k:a:{for(var l=a.key;r!==null;){if(r.key===l){if(l=a.type,l===j){if(r.tag===7){n(e,r.sibling),c=i(r,a.props.children),ro(c,a),c.return=e,e=c;break a}}else if(r.elementType===l||typeof l==`object`&&l&&l.$$typeof===ne&&Xa(l)===r.type){n(e,r.sibling),c=i(r,a.props),ro(c,a),c.return=e,e=c;break a}n(e,r);break}t(e,r),r=r.sibling}a.type===j?(c=Mi(a.props.children,e.mode,c,a.key),ro(c,a),c.return=e,e=c):(c=ji(a.type,a.key,a.props,null,e.mode,c),ro(c,a),c.return=e,e=c)}return o(e);case A:a:{for(l=a.key;r!==null;){if(r.key===l){if(r.tag===4&&r.stateNode.containerInfo===a.containerInfo&&r.stateNode.implementation===a.implementation){n(e,r.sibling),c=i(r,a.children||[]),c.return=e,e=c;break a}n(e,r);break}t(e,r),r=r.sibling}c=Fi(a,e.mode,c),c.return=e,e=c}return o(e);case ne:return a=Xa(a),_(e,r,a,c)}if(de(a))return h(e,r,a,c);if(ce(a)){if(l=ce(a),typeof l!=`function`)throw Error(s(150));return a=l.call(a),g(e,r,a,c)}if(typeof a.then==`function`)return _(e,r,no(a),c);if(a.$$typeof===P)return _(e,r,xa(e,a),c);io(e,a)}return typeof a==`string`&&a!==``||typeof a==`number`||typeof a==`bigint`?(a=``+a,r!==null&&r.tag===6?(n(e,r.sibling),c=i(r,a),c.return=e,e=c):(n(e,r),c=Ni(a,e.mode,c),c.return=e,e=c),o(e)):n(e,r)}return function(e,t,n,r){try{to=0;var i=_(e,t,n,r);return eo=null,i}catch(t){if(t===Wa||t===Ka)throw t;var a=Di(29,t,null,e.mode);return a.lanes=r,a.return=e,a}}}var oo=ao(!0),so=ao(!1),co=!1;function lo(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function uo(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function fo(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function po(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,J&2){var i=r.pending;return i===null?t.next=t:(t.next=i.next,i.next=t),r.pending=t,t=wi(e),Ci(e,null,n),t}return bi(e,r,t,n),wi(e)}function mo(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,n&4194048)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,ut(e,n)}}function ho(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var i=null,a=null;if(n=n.firstBaseUpdate,n!==null){do{var o={lane:n.lane,tag:n.tag,payload:n.payload,callback:null,next:null};a===null?i=a=o:a=a.next=o,n=n.next}while(n!==null);a===null?i=a=t:a=a.next=t}else i=a=t;n={baseState:r.baseState,firstBaseUpdate:i,lastBaseUpdate:a,shared:r.shared,callbacks:r.callbacks},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}var go=!1;function _o(){if(go){var e=Fa;if(e!==null)throw e}}function vo(e,t,n,r){go=!1;var i=e.updateQueue;co=!1;var a=i.firstBaseUpdate,o=i.lastBaseUpdate,s=i.shared.pending;if(s!==null){i.shared.pending=null;var c=s,l=c.next;c.next=null,o===null?a=l:o.next=l,o=c;var u=e.alternate;u!==null&&(u=u.updateQueue,s=u.lastBaseUpdate,s!==o&&(s===null?u.firstBaseUpdate=l:s.next=l,u.lastBaseUpdate=c))}if(a!==null){var d=i.baseState;o=0,u=l=c=null,s=a;do{var f=s.lane&-536870913,p=f!==s.lane;if(p?(X&f)===f:(r&f)===f){f!==0&&f===Pa&&(go=!0),u!==null&&(u=u.next={lane:0,tag:s.tag,payload:s.payload,callback:null,next:null});a:{var m=e,h=s;f=t;var g=n;switch(h.tag){case 1:if(m=h.payload,typeof m==`function`){d=m.call(g,d,f);break a}d=m;break a;case 3:m.flags=m.flags&-65537|128;case 0:if(m=h.payload,f=typeof m==`function`?m.call(g,d,f):m,f==null)break a;d=D({},d,f);break a;case 2:co=!0}}f=s.callback,f!==null&&(e.flags|=64,p&&(e.flags|=8192),p=i.callbacks,p===null?i.callbacks=[f]:p.push(f))}else p={lane:f,tag:s.tag,payload:s.payload,callback:s.callback,next:null},u===null?(l=u=p,c=d):u=u.next=p,o|=f;if(s=s.next,s===null){if(s=i.shared.pending,s===null)break;p=s,s=p.next,p.next=null,i.lastBaseUpdate=p,i.shared.pending=null}}while(1);u===null&&(c=d),i.baseState=c,i.firstBaseUpdate=l,i.lastBaseUpdate=u,a===null&&(i.shared.lanes=0),ad|=o,e.lanes=o,e.memoizedState=d}}function yo(e,t){if(typeof e!=`function`)throw Error(s(191,e));e.call(t)}function bo(e,t){var n=e.callbacks;if(n!==null)for(e.callbacks=null,e=0;ea?a:8;var o=z.T,s={};s.types=o===null?null:o.types,z.T=s,sc(e,!1,t,n);try{var c=i(),l=z.S;l!==null&&l(s,c),typeof c==`object`&&c&&typeof c.then==`function`?oc(e,t,Ra(c,r),Ad(e)):oc(e,t,r,Ad(e))}catch(n){oc(e,t,{then:function(){},status:`rejected`,reason:n},Ad())}finally{B.p=a,o!==null&&s.types!==null&&(o.types=s.types),z.T=o}}function Xs(){}function Zs(e,t,n,r){if(e.tag!==5)throw Error(s(476));var i=Qs(e).queue;Ys(e,i,t,V,n===null?Xs:function(){return $s(e),n(r)})}function Qs(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:V,baseState:V,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:cs,lastRenderedState:V},next:null};var n={};return t.next={memoizedState:n,baseState:n,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:cs,lastRenderedState:n},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function $s(e){var t=Qs(e);t.next===null&&(t=e.alternate.memoizedState),oc(e,t.next.queue,{},Ad())}function ec(){return ba(sh)}function tc(){return rs().memoizedState}function nc(){return rs().memoizedState}function rc(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var n=Ad();e=fo(n);var r=po(t,e,n);r!==null&&(Nd(r,t,n),mo(r,t,n)),t={cache:Da()},e.payload=t;return}t=t.return}}function ic(e,t,n){var r=Ad();n={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null},cc(e)?lc(t,n):(n=xi(e,t,n,r),n!==null&&(Nd(n,e,r),uc(n,t,r)))}function ac(e,t,n){oc(e,t,n,Ad())}function oc(e,t,n,r){var i={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null};if(cc(e))lc(t,i);else{var a=e.alternate;if(e.lanes===0&&(a===null||a.lanes===0)&&(a=t.lastRenderedReducer,a!==null))try{var o=t.lastRenderedState,s=a(o,n);if(i.hasEagerState=!0,i.eagerState=s,Ir(s,o))return bi(e,t,i,0),Qu===null&&yi(),!1}catch{}if(n=xi(e,t,i,r),n!==null)return Nd(n,e,r),uc(n,t,r),!0}return!1}function sc(e,t,n,r){if(r={lane:2,revertLane:Nf(),gesture:null,action:r,hasEagerState:!1,eagerState:null,next:null},cc(e)){if(t)throw Error(s(479))}else t=xi(e,n,r,2),t!==null&&Nd(t,e,2)}function cc(e){var t=e.alternate;return e===K||t!==null&&t===K}function lc(e,t){Vo=Bo=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function uc(e,t,n){if(n&4194048){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,ut(e,n)}}var dc={readContext:ba,use:os,useCallback:qo,useContext:qo,useEffect:qo,useImperativeHandle:qo,useLayoutEffect:qo,useInsertionEffect:qo,useMemo:qo,useReducer:qo,useRef:qo,useState:qo,useDebugValue:qo,useDeferredValue:qo,useTransition:qo,useSyncExternalStore:qo,useId:qo,useHostTransitionStatus:qo,useFormState:qo,useActionState:qo,useOptimistic:qo,useMemoCache:qo,useCacheRefresh:qo,useEffectEvent:qo},fc={readContext:ba,use:os,useCallback:function(e,t){return ns().memoizedState=[e,t===void 0?null:t],e},useContext:ba,useEffect:Is,useImperativeHandle:function(e,t,n){n=n==null?null:n.concat([e]),Ps(4194308,4,Hs.bind(null,t,e),n)},useLayoutEffect:function(e,t){return Ps(4194308,4,e,t)},useInsertionEffect:function(e,t){Ps(4,2,e,t)},useMemo:function(e,t){var n=ns();t=t===void 0?null:t;var r=e();if(Ho){Ke(!0);try{e()}finally{Ke(!1)}}return n.memoizedState=[r,t],r},useReducer:function(e,t,n){var r=ns();if(n!==void 0){var i=n(t);if(Ho){Ke(!0);try{n(t)}finally{Ke(!1)}}}else i=t;return r.memoizedState=r.baseState=i,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:i},r.queue=e,e=e.dispatch=ic.bind(null,K,e),[r.memoizedState,e]},useRef:function(e){var t=ns();return e={current:e},t.memoizedState=e},useState:function(e){e=vs(e);var t=e.queue,n=ac.bind(null,K,t);return t.dispatch=n,[e.memoizedState,n]},useDebugValue:Ws,useDeferredValue:function(e,t){return qs(ns(),e,t)},useTransition:function(){var e=vs(!1);return e=Ys.bind(null,K,e.queue,!0,!1),ns().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,n){var r=K,i=ns();if(G){if(n===void 0)throw Error(s(407));n=n()}else{if(n=t(),Qu===null)throw Error(s(349));X&127||ps(r,t,n)}i.memoizedState=n;var a={value:n,getSnapshot:t};return i.queue=a,Is(hs.bind(null,r,a,e),[e]),r.flags|=2048,Ms(9,{destroy:void 0},ms.bind(null,r,a,n,t),null),n},useId:function(){var e=ns(),t=Qu.identifierPrefix;if(G){var n=Ki,r=Gi;n=(r&~(1<<32-qe(r)-1)).toString(32)+n,t=`_`+t+`R_`+n,n=Uo++,0<\/script>`,a=a.removeChild(a.firstChild);break;case`select`:a=typeof r.is==`string`?o.createElement(`select`,{is:r.is}):o.createElement(`select`),r.multiple?a.multiple=!0:r.size&&(a.size=r.size);break;default:a=typeof r.is==`string`?o.createElement(i,{is:r.is}):o.createElement(i)}}a[_t]=t,a[vt]=r;a:for(o=t.child;o!==null;){if(o.tag===5||o.tag===6)a.appendChild(o.stateNode);else if(o.tag!==4&&o.tag!==27&&o.child!==null){o.child.return=o,o=o.child;continue}if(o===t)break a;for(;o.sibling===null;){if(o.return===null||o.return===t)break a;o=o.return}o.sibling.return=o.return,o=o.sibling}t.stateNode=a;a:switch(np(a,i,r),i){case`button`:case`input`:case`select`:case`textarea`:r=!!r.autoFocus;break a;case`img`:r=!0;break a;default:r=!1}r&&ul(t)}}return hl(t),t.subtreeFlags&=-33554433,dl(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,n),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==r&&ul(t);else{if(typeof r!=`string`&&t.stateNode===null)throw Error(s(166));if(e=_e.current,oa(t)){if(e=t.stateNode,n=t.memoizedProps,r=null,i=Qi,i!==null)switch(i.tag){case 27:case 5:r=i.memoizedProps}e[_t]=t,e=!!(e.nodeValue===n||r!==null&&!0===r.suppressHydrationWarning||$f(e.nodeValue,n)),e||ra(t,!0)}else e=lp(e).createTextNode(r),e[_t]=t,t.stateNode=e}return hl(t),null;case 31:if(n=t.memoizedState,e===null||e.memoizedState!==null){if(r=oa(t),n!==null){if(e===null){if(!r)throw Error(s(318));if(e=t.memoizedState,e=e===null?null:e.dehydrated,!e)throw Error(s(557));e[_t]=t}else sa(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;hl(t),e=!1}else n=ca(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),e=!0;if(!e)return t.flags&256?(Mo(t),t):(Mo(t),null);if(t.flags&128)throw Error(s(558))}return hl(t),null;case 13:if(r=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(i=oa(t),r!==null&&r.dehydrated!==null){if(e===null){if(!i)throw Error(s(318));if(i=t.memoizedState,i=i===null?null:i.dehydrated,!i)throw Error(s(317));i[_t]=t}else sa(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;hl(t),i=!1}else i=ca(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=i),i=!0;if(!i)return t.flags&256?(Mo(t),t):(Mo(t),null)}return Mo(t),t.flags&128?(t.lanes=n,t):(n=r!==null,e=e!==null&&e.memoizedState!==null,n&&(r=t.child,i=null,r.alternate!==null&&r.alternate.memoizedState!==null&&r.alternate.memoizedState.cachePool!==null&&(i=r.alternate.memoizedState.cachePool.pool),a=null,r.memoizedState!==null&&r.memoizedState.cachePool!==null&&(a=r.memoizedState.cachePool.pool),a!==i&&(r.flags|=2048)),n!==e&&n&&(t.child.flags|=8192),pl(t,t.updateQueue),hl(t),null);case 4:return be(),e===null&&Uf(t.stateNode.containerInfo),t.flags|=67108864,hl(t),null;case 10:return ma(t.type),hl(t),null;case 19:if(Fo(t),r=t.memoizedState,r===null)return hl(t),null;if(i=!!(t.flags&128),a=r.rendering,a===null){if(i)ml(r,!1);else{if(id!==0||e!==null&&e.flags&128)for(e=t.child;e!==null;){if(a=Io(e),a!==null){for(t.flags|=128,ml(r,!1),e=a.updateQueue,t.updateQueue=e,pl(t,e),t.subtreeFlags=0,e=n,n=t.child;n!==null;)Ai(n,e),n=n.sibling;return Po(t,No.current&1|2),G&&qi(t,r.treeForkCount),t.child}e=e.sibling}r.tail!==null&&Fe()>hd&&(t.flags|=128,i=!0,ml(r,!1),t.lanes=4194304)}}else{if(!i){if(e=Io(a),e!==null){if(t.flags|=128,i=!0,e=e.updateQueue,t.updateQueue=e,pl(t,e),ml(r,!0),r.tail===null&&r.tailMode!==`collapsed`&&r.tailMode!==`visible`&&!a.alternate&&!G)return hl(t),null}else 2*Fe()-r.renderingStartTime>hd&&n!==536870912&&(t.flags|=128,i=!0,ml(r,!1),t.lanes=4194304)}r.isBackwards?(a.sibling=t.child,t.child=a):(e=r.last,e===null?t.child=a:e.sibling=a,r.last=a)}if(r.tail!==null){e=r.tail;a:{for(n=e;n!==null;){if(n.alternate!==null){n=!1;break a}n=n.sibling}n=!0}return r.rendering=e,r.tail=e.sibling,r.renderingStartTime=Fe(),e.sibling=null,a=No.current,a=i?a&1|2:a&1,r.tailMode===`visible`||r.tailMode===`collapsed`||!n||G?Po(t,a):(n=a,H(Eo,t),H(No,n),Do===null&&(Do=t)),G&&qi(t,r.treeForkCount),e}return hl(t),null;case 22:case 23:return Mo(t),To(),r=t.memoizedState!==null,e===null?r&&(t.flags|=8192):e.memoizedState!==null!==r&&(t.flags|=8192),r?n&536870912&&!(t.flags&128)&&(hl(t),t.subtreeFlags&6&&(t.flags|=8192)):hl(t),n=t.updateQueue,n!==null&&pl(t,n.retryQueue),n=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(n=e.memoizedState.cachePool.pool),r=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(r=t.memoizedState.cachePool.pool),r!==n&&(t.flags|=2048),e!==null&&he(Ba),null;case 24:return n=null,e!==null&&(n=e.memoizedState.cache),t.memoizedState.cache!==n&&(t.flags|=2048),ma(Ea),hl(t),null;case 25:return null;case 30:return t.flags|=33554432,hl(t),null}throw Error(s(156,t.tag))}function _l(e,t){switch(Xi(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return ma(Ea),be(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return Se(t),null;case 31:if(t.memoizedState!==null){if(Mo(t),t.alternate===null)throw Error(s(340));sa()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(Mo(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(s(340));sa()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return Fo(t),e=t.flags,e&65536?(t.flags=e&-65537|128,e=t.memoizedState,e!==null&&(e.rendering=null,e.tail=null),t.flags|=4,t):null;case 4:return be(),null;case 10:return ma(t.type),null;case 22:case 23:return Mo(t),To(),e!==null&&he(Ba),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return ma(Ea),null;case 25:return null;default:return null}}function vl(e,t){switch(Xi(t),t.tag){case 3:ma(Ea),be();break;case 26:case 27:case 5:Se(t);break;case 4:be();break;case 31:t.memoizedState!==null&&Mo(t);break;case 13:Mo(t);break;case 19:Fo(t);break;case 10:ma(t.type);break;case 22:case 23:Mo(t),To(),e!==null&&he(Ba);break;case 24:ma(Ea)}}function yl(e,t){try{var n=t.updateQueue,r=n===null?null:n.lastEffect;if(r!==null){var i=r.next;n=i;do{if((n.tag&e)===e){r=void 0;var a=n.create,o=n.inst;r=a(),o.destroy=r}n=n.next}while(n!==i)}}catch(e){Q(t,t.return,e)}}function bl(e,t,n){try{var r=t.updateQueue,i=r===null?null:r.lastEffect;if(i!==null){var a=i.next;r=a;do{if((r.tag&e)===e){var o=r.inst,s=o.destroy;if(s!==void 0){o.destroy=void 0,i=t;var c=n,l=s;try{l()}catch(e){Q(i,c,e)}}}r=r.next}while(r!==a)}}catch(e){Q(t,t.return,e)}}function xl(e){var t=e.updateQueue;if(t!==null){var n=e.stateNode;try{bo(t,n)}catch(t){Q(e,e.return,t)}}}function Sl(e,t,n){n.props=yc(e.type,e.memoizedProps),n.state=e.memoizedState;try{n.componentWillUnmount()}catch(n){Q(e,t,n)}}function Cl(e,t){try{var n=e.ref;if(n!==null){switch(e.tag){case 26:case 27:case 5:var r=e.stateNode;break;case 30:var i=e.stateNode,a=fi(e.memoizedProps,i);(i.ref===null||i.ref.name!==a)&&(i.ref=Pp(a)),r=i.ref;break;case 7:if(e.stateNode===null){var o=new Fp(e);h(e.child,!1,Qp,o,void 0,void 0),e.stateNode=o}r=e.stateNode;break;default:r=e.stateNode}typeof n==`function`?e.refCleanup=n(r):n.current=r}}catch(n){Q(e,t,n)}}function wl(e,t){var n=e.ref,r=e.refCleanup;if(n!==null){if(typeof r==`function`)try{r()}catch(n){Q(e,t,n)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof n==`function`)try{n(null)}catch(n){Q(e,t,n)}else n.current=null}}function Tl(e,t){if((e.tag===5||e.tag===27||e.tag===6)&&e.alternate===null&&t!==null)for(var n=0;n title`))),np(r,t,n),r[_t]=e,jt(r),t=r;break a;case`link`:if(a=Gm(`link`,`href`,i).get(t+(n.href||``))){for(o=0;og&&(o=g,g=h,h=o);var _=Br(s,h),v=Br(s,g);if(_&&v&&(p.rangeCount!==1||p.anchorNode!==_.node||p.anchorOffset!==_.offset||p.focusNode!==v.node||p.focusOffset!==v.offset)){var y=d.createRange();y.setStart(_.node,_.offset),p.removeAllRanges(),h>g?(p.addRange(y),p.extend(v.node,v.offset)):(y.setEnd(v.node,v.offset),p.addRange(y))}}}}for(d=[],p=s;p=p.parentNode;)p.nodeType===1&&d.push({element:p,left:p.scrollLeft,top:p.scrollTop});for(typeof s.focus==`function`&&s.focus(),s=0;sn?32:n,z.T=null,n=Cd,Cd=null;var a=yd,o=xd;if(vd=0,bd=yd=null,xd=0,J&6)throw Error(s(331));var c=J;if(J|=4,qu(a.current),zu(a,a.current,o,n),J=c,Ef(0,!1),Ge&&typeof Ge.onPostCommitFiberRoot==`function`)try{Ge.onPostCommitFiberRoot(We,a)}catch{}return!0}finally{B.p=i,z.T=r,lf(e,t)}}function ff(e,t,n){t=Li(n,t),t=Tc(e.stateNode,t,2),e=po(e,t,2),e!==null&&(st(e,2),Tf(e))}function Q(e,t,n){if(e.tag===3)ff(e,e,n);else for(;t!==null;){if(t.tag===3){ff(t,e,n);break}if(t.tag===1){var r=t.stateNode;if(typeof t.type.getDerivedStateFromError==`function`||typeof r.componentDidCatch==`function`&&(_d===null||!_d.has(r))){e=Li(n,e),n=Ec(2),r=po(t,n,2),r!==null&&(Dc(n,r,t,e),st(r,2),Tf(r));break}}t=t.return}}function pf(e,t,n){var r=e.pingCache;if(r===null){r=e.pingCache=new Zu;var i=new Set;r.set(t,i)}else i=r.get(t),i===void 0&&(i=new Set,r.set(t,i));i.has(n)||(nd=!0,i.add(n),e=mf.bind(null,e,t,n),t.then(e,e))}function mf(e,t,n){var r=e.pingCache;r!==null&&r.delete(t),e.pingedLanes|=e.suspendedLanes&n,e.warmLanes&=~n,Qu===e&&(X&n)===n&&(id===4||id===3&&(X&62914560)===X&&300>Fe()-pd?J&2?sd|=n:Bd(e,0):sd|=n,ld===X&&(ld=0)),Tf(e)}function hf(e,t){t===0&&(t=at()),e=Si(e,t),e!==null&&(st(e,t),Tf(e))}function gf(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),hf(e,n)}function _f(e,t){var n=0;switch(e.tag){case 31:case 13:var r=e.stateNode,i=e.memoizedState;i!==null&&(n=i.retryLane);break;case 19:r=e.stateNode;break;case 22:r=e.stateNode._retryCache;break;default:throw Error(s(314))}r!==null&&r.delete(t),hf(e,n)}function vf(e,t){return je(e,t)}var yf=null,bf=null,xf=!1,Sf=!1,Cf=!1,wf=0;function Tf(e){e!==bf&&e.next===null&&(bf===null?yf=bf=e:bf=bf.next=e),Sf=!0,xf||(xf=!0,Mf())}function Ef(e,t){if(!Cf&&Sf){Cf=!0;do for(var n=!1,r=yf;r!==null;){if(!t){if(e!==0){var i=r.pendingLanes;if(i===0)var a=0;else{var o=r.suspendedLanes,s=r.pingedLanes;a=(1<<31-qe(42|e)+1)-1,a&=i&~(o&~s),a=a&201326741?a&201326741|1:a?a|2:0}a!==0&&(n=!0,jf(r,a))}else a=X,a=tt(r,r===Qu?a:0,r.cancelPendingCommit!==null||r.timeoutHandle!==-1),!(a&3)||nt(r,a)||(n=!0,jf(r,a))}r=r.next}while(n);Cf=!1}}function Df(){Of()}function Of(){Sf=xf=!1;var e=0;wf!==0&&hp()&&(e=wf);for(var t=Fe(),n=null,r=yf;r!==null;){var i=r.next,a=kf(r,t);a===0?(r.next=null,n===null?yf=i:n.next=i,i===null&&(bf=n)):(n=r,(e!==0||a&3)&&(Sf=!0)),r=i}vd!==0&&vd!==5||Ef(e,!1),wf!==0&&(wf=0)}function kf(e,t){for(var n=e.suspendedLanes,r=e.pingedLanes,i=e.expirationTimes,a=e.pendingLanes&-62914561;0s)break;var u=c.transferSize,d=c.initiatorType;u&&ap(d)&&(c=c.responseEnd,o+=u*(c$m){s.length=o;break}f=new Promise(jp.bind(f)),s.push(f)}}}if(0`u`?null:document;function Tm(e,t,n){var r=wm;if(r&&typeof t==`string`&&t){var i=Zt(t);i=`link[rel="`+e+`"][href="`+i+`"]`,typeof n==`string`&&(i+=`[crossorigin="`+n+`"]`),ym.has(i)||(ym.add(i),e={rel:e,crossOrigin:n,href:t},r.querySelector(i)===null&&(t=r.createElement(`link`),np(t,`link`,e),jt(t),r.head.appendChild(t)))}}function Em(e){xm.D(e),Tm(`dns-prefetch`,e,null)}function Dm(e,t){xm.C(e,t),Tm(`preconnect`,e,t)}function Om(e,t,n){xm.L(e,t,n);var r=wm;if(r&&e&&t){var i=`link[rel="preload"][as="`+Zt(t)+`"]`;t===`image`&&n&&n.imageSrcSet?(i+=`[imagesrcset="`+Zt(n.imageSrcSet)+`"]`,typeof n.imageSizes==`string`&&(i+=`[imagesizes="`+Zt(n.imageSizes)+`"]`)):i+=`[href="`+Zt(e)+`"]`;var a=i;switch(t){case`style`:a=Pm(e);break;case`script`:a=Rm(e)}if(!(vm.has(a)||(e=D({rel:`preload`,href:t===`image`&&n&&n.imageSrcSet?void 0:e,as:t},n),vm.set(a,e),r.querySelector(i)!==null||t===`style`&&r.querySelector(Fm(a))||t===`script`&&r.querySelector(zm(a))))){var o=r.createElement(`link`);np(o,`link`,e),t===`style`&&(o[Tt]=!0,o.onload=o.onerror=function(){Mt(o)}),jt(o),r.head.appendChild(o)}}}function km(e,t){xm.m(e,t);var n=wm;if(n&&e){var r=t&&typeof t.as==`string`?t.as:`script`,i=`link[rel="modulepreload"][as="`+Zt(r)+`"][href="`+Zt(e)+`"]`,a=i;switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:a=Rm(e)}if(!vm.has(a)&&(e=D({rel:`modulepreload`,href:e},t),vm.set(a,e),n.querySelector(i)===null)){switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:if(n.querySelector(zm(a)))return}r=n.createElement(`link`),np(r,`link`,e),jt(r),n.head.appendChild(r)}}}function Am(e,t,n){xm.S(e,t,n);var r=wm;if(r&&e){var i=At(r).hoistableStyles,a=Pm(e);t||=`default`;var o=i.get(a);if(!o){var s={loading:0,preload:null};if(o=r.querySelector(Fm(a)))s.loading=5;else{e=D({rel:`stylesheet`,href:e,"data-precedence":t},n),(n=vm.get(a))&&Hm(e,n);var c=o=r.createElement(`link`);jt(c),np(c,`link`,e),c._p=new Promise(function(e,t){c.onload=e,c.onerror=t}),c.addEventListener(`load`,function(){s.loading|=1}),c.addEventListener(`error`,function(){s.loading|=2}),s.loading|=4,Vm(o,t,r)}o={type:`stylesheet`,instance:o,count:1,state:s},i.set(a,o)}}}function jm(e,t){xm.X(e,t);var n=wm;if(n&&e){var r=At(n).hoistableScripts,i=Rm(e),a=r.get(i);a||(a=n.querySelector(zm(i)),a||(e=D({src:e,async:!0},t),(t=vm.get(i))&&Um(e,t),a=n.createElement(`script`),jt(a),np(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function Mm(e,t){xm.M(e,t);var n=wm;if(n&&e){var r=At(n).hoistableScripts,i=Rm(e),a=r.get(i);a||(a=n.querySelector(zm(i)),a||(e=D({src:e,async:!0,type:`module`},t),(t=vm.get(i))&&Um(e,t),a=n.createElement(`script`),jt(a),np(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function Nm(e,t,n,r){var i=(i=_e.current)?bm(i):null;if(!i)throw Error(s(446));switch(e){case`meta`:case`title`:return null;case`style`:return typeof n.precedence==`string`&&typeof n.href==`string`?(n=Pm(n.href),t=At(i).hoistableStyles,r=t.get(n),r||(r={type:`style`,instance:null,count:0,state:null},t.set(n,r)),r):{type:`void`,instance:null,count:0,state:null};case`link`:if(n.rel===`stylesheet`&&typeof n.href==`string`&&typeof n.precedence==`string`){e=Pm(n.href);var a=At(i).hoistableStyles,o=a.get(e);if(o||(i=i.ownerDocument||i,o={type:`stylesheet`,instance:null,count:0,state:{loading:0,preload:null}},a.set(e,o),(a=i.querySelector(Fm(e)))?a._p||(o.instance=a,o.state.loading=5):(a=vm.get(e),a||(a={rel:`preload`,as:`style`,href:n.href,crossOrigin:n.crossOrigin,integrity:n.integrity,media:n.media,hrefLang:n.hrefLang,referrerPolicy:n.referrerPolicy},vm.set(e,a)),Lm(i,e,a,o.state))),t&&r===null)throw Error(s(528,``));return o}if(t&&r!==null)throw Error(s(529,``));return null;case`script`:return t=n.async,n=n.src,typeof n==`string`&&t&&typeof t!=`function`&&typeof t!=`symbol`?(n=Rm(n),t=At(i).hoistableScripts,r=t.get(n),r||(r={type:`script`,instance:null,count:0,state:null},t.set(n,r)),r):{type:`void`,instance:null,count:0,state:null};default:throw Error(s(444,e))}}function Pm(e){return`href="`+Zt(e)+`"`}function Fm(e){return`link[rel="stylesheet"][`+e+`]`}function Im(e){return D({},e,{"data-precedence":e.precedence,precedence:null})}function Lm(e,t,n,r){if(t=e.querySelector(`link[rel="preload"][as="style"][`+t+`]`)){if(!0!==t[Tt]){r.loading=1;return}}else t=e.createElement(`link`),t[Tt]=!0,t.onload=t.onerror=Mt.bind(null,t),np(t,`link`,n),jt(t),e.head.appendChild(t);r.preload=t,t.addEventListener(`load`,function(){return r.loading|=1}),t.addEventListener(`error`,function(){return r.loading|=2})}function Rm(e){return`[src="`+Zt(e)+`"]`}function zm(e){return`script[async]`+e}function Bm(e,t,n){if(t.count++,t.instance===null)switch(t.type){case`style`:var r=e.querySelector(`style[data-href~="`+Zt(n.href)+`"]`);if(r)return t.instance=r,jt(r),r;var i=D({},n,{"data-href":n.href,"data-precedence":n.precedence,href:null,precedence:null});return r=(e.ownerDocument||e).createElement(`style`),jt(r),np(r,`style`,i),Vm(r,n.precedence,e),t.instance=r;case`stylesheet`:i=Pm(n.href);var a=e.querySelector(Fm(i));if(a)return t.state.loading|=4,t.instance=a,jt(a),a;r=Im(n),(i=vm.get(i))&&Hm(r,i),a=(e.ownerDocument||e).createElement(`link`),jt(a);var o=a;return o._p=new Promise(function(e,t){o.onload=e,o.onerror=t}),np(a,`link`,r),t.state.loading|=4,Vm(a,n.precedence,e),t.instance=a;case`script`:return a=Rm(n.src),(i=e.querySelector(zm(a)))?(t.instance=i,jt(i),i):(r=n,(i=vm.get(a))&&(r=D({},n),Um(r,i)),e=e.ownerDocument||e,i=e.createElement(`script`),jt(i),np(i,`link`,r),e.head.appendChild(i),t.instance=i);case`void`:return null;default:throw Error(s(443,t.type))}else t.type===`stylesheet`&&!(t.state.loading&4)&&(r=t.instance,t.state.loading|=4,Vm(r,n.precedence,e));return t.instance}function Vm(e,t,n){for(var r=n.querySelectorAll(`link[rel="stylesheet"][data-precedence],style[data-precedence]`),i=r.length?r[r.length-1]:null,a=i,o=0;o title`):null)}function qm(e,t,n){if(n===1||t.itemProp!=null)return!1;switch(e){case`meta`:case`title`:return!0;case`style`:if(typeof t.precedence!=`string`||typeof t.href!=`string`||t.href===``)break;return!0;case`link`:if(typeof t.rel!=`string`||typeof t.href!=`string`||t.href===``||t.onLoad||t.onError)break;switch(t.rel){case`stylesheet`:return e=t.disabled,typeof t.precedence==`string`&&e==null;default:return!0}case`script`:if(t.async&&typeof t.async!=`function`&&typeof t.async!=`symbol`&&!t.onLoad&&!t.onError&&t.src&&typeof t.src==`string`)return!0}return!1}function Jm(e,t){return e===`img`&&t.src!=null&&t.src!==``&&t.onLoad==null&&t.loading!==`lazy`}function Ym(e){return!(e.type===`stylesheet`&&!(e.state.loading&3))}function Xm(e){return(e.width||100)*(e.height||100)*(typeof devicePixelRatio==`number`?devicePixelRatio:1)*.25}function Zm(e,t){typeof t.decode==`function`&&(e.imgCount++,t.complete||(e.imgBytes+=Xm(t),e.suspenseyImages.push(t)),e=rh.bind(e),t.decode().then(e,e))}function Qm(e,t,n,r){if(n.type===`stylesheet`&&(typeof r.media!=`string`||!1!==matchMedia(r.media).matches)&&!(n.state.loading&4)){if(n.instance===null){var i=Pm(r.href),a=t.querySelector(Fm(i));if(a){t=a._p,typeof t==`object`&&t&&typeof t.then==`function`&&(e.count++,e=nh.bind(e),t.then(e,e)),n.state.loading|=4,n.instance=a,jt(a);return}a=t.ownerDocument||t,r=Im(r),(i=vm.get(i))&&Hm(r,i),a=a.createElement(`link`),jt(a);var o=a;o._p=new Promise(function(e,t){o.onload=e,o.onerror=t}),np(a,`link`,r),n.instance=a}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(n,t),(t=n.state.preload)&&!(n.state.loading&3)&&(e.count++,n=nh.bind(e),t.addEventListener(`load`,n),t.addEventListener(`error`,n))}}var $m=0;function eh(e,t){return e.stylesheets&&e.count===0&&ah(e,e.stylesheets),0$m?50:800)+t);return e.unsuspend=n,function(){e.unsuspend=null,clearTimeout(r),clearTimeout(i)}}:null}function th(e){if(e.count===0&&(e.imgCount===0||!e.waitingForImages)){if(e.stylesheets)ah(e,e.stylesheets);else if(e.unsuspend){var t=e.unsuspend;e.unsuspend=null,t()}}}function nh(){this.count--,th(this)}function rh(){this.imgCount--,th(this)}var ih=null;function ah(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,ih=new Map,t.forEach(oh,e),ih=null,nh.call(e))}function oh(e,t){if(!(t.state.loading&4)){var n=ih.get(e);if(n)var r=n.get(null);else{n=new Map,ih.set(e,n);for(var i=e.querySelectorAll(`link[data-precedence],style[data-precedence]`),a=0;a{function n(){if(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<`u`&&typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE==`function`)try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=s()}))(),l=n(),u=``;function d(e){u=e}var f=class extends Error{code;status;result;constructor(e,t,n,r){super(t),this.code=e,this.status=n,this.result=r}};async function p(e,t){let n=await fetch(`/admin/api${e}`,{...t,credentials:`same-origin`,headers:{"Content-Type":`application/json; charset=utf-8`,...u?{"X-Iris-CSRF":u}:{},...t?.headers}});if(!n.ok){let e=await n.json().catch(()=>({})),t=e.error||{};throw[`login_required`,`setup_required`,`csrf_failed`].includes(t.code)&&dispatchEvent(new Event(`iris-auth`)),new f(t.code||`request_failed`,t.message||(t.fields?`请检查输入:${t.fields.map(e=>`${e.field.split(`.`).pop()}:${e.message}`).join(`;`)}`:`请求失败,请重试`),n.status,e.result)}return n}async function m(e,t){let n=await p(e,t);return{data:await n.json(),status:n.status,headers:n.headers}}async function h(e,t){let n=await p(e,t);if(n.headers.get(`Content-Type`)?.split(`;`)[0].trim()!==`application/zip`)throw new f(`invalid_download`,`没有收到 ZIP 备份,请刷新登录状态后重试`,n.status);return{blob:await n.blob(),headers:n.headers}}async function g(e,t){return(await m(e,t)).data}var _=(e,t)=>({method:e,...t===void 0?{}:{body:JSON.stringify(t)}}),v=e=>e instanceof f?e.status===410&&[`entry_profile_legacy_write_retired`,`entry_profile_publish_mode_retired`].includes(e.code)?`旧画像的整版编辑、回滚和候选审批已退役。请在入口画像页逐条管理画像记忆;旧版本仅供查看。`:e.message:`无法连接服务,请检查服务是否仍在运行`;function y(e,t=0){let[n,r]=(0,l.useState)(null),[i,a]=(0,l.useState)(``),[o,s]=(0,l.useState)(e!==null),[c,u]=(0,l.useState)(0),d=(0,l.useCallback)(()=>{s(!0),u(e=>e+1)},[]);return(0,l.useEffect)(()=>{r(null),a(``)},[e]),(0,l.useEffect)(()=>{if(s(e!==null),e===null)return;let n=new AbortController,i=!0,o,c=async()=>{try{let t=await g(e,{signal:n.signal});i&&(r(t),a(``))}catch(e){i&&!n.signal.aborted&&a(v(e))}finally{i&&s(!1)}i&&t&&(o=setTimeout(c,t))};return c(),()=>{i=!1,n.abort(),clearTimeout(o)}},[e,t,c]),{data:n,error:i,refresh:d,loading:o}}var b=e((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.fragment`);function r(e,n,r){var i=null;if(r!==void 0&&(i=``+r),n.key!==void 0&&(i=``+n.key),`key`in n)for(var a in r={},n)a!==`key`&&(r[a]=n[a]);else r=n;return n=r.ref,{$$typeof:t,type:e,key:i,ref:n===void 0?null:n,props:r}}e.Fragment=n,e.jsx=r,e.jsxs=r})),x=e(((e,t)=>{t.exports=b()}))(),S=e=>e?new Date(e).toLocaleString(`zh-CN`,{month:`numeric`,day:`numeric`,hour:`2-digit`,minute:`2-digit`}):`暂无记录`,C=e=>e==null?`—`:`${(e/1e3).toFixed(1)} 秒`,w=e=>e?new Date(e).toLocaleString(`zh-CN`):`暂无记录`;function T({total:e,offset:t,limit:n=30,change:r}){return e<=n&&t===0?null:(0,x.jsxs)(`div`,{className:`pagination`,children:[(0,x.jsx)(`button`,{className:`secondary`,disabled:t===0,onClick:()=>r(Math.max(0,t-n)),children:`上一页`}),(0,x.jsxs)(`span`,{children:[`第 `,Math.floor(t/n)+1,` 页 · 共 `,e,` 条`]}),(0,x.jsx)(`button`,{className:`secondary`,disabled:t+n>=e,onClick:()=>r(t+n),children:`下一页`})]})}var E=e=>({active:`有效`,forgotten:`已遗忘`,deleted:`已删除`})[e]||e,D=e=>({normal:`正常`,temporarily_unavailable:`暂时不可用`,invalid_key:`密钥无效`,configuration_error:`配置错误`,account_problem:`账户异常`,usage_limit:`达到今日用量上限`,rate_limited:`限流退避中`})[e]||e,O=e=>({pending:`已接收 · 待学习`,batched:`已接收 · 批次处理中`,learned:`学习已完成`,abandoned:`学习放弃 · 未记住`,refused:`内容拒绝 · 未记住`,filtered:`已过滤 · 不参与学习`})[e]||e;function k(e){return e?e.state===`succeeded`?e.result?.created?.length||e.result?.updated?.length?`学习成功 · 新增 ${e.result.created?.length||0} / 更新 ${e.result.updated?.length||0}`:`学习成功,未形成新记忆`:{running:`正在学习`,waiting:e.next_retry_at?`失败后等待重试`:`等待学习`,abandoned:`已放弃 · 未记住`,refused:`已拒绝 · 未记住`}[e.state]||e.state:`暂无批次`}function A({children:e,error:t=!1}){return(0,x.jsx)(`div`,{className:`notice ${t?`error`:``}`,role:t?`alert`:`status`,children:e})}function j({title:e,children:t}){return(0,x.jsxs)(`div`,{className:`empty`,children:[(0,x.jsx)(`span`,{className:`empty-mark`,"aria-hidden":!0,children:`✳`}),(0,x.jsx)(`h3`,{children:e}),t&&(0,x.jsx)(`p`,{children:t})]})}function M({children:e,tone:t=``}){return(0,x.jsx)(`span`,{className:`badge ${t}`,children:e})}function ee({title:e,onClose:t,children:n,closeDisabled:r=!1}){let i=(0,l.useRef)(null),a=(0,l.useRef)(t);return a.current=r?()=>{}:t,(0,l.useEffect)(()=>{let e=document.activeElement;(i.current?.querySelector(`button,input,textarea,select`))?.focus();let t=e=>{if(e.key===`Escape`&&(e.preventDefault(),a.current()),e.key===`Tab`){let t=[...i.current?.querySelectorAll(`button:not(:disabled),a[href],input:not(:disabled),textarea:not(:disabled),select:not(:disabled),[tabindex="0"]`)||[]],n=t[0],r=t[t.length-1];e.shiftKey&&document.activeElement===n?(e.preventDefault(),r?.focus()):!e.shiftKey&&document.activeElement===r&&(e.preventDefault(),n?.focus())}},n=document.body.style.overflow;return document.body.style.overflow=`hidden`,document.addEventListener(`keydown`,t),()=>{document.body.style.overflow=n,document.removeEventListener(`keydown`,t),e?.focus()}},[]),(0,x.jsx)(`div`,{className:`overlay`,children:(0,x.jsxs)(`section`,{ref:i,className:`dialog`,role:`dialog`,"aria-modal":`true`,"aria-label":e,children:[(0,x.jsxs)(`div`,{className:`dialog-title`,children:[(0,x.jsx)(`h2`,{children:e}),(0,x.jsx)(`button`,{className:`icon-button`,"aria-label":`关闭详情`,disabled:r,onClick:t,children:`×`})]}),n]})})}function N({value:e}){return e?(0,x.jsx)(`time`,{dateTime:e,children:e.replace(`T`,` `).replace(/\.\d+(?=[+-]|Z$)/,``).replace(/([+-]\d{2}:\d{2}|Z)$/,` $1`)}):(0,x.jsx)(x.Fragment,{children:`暂无记录`})}function P(e,t){return Object.fromEntries(Object.keys(t).filter(n=>!Object.is(e[n],t[n])).map(e=>[e,t[e]]))}function F(e){let[t,n]=(0,l.useState)({});function r(t,r){n(n=>{let i={...n};return Object.is(e[t],r)?delete i[t]:i[t]=r,i})}return{draft:{...e,...t},change:r,reset:()=>n({})}}function I({value:e,busy:t,saveError:n,nativeImagesAvailable:r,chatEnabled:i,external:a,save:o}){let s={daily_token_limit:e.daily_token_limit,learning_concurrency:e.learning_concurrency,native_image_learning:e.native_image_learning===!0,media_retention_days:e.media_retention_days??7},{draft:c,change:u,reset:d}=F({daily_token_limit:s.daily_token_limit?.toString()||``,learning_concurrency:String(s.learning_concurrency),native_image_learning:s.native_image_learning,media_retention_days:String(s.media_retention_days)}),[f,p]=(0,l.useState)(``),[m,h]=(0,l.useState)(!1);async function g(e){if(e.preventDefault(),t)return;p(``),h(!1);let n=c.daily_token_limit.trim()?Number(c.daily_token_limit):null,r=Number(c.learning_concurrency),i=Number(c.media_retention_days);if(n!==null&&(!Number.isInteger(n)||n<1)){p(`每日 token 上限须为正整数,留空表示不限`);return}if(!c.learning_concurrency.trim()||!Number.isInteger(r)||r<1||r>32){p(`学习并发须为 1—32 的整数`);return}if(!c.media_retention_days.trim()||!Number.isInteger(i)||i<1||i>36500){p(`原图保留天数须为 1—36500 的整数`);return}let a=P(s,{daily_token_limit:n,learning_concurrency:r,native_image_learning:c.native_image_learning,media_retention_days:i});Object.keys(a).length&&await o(a)&&(d(),h(!0))}return(0,x.jsxs)(`section`,{className:`panel settings-panel`,"aria-label":`用量与学习`,children:[(0,x.jsx)(`h2`,{children:`用量与学习`}),(0,x.jsx)(`form`,{onSubmit:g,noValidate:!0,onChange:()=>h(!1),children:(0,x.jsxs)(`fieldset`,{className:`lifecycle-fieldset`,disabled:t,children:[(0,x.jsxs)(`label`,{children:[`每日 token 上限`,(0,x.jsx)(`input`,{"aria-label":`每日 token 上限`,type:`number`,min:1,step:1,value:c.daily_token_limit,placeholder:`不限`,onChange:e=>u(`daily_token_limit`,e.target.value)})]}),(0,x.jsxs)(`label`,{children:[`学习并发`,(0,x.jsx)(`input`,{"aria-label":`学习并发`,type:`number`,required:!0,min:1,max:32,step:1,value:c.learning_concurrency,onChange:e=>u(`learning_concurrency`,e.target.value)})]}),(0,x.jsx)(`p`,{className:`muted`,children:`按角色时区每日恢复;在途调用和未报告的 token 可能使实际用量超过上限。`}),(0,x.jsxs)(`label`,{children:[`原图保留天数`,(0,x.jsx)(`input`,{"aria-label":`原图保留天数`,type:`number`,required:!0,min:1,max:36500,step:1,value:c.media_retention_days,onChange:e=>u(`media_retention_days`,e.target.value)}),(0,x.jsx)(`small`,{children:`1—36500 的整数,默认 7 天;与消息保留天数分别设置。`})]}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`到期由每日维护只清理原图字节,理解文本保留。作为记忆来源的图片、正在理解的图片受保护。`}),(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,"aria-describedby":`native-image-learning-help native-image-learning-availability`,checked:c.native_image_learning,disabled:t||!r,onChange:e=>u(`native_image_learning`,e.target.checked)}),`学习时直接看原图`]}),(0,x.jsx)(`p`,{className:`lifecycle-help`,id:`native-image-learning-help`,children:`默认关闭。开启后,后续学习把原图交给对话模型;图片描述仍用于回复准备、检索与管理页。超限或不可用的图片沿用描述或占位。`}),(0,x.jsx)(`p`,{className:`lifecycle-help`,id:`native-image-learning-availability`,children:r?a?`这是运行设置,使用外部模型配置时也可以保存。`:`使用已保存的对话模型图片能力;保存后对后续学习生效。`:`${i?`当前对话模型未启用图片输入(vision),此设置暂不生效。`:`当前对话模型未启用,无法直接看原图。`}${a?`请在外部模型配置中启用对话模型及 vision。`:`请先启用并保存对话模型的“支持图片输入(vision)”。`}`}),(f||n)&&(0,x.jsx)(A,{error:!0,children:f||n}),m&&(0,x.jsx)(A,{children:`用量与学习设置已保存`}),(0,x.jsx)(`button`,{className:`primary`,children:`保存用量与学习`})]})})]})}function te({value:e,busy:t,saveError:n,save:r}){let i={...e,internal_question_expiry_days:e.internal_question_expiry_days??7},{draft:a,change:o,reset:s}=F({default_reminder_minutes:String(i.default_reminder_minutes),overdue_reminders:i.overdue_reminders,internal_question_expiry_days:String(i.internal_question_expiry_days)}),[c,u]=(0,l.useState)(``),[d,f]=(0,l.useState)(!1);async function p(e){if(e.preventDefault(),t)return;u(``),f(!1);let n=Number(a.default_reminder_minutes),o=Number(a.internal_question_expiry_days);if(!a.default_reminder_minutes.trim()||!Number.isInteger(n)||n<0||n>525600){u(`默认提醒提前量须为 0—525600 的整数`);return}if(!a.internal_question_expiry_days.trim()||!Number.isInteger(o)||o<1||o>365){u(`学习产生的询问保留天数须为 1—365 的整数`);return}let c=P(i,{default_reminder_minutes:n,overdue_reminders:a.overdue_reminders,internal_question_expiry_days:o});Object.keys(c).length&&await r(c)&&(s(),f(!0))}return(0,x.jsxs)(`section`,{className:`panel settings-panel`,"aria-label":`目标与提醒`,children:[(0,x.jsx)(`h2`,{children:`目标与提醒`}),(0,x.jsx)(`p`,{children:`未单独填写提前量的普通目标使用默认值。询问不安排提醒,过期不会自动放弃目标。`}),(0,x.jsx)(`form`,{onSubmit:p,noValidate:!0,onChange:()=>f(!1),children:(0,x.jsxs)(`fieldset`,{className:`lifecycle-fieldset`,disabled:t,children:[(0,x.jsxs)(`label`,{children:[`默认提醒提前量(分钟)`,(0,x.jsx)(`input`,{"aria-label":`默认提醒提前量(分钟)`,type:`number`,min:0,max:525600,step:1,required:!0,value:a.default_reminder_minutes,onChange:e=>o(`default_reminder_minutes`,e.target.value)}),(0,x.jsx)(`small`,{children:`0—525600 的整数,默认 60 分钟;0 表示到期时提醒。`})]}),(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:a.overdue_reminders,onChange:e=>o(`overdue_reminders`,e.target.checked)}),`启用过期提醒`]}),(0,x.jsxs)(`p`,{className:`lifecycle-help`,children:[`过期提醒每日最多一次。`,(0,x.jsx)(`a`,{href:`#/state?tab=notifications`,children:`查看提醒`}),`;“已取走”只表示宿主拿到了。`]}),(0,x.jsxs)(`label`,{children:[`学习产生的询问保留天数`,(0,x.jsx)(`input`,{"aria-label":`学习产生的询问保留天数`,type:`number`,min:1,max:365,step:1,required:!0,value:a.internal_question_expiry_days,onChange:e=>o(`internal_question_expiry_days`,e.target.value)}),(0,x.jsx)(`small`,{children:`1—365 的整数,默认 7 天。`})]}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`只作用于学习产生且仍未结束的询问,到期由每日维护自动结束。宿主或管理员创建的询问和普通目标不受影响。`}),(c||n)&&(0,x.jsx)(A,{error:!0,children:c||n}),d&&(0,x.jsx)(A,{children:`目标与提醒设置已保存`}),(0,x.jsx)(`button`,{className:`primary`,children:`保存目标与提醒设置`})]})})]})}var L={initial_setting:`初始设定`,periodic:`定期更新`,regenerate:`重新生成`,admin_edit:`管理员编辑`,rollback:`回滚`},ne={current:`当前`,pending:`待确认`,rejected:`已拒绝`,superseded:`已被后续候选替代`,history:`历史已发布`},R={small:`小`,medium:`中`,large:`大`},re={memory:`记忆依据`,admin:`手写`,initial_template:`初始模板`},ie={modified:`记忆已修改`,forgotten:`记忆已遗忘`,deleted:`记忆已删除或清除`,no_longer_self_memory:`已不属于自我记忆`,sources_changed:`来源已变化`,daily_token_limit:`达到每日用量上限`,no_self_evidence:`暂无有效自我记忆依据`,not_due:`尚未满足定期更新条件`,evidence_changed:`依据已变化`,current_version_changed:`当前版本已变化`,interrupted:`服务中断,任务未完成`,worker_unavailable:`生成工作线程不可用`,unconfigured:`尚未配置生成模型`,unexpected_error:`生成时发生异常`,timeout:`模型调用超时`,invalid_output:`模型输出不符合要求`,paused:`模型用途已暂停`,usage_limit:`达到每日用量上限`,temporarily_unavailable:`模型暂时不可用`,configuration_error:`模型配置错误`,invalid_key:`模型密钥无效`,account_problem:`模型账户异常`,rate_limited:`模型限流`,"administrator rejected":`管理员拒绝采用`,"sentences must be an array":`句子列表格式无效`,"empty persona":`persona 正文为空`,"persona exceeds 800 characters":`persona 正文超过 800 字`,"residual memory or participant reference":`正文残留记忆或参与者编号`,"under 300 characters: concise evidence-bound text is allowed":`不足 300 字:允许依据有限时保持简短`,"initial template retains the pre-M3 length behavior":`初始模板沿用此前的长度规则`,"nonempty text required":`句子不能为空`,"one sentence per item required":`每项须为一句话`,"invalid administrator attribution":`手写归属无效`,"missing or unknown evidence":`缺少依据或依据未知`,"invalid model verdict":`模型判断格式无效`,"single-date/unknown-date evidence needs a scene qualifier":`单日或日期未知的依据需要场景限定`,"invalid change degree":`变化程度无效`,"model check must cover every sentence, in order":`模型检查须按顺序覆盖每句话`,"model check reason required":`模型检查缺少理由`};function ae(e){let t=e.match(/^sentence (\d+):\s*(.*)$/);return t?`第 ${t[1]} 句:${ae(t[2])}`:ie[e]||e}var oe=e=>e===`queued`||e===`running`;function se(e,t){return oe(e)?{queued:`等待生成`,generating:`正在生成候选`,checking:`正在检查候选`}[t]||`正在生成候选`:{current:`已发布 persona`,pending:`候选待确认,当前版本仍保留`,rejected:`候选被拒绝,当前版本仍保留`,skipped:`本次未生成候选`,conflict:`生成期间版本或依据发生变化,未发布`,failed:`生成失败,当前版本仍保留`}[e]||e}var ce={disputed:`争议`,insufficient_support:`依据不足`,superseded:`已被替代`},le={pending:`待确认`,confirmed:`已确认`,cleared:`已清除`},ue=[[`max_calls`,`记忆整理(合并/矛盾/依赖)每轮调用上限`,300],[`entry_profile_max_calls`,`入口画像每轮调用上限`,60],[`person_summary_max_calls`,`人物摘要每轮调用上限`,40],[`persona_max_calls`,`persona 每轮调用上限`,30]],de={memory:`记忆整理(合并/矛盾/依赖)`,entry_profile:`入口画像`,person_summary:`人物摘要`,persona:`persona`},z=[[`merge_enabled`,`合并重复记忆`],[`conflict_enabled`,`矛盾检查与建议`],[`dependency_enabled`,`派生依据复核与建议`],[`persona_enabled`,`定期更新 persona`],[`person_summary_enabled`,`定期更新人物摘要`],[`goal_review_enabled`,`目标依据复核`]];function B(e){return{disabled:`本次设置已关闭`,model_items_disabled:`记忆模型整理项目均已关闭`,usage_limit:`每日 token 上限已用尽`,paused:`模型用途已暂停`,interrupted:`运行已中断`,call_budget:`模型调用次数预算已用尽`,persona_busy:`已有 persona 任务正在运行`,checks_rejected:`persona 检查未通过,候选被拒绝`,revision_conflict:`对象修订已变化,跳过本次写入`,unsafe_write:`未通过写入保护校验`,invalid_response:`模型返回格式无效`,invalid_json:`模型返回的 JSON 无效`,temporary_unavailable:`模型暂时不可用`,cooldown:`尚未到定期更新时间`,no_changes:`没有需要更新的变化`,stale:`判断期间目标或依据已变化,等待重新复核`,lease_expired:`本次判断任务已超时,等待重新复核`,configuration_changed:`判断设置已变化,等待重新复核`,goal_closed:`目标已结束,取消待复核任务`,in_progress:`已有复核任务正在运行`,queue_full:`判断排队已满`,configuration:`模型尚未配置或配置无效`,budget:`预算已耗尽`,invalid:`模型输出未通过校验`,source_unavailable:`来源已不可用`,insufficient_new_memories:`新增自我记忆不足,尚未到更新条件`,too_soon:`距离上次更新尚不足一个周期`}[e]||ae(e)}var V=e=>({...e,person_summary_enabled:e.person_summary_enabled??!0,entry_profile_max_calls:e.entry_profile_max_calls??60,person_summary_max_calls:e.person_summary_max_calls??40,persona_max_calls:e.persona_max_calls??30});function fe({value:e,timezone:t,busy:n,saveError:r,save:i}){let a=V(e),{draft:o,change:s,reset:c}=F({...a,max_calls:String(a.max_calls),entry_profile_max_calls:String(a.entry_profile_max_calls),person_summary_max_calls:String(a.person_summary_max_calls),persona_max_calls:String(a.persona_max_calls)}),[u,d]=(0,l.useState)(``),[f,p]=(0,l.useState)(!1);async function m(e){if(e.preventDefault(),n)return;if(d(``),p(!1),!/^(?:[01][0-9]|2[0-3]):[0-5][0-9]$/.test(o.maintenance_time)){d(`整理运行时间须为 HH:MM,范围 00:00—23:59`);return}for(let[e,t]of ue){let n=Number(o[e]);if(!o[e].trim()||!Number.isInteger(n)||n<0||n>1e3){d(`${t}须为 0—1000 的整数`);return}}let t=P(a,{...o,max_calls:Number(o.max_calls),entry_profile_max_calls:Number(o.entry_profile_max_calls),person_summary_max_calls:Number(o.person_summary_max_calls),persona_max_calls:Number(o.persona_max_calls)});Object.keys(t).length&&await i(t)&&(c(),p(!0))}return(0,x.jsxs)(`section`,{className:`panel settings-panel`,"aria-label":`梦境整理设置`,id:`consolidation-settings`,children:[(0,x.jsx)(`h2`,{children:`梦境整理`}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`整理不中断接收和学习。修改只影响之后接受的新运行,已接受的运行与续跑沿用其设置快照。`}),(0,x.jsx)(`form`,{onSubmit:m,noValidate:!0,onChange:()=>p(!1),children:(0,x.jsxs)(`fieldset`,{disabled:n,className:`lifecycle-fieldset`,children:[(0,x.jsxs)(`label`,{children:[`整理运行时间`,(0,x.jsx)(`input`,{"aria-label":`整理运行时间`,type:`text`,required:!0,maxLength:5,placeholder:`03:00`,value:o.maintenance_time,onChange:e=>s(`maintenance_time`,e.target.value)}),(0,x.jsxs)(`small`,{children:[`HH:MM · 角色时区 `,t||`未设置`,`,与每日记忆维护共用时间。`]})]}),(0,x.jsx)(`div`,{className:`form-grid`,children:ue.map(([e,t,n])=>(0,x.jsxs)(`label`,{children:[t,(0,x.jsx)(`input`,{"aria-label":t,type:`number`,min:0,max:1e3,step:1,required:!0,value:o[e],onChange:t=>s(e,t.target.value)}),(0,x.jsxs)(`small`,{children:[`0—1000 的整数,默认 `,n,` 次。`]})]},e))}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`以上均为每轮调用上限,各步骤互不占用;HTTP 重试和 JSON 修正计入所属步骤。0 表示停用该步骤的模型调用,其他步骤、记忆生命周期维护与开启的目标依据复核仍会执行。`}),z.map(([e,t])=>(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:o[e],onChange:t=>s(e,t.target.checked)}),t]},e)),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`persona 与人物摘要需满足各自更新条件且在各自上限内至少剩余 2 次调用名额。人物摘要开关只影响之后的整理,不关闭已发布摘要的宿主读取。`}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`矛盾和依赖复核只产生管理员可见的模型建议;目标依据复核不自动完成或放弃目标。`}),(u||r)&&(0,x.jsx)(A,{error:!0,children:u||r}),f&&(0,x.jsx)(A,{children:`梦境整理设置已保存`}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`primary`,children:`保存梦境整理设置`}),(0,x.jsx)(`button`,{type:`button`,onClick:()=>{c(),d(``),p(!1)},children:`还原整理设置`})]})]})}),(0,x.jsx)(`a`,{href:`#/status`,children:`查看整理报告或手动运行`})]})}function pe({value:e,busy:t,save:n}){let r=e=>({enabled:e.enabled,budget_seconds:String(e.budget_seconds),concurrency:String(e.concurrency),queue_limit:String(e.queue_limit)}),[i,a]=(0,l.useState)(()=>r(e)),o=(0,l.useRef)(!1),[s,c]=(0,l.useState)(``),[u,d]=(0,l.useState)(!1);(0,l.useEffect)(()=>{o.current||a(r(e))},[e]);function f(e,t){o.current=!0,d(!1),a(n=>({...n,[e]:t}))}async function p(e){if(e.preventDefault(),t)return;c(``),d(!1);let s=Number(i.budget_seconds),l=Number(i.concurrency),u=Number(i.queue_limit);if(!i.budget_seconds.trim()||!Number.isFinite(s)||s<=0||s>10){c(`目标去重判断预算须大于 0 且不超过 10 秒`);return}if(!i.concurrency.trim()||!Number.isInteger(l)||l<1||l>8){c(`目标去重判断并发须为 1—8 的整数`);return}if(!i.queue_limit.trim()||!Number.isInteger(u)||u<0||u>64){c(`目标去重判断排队上限须为 0—64 的整数`);return}let f=await n({enabled:i.enabled,budget_seconds:s,concurrency:l,queue_limit:u});f&&(o.current=!1,a(r(f)),d(!0))}return(0,x.jsxs)(`form`,{className:`judge-settings`,onSubmit:p,noValidate:!0,"aria-label":`目标去重判断设置`,children:[(0,x.jsx)(`h3`,{children:`目标判断开关与排队`}),(0,x.jsxs)(`fieldset`,{disabled:t,className:`lifecycle-fieldset`,children:[(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:i.enabled,onChange:e=>f(`enabled`,e.target.checked)}),`启用目标去重判断`]}),(0,x.jsxs)(`label`,{children:[`目标去重方法`,(0,x.jsx)(`input`,{"aria-label":`目标去重方法`,readOnly:!0,value:i.enabled?`C2(批量判断与可能重复提示)`:`A(确定性规则)`}),(0,x.jsx)(`small`,{children:`方法由后端固定;管理接口目前不提供方法切换。`})]}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`关闭后使用确定性规则。开启时若模型暂时不可用,先保留目标并等待复核;管理员创建的目标始终只标可能重复,不自动合并。清除独立模型配置只恢复沿用,不会关闭判断。`}),(0,x.jsxs)(`div`,{className:`form-grid`,children:[(0,x.jsxs)(`label`,{children:[`目标去重判断预算(秒)`,(0,x.jsx)(`input`,{type:`number`,"aria-label":`目标去重判断预算(秒)`,min:.01,max:10,step:`any`,required:!0,value:i.budget_seconds,onChange:e=>f(`budget_seconds`,e.target.value)}),(0,x.jsx)(`small`,{children:`大于 0 且不超过 10,含排队和模型调用。`})]}),(0,x.jsxs)(`label`,{children:[`目标去重判断并发`,(0,x.jsx)(`input`,{type:`number`,min:1,max:8,step:1,required:!0,value:i.concurrency,onChange:e=>f(`concurrency`,e.target.value)})]}),(0,x.jsxs)(`label`,{children:[`目标去重判断排队上限`,(0,x.jsx)(`input`,{type:`number`,min:0,max:64,step:1,required:!0,value:i.queue_limit,onChange:e=>f(`queue_limit`,e.target.value)})]})]}),s&&(0,x.jsx)(A,{error:!0,children:s}),u&&(0,x.jsx)(A,{children:`目标去重判断设置已保存`}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`primary`,children:`保存目标去重判断设置`}),(0,x.jsx)(`button`,{type:`button`,onClick:()=>{o.current=!1,a(r(e)),c(``),d(!1)},children:`还原目标判断设置`})]})]})]})}function me(){return(0,x.jsxs)(`details`,{className:`persona-guide panel`,children:[(0,x.jsx)(`summary`,{children:`persona 从哪里来?与当前状态、目标有什么区别?`}),(0,x.jsxs)(`figure`,{children:[(0,x.jsx)(`figcaption`,{children:`经历成为自我认知,经过提炼与检查后形成 persona。`}),(0,x.jsxs)(`ol`,{className:`persona-flow`,children:[(0,x.jsx)(`li`,{children:`初始背景 + 持续经历`}),(0,x.jsxs)(`li`,{children:[`自我认知`,(0,x.jsx)(`small`,{children:`有来源的自我记忆`})]}),(0,x.jsxs)(`li`,{children:[`结合生成目标 + 监管要求`,(0,x.jsx)(`small`,{children:`由管理员设定,不从记忆中改写`})]}),(0,x.jsxs)(`li`,{children:[`梦境整理中提炼与检查`,(0,x.jsx)(`small`,{children:`逐句依据与表达检查`})]}),(0,x.jsxs)(`li`,{children:[`persona`,(0,x.jsx)(`small`,{children:`按发布方式发布或等待确认`})]})]})]}),(0,x.jsxs)(`dl`,{className:`persona-distinction`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`当前状态`}),(0,x.jsx)(`dd`,{children:`现在在做什么、心情如何,由宿主报告,可能过时。`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`目标与询问`}),(0,x.jsx)(`dd`,{children:`未来要做或要问的事,跨入口共享;提醒被取走不代表目标完成。`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`persona`}),(0,x.jsx)(`dd`,{children:`相对稳定的自我表达,有版本与依据;不是当前心情,也不是待办清单。`})]})]}),(0,x.jsx)(`p`,{children:`宿主结合当前状态、目标、persona、相关记忆和本入口近期消息,组织上下文并决定说什么、做什么。`}),(0,x.jsx)(`p`,{className:`muted`,children:`“待更新”表示当前版本有失效依据;“待确认”表示已有候选等待管理员决定。两者可以同时出现。`})]})}function he({value:e,busy:t,save:n}){let[r,i]=(0,l.useState)(e),[a,o]=(0,l.useState)(``),s=(0,l.useRef)(!1);return(0,l.useEffect)(()=>{s.current||i(e)},[e]),(0,x.jsxs)(`section`,{className:`panel settings-panel persona-settings`,children:[(0,x.jsx)(`h2`,{children:`persona 的生成与发布`}),(0,x.jsx)(`p`,{children:`生成目标和监管要求只能由管理员修改,学习和整理不能修改它们。保存只影响之后接受的任务;已接受的任务、已有候选和当前 persona 保持原设置。`}),(0,x.jsxs)(`form`,{noValidate:!0,onSubmit:async e=>{if(e.preventDefault(),t)return;let a=r.goal.trim(),c=r.rules.trim();if(!a||[...a].length>4e3){o(`生成目标须为 1—4000 字,不能只含空白`);return}if(!c||[...c].length>16e3){o(`监管要求须为 1—16000 字,不能只含空白`);return}o(``);let l=await n({goal:a,rules:c,publish_mode:r.publish_mode});l&&(s.current=!1,i(l))},children:[(0,x.jsxs)(`label`,{children:[`persona 发布方式`,(0,x.jsxs)(`select`,{disabled:t,value:r.publish_mode,onChange:e=>{s.current=!0,i({...r,publish_mode:e.target.value})},children:[(0,x.jsx)(`option`,{value:`small_medium_auto`,children:`小或中自动发布`}),(0,x.jsx)(`option`,{value:`all_auto`,children:`全部自动`}),(0,x.jsx)(`option`,{value:`all_manual`,children:`全部人工确认(默认)`})]})]}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`M3 的 persona 门槛尚未达到,默认采用“全部人工确认”:检查通过的候选也先由管理员确认,确认后才生效。可以改回“小或中自动发布”或“全部自动”。`}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`所有候选都要经过检查。“小或中自动发布”会自动发布检查通过的小、中变化,大变化等待确认。`}),(0,x.jsx)(A,{children:`自动候选删去或改动手写内容时按“大变化”处理。选择“全部自动”后,检查通过的大变化也会直接发布,包括删改手写内容;不会等待确认。`}),(0,x.jsxs)(`label`,{children:[`生成目标`,(0,x.jsx)(`textarea`,{rows:4,disabled:t,value:r.goal,onChange:e=>{s.current=!0,i({...r,goal:e.target.value})}})]}),(0,x.jsxs)(`label`,{children:[`监管要求`,(0,x.jsx)(`textarea`,{rows:6,disabled:t,value:r.rules,onChange:e=>{s.current=!0,i({...r,rules:e.target.value})}})]}),a&&(0,x.jsx)(A,{error:!0,children:a}),(0,x.jsx)(`button`,{className:`primary`,disabled:t,children:`保存 persona 设置`})]}),(0,x.jsx)(`p`,{children:(0,x.jsx)(`a`,{href:`#/persona`,children:`查看 persona 的依据、候选和版本历史`})}),(0,x.jsx)(me,{})]})}var H=[[`forget_threshold`,`遗忘阈值 F`,1,99],[`restore_threshold`,`恢复阈值 H`,2,100],[`feedback_increment`,`实际使用增幅`,0,100],[`confirmation_increment`,`再次确认增幅`,0,100],[`decay_amount`,`每次衰减幅度`,0,100],[`dependency_penalty`,`依据失效扣减`,0,100],[`auto_delete_days`,`遗忘后自动删除天数`,1,36500],[`upcoming_delete_days`,`即将删除窗口(天)`,1,36500],[`message_retention_days`,`消息保留天数`,1,36500]];function U(e){let t=Object.fromEntries(H.map(([t])=>[t,String(e[t])]));return{...e,...t}}function ge({value:e,timezone:t,managedTime:n=!1}){let[r,i]=(0,l.useState)(()=>U(e)),a=(0,l.useRef)(!1),[o,s]=(0,l.useState)(!1),[c,u]=(0,l.useState)(``),[d,f]=(0,l.useState)(!1);(0,l.useEffect)(()=>{a.current||i(U(e))},[e]);function p(e,t){a.current=!0,f(!1),i(n=>({...n,[e]:t}))}async function m(e){if(e.preventDefault(),o)return;u(``),f(!1);for(let[e,t,n,i]of H){let a=Number(r[e]);if(!r[e].trim()||!Number.isInteger(a)||ai){u(`${t}须为 ${n}—${i} 的整数`);return}}if(Number(r.restore_threshold)<=Number(r.forget_threshold)){u(`恢复阈值 H 必须大于遗忘阈值 F`);return}if(!n&&!/^(?:[01][0-9]|2[0-3]):[0-5][0-9]$/.test(r.maintenance_time)){u(`维护时间须为 HH:MM 格式,范围 00:00—23:59`);return}let{maintenance_time:t,...c}={...r,...Object.fromEntries(H.map(([e])=>[e,Number(r[e])]))};s(!0);try{let e=await g(`/settings/lifecycle`,_(`PATCH`,n?c:{...c,maintenance_time:t}));i(U(e.lifecycle)),a.current=!1,f(!0)}catch(e){u(v(e))}finally{s(!1)}}return(0,x.jsxs)(`section`,{className:`panel settings-panel full-width`,children:[(0,x.jsx)(`h2`,{children:`记忆生命周期`}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`有效记忆低于 F 时遗忘,遗忘记忆达到 H 时恢复;两阈值之间保持原状态。置顶不自动恢复。`}),n&&(0,x.jsxs)(`p`,{className:`lifecycle-help`,children:[`每日运行时间 `,e.maintenance_time,`(`,t||`角色时区`,`),在梦境整理设置中修改。`]}),(0,x.jsx)(`form`,{onSubmit:m,noValidate:!0,children:(0,x.jsxs)(`fieldset`,{disabled:o,className:`lifecycle-fieldset`,children:[(0,x.jsxs)(`div`,{className:`lifecycle-settings-grid`,children:[H.map(([e,t,n,i])=>(0,x.jsxs)(`label`,{children:[t,(0,x.jsx)(`input`,{"aria-label":t,type:`number`,required:!0,min:n,max:i,step:1,value:r[e],onChange:t=>p(e,t.target.value)}),(0,x.jsxs)(`small`,{children:[n,`—`,i,`,整数`]})]},e)),!n&&(0,x.jsxs)(`label`,{children:[`维护时间`,(0,x.jsx)(`input`,{"aria-label":`维护时间`,required:!0,type:`text`,inputMode:`text`,placeholder:`03:00`,maxLength:5,value:r.maintenance_time,onChange:e=>p(`maintenance_time`,e.target.value)}),(0,x.jsxs)(`small`,{children:[`HH:MM · 角色时区 `,t||`未设置`]})]})]}),(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:r.auto_delete_enabled,onChange:e=>p(`auto_delete_enabled`,e.target.checked)}),`自动删除遗忘记忆`]}),(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:r.abandoned_retry_enabled,onChange:e=>p(`abandoned_retry_enabled`,e.target.checked)}),`自动重试已放弃批次`]}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`维护按实际执行次数衰减,遗忘和置顶记忆不衰减。依据失效时每个依据只扣一次,置顶期间暂缓扣减。自动重试仅处理角色时区前一天放弃的批次,每批最多一次;内容拒绝不自动重试。`}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`关闭自动删除后仍保留天数设置,“即将删除”列表为空。消息只有超过保留期、已结束学习且没有受保护的引用时才清理。新设置用于以后接受的维护,当前运行沿用接受时的设置。`}),c&&(0,x.jsx)(A,{error:!0,children:c}),d&&(0,x.jsx)(A,{children:`生命周期设置已保存`}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`primary`,children:o?`正在保存…`:`保存生命周期设置`}),(0,x.jsx)(`button`,{type:`button`,className:`secondary`,onClick:()=>{i(U(e)),a.current=!1,u(``),f(!1)},children:`还原为最近读取的设置`})]})]})})]})}var _e={person_summary_settings:`更新人物摘要设置`,person_summary_edit:`编辑发布人物摘要`,person_summary_confirm:`确认人物摘要候选`,person_summary_reject:`拒绝人物摘要候选`,person_summary_rollback:`回滚人物摘要`,person_summary_regenerate_requested:`请求重新生成人物摘要`,person_summary_generation_requested:`请求生成人物摘要`,person_summary_generation_published:`人物摘要生成并发布`,person_summary_generation_candidate:`人物摘要待确认`,person_summary_generation_rejected:`人物摘要检查未通过`,person_summary_generation_skipped:`跳过人物摘要生成`,person_summary_generation_interrupted:`人物摘要生成中断`,token_create:`创建宿主令牌`,token_revoke:`撤销宿主令牌`,token_limits_saved:`更新宿主令牌限流`,backup_export:`导出备份`,backup_import:`从备份导入`,consolidation_settings_saved:`更新梦境整理设置`,goal_dedup_judge_saved:`更新目标去重判断设置`,consolidation_merge:`整理合并记忆`,consolidation_conflict:`整理提出矛盾建议`,consolidation_dependency:`整理提出依赖复核建议`,consolidation_annotation_confirm:`确认整理建议`,consolidation_annotation_clear:`清除整理建议`,goal_basis_review:`目标依据复核`,goal_basis_clear:`清除目标依据标注`,persona_settings_saved:`更新 persona 设置`,persona_edit:`编辑发布 persona`,persona_confirm:`确认 persona 候选`,persona_reject:`拒绝 persona 候选`,persona_rollback:`回滚 persona`,persona_current:`发布 persona`,persona_pending:`persona 候选待确认`,persona_rejected:`persona 候选被拒绝`,persona_generation_requested:`请求生成 persona`,persona_generation_current:`persona 生成并发布`,persona_generation_pending:`persona 生成后待确认`,persona_generation_rejected:`persona 生成检查未通过`,persona_generation_skipped:`跳过 persona 生成`,persona_generation_conflict:`persona 生成遇到版本或依据冲突`,persona_generation_failed:`persona 生成失败`,persona_generation_interrupted:`persona 生成中断`,goal_dedup_judged:`目标去重判断结果`,goal_dedup_queued:`目标待去重复核`,goal_create:`创建目标`,goal_update:`更新目标`,goal_merge:`合并重复目标`,goal_duplicate_dismiss:`驳回目标重复`,settings_goals:`更新目标与提醒设置`,memory_adjust:`调整记忆`,memory_forget:`手动遗忘`,memory_bulk_forget:`批量遗忘记忆`,memory_bulk_delete:`批量删除记忆`,memory_bulk_purge:`批量彻底清除记忆`,memory_restore:`恢复记忆`,memory_purge:`彻底清除记忆`,memory_recreate:`按旧内容新建`,memory_revision:`人工修订记忆`,lifecycle_saved:`更新生命周期设置`,state_settings_saved:`更新当前状态设置`,maintenance_requested:`请求维护`,maintenance_completed:`维护完成`,batch_relearn:`重新学习批次`,batch_result:`批次结果`,learn_requested:`请求立即学习`,feedback:`使用反馈`,feedback_rejected:`使用反馈被拒绝`,learn_rejected:`立即学习请求被拒绝`,trial_media_uploaded:`上传试用图片`,trial_entry_created:`创建试用入口`,trial_speaker_created:`创建发言人`,trial_message_received:`试用消息接收`,trial_prepare:`试用回复准备`,trial_reply:`试用角色回复`,setup_password:`设置管理员密码`,setup_completed:`完成首次设置`,models_saved:`更新模型配置`,role_saved:`更新角色设置`,limits_saved:`更新用量与并发`,model_retry:`请求模型重试`,model_test:`测试模型连接`,recall_judge_saved:`更新召回判断设置`,entry_visibility:`更新入口记忆可见范围`,entry_settings_updated:`更新入口节奏与过滤`,subject_alias_added:`添加人物别名`,subject_alias_removed:`删除人物别名`,subject_link_denied:`否认人物联系`,subjects_merged:`确认并合并人物`,models_imported:`导入模型配置`,login:`管理员登录`,logout:`退出登录`},ve={person_summary:`人物摘要`,local_cli:`本机命令行`,persona:`persona 更新`,consolidation:`梦境整理`,goal_dedup:`目标去重判断`,learning:`学习`,admin:`管理员`,host:`宿主`,system:`系统`,scheduler:`后台调度`,maintenance:`维护`,local_import:`本机导入`},ye={person_summary:`人物摘要`,host_token:`宿主令牌`,backup:`备份`,persona:`persona 版本`,persona_attempt:`persona 生成任务`,goal:`目标`,memory:`记忆`,memory_bulk:`批量记忆操作`,batch:`批次`,entry:`入口`,subject:`人物`,subject_link:`人物联系`,model:`模型`,settings:`设置`,maintenance:`维护`,recall:`召回`,request:`请求`};function be({initialQuery:e=``}){let t=new URLSearchParams(e),[n,r]=(0,l.useState)({time_from:``,time_to:``,action:``,actor:``,object_type:t.get(`object_type`)||``,object_id:t.get(`object_id`)||``}),i=e=>new URLSearchParams(Object.entries(e).filter(([,e])=>!!e)).toString(),[a,o]=(0,l.useState)(()=>i(n)),[s,c]=(0,l.useState)(0),[u,d]=(0,l.useState)(``),f=y(`/operations?${a}&limit=30&offset=${s}`),p=(e,t)=>r(n=>({...n,[e]:t}));function m(e){if(e.preventDefault(),n.time_from&&n.time_to&&n.time_from>n.time_to){d(`开始日期不能晚于结束日期`);return}d(``),c(0),o(i(n)),f.refresh()}return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{className:`page-heading`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`p`,{className:`eyebrow`,children:`每次变更,均有记录`}),(0,x.jsx)(`h1`,{children:`操作记录`}),(0,x.jsx)(`p`,{children:`查看管理员、宿主与系统保存的操作摘要。`})]})}),(0,x.jsx)(`section`,{className:`panel`,children:(0,x.jsxs)(`form`,{onSubmit:m,className:`memory-filters`,children:[(0,x.jsxs)(`div`,{className:`filter-grid operation-filters`,children:[(0,x.jsxs)(`label`,{children:[`开始日期`,(0,x.jsx)(`input`,{type:`date`,value:n.time_from,onChange:e=>p(`time_from`,e.target.value)})]}),(0,x.jsxs)(`label`,{children:[`结束日期`,(0,x.jsx)(`input`,{type:`date`,value:n.time_to,onChange:e=>p(`time_to`,e.target.value)})]}),(0,x.jsxs)(`label`,{children:[`操作类型`,(0,x.jsxs)(`select`,{value:n.action,onChange:e=>p(`action`,e.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`全部类型`}),Object.entries(_e).map(([e,t])=>(0,x.jsx)(`option`,{value:e,children:t},e))]})]}),(0,x.jsxs)(`label`,{children:[`操作者`,(0,x.jsxs)(`select`,{value:n.actor,onChange:e=>p(`actor`,e.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`全部操作者`}),Object.entries(ve).map(([e,t])=>(0,x.jsx)(`option`,{value:e,children:t},e))]})]}),(0,x.jsxs)(`label`,{children:[`对象类型`,(0,x.jsxs)(`select`,{value:n.object_type,onChange:e=>p(`object_type`,e.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`全部对象`}),Object.entries(ye).map(([e,t])=>(0,x.jsx)(`option`,{value:e,children:t},e))]})]}),(0,x.jsxs)(`label`,{children:[`对象标识`,(0,x.jsx)(`input`,{value:n.object_id,maxLength:200,placeholder:`如记忆编号 8`,onChange:e=>p(`object_id`,e.target.value)})]})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`日期筛选按角色时区解释,结束日期包含当天;记录时间按本机时区显示。`}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`primary`,children:`筛选记录`}),(0,x.jsx)(`button`,{type:`button`,className:`secondary`,onClick:f.refresh,children:`刷新记录`})]})]})}),(u||f.error)&&(0,x.jsx)(A,{error:!0,children:u||f.error}),(0,x.jsx)(`div`,{className:`list-heading`,children:(0,x.jsx)(`span`,{children:f.data?`共 ${f.data.total} 条`:`正在读取…`})}),f.data?.items.length===0&&(0,x.jsx)(j,{title:`没有符合条件的操作记录`}),(0,x.jsx)(`div`,{className:`learning-list`,children:f.data?.items.map(e=>(0,x.jsxs)(`article`,{className:`panel operation-card`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:_e[e.action]||e.action}),(0,x.jsxs)(`span`,{className:`muted`,children:[`记录 #`,e.id]})]}),(0,x.jsxs)(`p`,{children:[w(e.created_at),` · `,ve[e.actor]||e.actor]}),e.object_type&&(0,x.jsxs)(`p`,{children:[`对象:`,ye[e.object_type]||e.object_type,e.object_id===null?``:` · ${e.object_id}`]}),(0,x.jsxs)(`details`,{children:[(0,x.jsx)(`summary`,{children:`查看记录详情`}),(0,x.jsx)(`pre`,{className:`record-json`,children:JSON.stringify(e.details,null,2)})]})]},e.id))}),f.data&&(0,x.jsx)(T,{total:f.data.total,offset:s,change:c})]})}var xe=[`chat`,`embedding`,`recall_judge`,`goal_dedup_judge`,`image_understanding`],Se={chat:`对话模型`,embedding:`Embedding 模型`,recall_judge:`召回判断模型`,goal_dedup_judge:`目标去重判断模型`,image_understanding:`图片理解模型`},Ce=()=>Intl.DateTimeFormat().resolvedOptions().timeZone||`Asia/Shanghai`,we=e=>e.inherited?{enabled:!1}:{enabled:e.enabled,base_url:e.base_url,model:e.model,dimensions:e.dimensions,reasoning_effort:e.reasoning_effort,...e.vision===void 0?{}:{vision:e.vision},...e.clearKey?{api_key:``}:e.key?{api_key:e.key}:{}};function Te({value:e,change:t}){return(0,x.jsxs)(`div`,{className:`form-grid`,children:[(0,x.jsxs)(`label`,{children:[`角色名`,(0,x.jsx)(`input`,{required:!0,maxLength:100,value:e.name,onChange:n=>t({...e,name:n.target.value})})]}),(0,x.jsxs)(`label`,{children:[`时区`,(0,x.jsx)(`input`,{required:!0,value:e.timezone||``,placeholder:`Asia/Shanghai`,onChange:n=>t({...e,timezone:n.target.value})})]}),(0,x.jsxs)(`label`,{className:`full-width`,children:[`背景材料(可选)`,(0,x.jsx)(`textarea`,{maxLength:16e3,rows:4,value:e.background,onChange:n=>t({...e,background:n.target.value})}),(0,x.jsx)(`small`,{children:`保存为“设定”的自我记忆,不会当作亲身经历。`})]})]})}function Ee({kind:e,value:t,change:n,settings:r}){let i=Se[e],a=r.model_source===`external`,o=r.presets.find(e=>e.id===`ark-glm`)?.reasoning_effort,[s,c]=(0,l.useState)(``),[u,d]=(0,l.useState)(!1),f=e===`recall_judge`||e===`goal_dedup_judge`,p=e===`image_understanding`,m=(f||p)&&t.inherited,h=m&&!r.models[e].inherited,y=m?r.models.chat.enabled&&!h:t.enabled,b=async()=>{d(!0),c(``);try{let n=await g(`/settings/models/${e}/test`,_(`POST`,a||m?{}:we(t)));c(`${n.message} · ${n.duration_ms} ms`)}catch(e){c(v(e))}finally{d(!1)}};return(0,x.jsxs)(`div`,{className:`model-fields`,children:[f||p?(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,disabled:a,checked:p?t.enabled&&!t.inherited:!t.inherited,onChange:e=>{c(``),n({...t,inherited:!e.target.checked&&(!p||!!r.models.chat.vision),enabled:!p||e.target.checked})}}),`单独配置`,i]}):(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,disabled:a,checked:t.enabled,onChange:e=>n({...t,enabled:e.target.checked})}),`启用`,i]}),m?(0,x.jsxs)(`p`,{children:[p?`沿用已保存的对话模型接口、模型、密钥和推理档位。当前模型:`:`沿用已保存的对话模型接口、模型和密钥,推理档位 high。当前模型:`,r.models.chat.model||`未配置`,`。`]}):(0,x.jsxs)(`fieldset`,{disabled:a||!t.enabled,children:[e!==`embedding`&&e!==`image_understanding`&&(0,x.jsxs)(`label`,{children:[i,`服务商预设`,(0,x.jsxs)(`select`,{defaultValue:``,onChange:e=>{let i=r.presets.find(t=>t.id===e.target.value);i&&n({...t,base_url:i.base_url,model:i.model,reasoning_effort:i.reasoning_effort})},children:[(0,x.jsx)(`option`,{value:``,children:`自定义 OpenAI 兼容服务`}),r.presets.map(e=>(0,x.jsx)(`option`,{value:e.id,children:e.name},e.id))]})]}),(0,x.jsxs)(`label`,{children:[i,`接口地址`,(0,x.jsx)(`input`,{type:`url`,required:t.enabled,value:t.base_url,placeholder:`https://…/v1`,onChange:e=>n({...t,base_url:e.target.value})})]}),(0,x.jsxs)(`label`,{children:[i,`模型名`,(0,x.jsx)(`input`,{required:t.enabled,value:t.model,maxLength:200,onChange:e=>n({...t,model:e.target.value})})]}),(0,x.jsxs)(`label`,{children:[i,` API key`,(0,x.jsx)(`input`,{"aria-label":`${i} API key`,type:`password`,autoComplete:`new-password`,value:t.key||``,placeholder:t.key_set?`已设置;留空保留`:`未设置(本地服务可留空)`,onChange:e=>n({...t,key:e.target.value,clearKey:!1})}),(0,x.jsxs)(`small`,{children:[`密钥`,t.key_set?`已设置`:`未设置`,`,保存后不回显。`]})]}),t.key_set&&(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:t.clearKey||!1,onChange:e=>n({...t,clearKey:e.target.checked,key:``})}),`移除已保存的密钥`]}),e===`chat`&&(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:!!t.vision,onChange:e=>n({...t,vision:e.target.checked})}),`支持图片输入(vision)`,(0,x.jsx)(`small`,{children:`对话模型支持图片输入。开启后,图片理解未单独配置时沿用对话模型。学习时是否直接看原图,请在“用量与学习”中设置。`})]}),e===`embedding`?(0,x.jsxs)(`label`,{children:[i,`向量维度`,(0,x.jsx)(`input`,{type:`number`,min:1,max:65536,value:t.dimensions??``,onChange:e=>n({...t,dimensions:e.target.value?Number(e.target.value):null})}),(0,x.jsx)(`small`,{children:`可选;更换模型或维度后须重新标定召回。`})]}):(0,x.jsxs)(`label`,{children:[i,`推理档位`,(0,x.jsx)(`input`,{"aria-label":`${i}推理档位`,value:t.reasoning_effort||``,maxLength:50,placeholder:f?`留空使用 high`:`可选;留空不发送`,onChange:e=>n({...t,reasoning_effort:e.target.value||null})}),o&&e!==`image_understanding`&&(0,x.jsxs)(`small`,{children:[`火山方舟 GLM 预设使用 `,o,`。`]}),f&&(0,x.jsx)(`small`,{children:`判断档位留空时,后端使用 high。`})]})]}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{type:`button`,disabled:u||!y,onClick:()=>void b(),children:u?`正在测试…`:`测试${i}连接`}),s&&(0,x.jsx)(`span`,{role:`status`,children:s})]}),h&&(0,x.jsx)(`p`,{className:`muted`,children:`保存沿用设置后可测试连接。`})]})}function De({done:e}){let t=y(`/settings`);return t.error?(0,x.jsxs)(A,{error:!0,children:[t.error,(0,x.jsx)(`button`,{onClick:t.refresh,children:`重新加载`})]}):t.data?(0,x.jsx)(Oe,{settings:t.data,done:e}):(0,x.jsx)(`p`,{role:`status`,children:`正在读取设置…`})}function Oe({settings:e,done:t}){let[n,r]=(0,l.useState)({...e.role,timezone:e.role.timezone||Ce()}),[i,a]=(0,l.useState)(e.models),[o,s]=(0,l.useState)(!1),[c,u]=(0,l.useState)(``);return(0,x.jsxs)(`form`,{onSubmit:async r=>{r.preventDefault(),s(!0),u(``);try{if(e.model_source===`local`)for(let t of[`chat`,`embedding`])(i[t].enabled||e.models[t].enabled)&&await g(`/settings/models/${t}`,_(`PUT`,we(i[t])));await g(`/setup/complete`,_(`POST`,n)),history.replaceState(null,``,`/#/trial`),t()}catch(e){u(v(e))}finally{s(!1)}},className:`setup-form`,children:[(0,x.jsxs)(`section`,{children:[(0,x.jsx)(`h2`,{children:`2 · 认识角色`}),(0,x.jsx)(Te,{value:n,change:e=>r({...e,timezone:e.timezone||Ce()})})]}),(0,x.jsxs)(`section`,{children:[(0,x.jsx)(`h2`,{children:`3 · 配置模型`}),(0,x.jsx)(`p`,{children:`对话模型用于学习和试用回复,也可以稍后再配。Embedding 可选,未配置时使用全文检索。`}),e.model_source===`external`&&(0,x.jsx)(A,{children:`配置来自外部文件,只读;请在外部文件中修改。`}),[`chat`,`embedding`].map(t=>(0,x.jsxs)(`div`,{className:`setup-model`,children:[(0,x.jsx)(`h3`,{children:t===`chat`?`对话模型`:`Embedding 模型(可选)`}),(0,x.jsx)(Ee,{kind:t,value:i[t],change:e=>a({...i,[t]:e}),settings:e})]},t))]}),!i.chat.enabled&&(0,x.jsx)(A,{children:`未配置模型,暂不学习;完成设置后仍可接收消息。`}),c&&(0,x.jsx)(A,{error:!0,children:c}),(0,x.jsx)(`button`,{className:`primary`,disabled:o,children:o?`正在保存…`:`完成设置并开始试用`})]})}function ke(){let e=y(`/settings`,2e3);return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{className:`page-heading`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`span`,{className:`eyebrow`,children:`管理`}),(0,x.jsx)(`h1`,{children:`设置`}),(0,x.jsx)(`p`,{children:`保存后对新的工作生效。`})]})}),e.error&&(0,x.jsx)(A,{error:!0,children:e.error}),e.data?(0,x.jsx)(Ae,{settings:e.data}):(0,x.jsx)(`p`,{children:`正在读取设置…`})]})}function Ae({settings:e}){let[t,n]=(0,l.useState)(e);(0,l.useEffect)(()=>n(e),[e]);let[r,i]=(0,l.useState)({...t.role,timezone:t.role.timezone||Ce()}),[a,o]=(0,l.useState)(t.models),[s,c]=(0,l.useState)(``),[u,d]=(0,l.useState)(``),[f,p]=(0,l.useState)(``),[m,h]=(0,l.useState)(!1),[y,b]=(0,l.useState)(String(t.state.stale_after_minutes)),S=(0,l.useRef)(!1),C=(0,l.useRef)(new Set);(0,l.useEffect)(()=>{S.current||b(String(t.state.stale_after_minutes))},[t.state.stale_after_minutes]);let w=async(e,t,r)=>{if(!m){h(!0),d(``),p(``);try{let i=await g(e,_(t,r));n(i),e===`/settings/state`&&(S.current=!1,b(String(i.state.stale_after_minutes)));for(let t of xe)e===`/settings/models/${t}`&&(C.current.delete(t),o(e=>Object.fromEntries(xe.map(n=>[n,n===t||!C.current.has(n)?i.models[n]:e[n]]))));return p(`已保存`),i}catch(t){return c(e),d(v(t)),null}finally{h(!1)}}};return(0,x.jsxs)(`div`,{className:`settings-grid`,children:[u&&![`/settings/limits`,`/settings/goals`,`/settings/consolidation`].includes(s)&&(0,x.jsx)(A,{error:!0,children:u}),f&&(0,x.jsx)(A,{children:f}),(0,x.jsxs)(`section`,{className:`panel settings-panel`,children:[(0,x.jsx)(`h2`,{children:`角色`}),(0,x.jsxs)(`form`,{onSubmit:e=>{e.preventDefault(),w(`/settings/role`,`PATCH`,r)},children:[(0,x.jsx)(Te,{value:r,change:e=>i({...e,timezone:e.timezone||Ce()})}),(0,x.jsx)(`button`,{disabled:m,className:`primary`,children:`保存角色`})]})]}),t.model_source===`external`&&(0,x.jsx)(A,{children:`配置来自外部文件,只读;数据库模型配置和 secrets.json 不用于本次服务。`}),xe.filter(e=>t.models[e]).map(e=>(0,x.jsxs)(`section`,{className:`panel settings-panel`,"aria-label":Se[e],children:[(0,x.jsx)(`h2`,{children:Se[e]}),(0,x.jsxs)(`p`,{children:[`当前状态:`,e===`image_understanding`&&!t.models[e].enabled?`未启用`:D(t.health[e]?.state||`configuration_error`)]}),e===`image_understanding`&&(0,x.jsxs)(`p`,{children:[t.models[e].inherited?`当前图片理解沿用对话模型。`:t.models[e].enabled?`当前图片理解使用独立配置。`:`当前图片理解未启用。`,`未单独配置且对话模型开启 vision 时会自动沿用;取消独立配置会恢复此规则。 测试连接会发送一张固定测试图片,健康状态与用量仍按图片理解用途记录。`]}),(0,x.jsxs)(`form`,{onSubmit:t=>{t.preventDefault(),w(`/settings/models/${e}`,`PUT`,we(a[e]))},children:[(0,x.jsx)(Ee,{kind:e,value:a[e],change:t=>{C.current.add(e),o({...a,[e]:t})},settings:t}),t.model_source===`local`&&(0,x.jsxs)(`button`,{className:`primary`,disabled:m,children:[`保存`,Se[e]]})]}),[`temporarily_unavailable`,`account_problem`].includes(t.health[e]?.state)&&(0,x.jsx)(`button`,{onClick:()=>void w(`/settings/models/${e}/retry`,`POST`,{}),children:`立即重试`}),e===`goal_dedup_judge`&&t.goal_dedup_judge&&(0,x.jsx)(pe,{value:t.goal_dedup_judge,busy:m,save:async e=>(await w(`/settings/goal-dedup-judge`,`PATCH`,e))?.goal_dedup_judge||null}),e===`recall_judge`&&(0,x.jsx)(je,{value:t.recall_judge})]},e)),(0,x.jsx)(I,{value:t,busy:m,saveError:s===`/settings/limits`?u:``,nativeImagesAvailable:t.models.chat.enabled&&t.models.chat.vision===!0,chatEnabled:t.models.chat.enabled,external:t.model_source===`external`,save:e=>w(`/settings/limits`,`PATCH`,e)}),(0,x.jsxs)(`section`,{className:`panel settings-panel`,children:[(0,x.jsx)(`h2`,{children:`当前状态`}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`宿主报告的活动与情绪供当前回复使用。超过设定分钟数未更新时,只标注“可能过时”,不会自动结束活动。`}),(0,x.jsxs)(`form`,{noValidate:!0,onSubmit:e=>{if(e.preventDefault(),m)return;let t=Number(y);if(!y.trim()||!Number.isInteger(t)||t<1||t>525600){p(``),c(`/settings/state`),d(`可能过时的分钟数须为 1—525600 的整数`);return}w(`/settings/state`,`PATCH`,{stale_after_minutes:t})},children:[(0,x.jsxs)(`label`,{children:[`可能过时的分钟数`,(0,x.jsx)(`input`,{"aria-label":`可能过时的分钟数`,type:`number`,required:!0,min:1,max:525600,step:1,disabled:m,value:y,onChange:e=>{S.current=!0,b(e.target.value),p(``)}}),(0,x.jsx)(`small`,{children:`1—525600 的整数,默认 30 分钟;严格超过此时长才标记。`})]}),(0,x.jsxs)(`p`,{className:`lifecycle-help`,children:[`保存后立即影响后续状态读取。`,(0,x.jsx)(`a`,{href:`#/state`,children:`查看当前状态`})]}),(0,x.jsx)(`button`,{className:`primary`,disabled:m,children:`保存当前状态设置`})]})]}),(0,x.jsx)(te,{value:t.goals,busy:m,saveError:s===`/settings/goals`?u:``,save:async e=>(await w(`/settings/goals`,`PATCH`,e))?.goals||null}),t.consolidation&&(0,x.jsx)(fe,{value:t.consolidation,saveError:s===`/settings/consolidation`?u:``,timezone:t.role.timezone,busy:m,save:async e=>(await w(`/settings/consolidation`,`PATCH`,e))?.consolidation||null}),(0,x.jsx)(he,{value:t.persona,busy:m,save:async e=>(await w(`/settings/persona`,`PATCH`,e))?.persona||null}),(0,x.jsxs)(`section`,{className:`panel settings-panel`,children:[(0,x.jsx)(`h2`,{children:`最近操作`}),(0,x.jsx)(`a`,{className:`text-button`,href:`#/operations`,children:`查看全部操作记录`}),(0,x.jsx)(`ul`,{className:`operations`,children:t.operations.map(e=>(0,x.jsxs)(`li`,{children:[(0,x.jsx)(`span`,{children:_e[e.action]||e.action}),(0,x.jsxs)(`small`,{children:[new Date(e.created_at).toLocaleString(`zh-CN`),` ·`,` `,ve[e.actor]||e.actor]})]},e.id))})]}),(0,x.jsx)(ge,{managedTime:!!t.consolidation,value:t.lifecycle,timezone:t.role.timezone})]})}function je({value:e}){let[t,n]=(0,l.useState)(e.enabled),[r,i]=(0,l.useState)(String(e.concurrency)),[a,o]=(0,l.useState)(String(e.queue_limit)),[s,c]=(0,l.useState)(!1),[u,d]=(0,l.useState)(``),[f,p]=(0,l.useState)(!1);async function m(e){if(e.preventDefault(),!s){if(p(!1),!r.trim()||!Number.isInteger(Number(r))||Number(r)<1||Number(r)>8){d(`召回判断并发须为 1—8 的整数`);return}if(!a.trim()||!Number.isInteger(Number(a))||Number(a)<0||Number(a)>64){d(`召回判断排队上限须为 0—64 的整数`);return}c(!0),d(``);try{await g(`/settings/recall-judge`,_(`PATCH`,{enabled:t,concurrency:Number(r),queue_limit:Number(a)})),p(!0)}catch(e){d(v(e))}finally{c(!1)}}}return(0,x.jsxs)(`form`,{className:`judge-settings`,onSubmit:m,noValidate:!0,children:[(0,x.jsx)(`h3`,{children:`判断开关与排队`}),(0,x.jsx)(`p`,{children:`每次回复准备最多判断 8 条相关记忆,总预算 10 秒(含排队)。判断失败或暂停时保留仍有效的原召回;人物要点不参与判断。`}),u&&(0,x.jsx)(A,{error:!0,children:u}),f&&(0,x.jsx)(A,{children:`召回判断设置已保存`}),(0,x.jsxs)(`fieldset`,{className:`lifecycle-fieldset`,disabled:s,children:[(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:t,onChange:e=>n(e.target.checked)}),`启用召回判断`]}),(0,x.jsx)(`p`,{className:`muted`,children:`关闭后保留基础召回。清除独立模型配置只会恢复沿用对话模型,不会关闭判断。`}),(0,x.jsxs)(`div`,{className:`form-grid`,children:[(0,x.jsxs)(`label`,{children:[`召回判断并发`,(0,x.jsx)(`input`,{type:`number`,min:1,max:8,step:1,required:!0,value:r,onChange:e=>i(e.target.value)})]}),(0,x.jsxs)(`label`,{children:[`召回判断排队上限`,(0,x.jsx)(`input`,{type:`number`,min:0,max:64,step:1,required:!0,value:a,onChange:e=>o(e.target.value)})]})]})]}),(0,x.jsx)(`button`,{className:`primary`,disabled:s,children:`保存召回判断设置`})]})}function Me({children:e}){let[t,n]=(0,l.useState)(null),[r,i]=(0,l.useState)(``),a=(0,l.useCallback)(()=>{g(`/session`).then(e=>{d(e.csrf_token),n(e),i(``)}).catch(e=>i(v(e)))},[]);return(0,l.useEffect)(()=>(a(),addEventListener(`iris-auth`,a),()=>removeEventListener(`iris-auth`,a)),[a]),t?.configured&&t.authenticated?e(a):(0,x.jsxs)(`main`,{className:`access-page`,children:[(0,x.jsxs)(`div`,{className:`access-brand`,children:[(0,x.jsx)(`span`,{"aria-hidden":!0,children:`✳`}),` Iris `,(0,x.jsx)(`small`,{children:`相处与记忆`})]}),(0,x.jsxs)(`div`,{className:`panel access-card`,children:[(0,x.jsx)(`span`,{className:`eyebrow`,children:`仅本机管理`}),(0,x.jsx)(`h1`,{children:t?.configured?`管理员登录`:`首次设置`}),r&&(0,x.jsxs)(A,{error:!0,children:[r,(0,x.jsx)(`button`,{onClick:a,children:`重新连接`})]}),t?t.authenticated?(0,x.jsx)(De,{done:a}):(0,x.jsx)(Ne,{creating:!t.admin_exists,configured:t.configured,setupCodeRequired:!!t.setup_code_required,done:a}):(0,x.jsx)(`p`,{children:`正在连接…`})]})]})}function Ne({creating:e,configured:t,setupCodeRequired:n,done:r}){let[i,a]=(0,l.useState)(``),[o,s]=(0,l.useState)(``),[c,u]=(0,l.useState)(``),[d,f]=(0,l.useState)(``),[p,m]=(0,l.useState)(!1);return(0,x.jsxs)(`form`,{className:`password-form`,onSubmit:async n=>{if(n.preventDefault(),e&&i!==o){f(`两次密码不一致`);return}m(!0),f(``);try{await g(e?`/setup/password`:`/login`,_(`POST`,{password:i,...e&&c?{setup_code:c}:{}})),a(``),s(``),u(``),t&&location.pathname!==`/`&&history.replaceState(null,``,`/#/trial`),r()}catch(e){f(v(e))}finally{m(!1)}},children:[(0,x.jsxs)(`p`,{children:[e?`1 · 先设置管理员密码,保护记忆与设置。`:`请输入管理员密码。`,!e&&!t&&`登录后继续完成首次设置。`]}),(0,x.jsxs)(`label`,{children:[`管理员密码`,(0,x.jsx)(`input`,{required:!0,type:`password`,"aria-label":`管理员密码`,minLength:8,maxLength:256,autoComplete:e?`new-password`:`current-password`,value:i,onChange:e=>a(e.target.value)}),(0,x.jsx)(`small`,{children:`至少 8 个字符。`})]}),e&&(0,x.jsxs)(`label`,{children:[`确认密码`,(0,x.jsx)(`input`,{required:!0,type:`password`,minLength:8,maxLength:256,autoComplete:`new-password`,value:o,onChange:e=>s(e.target.value)})]}),e&&n&&(0,x.jsxs)(`label`,{children:[`设置码`,(0,x.jsx)(`input`,{required:!0,type:`password`,"aria-label":`设置码`,maxLength:128,autoComplete:`off`,value:c,onChange:e=>u(e.target.value)}),(0,x.jsx)(`small`,{children:`从服务启动日志取得;仅首次设置使用。`})]}),d&&(0,x.jsx)(A,{error:!0,children:d}),(0,x.jsx)(`button`,{className:`primary`,disabled:p,children:p?`正在验证…`:e?`设置密码并继续`:`登录`})]})}function Pe({value:e}){return e.kind===`all`?(0,x.jsx)(`span`,{children:`全部入口`}):e.kind===`prefix`?(0,x.jsxs)(`span`,{children:[`入口前缀:`,(0,x.jsx)(`code`,{children:e.prefix})]}):(0,x.jsxs)(`span`,{children:[`入口列表:`,e.entries.map((e,t)=>(0,x.jsxs)(`span`,{children:[t>0&&`、`,(0,x.jsx)(`code`,{children:e})]},e))]})}function Fe(){let e=y(`/tokens`,5e3),[t,n]=(0,l.useState)(!1),[r,i]=(0,l.useState)(null),[a,o]=(0,l.useState)(!1),[s,c]=(0,l.useState)(``),[u,d]=(0,l.useState)(``);return(0,x.jsxs)(`section`,{className:`panel access-panel`,"aria-label":`宿主令牌`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:`宿主令牌`}),(0,x.jsx)(`button`,{className:`primary`,onClick:()=>{d(``),n(!0)},children:`创建宿主令牌`})]}),(0,x.jsx)(`p`,{children:`每个宿主使用自己的令牌。入口范围控制该宿主可以操作哪些入口,不是记忆可见范围设置。`}),e.data&&(0,x.jsxs)(`p`,{className:`muted`,children:[`每令牌限流:每秒 `,e.data.rate_limits.rate_per_second,` 次,突发上限`,` `,e.data.rate_limits.burst,` 次。`]}),u&&(0,x.jsx)(A,{children:u}),e.error&&(0,x.jsxs)(A,{error:!0,children:[e.error,(0,x.jsx)(`button`,{onClick:e.refresh,children:`重试令牌列表`})]}),!e.data&&!e.error&&(0,x.jsx)(`p`,{children:`正在读取令牌…`}),e.data?.items.length===0&&(0,x.jsx)(j,{title:`尚未创建宿主令牌`,children:`创建令牌后,将它配置到同一台电脑上的宿主程序。`}),(0,x.jsx)(`div`,{className:`access-records`,children:e.data?.items.map(e=>(0,x.jsxs)(`article`,{className:`access-record`,"aria-label":`${e.host} · ${e.id}`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h3`,{children:e.host}),(0,x.jsx)(M,{tone:e.revoked_at?``:`green`,children:e.revoked_at?`已撤销`:`有效`})]}),(0,x.jsx)(`p`,{children:(0,x.jsx)(Pe,{value:e.scope})}),(0,x.jsxs)(`dl`,{className:`access-facts`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`创建时间`}),(0,x.jsx)(`dd`,{children:(0,x.jsx)(N,{value:e.created_at})})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`最近使用`}),(0,x.jsx)(`dd`,{children:e.last_used_at?(0,x.jsx)(N,{value:e.last_used_at}):`尚未使用`})]}),e.revoked_at&&(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`撤销时间`}),(0,x.jsx)(`dd`,{children:(0,x.jsx)(N,{value:e.revoked_at})})]})]}),(0,x.jsxs)(`p`,{className:`muted`,children:[`令牌 ID:`,(0,x.jsx)(`code`,{children:e.id})]}),!e.revoked_at&&(0,x.jsxs)(`button`,{className:`danger-button`,onClick:()=>{c(``),i(e)},children:[`撤销 `,e.host,` 的令牌`]})]},e.id))}),(0,x.jsx)(`p`,{children:(0,x.jsx)(`a`,{href:`#/operations?object_type=host_token`,children:`查看令牌操作记录`})}),t&&(0,x.jsx)(Ie,{close:()=>n(!1),created:e.refresh}),r&&(0,x.jsx)(ee,{title:`撤销宿主令牌`,onClose:()=>i(null),closeDisabled:a,children:(0,x.jsxs)(`div`,{className:`access-dialog`,children:[(0,x.jsxs)(`p`,{children:[`即将撤销 `,(0,x.jsx)(`strong`,{children:r.host}),` 的令牌(`,r.id,`)。后续宿主请求立即失效,无法恢复此令牌;再次接入需要创建新令牌。`]}),s&&(0,x.jsx)(A,{error:!0,children:s}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{disabled:a,onClick:()=>i(null),children:`取消`}),(0,x.jsx)(`button`,{className:`danger-button`,disabled:a,onClick:async()=>{if(!a){o(!0),c(``);try{await g(`/tokens/${encodeURIComponent(r.id)}/revoke`,_(`POST`,{})),i(null),d(`令牌已撤销`),e.refresh()}catch(e){c(v(e))}finally{o(!1)}}},children:a?`正在撤销…`:`确认撤销`})]})]})})]})}function Ie({close:e,created:t}){let n=y(`/catalog`),[r,i]=(0,l.useState)(``),[a,o]=(0,l.useState)(`entries`),[s,c]=(0,l.useState)(``),[u,d]=(0,l.useState)(``),[f,p]=(0,l.useState)(!1),[m,h]=(0,l.useState)(``),[b,S]=(0,l.useState)(null),[C,w]=(0,l.useState)(``);return(0,x.jsx)(ee,{title:b?`令牌已创建 · 仅显示这一次`:`创建宿主令牌`,onClose:e,closeDisabled:f,children:(0,x.jsx)(`div`,{className:`access-dialog`,children:b?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(A,{children:[`请现在复制并交给 `,b.host,` `,`保存。关闭此窗口、离开页面或刷新后,无法再次查看令牌原文;丢失后只能撤销并重新创建。`]}),(0,x.jsxs)(`label`,{children:[`新令牌原文`,(0,x.jsx)(`textarea`,{className:`token-secret`,readOnly:!0,rows:3,spellCheck:!1,autoComplete:`off`,value:b.token,onFocus:e=>e.target.select()})]}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{className:`primary`,onClick:async()=>{try{await navigator.clipboard.writeText(b.token),w(`已复制,请妥善保存`)}catch{w(`无法自动复制,请选择令牌原文并手动复制。`)}},children:`复制令牌`}),(0,x.jsx)(`button`,{onClick:e,children:`关闭并清除原文`})]}),C&&(0,x.jsx)(A,{children:C})]}):(0,x.jsx)(`form`,{noValidate:!0,onSubmit:async e=>{if(e.preventDefault(),f)return;let n=s.split(/\r?\n/).filter(e=>e!==``);if(!r.trim()||[...r.trim()].length>100){h(`宿主名称须为 1—100 字,不能只含空白`);return}if(a===`entries`&&(!n.length||n.length>1e3||new Set(n).size!==n.length||n.some(e=>!e.trim()||[...e].length>200||e.includes(`\0`)))){h(`请填写 1—1000 个不重复的入口 ID,每行一个,每个为 1—200 字,不能只含空白。`);return}if(a===`prefix`&&(!u.trim()||[...u].length>200||u.includes(`\0`))){h(`入口前缀须为 1—200 字,不能只含空白`);return}let i=a===`entries`?{kind:a,entries:n}:a===`prefix`?{kind:a,prefix:u}:{kind:a};p(!0),h(``);try{let e=await g(`/tokens`,_(`POST`,{host:r.trim(),scope:i}));S(e),t()}catch(e){h(`${v(e)}。如请求已提交但结果不明确,请刷新列表核对;若令牌已创建却未取得原文,请撤销后重新创建。`),t()}finally{p(!1)}},children:(0,x.jsxs)(`fieldset`,{disabled:f,children:[(0,x.jsxs)(`label`,{children:[`宿主名称`,(0,x.jsx)(`input`,{value:r,maxLength:100,onChange:e=>i(e.target.value),placeholder:`例如:本机聊天机器人`})]}),(0,x.jsxs)(`label`,{children:[`入口范围`,(0,x.jsxs)(`select`,{value:a,onChange:e=>o(e.target.value),children:[(0,x.jsx)(`option`,{value:`entries`,children:`入口列表`}),(0,x.jsx)(`option`,{value:`prefix`,children:`入口前缀`}),(0,x.jsx)(`option`,{value:`all`,children:`全部入口`})]})]}),a===`entries`&&(0,x.jsxs)(x.Fragment,{children:[!!n.data?.entries.length&&(0,x.jsxs)(`label`,{children:[`添加已有入口`,(0,x.jsxs)(`select`,{value:``,onChange:e=>{e.target.value&&!s.split(/\r?\n/).includes(e.target.value)&&c(s?`${s}\n${e.target.value}`:e.target.value)},children:[(0,x.jsx)(`option`,{value:``,children:`选择入口加入列表`}),n.data.entries.map(e=>(0,x.jsxs)(`option`,{value:e.id,children:[e.name,` · `,e.id]},e.id))]})]}),(0,x.jsxs)(`label`,{children:[`入口 ID 列表`,(0,x.jsx)(`textarea`,{rows:4,value:s,onChange:e=>c(e.target.value),placeholder:`group-a +private-a`})]}),n.error&&(0,x.jsx)(`p`,{className:`muted`,children:`已有入口暂时无法读取,仍可手动填写入口 ID。`})]}),a===`prefix`&&(0,x.jsxs)(`label`,{children:[`入口 ID 前缀`,(0,x.jsx)(`input`,{value:u,onChange:e=>d(e.target.value),maxLength:200,placeholder:`例如:astrbot:`})]}),(0,x.jsx)(`p`,{children:`列表和前缀按入口 ID 原字符匹配,区分大小写;前缀不是通配符。可以授权尚未创建的入口。范围创建后不可修改,需要调整时请新建令牌并撤销旧令牌。`}),a===`all`&&(0,x.jsx)(A,{children:`此令牌可访问全部现有及今后创建的入口。`}),m&&(0,x.jsx)(A,{error:!0,children:m}),(0,x.jsx)(`button`,{className:`primary`,disabled:f,children:f?`正在创建…`:`创建并显示令牌`})]})})})})}function Le(e){return Number.isFinite(e)?e<1024?`${e} B`:e<1024**2?`${(e/1024).toFixed(1)} KiB`:`${(e/1024**2).toFixed(1)} MiB`:`未记录`}function Re(){let e=y(`/backups?limit=30`,5e3),[t,n]=(0,l.useState)(!1),[r,i]=(0,l.useState)(!1),[a,o]=(0,l.useState)(``),[s,c]=(0,l.useState)(null),u=(0,l.useRef)(null);return(0,l.useEffect)(()=>()=>u.current?.abort(),[]),(0,l.useEffect)(()=>()=>{s&&URL.revokeObjectURL(s.url)},[s]),(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`section`,{className:`panel access-panel`,"aria-label":`导出备份`,children:[(0,x.jsx)(`h2`,{children:`导出备份`}),(0,x.jsx)(`p`,{children:`服务运行时即可导出数据库与媒体的一致快照。备份包含原始消息和记忆,请妥善保存。`}),(0,x.jsxs)(`form`,{onSubmit:async n=>{if(n.preventDefault(),r)return;let a=new AbortController;u.current=a,i(!0),o(``),c(null);try{let{blob:e,headers:n}=await h(`/backups/export`,{..._(`POST`,{include_secrets:t}),signal:a.signal});if(a.signal.aborted)return;let r=n.get(`X-Iris-Backup-Includes-Secrets`)===`true`||t,i=n.get(`X-Iris-Backup-Id`),o=`iris-backup${i&&/^[a-f0-9]{32}$/.test(i)?`-${i}`:``}${r?`-with-secrets`:``}.zip`,s=URL.createObjectURL(e);c({url:s,filename:o,includesSecrets:r});let l=document.createElement(`a`);l.href=s,l.download=o,document.body.append(l),l.click(),l.remove()}catch(e){a.signal.aborted||o(v(e))}finally{a.signal.aborted||(i(!1),e.refresh())}},children:[(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:t,disabled:r,onChange:e=>n(e.target.checked),"aria-describedby":`backup-key-help`}),`包含模型密钥`]}),(0,x.jsx)(`p`,{id:`backup-key-help`,className:`muted`,children:`默认不包含模型密钥。选择包含时只导出本实例已保存的密钥,不包含外部模型配置文件或环境变量中的密钥。`}),t&&(0,x.jsxs)(A,{error:!0,children:[(0,x.jsx)(`strong`,{children:`包含模型密钥的 ZIP 不加密。`}),`请只保存到可信位置,不要分享或提交到代码仓库。`]}),(0,x.jsx)(`button`,{className:`primary`,disabled:r,children:r?`正在导出,请稍候…`:t?`导出并下载(含模型密钥)`:`导出并下载备份`})]}),a&&(0,x.jsxs)(A,{error:!0,children:[a,`。如未取得备份文件,请重新导出。`]}),s&&(0,x.jsxs)(A,{children:[`已生成备份并请求浏览器下载。若下载未开始,可`,(0,x.jsx)(`a`,{href:s.url,download:s.filename,children:`保存本次备份`}),`。`,s.includesSecrets&&(0,x.jsx)(`p`,{children:(0,x.jsx)(`strong`,{children:`本次备份含未加密的模型密钥,请勿分享。`})})]}),(0,x.jsx)(`h3`,{children:`最近的导出记录`}),(0,x.jsx)(`p`,{className:`muted`,children:`最多显示最近 30 次。记录不保留可再次下载的文件,需要时请重新导出。`}),e.error&&(0,x.jsxs)(A,{error:!0,children:[e.error,(0,x.jsx)(`button`,{onClick:e.refresh,children:`重试导出记录`})]}),!e.data&&!e.error&&(0,x.jsx)(`p`,{children:`正在读取导出记录…`}),e.data?.items.length===0&&(0,x.jsx)(j,{title:`还没有导出记录`}),(0,x.jsx)(`div`,{className:`access-records`,children:e.data?.items.map(e=>(0,x.jsxs)(`article`,{className:`access-record`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h4`,{children:(0,x.jsx)(N,{value:e.created_at})}),(0,x.jsx)(M,{tone:e.includes_model_secrets?`danger`:`green`,children:e.includes_model_secrets?`含模型密钥`:`不含模型密钥`})]}),(0,x.jsxs)(`p`,{children:[Le(e.size),` · `,e.file_count??`未记录`,` 个文件 · `,e.media_included?`含媒体`:`无媒体`]}),(0,x.jsxs)(`p`,{children:[`格式版本 `,e.format_version??`未记录`,` · 迁移版本`,` `,e.migration_version??`未记录`]}),(0,x.jsxs)(`p`,{children:[(e.trigger||e.purpose)===`scheduled`?`定时`:(e.trigger||e.purpose)===`pre_import`?`导入前自动备份`:`手动导出`,` `,`·`,` `,e.actor===`admin`?`管理员`:e.actor===`local_cli`?`本机命令行`:e.actor===`scheduler`?`调度器`:e.actor]}),(0,x.jsxs)(`p`,{className:`muted`,children:[`备份 ID:`,(0,x.jsx)(`code`,{children:e.backup_id})]})]},e.backup_id))}),(0,x.jsx)(`p`,{children:(0,x.jsx)(`a`,{href:`#/operations?object_type=backup`,children:`查看导出与导入操作记录`})})]}),(0,x.jsxs)(`section`,{className:`panel access-panel`,"aria-label":`离线导入`,children:[(0,x.jsx)(`h2`,{children:`从备份导入`}),(0,x.jsx)(`p`,{children:`导入需要停止 Iris 服务,在本机命令行操作。先确认备份与目标数据目录,再按以下步骤恢复。`}),(0,x.jsxs)(`ol`,{className:`import-steps`,children:[(0,x.jsx)(`li`,{children:`停止 Iris 服务和其他配置命令。`}),(0,x.jsxs)(`li`,{children:[`将示例路径替换为自己的路径。导入到新目录:`,(0,x.jsx)(`pre`,{children:(0,x.jsx)(`code`,{children:`uv run iris --data-dir /path/to/new-data backup import /path/to/backup.zip`})})]}),(0,x.jsxs)(`li`,{children:[`覆盖已有实例时,确认目标后添加覆盖参数:`,(0,x.jsx)(`pre`,{children:(0,x.jsx)(`code`,{children:`uv run iris --data-dir /path/to/iris-data backup import /path/to/backup.zip --confirm-overwrite`})}),`覆盖前会在数据目录旁自动备份现有实例;备份失败不会覆盖。`]}),(0,x.jsx)(`li`,{children:`导入完成后按原方式启动服务,检查记忆、媒体与模型设置。`})]}),(0,x.jsx)(A,{children:`不含模型密钥的备份导入后,需要重新配置密钥,或继续使用原有外部配置;不会沿用目标目录原来的模型密钥。`}),(0,x.jsx)(`p`,{children:`覆盖前会单独保存目标实例原有的模型密钥,以便人工恢复;请私密保存该归档。它不会自动配给导入后的模型设置。`}),e.data?.import_instructions&&(0,x.jsxs)(`p`,{className:`muted`,children:[`服务提供的导入说明:`,e.data.import_instructions]})]})]})}function ze(){let e=`http://127.0.0.1${location.port?`:${location.port}`:``}/api/v1`;return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{className:`page-heading`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`p`,{className:`eyebrow`,children:`接入与备份`}),(0,x.jsx)(`h1`,{children:`接入与数据`}),(0,x.jsx)(`p`,{children:`连接同一台电脑上的宿主,管理令牌与实例备份。`})]})}),(0,x.jsxs)(`section`,{className:`panel access-panel`,"aria-label":`接入说明`,children:[(0,x.jsx)(`h2`,{children:`把宿主连到 Iris`}),(0,x.jsxs)(`p`,{children:[`宿主程序与 Iris 在同一台电脑上运行。先创建令牌,在宿主配置中保存,再访问`,` `,(0,x.jsx)(`code`,{children:e}),`。端口与当前 Iris 服务一致。`]}),(0,x.jsxs)(`p`,{children:[`请求使用 `,(0,x.jsx)(`code`,{children:`Authorization: Bearer <令牌>`}),`。管理员登录会话不能代替宿主令牌;Iris 的宿主接口负责接收消息与准备回复,不生成对外回复。`]}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`a`,{href:`/docs`,target:`_blank`,rel:`noreferrer`,children:`打开接口文档`}),(0,x.jsx)(`a`,{href:`/openapi.json`,target:`_blank`,rel:`noreferrer`,children:`查看 OpenAPI 契约`})]})]}),(0,x.jsx)(Fe,{}),(0,x.jsx)(`div`,{className:`access-data-grid`,children:(0,x.jsx)(Re,{})})]})}function Be({value:e,openMemory:t}){return(0,x.jsxs)(`div`,{className:`trial-diagnostic`,"aria-label":`召回候选与判断分`,children:[(0,x.jsxs)(`p`,{className:`fine-print`,children:[`触发消息 #`,e.message_id,` · 准备于 `,w(e.prepared_at),(0,x.jsx)(`br`,{}),`召回记录 `,e.recall_id]}),!e.candidates.length&&(0,x.jsx)(`p`,{children:`本次没有额外召回候选。`}),e.candidates.map(e=>(0,x.jsxs)(`div`,{className:`entry-profile-evidence`,children:[(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>t(e.id),children:[`记忆 #`,e.id,` · 当时修订 `,e.revision]}),(0,x.jsxs)(`p`,{children:[e.reason===`person_highlight`?`人物要点(不参与判断)`:e.support==null?`判断分:未取得`:`判断分:${e.support} / 100`,` `,(0,x.jsx)(M,{children:{retained:`保留`,removed:`已去掉`,stale:`复核时失效`}[e.outcome]||e.outcome})]})]},e.id)),(0,x.jsx)(`p`,{className:`fine-print`,children:`以上是当次准备的诊断,链接打开记忆的当前详情;查看诊断不会再次召回或增加使用次数。`})]})}var Ve=[`image/png`,`image/jpeg`,`image/gif`,`image/webp`],He=e=>e>=1048576?`${(e/1048576).toFixed(1)} MiB`:`${Math.ceil(e/1024)} KiB`;function Ue({media:e}){return e?.length?(0,x.jsx)(`div`,{className:`message-media`,children:e.map((e,t)=>(0,x.jsx)(We,{item:e,number:t+1},e.id))}):null}function We({item:e,number:t}){let[n,r]=(0,l.useState)(!1),i=e.kind===`image`&&Ve.includes(e.content_type),a=i&&e.understanding_source===`unprocessed`&&!!e.completed_at,o=i&&e.understanding_source===`unprocessed`&&!e.completed_at,s=e.kind===`audio`?`音频`:e.kind===`video`?`视频`:`文件`;return(0,x.jsxs)(`div`,{className:`media-card`,children:[(0,x.jsx)(`a`,{href:e.file_url,target:`_blank`,rel:`noopener noreferrer`,"aria-label":i?`查看图片 ${t} 原图`:`查看${s}附件 ${t}`,children:i?n?(0,x.jsx)(`span`,{children:`图片不可用或已清理`}):(0,x.jsx)(`img`,{src:e.file_url,alt:`图片 ${t}`,loading:`lazy`,onError:()=>r(!0)}):`${s}附件 ${t}`}),(0,x.jsxs)(`small`,{children:[e.content_type,` · `,He(e.size_bytes)]}),(0,x.jsx)(`div`,{children:(0,x.jsx)(M,{tone:a||e.understanding_source===`refused`?`danger`:``,children:e.understanding_source_label})}),a&&(0,x.jsx)(`strong`,{className:`danger-text`,children:`理解失败`}),o&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`strong`,{children:`等待理解/理解中`}),(0,x.jsx)(`small`,{children:`未启用或暂停时也会保持等待。`})]}),(0,x.jsx)(`p`,{className:`media-description`,children:e.understanding_text}),e.completed_at&&(0,x.jsxs)(`small`,{children:[`完成时间:`,w(e.completed_at)]})]})}var Ge=10485760;function Ke(e,t){return t.throwIfAborted(),new Promise((n,r)=>{let i=new FileReader,a=()=>i.abort();i.onload=()=>n(String(i.result).split(`,`,2)[1]),i.onerror=()=>r(new f(`image_read_failed`,`无法读取图片 ${e.name},请重新选择`,0)),i.onabort=()=>r(new DOMException(`Aborted`,`AbortError`)),i.onloadend=()=>t.removeEventListener(`abort`,a),t.addEventListener(`abort`,a,{once:!0}),i.readAsDataURL(e)})}function qe(){let[e,t]=(0,l.useState)([]),n=(0,l.useRef)([]),r=(0,l.useRef)(new Map),i=e=>{n.current=e,t(e)};(0,l.useEffect)(()=>()=>{for(let e of n.current)URL.revokeObjectURL(e.url);r.current.clear()},[]);function a(e){if(n.current.length+e.length>100)throw new f(`too_many_images`,`每条消息最多发送 100 张图片`,0);for(let t of e){if(!Ve.includes(t.type))throw new f(`unsupported_media_type`,`${t.name}:仅支持 PNG、JPEG、GIF、WebP 图片`,0);if(t.size>Ge)throw new f(`media_too_large`,`${t.name}:图片超过单文件 10 MiB 上限`,413);if(!t.size)throw new f(`empty_image`,`${t.name}:图片文件为空`,0)}i([...n.current,...e.map(e=>({file:e,key:crypto.randomUUID(),url:URL.createObjectURL(e)}))])}function o(e){let t=n.current.find(t=>t.key===e);t&&URL.revokeObjectURL(t.url),r.current.delete(e),i(n.current.filter(t=>t.key!==e))}function s(){for(let e of n.current)URL.revokeObjectURL(e.url);r.current.clear(),i([])}async function c(e,t){let i=[],a=n.current;for(let[n,o]of a.entries()){e.throwIfAborted();let s=r.current.get(o.key);if(!s){t(`正在上传图片 ${n+1}/${a.length}…`);let i=await Ke(o.file,e);e.throwIfAborted();let c=await g(`/media`,{..._(`POST`,{content_type:o.file.type,data_base64:i}),signal:e});e.throwIfAborted(),s=c.id,r.current.set(o.key,s)}i.push(s)}return i}return{images:e,add:a,remove:o,clear:s,upload:c}}function Je({images:e,busy:t,add:n,remove:r}){return(0,x.jsxs)(`div`,{className:`trial-images`,children:[(0,x.jsxs)(`label`,{children:[`选择图片`,(0,x.jsx)(`input`,{type:`file`,accept:Ve.join(`,`),multiple:!0,disabled:t,onChange:e=>{n(Array.from(e.target.files||[])),e.target.value=``}})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`也可在消息框粘贴图片。PNG/JPEG/GIF/WebP,每张最多 10 MiB,可只发送图片。`}),!!e.length&&(0,x.jsx)(`ul`,{className:`draft-images`,"aria-label":`待发送图片`,children:e.map(e=>(0,x.jsxs)(`li`,{children:[(0,x.jsx)(`img`,{src:e.url,alt:`待发送图片:${e.file.name}`}),(0,x.jsxs)(`span`,{children:[e.file.name,` · `,He(e.file.size)]}),(0,x.jsx)(`button`,{type:`button`,disabled:t,onClick:()=>r(e.key),"aria-label":`移除图片 ${e.file.name}`,children:`移除`})]},e.key))})]})}function Ye(){let e=y(`/persona`,2e3),t=e.data;return(0,x.jsxs)(`section`,{className:`persona-summary`,"aria-label":`试用 persona`,children:[e.error&&(0,x.jsxs)(A,{error:!0,children:[e.error,`。persona 可能尚未更新。`,(0,x.jsx)(`button`,{onClick:e.refresh,children:`重试 persona`})]}),t?.needs_update&&(0,x.jsxs)(`p`,{children:[(0,x.jsx)(M,{tone:`warning`,children:`待更新`}),` `,t.stale_basis_count,` `,`条依据已失效,当前版本仍在使用。`]}),t?.pending&&(0,x.jsxs)(A,{children:[(0,x.jsx)(M,{tone:`warning`,children:`待确认`}),` `,(0,x.jsx)(`strong`,{children:`1 个 persona 候选等待确认`}),(0,x.jsxs)(`p`,{children:[`候选 v`,t.pending.id,` 尚未生效,当前版本仍在使用。`]}),(0,x.jsx)(`a`,{href:`#/persona?tab=current&focus=pending`,children:`查看候选与差异`})]}),(0,x.jsxs)(`details`,{open:!0,children:[(0,x.jsxs)(`summary`,{children:[`当前 persona`,t?.current?` · v${t.current.id}`:``]}),(0,x.jsx)(`p`,{className:`persona-content`,children:t?t.current?.content||`暂无 persona 版本`:`正在读取 persona…`})]}),(0,x.jsx)(`a`,{href:`#/persona`,children:`查看 persona 与自我`})]})}function Xe(e,t){let n=t.find(t=>t.id===e);return n?`${n.name}(${e})`:e}function Ze(e,t){return e.visibility===`shared`?`全部入口共享(默认)`:e.visibility===`entry_only`?`仅本入口`:e.visibility===`entries`?`指定入口:${e.visible_in.map(e=>Xe(e,t)).join(`、`)}`:`未返回,请重新加载`}function Qe(e,t){return e?e.shared?`全部入口`:e.visible_in.length?e.visible_in.map(e=>Xe(e,t)).join(`、`):`仅管理员可见`:`未返回,请重新加载详情`}function $e({entry:e,entries:t,value:n,busy:r,setBusy:i,onSaved:a}){let[o,s]=(0,l.useState)(n.visibility),[c,u]=(0,l.useState)(n.visible_in.filter(t=>t!==e.id)),[d,f]=(0,l.useState)(``);async function p(t){if(t.preventDefault(),!r){i(!0),f(``);try{await g(`/entries/${encodeURIComponent(e.id)}/visibility`,_(`PATCH`,{visibility:o,visible_in:o===`entries`?c:[]})),a()}catch(e){f(v(e))}finally{i(!1)}}}return(0,x.jsxs)(`form`,{className:`entry-settings-form entry-visibility-form`,onSubmit:p,children:[(0,x.jsx)(`h3`,{children:`记忆可见范围`}),(0,x.jsx)(`p`,{className:`muted`,id:`entry-visibility-help`,children:`这是查询时生效的设置。修改后立即影响该入口来源的全部已有记忆,无需重新学习,可随时改回。 多个来源或派生依据的限制共同生效,最终范围可在记忆详情查看。`}),d&&(0,x.jsx)(A,{error:!0,children:d}),(0,x.jsxs)(`fieldset`,{className:`lifecycle-fieldset`,disabled:r,children:[(0,x.jsxs)(`label`,{children:[`记忆可见范围`,(0,x.jsxs)(`select`,{value:o,"aria-describedby":`entry-visibility-help`,onChange:e=>s(e.target.value),children:[(0,x.jsx)(`option`,{value:`shared`,children:`全部入口共享(默认)`}),(0,x.jsx)(`option`,{value:`entry_only`,children:`仅本入口`}),(0,x.jsx)(`option`,{value:`entries`,children:`指定入口`})]})]}),o===`entries`&&(0,x.jsxs)(`fieldset`,{className:`lifecycle-fieldset`,children:[(0,x.jsx)(`legend`,{children:`选择可见入口(可多选)`}),(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:!0,disabled:!0}),Xe(e.id,[e]),` · 本入口始终包含`]}),t.filter(t=>t.id!==e.id).map(e=>(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:c.includes(e.id),onChange:t=>{u(t.target.checked?[...c,e.id]:c.filter(t=>t!==e.id))}}),Xe(e.id,t)]},e.id)),t.every(t=>t.id===e.id)&&(0,x.jsx)(`p`,{className:`muted`,children:`暂无其他入口可选。`})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`可见范围与下方的节奏、过滤分别保存。`}),(0,x.jsx)(`button`,{className:`primary`,disabled:r,children:r?`正在保存…`:`保存可见范围`})]})]})}var et={realtime:{name:`实时`,value:{count:4,idle_seconds:5,max_wait_seconds:60}},standard:{name:`标准`,value:{count:12,idle_seconds:600,max_wait_seconds:3600}},economy:{name:`省流`,value:{count:30,idle_seconds:1800,max_wait_seconds:14400}}};function tt(e){if(typeof e==`string`&&et[e])return et[e].name;try{let t=typeof e==`string`?JSON.parse(e):e;return`自定义 · ${t.count} 条 / 空闲 ${t.idle_seconds} 秒 / 最长 ${t.max_wait_seconds} 秒`}catch{return`未知节奏`}}function nt({value:e}){return e?(0,x.jsxs)(`div`,{className:`entry-filter-summary`,children:[(0,x.jsxs)(`p`,{children:[`最短字数:`,e.min_chars?`${e.min_chars} 字`:`不限制`]}),(0,x.jsxs)(`p`,{children:[`提及过滤:`,e.mention_only?`只学习提到角色的消息及前后各 ${e.context_messages} 条`:`关闭`]}),(0,x.jsxs)(`p`,{children:[`每小时批次上限:`,e.max_batches_per_hour||`不限制`]})]}):null}function rt({value:e}){return e?(0,x.jsxs)(`div`,{className:`entry-queue-wait`,children:[e.reason&&(0,x.jsx)(`p`,{className:`queue-reason`,children:e.reason===`hourly_batch_limit`?`达到每小时批次上限,消息排队等待`:e.reason===`filter_context`?`等待提及窗口的后续消息或空闲定案`:e.reason}),e.reason===`hourly_batch_limit`&&e.retry_at&&(0,x.jsxs)(`p`,{children:[`最早释放额度:`,w(e.retry_at),`(不是完成时间)`]}),e.batches_last_hour!==null&&(0,x.jsxs)(`p`,{className:`muted`,children:[`滚动 60 分钟已组成 `,e.batches_last_hour,` / `,e.limit,` 个批次`]}),(0,x.jsxs)(`p`,{className:`muted`,children:[`待过滤定案 `,e.filter_waiting_count,` 条 · 已过滤`,` `,e.filtered_count,` 条`]})]}):null}function it({entry:e,entries:t,onClose:n,onSaved:r}){let i=y(`/entries/${encodeURIComponent(e.id)}/settings`),[a,o]=(0,l.useState)(!1);return(0,x.jsxs)(ee,{title:`入口设置 · ${e.name}`,onClose:n,closeDisabled:a,children:[i.error&&(0,x.jsxs)(A,{error:!0,children:[i.error,(0,x.jsx)(`button`,{onClick:i.refresh,children:`重新加载`})]}),i.data?(0,x.jsxs)(x.Fragment,{children:[i.data.visibility?(0,x.jsx)($e,{entry:e,entries:t,value:i.data,busy:a,setBusy:o,onSaved:r}):(0,x.jsxs)(A,{error:!0,children:[`未读到可见范围,请重新加载入口设置。`,(0,x.jsx)(`button`,{onClick:i.refresh,children:`重新加载`})]}),(0,x.jsx)(at,{entry:e,value:i.data,busy:a,setBusy:o,onSaved:r})]}):(0,x.jsx)(`p`,{role:`status`,children:`正在读取入口设置…`})]})}function at({entry:e,value:t,busy:n,setBusy:r,onSaved:i}){let[a,o]=(0,l.useState)(typeof t.pace==`string`?t.pace:`custom`),s=typeof t.pace==`string`?et[t.pace].value:t.pace,[c,u]=(0,l.useState)({count:String(s.count),idle_seconds:String(s.idle_seconds),max_wait_seconds:String(s.max_wait_seconds)}),[d,f]=(0,l.useState)({min_chars:String(t.filters.min_chars),mention_only:t.filters.mention_only,context_messages:String(t.filters.context_messages),max_batches_per_hour:String(t.filters.max_batches_per_hour)}),[p,m]=(0,l.useState)(``),h=[[`min_chars`,`最短字数`,32768],[`context_messages`,`前后各 K 条消息`,100],[`max_batches_per_hour`,`每小时最多批次`,1e3]],y=[[`count`,`触发条数`,1e3],[`idle_seconds`,`空闲秒数`,86400],[`max_wait_seconds`,`最长等待秒数`,604800]];async function b(t){if(t.preventDefault(),!n){for(let[e,t,n]of h){let r=Number(d[e]);if(!d[e].trim()||!Number.isInteger(r)||r<0||r>n){m(`${t}须为 0—${n} 的整数`);return}}if(a===`custom`)for(let[e,t,n]of y){let r=Number(c[e]);if(!c[e].trim()||!Number.isInteger(r)||r<1||r>n){m(`${t}须为 1—${n} 的整数`);return}}r(!0),m(``);try{await g(`/entries/${encodeURIComponent(e.id)}/settings`,_(`PATCH`,{pace:a===`custom`?{count:Number(c.count),idle_seconds:Number(c.idle_seconds),max_wait_seconds:Number(c.max_wait_seconds)}:a,filters:{min_chars:Number(d.min_chars),mention_only:d.mention_only,context_messages:Number(d.context_messages),max_batches_per_hour:Number(d.max_batches_per_hour)}})),i()}catch(e){m(v(e))}finally{r(!1)}}}return(0,x.jsxs)(`form`,{className:`entry-settings-form`,onSubmit:b,noValidate:!0,children:[p&&(0,x.jsx)(A,{error:!0,children:p}),(0,x.jsxs)(`fieldset`,{className:`lifecycle-fieldset`,disabled:n,children:[(0,x.jsxs)(`label`,{children:[`学习节奏`,(0,x.jsxs)(`select`,{value:a,onChange:e=>o(e.target.value),children:[Object.entries(et).map(([e,t])=>(0,x.jsx)(`option`,{value:e,children:t.name},e)),(0,x.jsx)(`option`,{value:`custom`,children:`自定义`})]})]}),a===`custom`?(0,x.jsx)(`div`,{className:`form-grid`,children:y.map(([e,t,n])=>(0,x.jsxs)(`label`,{children:[t,(0,x.jsx)(`input`,{type:`number`,min:1,max:n,step:1,required:!0,value:c[e],onChange:t=>u({...c,[e]:t.target.value})})]},e))}):(0,x.jsxs)(`p`,{className:`muted`,children:[et[a].value.count,` 条 / 空闲`,` `,et[a].value.idle_seconds,` 秒 / 最长等待`,` `,et[a].value.max_wait_seconds,` 秒`]}),(0,x.jsx)(`h3`,{children:`高流量入口过滤`}),(0,x.jsxs)(`label`,{children:[`最短字数`,(0,x.jsx)(`input`,{"aria-label":`最短字数`,"aria-describedby":`min-chars-help`,type:`number`,min:0,max:32768,step:1,required:!0,value:d.min_chars,onChange:e=>f({...d,min_chars:e.target.value})})]}),(0,x.jsx)(`small`,{id:`min-chars-help`,children:`0 表示关闭;按正文去掉首尾空白后的字符数计算。`}),(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:d.mention_only,onChange:e=>f({...d,mention_only:e.target.checked})}),`只学习提到角色的消息`]}),(0,x.jsx)(`p`,{className:`muted`,children:`正文中出现角色名或已确认的角色别名才算提及;引用内容、发送者名字和“记住”本身不算。`}),(0,x.jsxs)(`label`,{children:[`前后各 K 条消息`,(0,x.jsx)(`input`,{"aria-label":`前后各 K 条消息`,"aria-describedby":`context-help`,type:`number`,min:0,max:100,step:1,required:!0,disabled:!d.mention_only,value:d.context_messages,onChange:e=>f({...d,context_messages:e.target.value})})]}),(0,x.jsx)(`small`,{id:`context-help`,children:`0 表示仅学习提及消息;按本入口原始消息顺序计数,等待后续消息或空闲后定案。`}),(0,x.jsxs)(`label`,{children:[`每小时最多批次`,(0,x.jsx)(`input`,{"aria-label":`每小时最多批次`,"aria-describedby":`hourly-help`,type:`number`,min:0,max:1e3,step:1,required:!0,value:d.max_batches_per_hour,onChange:e=>f({...d,max_batches_per_hour:e.target.value})})]}),(0,x.jsx)(`small`,{id:`hourly-help`,children:`0 表示关闭;按滚动 60 分钟内新组成的批次计数。立即学习也受此上限及提及窗口限制。`}),(0,x.jsx)(A,{children:`设置立即作用于尚未冻结的待处理消息,已组成批次保持原样。被过滤的消息仍保存并可用于近期对话,但不会进入学习、不算积压或记忆缺口;放宽或关闭过滤不会重新学习这些消息。`})]}),(0,x.jsx)(`button`,{className:`primary`,disabled:n,children:n?`正在保存…`:`保存节奏与过滤`})]})}var ot={no_candidates:`没有需要判断的相关候选`,host_disabled:`本次请求已关闭判断`,configuration_disabled:`设置中已关闭判断`,unconfigured:`未配置判断模型`,configuration_error:`模型配置错误`,configuration:`模型配置或响应无效`,configuration_changed:`调用期间模型配置发生变化`,invalid_key:`密钥无效`,authentication:`密钥无效`,account_problem:`模型账户异常`,account:`模型账户异常`,usage_limit:`达到每日 token 上限`,rate_limited:`服务商限流,正在退避`,temporarily_unavailable:`模型用途已暂停`,paused:`模型用途已暂停`,queue_full:`判断排队已满`,queue_timeout:`排队超时`,timeout:`超过判断总预算`,retryable:`模型连接暂时失败`,invalid_output:`判断输出格式无效`,content_rejection:`模型拒绝判断内容`};function st({value:e}){return e?(0,x.jsxs)(`div`,{className:`judgment-summary`,"aria-label":`本次召回判断`,children:[(0,x.jsxs)(`p`,{children:[(0,x.jsx)(`strong`,{children:`召回判断:`}),(0,x.jsx)(M,{tone:e.status===`degraded`?`danger`:e.status===`applied`?`green`:``,children:{applied:`正常`,disabled:`已关闭`,degraded:`降级`}[e.status]||e.status})]}),e.reason&&(0,x.jsx)(`p`,{children:ot[e.reason]||`判断原因:${e.reason}`}),(0,x.jsxs)(`p`,{children:[`被判断去掉 `,e.removed_memory_ids.length,` 条记忆`]}),!!e.stale_memory_ids?.length&&(0,x.jsxs)(`p`,{children:[`另有 `,e.stale_memory_ids.length,` 条记忆在复核时失效`]}),(0,x.jsxs)(`p`,{className:`muted`,children:[`耗时 `,C(e.duration_ms),` · 总预算 `,e.budget_seconds,` `,`秒(含排队)`]}),e.status===`degraded`&&(0,x.jsx)(`p`,{children:`本次保留仍有效的原召回。`})]}):(0,x.jsx)(`p`,{className:`fine-print`,children:`本次未返回召回判断状态。`})}function ct({value:e}){return e?(0,x.jsxs)(`div`,{className:`subject-annotations`,children:[e.possible_same_as.map(e=>(0,x.jsxs)(`p`,{children:[`可能是同一人:`,e.subjects.map(e=>e.name).join(`、`),` · 相信程度`,` `,e.belief,` / 100。`,(0,x.jsx)(`a`,{href:`#/people?id=${encodeURIComponent(e.subjects[0].id)}`,children:`核对人物联系`})]},e.link_id)),e.roleplay.map(e=>(0,x.jsxs)(`p`,{children:[`扮演关系(虚构):`,e.actor.name,` 扮演 `,e.character.name,` ·`,` `,e.worlds.map(e=>e??`场景未知`).join(`、`),` · 相信程度`,` `,e.belief,` / 100`]},e.link_id))]}):null}var lt={open:`未结束`,completed:`已完成`,abandoned:`已放弃`},ut={normal:`普通目标`,question:`询问`},dt={internal:`内部`,host:`宿主`,admin:`管理员`},ft={soon:`临近提醒`,due:`到期提醒`,overdue:`过期提醒`,immediate:`即时提醒`},pt={pending:`待取走`,taken:`已取走`,cancelled:`已取消`},mt={created:`新建`,possible_duplicate:`可能重复,已分别保留`,merged:`已合并`,pending:`去重待复核,已保留`},ht=(e,t)=>{let n=t?.people.find(t=>t.id===e);return n?`${n.name}(${e})`:e},gt=(e,t)=>e?t?.entries.find(t=>t.id===e)?.name||e:`未指定`;function _t({goal:e}){return(0,x.jsxs)(`div`,{className:`detail-badges goal-badges`,children:[(0,x.jsx)(M,{children:ut[e.kind]}),(0,x.jsx)(M,{children:lt[e.state]}),(0,x.jsx)(M,{children:dt[e.origin]}),e.overdue?(0,x.jsx)(M,{tone:`danger`,children:`已过期`}):e.due_soon?(0,x.jsx)(M,{tone:`purple`,children:`临近截止`}):null,e.possible_duplicate&&(0,x.jsx)(M,{tone:`warning`,children:`可能重复`}),e.basis_needs_review&&(0,x.jsx)(M,{tone:`warning`,children:`依据可能不成立`}),e.merged_into&&(0,x.jsx)(M,{children:`已合并`})]})}function vt({goal:e}){return e.kind===`question`?(0,x.jsx)(x.Fragment,{children:`询问不设截止时间`}):e.deadline?e.deadline_unresolved?(0,x.jsxs)(`span`,{className:`danger-text`,children:[e.deadline,`(时间待明确,不安排提醒)`]}):(0,x.jsx)(N,{value:e.deadline}):(0,x.jsx)(x.Fragment,{children:`未设截止时间`})}function yt({goal:e,catalog:t}){return(0,x.jsxs)(`dl`,{className:`goal-facts`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`截止时间`}),(0,x.jsx)(`dd`,{children:(0,x.jsx)(vt,{goal:e})})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`提醒提前量`}),(0,x.jsx)(`dd`,{children:e.kind===`question`?`询问不安排提醒`:`${e.effective_reminder_minutes} 分钟${e.reminder_minutes===null?`(使用默认值)`:``}`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`涉及的人`}),(0,x.jsx)(`dd`,{children:e.people.map(e=>ht(e,t)).join(`、`)||`未指定`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`产生入口`}),(0,x.jsx)(`dd`,{children:gt(e.entry_id,t)})]})]})}function bt({receipt:e,openGoal:t}){return(0,x.jsxs)(`div`,{className:`notice`,role:`status`,children:[(0,x.jsxs)(`p`,{children:[`已创建目标 #`,e.submitted_id,` · `,mt[e.dedup.status]]}),(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>t(e.goal.id),children:[`查看目标 #`,e.goal.id]}),e.dedup.target_id&&e.dedup.target_id!==e.goal.id&&(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>t(e.dedup.target_id),children:[`查看可能重复的目标 #`,e.dedup.target_id]})]})}function xt({goal:e,locked:t,openMemory:n,clear:r}){return e.basis_annotations?.length?(0,x.jsxs)(`section`,{className:`panel goals-panel`,"aria-label":`目标依据复核`,children:[(0,x.jsx)(`h2`,{children:`依据可能不成立`}),(0,x.jsx)(`p`,{className:`goal-help`,children:`依据记忆已变化,请核对目标是否仍然成立;标注不会自动结束目标。`}),e.basis_annotations.map(i=>(0,x.jsxs)(`article`,{className:`goal-operation`,children:[(0,x.jsx)(`p`,{className:`report-text`,children:i.text}),(0,x.jsxs)(`p`,{children:[`依据修订 `,i.basis_revision,` · 观察到修订`,` `,i.observed_revision??`未知`]}),(0,x.jsxs)(`p`,{className:`muted`,children:[`复核时间:`,(0,x.jsx)(N,{value:i.created_at})]}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>n(i.memory_id),children:[`查看依据记忆 #`,i.memory_id]}),i.observed_merged_into!=null&&(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>n(i.observed_merged_into),children:[`已合并到记忆 #`,i.observed_merged_into]}),!e.merged_into&&(0,x.jsxs)(`button`,{disabled:t,onClick:()=>r(i),children:[`清除依据标注 #`,i.id]})]})]},i.id))]}):null}function St({goal:e,openGoal:t}){let n=e.dedup_review;return(0,x.jsxs)(`section`,{className:`panel goals-panel`,"aria-label":`目标去重判断`,children:[(0,x.jsx)(`h2`,{children:`目标去重判断`}),n?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(M,{tone:n.state===`done`?`green`:`warning`,children:{pending:`待复核`,running:`复核中`,done:`已判断`,cancelled:`已取消`}[n.state]}),(0,x.jsxs)(`p`,{children:[`方法 `,n.method,` · 输入修订 `,n.input_revision,` · 尝试`,` `,n.attempts,` 次`]}),n.result.status&&(0,x.jsxs)(`p`,{children:[`判断结果:`,mt[n.result.status]||n.result.status]}),n.result.reason&&(0,x.jsx)(`p`,{children:B(n.result.reason)}),n.result.target_id!=null&&(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>t(n.result.target_id),children:[`查看判断关联目标 #`,n.result.target_id]}),n.next_attempt_at&&(0,x.jsxs)(`p`,{children:[`下次复核:`,(0,x.jsx)(N,{value:n.next_attempt_at})]}),(0,x.jsxs)(`p`,{className:`muted`,children:[`最后更新:`,(0,x.jsx)(N,{value:n.updated_at})]}),[`pending`,`running`].includes(n.state)&&(0,x.jsx)(`p`,{className:`goal-help`,children:`已保留目标,等待模型复核;待复核不表示已经判定重复。`})]}):(0,x.jsx)(`p`,{className:`goal-help`,children:`没有异步复核任务记录。可能重复关系以当前目标标记为准。`}),(0,x.jsx)(`p`,{className:`goal-help`,children:`管理员手动创建的目标不会自动合并,判断为重复也只标记“可能重复”。`})]})}var Ct=e=>{let t=new Date(e);if(!Number.isFinite(t.getTime()))return``;let n=e=>String(e).padStart(2,`0`);return`${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())}T${n(t.getHours())}:${n(t.getMinutes())}:${n(t.getSeconds())}`};function wt({goal:e,catalog:t,busy:n,locked:r=!1,submit:i,cancel:a}){let[o,s]=(0,l.useState)(e?.content||``),[c,u]=(0,l.useState)(e?.kind||`normal`),[d,f]=(0,l.useState)(e?`keep`:`none`),[p,m]=(0,l.useState)(``),[h,g]=(0,l.useState)(e?.deadline&&!e.deadline_unresolved?Ct(e.deadline):``),[_,v]=(0,l.useState)(e?.reminder_minutes?.toString()??``),[y,b]=(0,l.useState)([]),[S,C]=(0,l.useState)(``),[w,T]=(0,l.useState)(``);function E(t){if(t.preventDefault(),n||r)return;if(T(``),!o.trim()||o.trim().length>4e3){T(`目标正文须为 1—4000 个字符且不为空白`);return}let a={content:o.trim()};if(c===`normal`){if(_.trim()&&(!Number.isInteger(Number(_))||Number(_)<0||Number(_)>525600)){T(`提醒提前量须为 0—525600 的整数,留空使用默认值`);return}if((!e||_!==(e.reminder_minutes?.toString()??``))&&(a.reminder_minutes=_.trim()?Number(_):null),d===`date`){if(!/^\d{4}-\d{2}-\d{2}$/.test(p)||!Number.isFinite(Date.parse(p))||new Date(p).toISOString().slice(0,10)!==p){T(`请选择有效的截止日期`);return}a.deadline=p}else if(d===`datetime`){let e=new Date(h);if(!h||!Number.isFinite(e.getTime())||Ct(e.toISOString())!==(h.length===16?h+`:00`:h)){T(`请选择有效的截止时间`);return}a.deadline=e.toISOString()}else d===`none`&&(a.deadline=null)}else e||(a.deadline=null,a.reminder_minutes=null);if(!e){if(y.length>100){T(`涉及的人最多 100 位`);return}Object.assign(a,{kind:c,people:y,entry_id:S||null})}i(a)}return(0,x.jsxs)(`form`,{className:`goal-form`,onSubmit:E,noValidate:!0,children:[w&&(0,x.jsx)(A,{error:!0,children:w}),(0,x.jsxs)(`fieldset`,{className:`lifecycle-fieldset`,disabled:n||r,children:[!e&&(0,x.jsxs)(`label`,{children:[`创建类型`,(0,x.jsxs)(`select`,{value:c,onChange:e=>u(e.target.value),children:[(0,x.jsx)(`option`,{value:`normal`,children:`普通目标`}),(0,x.jsx)(`option`,{value:`question`,children:`询问`})]})]}),(0,x.jsxs)(`label`,{children:[`目标正文`,(0,x.jsx)(`textarea`,{required:!0,maxLength:4e3,rows:4,value:o,onChange:e=>s(e.target.value)})]}),c===`question`?(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`询问没有截止时间和提醒,由宿主决定何时询问。`}):(0,x.jsxs)(x.Fragment,{children:[e&&(0,x.jsxs)(`p`,{children:[`当前截止时间:`,(0,x.jsx)(vt,{goal:e})]}),(0,x.jsxs)(`div`,{className:`form-grid`,children:[(0,x.jsxs)(`label`,{children:[`截止方式`,(0,x.jsxs)(`select`,{value:d,onChange:e=>f(e.target.value),children:[e&&(0,x.jsx)(`option`,{value:`keep`,children:`保持当前截止时间`}),(0,x.jsx)(`option`,{value:`none`,children:`不设截止时间`}),(0,x.jsx)(`option`,{value:`date`,children:`指定日期`}),(0,x.jsx)(`option`,{value:`datetime`,children:`指定日期和时间`})]})]}),(0,x.jsxs)(`label`,{children:[`提醒提前量(分钟)`,(0,x.jsx)(`input`,{type:`number`,min:0,max:525600,step:1,value:_,placeholder:`留空使用默认值`,onChange:e=>v(e.target.value)})]}),d===`date`&&(0,x.jsxs)(`label`,{children:[`截止日期`,(0,x.jsx)(`input`,{"aria-label":`截止日期`,type:`date`,required:!0,value:p,onChange:e=>m(e.target.value)}),(0,x.jsx)(`small`,{children:`按角色时区当天 23:59:59 截止。`})]}),d===`datetime`&&(0,x.jsxs)(`label`,{children:[`截止日期和时间`,(0,x.jsx)(`input`,{"aria-label":`截止日期和时间`,type:`datetime-local`,step:1,required:!0,value:h,onChange:e=>g(e.target.value)}),(0,x.jsxs)(`small`,{children:[`按本机时区`,` `,Intl.DateTimeFormat().resolvedOptions().timeZone,` `,`输入;保存后按角色时区显示。`]})]})]}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`留空提前量使用默认值;0 表示到期时提醒。修改期限或提前量会更新尚未取走的提醒,已取走的记录保留。`})]}),!e&&(0,x.jsxs)(`div`,{className:`form-grid`,children:[(0,x.jsxs)(`label`,{children:[`涉及的人`,(0,x.jsx)(`select`,{"aria-label":`涉及的人`,multiple:!0,size:4,value:y,onChange:e=>b(Array.from(e.target.selectedOptions,e=>e.value)),children:t?.people.filter(e=>![`self`,`scene`].includes(e.id)&&![`self`,`scene`].includes(e.kind||``)).map(e=>(0,x.jsx)(`option`,{value:e.id,children:ht(e.id,t)},e.id))}),(0,x.jsx)(`small`,{children:`可多选,也可不指定。`})]}),(0,x.jsxs)(`label`,{children:[`记录产生入口`,(0,x.jsxs)(`select`,{"aria-label":`记录产生入口`,value:S,onChange:e=>C(e.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`不指定`}),t?.entries.map(e=>(0,x.jsxs)(`option`,{value:e.id,children:[e.name,` · `,e.id]},e.id))]}),(0,x.jsx)(`small`,{children:`仅记录产生位置,所有入口共享此目标。`})]})]}),!e&&(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`管理员创建的目标独立保留;发现相似项只标“可能重复”,由管理员明确合并或驳回。`}),(0,x.jsx)(`div`,{className:`actions`,children:(0,x.jsx)(`button`,{className:`primary`,children:n?`正在保存…`:e?`保存目标`:`创建`})})]}),(0,x.jsx)(`button`,{type:`button`,className:`secondary`,disabled:n,onClick:a,children:`取消`})]})}function Tt({note:e,openGoal:t}){return(0,x.jsxs)(`article`,{className:`notification-card`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h3`,{children:ft[e.reminder_kind]}),(0,x.jsx)(M,{tone:e.status===`pending`?`purple`:``,children:pt[e.status]})]}),(0,x.jsx)(`p`,{className:`goal-content`,children:e.content}),(0,x.jsxs)(`div`,{className:`goal-time-lines`,children:[(0,x.jsxs)(`p`,{children:[`发布时间:`,(0,x.jsx)(N,{value:e.published_at})]}),(0,x.jsxs)(`p`,{children:[`计划时间:`,(0,x.jsx)(N,{value:e.scheduled_at})]}),e.deadline_at&&(0,x.jsxs)(`p`,{children:[`发布时的截止时间:`,(0,x.jsx)(N,{value:e.deadline_at})]}),e.taken_at&&(0,x.jsxs)(`p`,{children:[`取走时间:`,(0,x.jsx)(N,{value:e.taken_at})]}),e.cancelled_at&&(0,x.jsxs)(`p`,{children:[`取消时间:`,(0,x.jsx)(N,{value:e.cancelled_at})]})]}),(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>t(e.goal_id),children:[`查看目标 #`,e.goal_id]})]})}function Et({goalId:e,openGoal:t}){let[n,r]=(0,l.useState)(e?``:`pending`),[i,a]=(0,l.useState)(0),o=new URLSearchParams({limit:`30`,offset:String(i)});n&&o.set(`status`,n),e&&o.set(`goal_id`,String(e));let s=y(`/notifications?${o}`,i===0?2e3:0);return(0,x.jsxs)(`section`,{className:`panel goals-panel`,"aria-label":`提醒列表`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:e?`该目标的提醒`:`提醒`}),(0,x.jsx)(`button`,{className:`text-button`,onClick:s.refresh,children:`刷新提醒`})]}),(0,x.jsx)(`p`,{className:`goal-help`,children:`“已取走”只表示宿主拿到了提醒,不代表已送达用户或目标完成。此处查看不会取走提醒。`}),(0,x.jsxs)(`label`,{className:`notification-filter`,children:[`提醒状态`,(0,x.jsxs)(`select`,{value:n,onChange:e=>{r(e.target.value),a(0)},children:[(0,x.jsx)(`option`,{value:``,children:`全部`}),Object.entries(pt).map(([e,t])=>(0,x.jsx)(`option`,{value:e,children:t},e))]})]}),s.error&&(0,x.jsxs)(A,{error:!0,children:[s.error,`。`,s.data&&`以下为上次读取结果。`]}),!s.data&&!s.error&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取提醒…`}),s.data?.items.length===0&&(0,x.jsx)(j,{title:`当前范围没有提醒`,children:`有截止时间的普通目标会在临近、到期时产生提醒;询问不安排提醒。`}),s.data?.items.map(e=>(0,x.jsx)(Tt,{note:e,openGoal:t},e.id)),s.data&&(0,x.jsx)(T,{total:s.data.total,offset:i,change:a})]})}var Dt=`合并待核对(双方互有细节,不代表事实矛盾)`;function Ot({details:e,ids:t,openMemory:n,disabled:r=!1}){return(0,x.jsxs)(`div`,{className:`merge-detail-review`,children:[(0,x.jsx)(`p`,{children:`双方各有另一条没有的细节,未自动合并。采纳只确认建议,不执行合并,也不改正文和相信程度。`}),[`a`,`b`].map((i,a)=>(0,x.jsxs)(`div`,{children:[t[a]==null?(0,x.jsxs)(`strong`,{children:[`第 `,a+1,` 条记忆的独有细节`]}):(0,x.jsxs)(`button`,{disabled:r,className:`text-button`,onClick:()=>n(t[a]),children:[`记忆 #`,t[a],` 的独有细节`]}),e?.[i]?.length?(0,x.jsx)(`ul`,{children:e[i].map((e,t)=>(0,x.jsx)(`li`,{children:e},t))}):(0,x.jsx)(`p`,{className:`muted`,children:`未保存独有细节,请核对报告正文。`})]},i))]})}var kt={relationship:`与我的关系`,fact:`稳定事实`,preference:`偏好与习惯`,recent:`近期重要事项`},At={published:`已发布`,candidate:`待确认`,rejected:`已拒绝`,failed:`失败`,skipped:`已跳过`,conflict:`版本或依据冲突`,running:`生成中`};function jt(e){return{memory_purged:`依据记忆已彻底清除`,memory_unavailable:`依据记忆已遗忘或删除`,visibility_changed:`依据不再满足全部入口共享条件`,no_longer_related:`依据不再与此人物相关`,memory_changed:`依据记忆已修订`,subject_changed:`人物资料或关联发生变化`,subject_merged:`人物已合并`,subject_unavailable:`此人物当前不可生成摘要`,subject_kind:`此类主体不生成人物摘要`,time_range_expired:`近期事项已到期`,purged:`因彻底清除而清空`,disabled:`人物摘要开关已关闭`,insufficient_memories:`相关全局有效记忆不足(至少需要 8 条)`,no_changes_since_attempt:`上次被拒或确定性失败后,尚无新依据`,not_due:`尚未达到更新条件`,generation_in_progress:`管理员生成中,本轮已跳过`,interrupted:`任务被中断,可以重试`,invalid_output:`模型输出格式无效`,invalid_check_output:`模型检查格式无效`,invalid_check_item:`逐条检查格式无效`,too_many_deleted:`检查累计删去超过一半的模型条目`,empty:`没有可保留的摘要内容`,too_many_items:`条目数超出预算`,too_long:`摘要字数超出预算`,token_budget:`摘要 token 超出预算`,invalid_item_or_references:`条目或引用依据无效`,missing_time_range:`近期事项缺少时间范围`,invalid_or_expired_time_range:`时间范围无效或已经到期`,unexpected_time_range:`非近期事项带有不适用的时间范围`,too_many_relationships:`与我的关系最多保留一条`,timeout:`模型请求超时,可以重试`,retryable:`模型暂时失败,可以重试`,temporary_unavailable:`模型暂时不可用,可以稍后重试`,paused:`模型用途已暂停`,usage_limit:`已达到每日用量上限`,call_budget:`剩余模型调用预算不足`,unconfigured:`模型尚未配置`,configuration:`模型配置无效`,account:`模型账户不可用`,refused:`模型拒绝处理`,unexpected_error:`生成过程中发生错误,可以重试`,superseded:`已被新候选或编辑取代`,administrator_rejected:`管理员拒绝`,evidence_changed:`依据已变化,请刷新后重试`,current_version_changed:`当前版本已变化,请刷新后重试`,settings_or_subject_changed:`设置或人物资料已变化,请刷新后重试`,settings_changed:`设置已变化,请刷新后重试`,candidate_changed:`候选已变化,请刷新后重试`}[e]||e}var Mt=(e,t)=>`#/people?id=${encodeURIComponent(e)}${t?`&summary_version=${t}`:``}`;function Nt({basis:e,catalog:t,openMemory:n}){let r=y(e.memory?`/memories/${e.memory_id}`:null,5e3),i=r.data,a=[...new Set([i?.entry_id,...(i?.sources||[]).map(e=>e.message?.entry_id)].filter(e=>!!e))];return(0,x.jsxs)(`article`,{className:`persona-evidence`,children:[(0,x.jsxs)(`h4`,{children:[`记忆 #`,e.memory_id]}),(0,x.jsxs)(`p`,{className:`muted`,children:[`记录修订 `,e.revision,` ·`,` `,e.memory?`当前修订 ${e.memory.revision} · ${E(e.memory.lifecycle)}`:`当前记忆不可用`]}),(0,x.jsx)(`p`,{className:`persona-content`,children:e.content_at_revision??`该修订正文不可用`}),i&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{className:`muted`,children:[`当前记忆记录时间:`,(0,x.jsx)(N,{value:i.created_at}),`;事件时间:`,(0,x.jsx)(N,{value:i.event_time??null})]}),(0,x.jsxs)(`p`,{className:`muted`,children:[`当前来源入口类型:`,a.length?a.map(e=>{let n=t?.entries.find(t=>t.id===e);return n?`${{group:`群聊`,private:`私聊`}[n.kind]||n.kind} · ${n.name}`:`入口 ${e}(类型暂不可用)`}).join(`;`):i.sources.some(e=>e.kind===`initial_setting`)?`初始设定`:`未记录入口`]}),(0,x.jsx)(`small`,{children:`以上时间和入口来自当前记忆详情,不是该版本生成时的历史快照。`})]}),r.loading&&(0,x.jsx)(`p`,{children:`正在读取当前记忆元数据…`}),r.error&&(0,x.jsxs)(A,{error:!0,children:[r.error,(0,x.jsx)(`button`,{onClick:r.refresh,children:`重试记忆元数据`})]}),(0,x.jsxs)(`button`,{className:`text-button`,disabled:!e.memory,onClick:()=>n(e.memory_id),children:[`查看记忆 #`,e.memory_id]})]})}function Pt({sentence:e,index:t,catalog:n,openMemory:r}){let[i,a]=(0,l.useState)(!1),o=e.admin_written||e.origin===`admin`;return(0,x.jsxs)(`li`,{className:`persona-sentence`,children:[(0,x.jsxs)(`div`,{className:`persona-sentence-line`,children:[(0,x.jsxs)(`span`,{className:`muted`,children:[t+1,`.`]}),(0,x.jsx)(`p`,{children:e.text}),(0,x.jsx)(M,{tone:o?`warning`:``,children:o?`手写`:re[e.origin]||e.origin})]}),(0,x.jsxs)(`button`,{className:`text-button`,"aria-expanded":i,onClick:()=>a(!i),children:[i?`收起`:`展开`,`第 `,t+1,` 句依据`]}),i&&(0,x.jsxs)(`div`,{className:`persona-basis`,children:[(0,x.jsxs)(`p`,{children:[`该句的依据日期:`,e.dates.length?e.dates.join(`、`):`未记录日期`,`(`,e.date_count,` 个日期)`,e.initial_setting&&` · 含初始设定`]}),e.basis.map(e=>(0,x.jsx)(Nt,{basis:e,catalog:n,openMemory:r},`${e.memory_id}-${e.revision}`)),!e.basis.length&&(0,x.jsx)(`p`,{className:`muted`,children:o?`管理员手写内容,没有记忆依据;手写标记不代表模型检查通过。`:`初始模板,没有逐句记忆依据。`})]})]})}var Ft=e=>typeof e==`object`&&e&&!Array.isArray(e)?e:null;function It({value:e,index:t}){let n=Ft(e);if(!n)return(0,x.jsxs)(`li`,{children:[`第 `,t+1,` 句:检查结果格式不完整`]});let r=(e,t,n)=>typeof e==`boolean`?e?t:n:`未报告`;return(0,x.jsxs)(`li`,{children:[`第 `,typeof n.index==`number`?n.index:t+1,` `,`句:依据支持 `,r(n.supported,`是`,`否`),`;虚构`,` `,r(n.fabricated,`是`,`否`),`;场景限定`,` `,r(n.scene_qualified,`是`,`否`),typeof n.reason==`string`&&(0,x.jsx)(`p`,{children:n.reason}),Array.isArray(n.violations)&&n.violations.some(e=>typeof e==`string`)&&(0,x.jsxs)(`p`,{children:[`违反要求:`,n.violations.filter(e=>typeof e==`string`).join(`;`)]})]})}function Lt({version:e}){let{checks:t}=e,n=Ft(t.model);return(0,x.jsxs)(`div`,{className:`persona-checks`,children:[(0,x.jsx)(`h3`,{children:`检查结果`}),(0,x.jsxs)(`p`,{children:[t.passed===!0?`综合检查通过`:t.passed===!1?`综合检查未通过`:`没有综合检查结论`,t.administrator_published&&` · 管理员直接发布`]}),(0,x.jsx)(`p`,{className:`muted`,children:`手写标记表示内容的来源,不代表模型检查通过。`}),(0,x.jsx)(`h4`,{children:`确定性检查`}),(0,x.jsx)(`p`,{children:t.deterministic?.passed===!0?`通过`:t.deterministic?.passed===!1?`未通过`:`没有确定性检查记录`}),!!t.deterministic?.errors?.length&&(0,x.jsx)(`ul`,{children:t.deterministic.errors.map((e,t)=>(0,x.jsx)(`li`,{children:ae(e)},t))}),!!t.deterministic?.warnings?.length&&(0,x.jsx)(`ul`,{className:`muted`,children:t.deterministic.warnings.map((e,t)=>(0,x.jsxs)(`li`,{children:[`提示:`,ae(e)]},t))}),(0,x.jsx)(`h4`,{children:`模型检查`}),t.model==null?(0,x.jsx)(`p`,{children:`未进行模型检查`}):n?(0,x.jsxs)(x.Fragment,{children:[typeof n.change_degree==`string`&&(0,x.jsxs)(`p`,{children:[`判断的变化程度:`,R[n.change_degree]||n.change_degree]}),typeof n.reason==`string`&&(0,x.jsx)(`p`,{children:n.reason}),Array.isArray(n.sentences)?(0,x.jsx)(`ul`,{children:n.sentences.map((e,t)=>(0,x.jsx)(It,{value:e,index:t},t))}):(0,x.jsx)(`p`,{children:`逐句检查结果格式不完整`})]}):(0,x.jsx)(`p`,{children:`模型检查结果格式不完整`}),!!t.model_errors?.length&&(0,x.jsx)(`ul`,{children:t.model_errors.map((e,t)=>(0,x.jsx)(`li`,{children:ae(e)},t))}),t.admin_content_removed_or_changed&&(0,x.jsx)(A,{children:`候选删去或改动了手写内容,变化程度按“大”处理。默认发布方式需要确认;“全部自动”模式会直接发布检查通过的候选。`})]})}function Rt({id:e,title:t,catalog:n,openMemory:r,onAction:i,locked:a=!1,currentID:o,history:s=!1}){let c=y(`/persona/versions/${e}`,5e3),l=c.data;return(0,x.jsxs)(`section`,{className:`panel persona-version`,"aria-label":t,children:[l&&(0,x.jsxs)(`h2`,{children:[t,` · v`,e]}),c.error&&(0,x.jsxs)(A,{error:!0,children:[c.error,(0,x.jsx)(`button`,{onClick:c.refresh,children:`重试版本详情`})]}),l?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`persona-meta`,children:[(0,x.jsx)(M,{tone:l.status===`pending`||l.status===`rejected`?`warning`:``,children:ne[l.status]}),(0,x.jsx)(`span`,{children:L[l.source]||l.source}),(0,x.jsxs)(`span`,{children:[`变化程度:`,l.change_degree?R[l.change_degree]||l.change_degree:`未记录`]})]}),(0,x.jsxs)(`p`,{className:`muted`,children:[`生成时间:`,(0,x.jsx)(N,{value:l.generated_at}),` · 发布时间:`,(0,x.jsx)(N,{value:l.published_at})]}),(0,x.jsxs)(`p`,{className:`muted`,children:[l.base_version_id?`基于 v${l.base_version_id}`:`初始版本`,l.rollback_of&&` · 回滚自 v${l.rollback_of}`]}),(0,x.jsx)(`ol`,{className:`persona-sentences`,children:l.sentences.map((e,t)=>(0,x.jsx)(Pt,{sentence:e,index:t,catalog:n,openMemory:r},`${t}-${e.text}`))}),!l.sentences.length&&(0,x.jsx)(`p`,{className:`persona-content`,children:l.content}),!!l.rejection_reasons.length&&(0,x.jsxs)(`div`,{className:`notice error`,children:[(0,x.jsx)(`h3`,{children:`拒绝原因`}),(0,x.jsx)(`ul`,{children:l.rejection_reasons.map((e,t)=>(0,x.jsx)(`li`,{children:ae(e)},t))})]}),(0,x.jsx)(Lt,{version:l}),l.settings&&(0,x.jsxs)(`details`,{children:[(0,x.jsx)(`summary`,{children:`本次候选接受时的设置`}),(0,x.jsxs)(`p`,{children:[`发布方式:`,{small_medium_auto:`小或中自动发布`,all_auto:`全部自动`,all_manual:`全部人工确认`}[l.settings.publish_mode]||l.settings.publish_mode]}),(0,x.jsx)(`h4`,{children:`生成目标`}),(0,x.jsx)(`p`,{className:`persona-content`,children:l.settings.goal}),(0,x.jsx)(`h4`,{children:`监管要求`}),(0,x.jsx)(`p`,{className:`persona-content`,children:l.settings.rules})]}),(0,x.jsxs)(`div`,{className:`persona-actions`,children:[i&&o&&l.status===`pending`&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`button`,{className:`primary`,disabled:a||!!c.error,onClick:()=>i(`confirm`,l),children:`确认发布候选`}),(0,x.jsx)(`button`,{disabled:a||!!c.error,onClick:()=>i(`reject`,l),children:`拒绝候选`})]}),i&&o&&s&&[`current`,`history`].includes(l.status)&&(0,x.jsx)(`button`,{disabled:a||!!c.error,onClick:()=>i(`rollback`,l),children:`回滚到此版本`}),(0,x.jsx)(`a`,{href:`#/operations?object_type=persona&object_id=${e}`,children:`查看版本操作记录`})]})]}):(0,x.jsx)(`p`,{children:`正在读取版本详情…`})]})}function zt({sentences:e,start:t}){return e.length?(0,x.jsx)(`ol`,{className:`persona-diff-sentences`,start:t,children:e.map((e,t)=>(0,x.jsxs)(`li`,{children:[(0,x.jsx)(`p`,{children:e.text}),(0,x.jsxs)(`small`,{children:[re[e.origin]||e.origin,` · 依据:`,e.basis.length?e.basis.map(e=>`#${e.memory_id} 修订 ${e.revision}`).join(`、`):`无`,` `,`· 日期:`,e.dates.join(`、`)||`未记录`,`(`,e.date_count,` 个日期)`,e.initial_setting&&` · 初始设定`]})]},t))}):(0,x.jsx)(`p`,{className:`muted`,children:`无句子`})}function Bt({before:e,after:t}){let n=y(`/persona/diff?before_version=${e}&after_version=${t}`);return(0,x.jsxs)(`section`,{className:`persona-diff`,"aria-label":`版本差异 v${e} 到 v${t}`,children:[(0,x.jsxs)(`h3`,{children:[`逐句差异:v`,e,` → v`,t]}),n.error&&(0,x.jsxs)(A,{error:!0,children:[n.error,(0,x.jsx)(`button`,{onClick:n.refresh,children:`重试版本对比`})]}),!n.data&&!n.error&&(0,x.jsx)(`p`,{children:`正在读取差异…`}),n.data?.changes.length===0&&(0,x.jsx)(`p`,{children:`这两个版本的句子与依据没有差异。`}),n.data?.changes.map((n,r)=>(0,x.jsxs)(`article`,{className:`persona-change persona-change-${n.kind}`,children:[(0,x.jsx)(`h4`,{children:{insert:`新增句子`,delete:`删除句子`,replace:`改写句子`,basis_changed:`正文相同,依据或归属变化`}[n.kind]}),(0,x.jsxs)(`div`,{className:`persona-diff-columns`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsxs)(`strong`,{children:[`之前 · v`,e]}),(0,x.jsx)(zt,{sentences:n.before,start:n.before_start})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsxs)(`strong`,{children:[`之后 · v`,t]}),(0,x.jsx)(zt,{sentences:n.after,start:n.after_start})]})]})]},r))]})}function W({value:e,openMemory:t}){return(0,x.jsxs)(`details`,{className:`source consolidation-excerpts`,children:[(0,x.jsx)(`summary`,{children:`查看来源摘录`}),(0,x.jsx)(`p`,{className:`fine-print`,children:`本次模型判断时的来源摘录;完整来源与前后文可在记忆详情查看。`}),!e?.length&&(0,x.jsx)(`p`,{children:`没有保存的来源摘录。`}),e?.map((e,n)=>(0,x.jsxs)(`div`,{children:[(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>t(e.memory_id),children:[`记忆 #`,e.memory_id]}),!e.sources.length&&(0,x.jsx)(`p`,{className:`quiet`,children:`没有可用的来源消息摘录。`}),e.sources.map(e=>(0,x.jsxs)(`article`,{className:`consolidation-excerpt`,children:[(0,x.jsxs)(`p`,{className:`muted`,children:[`消息 #`,e.id,` · `,e.entry_name||e.entry_id,` ·`,` `,{private:`私聊`,group:`群聊`,trial:`试用`}[e.entry_kind||``]||e.entry_kind,` `,`· `,e.sender_name||e.sender,` ·`,` `,(0,x.jsx)(N,{value:e.at||e.occurred_at||null})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:{message:`他人消息`,self_output:`角色输出`,action_result:`行动结果`,event:`事件`}[e.kind]||e.kind}),(0,x.jsx)(`blockquote`,{children:e.text}),e.quote_content&&(0,x.jsxs)(`div`,{className:`source-quote`,children:[(0,x.jsxs)(`small`,{children:[`原消息引用 `,e.quote_author||``]}),(0,x.jsx)(`blockquote`,{children:e.quote_content})]})]},e.id))]},`${e.memory_id}:${n}`))]})}function Vt({name:e,items:t,openMemory:n}){let[r,i]=(0,l.useState)(0);return(0,x.jsxs)(`section`,{className:`detail-section`,"aria-label":e,children:[(0,x.jsxs)(`h3`,{children:[e,` `,(0,x.jsx)(M,{children:t.length})]}),e.includes(`建议`)&&(0,x.jsx)(`p`,{className:`fine-print`,children:`仅管理员可见。采纳只记录确认,不改正文和相信程度;已确认的建议也不进入宿主召回。`}),!t.length&&(0,x.jsx)(`p`,{className:`quiet`,children:`本次暂无记录。`}),t.slice(r,r+30).map(e=>{let t=e.details;return(0,x.jsxs)(`article`,{className:`maintenance-item`,children:[e.outcome===`merged`?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`actions`,children:[t.absorbed_ids?.map(e=>(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>n(e),children:[`记忆 #`,e]},e)),(0,x.jsx)(`span`,{children:`并入`}),t.result_id!=null&&(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>n(t.result_id),children:[`记忆 #`,t.result_id]})]}),(0,x.jsx)(`p`,{children:`全部来源已归入保留记忆;被合并的记忆保留为占位。`}),(0,x.jsxs)(`p`,{children:[`来源消息:`,t.source_messages?.map(e=>`#${e}`).join(`、`)||`无消息来源`,` `,`· 重定向派生依据 `,t.redirected_dependencies??0,` 处`]})]}):(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(M,{tone:`warning`,children:`模型建议`}),` `,(0,x.jsx)(`span`,{children:t.suggestion_type===`merge_details`?Dt:e.outcome===`conflicts`?`矛盾检查`:`依赖复核`}),t.suggestion_type===`merge_details`&&(0,x.jsx)(Ot,{details:t.unique_details,ids:t.before_memories?.slice(0,2).map(e=>e.id)||[],openMemory:n}),t.suggestions?.map(e=>(0,x.jsxs)(`div`,{className:`suggestion-summary`,children:[(0,x.jsxs)(`p`,{children:[(0,x.jsx)(M,{children:t.suggestion_type===`merge_details`?`合并待核对`:ce[e.kind]||e.kind}),` `,(0,x.jsx)(M,{children:le[e.review_status]}),` 建议 #`,e.id]}),(0,x.jsx)(`p`,{children:e.text}),e.memory_id!=null&&(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>n(e.memory_id),children:[`查看记忆 #`,e.memory_id,` 的建议`]}),e.confirmed_at&&(0,x.jsxs)(`p`,{className:`muted`,children:[`管理员确认:`,(0,x.jsx)(N,{value:e.confirmed_at})]}),e.cleared_at&&(0,x.jsxs)(`p`,{className:`muted`,children:[`管理员清除:`,(0,x.jsx)(N,{value:e.cleared_at})]})]},e.id)),!t.suggestions?.length&&e.memory_id!=null&&(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>n(e.memory_id),children:[`查看记忆 #`,e.memory_id]})]}),t.report&&(0,x.jsx)(`p`,{className:`report-text`,children:t.report}),!!t.before_memories?.length&&(0,x.jsxs)(`details`,{className:`source`,children:[(0,x.jsx)(`summary`,{children:`涉及的记忆与修订快照`}),t.before_memories.map(e=>{let r=t.after_memories?.find(t=>t.id===e.id);return(0,x.jsxs)(`div`,{children:[(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>n(e.id),children:[`记忆 #`,e.id]}),(0,x.jsxs)(`span`,{children:[` `,`· 修订 `,e.revision,r&&` → ${r.revision}`]}),(0,x.jsx)(`p`,{className:`report-text`,children:e.content||`正文已不可用`}),r?.content!==e.content&&(0,x.jsxs)(`p`,{className:`report-text`,children:[`整理后:`,r?.content||`正文已不可用`]})]},e.id)})]}),(0,x.jsx)(W,{value:t.source_excerpts,openMemory:n}),(0,x.jsx)(`small`,{children:(0,x.jsx)(N,{value:e.created_at})})]},`${e.phase}:${e.item_key}`)}),(0,x.jsx)(T,{total:t.length,offset:r,change:i})]})}function Ht({data:e}){let[t,n]=(0,l.useState)(0),r=e.items.filter(e=>e.outcome===`goals_reviewed`);return!e.goal_review&&!r.length?null:(0,x.jsxs)(`section`,{className:`detail-section`,"aria-label":`目标复核结果`,children:[(0,x.jsx)(`h3`,{children:`目标复核结果`}),(0,x.jsx)(`p`,{children:e.goal_review?.enabled===!1?`未执行:${B(e.goal_review.skip_reason||`disabled`)}`:`已检查 ${e.goal_review?.checked??0} 个目标,${r.length} 个目标的依据标注发生变化。`}),(0,x.jsx)(`p`,{className:`fine-print`,children:`复核只更新依据标注,不自动完成或放弃目标,也不改变提醒。`}),r.slice(t,t+30).map(e=>(0,x.jsxs)(`article`,{className:`maintenance-item`,children:[(0,x.jsxs)(`a`,{href:`#/state?tab=goals&id=${e.object_id}`,children:[`查看目标 #`,e.object_id]}),(0,x.jsxs)(`p`,{children:[`新增或重新启用标注:`,e.details.annotation_ids?.map(e=>`#${e}`).join(`、`)||`无`]}),(0,x.jsxs)(`p`,{children:[`结束的旧标注:`,e.details.ended_annotation_ids?.map(e=>`#${e}`).join(`、`)||`无`]}),(0,x.jsx)(`small`,{children:(0,x.jsx)(N,{value:e.created_at})})]},e.item_key)),(0,x.jsx)(T,{total:r.length,offset:t,change:n})]})}function Ut({data:e}){let[t,n]=(0,l.useState)(0),r=e.items.filter(e=>e.outcome===`person_summary`);return!r.length&&e.consolidation?.settings.person_summary_enabled==null?null:(0,x.jsxs)(`section`,{className:`detail-section`,"aria-label":`人物摘要处理结果`,children:[(0,x.jsxs)(`h3`,{children:[`人物摘要处理结果 `,(0,x.jsx)(M,{children:r.length})]}),e.consolidation?.settings.person_summary_enabled===!1&&(0,x.jsx)(`p`,{children:`本次运行已关闭人物摘要更新。`}),!r.length&&(0,x.jsx)(`p`,{children:`本次没有人物摘要处理记录。`}),r.slice(t,t+30).map(e=>(0,x.jsxs)(`article`,{className:`maintenance-item`,children:[(0,x.jsx)(`p`,{children:(0,x.jsx)(M,{children:At[e.details.status||``]||e.details.status||`未记录结果`})}),e.details.subject_id?(0,x.jsxs)(`a`,{href:Mt(e.details.subject_id,e.details.version),children:[`查看人物 `,e.details.subject_id,e.details.version?` 的摘要 v${e.details.version}`:` 的摘要与任务`]}):(0,x.jsx)(`p`,{children:`人物摘要步骤异常,未关联具体人物。`}),e.reason&&(0,x.jsx)(`p`,{children:jt(e.reason)}),e.details.attempt_id!=null&&(0,x.jsxs)(`p`,{children:[`生成任务 #`,e.details.attempt_id]}),(0,x.jsx)(`small`,{children:(0,x.jsx)(N,{value:e.created_at})})]},e.item_key)),(0,x.jsx)(T,{total:r.length,offset:t,change:n})]})}function Wt({data:e}){let t=e.items.filter(e=>e.outcome===`model_step_budget`),n=e.items.filter(e=>e.outcome===`backlog_trimmed`),r=e.question_expiry;return(0,x.jsxs)(x.Fragment,{children:[(e.consolidation||t.length>0)&&(0,x.jsxs)(`section`,{className:`detail-section`,"aria-label":`各步骤模型调用上限与用量`,children:[(0,x.jsx)(`h3`,{children:`各步骤模型调用上限与用量`}),(0,x.jsx)(`p`,{className:`fine-print`,children:`每一步独立计数,包含重试和修正;上限沿用本次运行接受时的设置。未到期、关闭或没有任务的步骤可能没有记录。`}),!t.length&&(0,x.jsx)(`p`,{className:`quiet`,children:`本次未记录步骤用量。`}),t.map(e=>(0,x.jsxs)(`article`,{className:`maintenance-item`,"aria-label":de[e.details.step||``]||e.details.step||`未知步骤`,children:[(0,x.jsx)(`h4`,{children:de[e.details.step||``]||e.details.step||`未知步骤`}),(0,x.jsxs)(`p`,{children:[`本轮上限:`,e.details.max_calls??`未记录`,` 次 · 已用:`,e.details.calls_used??`未记录`,` 次`]}),(0,x.jsxs)(`p`,{children:[`停止原因:`,e.reason?B(e.reason):`未记录`]})]},e.item_key))]}),!!n.length&&(0,x.jsxs)(`section`,{className:`detail-section`,"aria-label":`配对积压修剪`,children:[(0,x.jsx)(`h3`,{children:`配对积压修剪`}),n.map(e=>(0,x.jsxs)(`p`,{children:[`配对积压修剪:`,e.details.count??`未记录`,` 项 · 待处理配对上限:`,e.details.limit??`未记录`,` 项`]},e.item_key)),(0,x.jsx)(`p`,{className:`fine-print`,children:`仅修剪待处理配对,不改变记忆;相关记忆发生变化后可重新规划。`})]}),r&&(0,x.jsxs)(`section`,{className:`detail-section`,"aria-label":`询问到期结束`,children:[(0,x.jsx)(`h3`,{children:`询问到期结束`}),(0,x.jsxs)(`p`,{children:[`到期自动结束的询问:`,r.count,` 条`]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`仅学习产生且超过保留天数仍未结束的询问;宿主或管理员创建的询问和普通目标不受影响。`})]})]})}function Gt({data:e,openMemory:t}){let n=e.summary.model_calls,r=e.persona;return(0,x.jsxs)(x.Fragment,{children:[e.consolidation&&(0,x.jsxs)(`section`,{className:`detail-section`,"aria-label":`本次整理与模型用量`,children:[(0,x.jsx)(`h3`,{children:`本次整理与模型用量`}),(0,x.jsxs)(`p`,{children:[`后续待处理项目:`,e.consolidation.deferred,` 项`,e.consolidation.skip_reason&&` · ${B(e.consolidation.skip_reason)}`]}),n&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{children:[`模型调用 `,n.count,` 次 · 输入 `,n.prompt_tokens??0,` `,`token · 输出 `,n.completion_tokens??0,` token · 总耗时`,` `,C(n.duration_ms??0)]}),(0,x.jsxs)(`p`,{className:`fine-print`,children:[n.unknown_usage_calls??0,` `,`次调用用量未知;用量为四步骤已知合计,包含实际重试、入口画像、persona 及人物摘要调用。`]})]}),(0,x.jsxs)(`details`,{children:[(0,x.jsx)(`summary`,{children:`本次接受任务时的整理设置`}),ue.map(([t,n])=>(0,x.jsxs)(`p`,{children:[n,`:`,e.consolidation?.settings[t]??`未记录`]},t)),z.map(([t,n])=>(0,x.jsxs)(`p`,{children:[n,`:`,e.consolidation?.settings[t]==null?`未记录`:e.consolidation.settings[t]?`开启`:`关闭`]},t)),(0,x.jsx)(`p`,{className:`fine-print`,children:`设置修改只影响之后接受的新运行。`})]})]}),(0,x.jsx)(Wt,{data:e}),(e.consolidation||e.items.some(e=>e.phase===`consolidation`))&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(Vt,{name:`记忆合并`,items:e.items.filter(e=>e.outcome===`merged`),openMemory:t}),(0,x.jsx)(Vt,{name:`整理建议(模型建议)`,items:e.items.filter(e=>[`conflicts`,`dependencies_reviewed`].includes(e.outcome)),openMemory:t})]}),r&&(0,x.jsxs)(`section`,{className:`detail-section`,"aria-label":`persona 变化`,children:[(0,x.jsx)(`h3`,{children:`persona 变化`}),(0,x.jsxs)(`p`,{children:[(0,x.jsx)(M,{tone:r.status===`published`?`green`:``,children:{published:`已发布`,pending:`待确认,当前版本保留`,rejected:`已拒绝,当前版本保留`,not_due:`尚未到更新条件`,skipped:`已跳过`,failed:`失败`,conflict:`版本或依据冲突`,running:`更新中`}[r.status]||r.status}),r.change_degree&&` · 变化程度:${R[r.change_degree]||r.change_degree}`]}),r.reason&&(0,x.jsx)(`p`,{children:B(r.reason)}),r.version_id&&r.base_version_id?(0,x.jsxs)(`a`,{href:`#/persona?tab=history&version=${r.version_id}&before=${r.base_version_id}&after=${r.version_id}`,children:[`对比 persona v`,r.base_version_id,` → v`,r.version_id]}):(0,x.jsx)(`a`,{href:`#/persona?tab=attempts`,children:`查看 persona 生成记录`}),r.content&&(0,x.jsxs)(`details`,{children:[(0,x.jsx)(`summary`,{children:`查看候选正文与检查`}),(0,x.jsx)(`p`,{className:`persona-content`,children:r.content}),r.checks&&(0,x.jsx)(Lt,{version:{checks:r.checks}})]})]}),(0,x.jsx)(Ut,{data:e}),(0,x.jsx)(Ht,{data:e})]})}function Kt({detail:e,busy:t,blocked:n,setBusy:r,saved:i,failed:a,openMemory:o,close:s}){let[c,u]=(0,l.useState)(null),d=t||n;async function f(){if(c&&!d){r(!0);try{i(await g(`/memories/${e.id}/annotations/${c.annotation.id}${c.kind===`confirm`?`/confirm`:``}`,_(c.kind===`confirm`?`POST`:`DELETE`,{expected_revision:c.revision}))),u(null)}catch(e){a(e)}finally{r(!1)}}}return(0,x.jsxs)(`section`,{className:`detail-section`,"aria-label":`整理建议`,children:[(0,x.jsxs)(`h3`,{children:[`整理建议 `,(0,x.jsx)(M,{children:`模型建议 · 仅管理员可见`})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`建议可能有误,请结合来源核对。未确认和已确认的建议都不会进入宿主召回。`}),!e.consolidation_annotations?.length&&(0,x.jsx)(`p`,{className:`quiet`,children:`暂无整理建议。`}),e.consolidation_annotations?.map(n=>(0,x.jsxs)(`article`,{className:`maintenance-item`,children:[(0,x.jsxs)(`div`,{className:`detail-badges`,children:[(0,x.jsx)(M,{tone:`warning`,children:n.report.suggestion_type===`merge_details`?Dt:ce[n.kind]||n.kind}),(0,x.jsx)(M,{children:le[n.review_status]}),n.modified_since_annotation&&(0,x.jsx)(M,{tone:`warning`,children:`标注后已修改`}),(0,x.jsxs)(`span`,{className:`muted`,children:[`建议 #`,n.id]})]}),n.report.suggestion_type===`merge_details`&&(0,x.jsx)(Ot,{details:n.report.unique_details,ids:n.report.detail_memory_ids||n.related_memory_ids,openMemory:o,disabled:t}),(0,x.jsx)(`p`,{className:`report-text`,children:n.text}),(0,x.jsxs)(`p`,{className:`muted`,children:[`标注时修订 `,n.memory_revision,` · `,(0,x.jsx)(N,{value:n.created_at})]}),n.confirmed_at&&(0,x.jsxs)(`p`,{children:[`管理员已确认 · `,(0,x.jsx)(N,{value:n.confirmed_at})]}),(0,x.jsxs)(`div`,{className:`actions`,children:[n.related_memory_ids.filter(t=>t!==e.id).map(e=>(0,x.jsxs)(`button`,{className:`text-button`,disabled:t,onClick:()=>o(e),children:[`相关记忆 #`,e]},e)),n.superseded_by!=null&&(0,x.jsxs)(`button`,{className:`text-button`,disabled:t,onClick:()=>o(n.superseded_by),children:[`建议的替代记忆 #`,n.superseded_by]})]}),n.report.reason&&(0,x.jsx)(`p`,{className:`report-text`,children:n.report.reason}),(0,x.jsx)(W,{value:n.report.source_excerpts,openMemory:o}),(0,x.jsxs)(`a`,{href:`#/status?run=${n.report.run_id}`,onClick:e=>{t?e.preventDefault():s()},children:[`查看整理报告 #`,n.report.run_id]}),(0,x.jsxs)(`div`,{className:`actions suggestion-actions`,children:[n.review_status===`pending`&&(0,x.jsxs)(`button`,{disabled:d||!!c,onClick:()=>u({kind:`confirm`,annotation:n,revision:e.revision}),children:[`采纳建议 #`,n.id]}),(0,x.jsxs)(`button`,{disabled:d||!!c,onClick:()=>u({kind:`clear`,annotation:n,revision:e.revision}),children:[`清除建议 #`,n.id]})]}),c?.annotation.id===n.id&&(0,x.jsxs)(`div`,{className:`delete-confirm`,role:`group`,"aria-label":`确认建议操作`,children:[(0,x.jsx)(`p`,{children:c.kind===`confirm`?n.report.suggestion_type===`merge_details`?`采纳只记录管理员确认,不执行合并,不改正文和相信程度;建议仍只对管理员可见。`:`采纳只记录管理员确认,不改正文和相信程度;建议仍只对管理员可见。`:`清除会撤下这条整理建议并保留操作记录,不改正文和相信程度。`}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`primary`,disabled:d,onClick:()=>void f(),children:c.kind===`confirm`?`确认采纳建议`:`确认清除建议`}),(0,x.jsx)(`button`,{disabled:t,onClick:()=>u(null),children:`取消建议操作`})]})]})]},n.id))]})}function qt({notice:e}){return e?(0,x.jsx)(A,{children:e.message}):null}var Jt={memory_source:`仍是其他记忆的来源`,batch_segment:`等待或运行中的批次仍在使用`,goal_source:`仍是目标的来源`,subject_alias:`仍是主体别名的证据`,subject_link:`仍是主体联系的证据`,learning_request:`立即学习请求仍在使用`};function Yt({result:e}){return(0,x.jsxs)(`div`,{className:`lifecycle-stack`,children:[(0,x.jsxs)(A,{children:[`已彻底清除记忆 #`,e.memory_id]}),(0,x.jsx)(qt,{notice:e.backup_notice}),(0,x.jsxs)(`section`,{children:[(0,x.jsx)(`h3`,{children:`已删除的来源消息`}),e.deleted_message_ids.length?(0,x.jsx)(`ul`,{children:e.deleted_message_ids.map(e=>(0,x.jsxs)(`li`,{children:[`消息 #`,e,` · 没有其他受保护的引用`]},e))}):(0,x.jsx)(`p`,{className:`quiet`,children:`没有删除来源消息。`})]}),(0,x.jsxs)(`section`,{children:[(0,x.jsx)(`h3`,{children:`被保留的来源消息及原因`}),e.retained_messages.length?(0,x.jsx)(`ul`,{children:e.retained_messages.map(e=>(0,x.jsxs)(`li`,{children:[`消息 #`,e.message_id,` ·`,` `,e.reasons.map(e=>Jt[e]||e).join(`;`)]},e.message_id))}):(0,x.jsx)(`p`,{className:`quiet`,children:`没有被保留的来源消息。`})]})]})}function Xt({detail:e,busy:t,blocked:n,setBusy:r,saved:i,failed:a,purged:o,recreated:s}){let[c,u]=(0,l.useState)(null),[d,f]=(0,l.useState)(!1),[p,m]=(0,l.useState)(``),[h,v]=(0,l.useState)(``),[y,b]=(0,l.useState)(``),[S,C]=(0,l.useState)(``),w=t||n,T=new Map;for(let t of e.revisions)T.set(t.revision_after,t.after);for(let t of e.revisions)T.set(t.revision_before,t.before);let E=T.get(Number(S));async function D(t,n={}){if(!w){r(!0);try{let r=`/memories/${e.id}/${t}`,a=_(t===`lifecycle`?`PATCH`:`POST`,{expected_revision:e.revision,...n});t===`purge`?o(await g(r,a)):t===`recreate`?s((await g(r,a)).id):i(await g(r,a)),u(null),f(!1)}catch(e){a(e)}finally{r(!1)}}}function O(t){if(t.preventDefault(),b(``),[p,h].some(e=>!e.trim()||!Number.isInteger(Number(e))||Number(e)<0||Number(e)>100)){b(`重要度和保留强度须为 0—100 的整数`);return}let n={};if(Number(p)!==e.importance&&(n.importance=Number(p)),Number(h)!==e.retention&&(n.retention=Number(h)),!Object.keys(n).length){u(null);return}D(`lifecycle`,n)}let k=()=>{u(null),f(!1),b(``)};return(0,x.jsxs)(`section`,{className:`detail-section lifecycle-stack`,"aria-label":`生命周期操作`,children:[(0,x.jsx)(`h3`,{children:`生命周期操作`}),!c&&(0,x.jsxs)(`div`,{className:`actions`,children:[e.lifecycle!==`deleted`&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`button`,{className:`secondary`,disabled:w,onClick:()=>void D(`lifecycle`,{pinned:!e.pinned}),children:e.pinned?`取消置顶`:`置顶记忆`}),e.lifecycle===`forgotten`?(0,x.jsx)(`button`,{className:`secondary`,disabled:w,onClick:()=>void D(`restore`),children:`恢复记忆`}):(0,x.jsx)(`button`,{className:`secondary`,disabled:w,onClick:()=>u(`forget`),children:`手动遗忘`}),(0,x.jsx)(`button`,{className:`secondary`,disabled:w,onClick:()=>{u(`scores`),m(String(e.importance)),v(String(e.retention))},children:`调整分数`})]}),(0,x.jsx)(`button`,{className:`secondary`,disabled:w||!T.size,onClick:()=>{C(``),u(`recreate`)},children:`按旧内容新建`}),(0,x.jsx)(`button`,{className:`text-button danger-text`,disabled:w,onClick:()=>u(`purge`),children:`彻底清除`})]}),!T.size&&(0,x.jsx)(`p`,{className:`fine-print`,children:`尚无历史修订可用于“按旧内容新建”。`}),!!e.pinned&&e.lifecycle!==`deleted`&&(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`置顶记忆不自动衰减、遗忘、扣减或删除。置顶不会自动恢复已遗忘的记忆。`}),c===`scores`&&(0,x.jsx)(`form`,{onSubmit:O,noValidate:!0,children:(0,x.jsxs)(`fieldset`,{className:`lifecycle-fieldset`,disabled:w,children:[(0,x.jsxs)(`div`,{className:`form-grid`,children:[(0,x.jsxs)(`label`,{children:[`调整重要度`,(0,x.jsx)(`input`,{type:`number`,min:0,max:100,step:1,required:!0,value:p,onChange:e=>m(e.target.value)})]}),(0,x.jsxs)(`label`,{children:[`调整保留强度`,(0,x.jsx)(`input`,{type:`number`,min:0,max:100,step:1,required:!0,value:h,onChange:e=>v(e.target.value)})]})]}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`保留强度调整会按当前阈值判断遗忘或恢复。`}),y&&(0,x.jsx)(A,{error:!0,children:y}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`primary`,children:`保存分数`}),(0,x.jsx)(`button`,{className:`secondary`,type:`button`,onClick:k,children:`取消调整`})]})]})}),c===`forget`&&(0,x.jsxs)(`div`,{className:`delete-confirm`,children:[(0,x.jsx)(`p`,{children:`确认手动遗忘?保留强度会降至遗忘阈值以下,并取消置顶;此后只参与深度召回。恢复时不会重新置顶。`}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`primary`,disabled:w,onClick:()=>void D(`forget`),children:`确认遗忘`}),(0,x.jsx)(`button`,{className:`secondary`,disabled:t,onClick:k,children:`取消遗忘`})]})]}),c===`purge`&&(0,x.jsxs)(`div`,{className:`purge-confirm`,children:[(0,x.jsx)(`h3`,{children:`彻底清除不可撤销`}),(0,x.jsx)(`p`,{children:`将删除记忆正文、修订历史,以及只被这条记忆引用且没有其他受保护引用的来源消息。其他引用仍需要的消息会保留,执行后显示消息标识与原因。`}),(0,x.jsx)(`p`,{children:`同时清空可关联的模型原始输出等正文副本。`}),(0,x.jsx)(qt,{notice:e.purge_preview?.backup_notice}),(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:d,disabled:w,onChange:e=>f(e.target.checked)}),`我理解此操作不可撤销`]}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`danger-button`,disabled:w||!d,onClick:()=>void D(`purge`,{confirm:!0}),children:`再次确认并彻底清除`}),(0,x.jsx)(`button`,{className:`secondary`,disabled:t,onClick:k,children:`取消清除`})]})]}),c===`recreate`&&(0,x.jsxs)(`div`,{className:`lifecycle-stack`,children:[(0,x.jsxs)(`label`,{children:[`选择历史修订`,(0,x.jsxs)(`select`,{disabled:w,value:S,onChange:e=>C(e.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`请选择修订`}),[...T.keys()].sort((e,t)=>t-e).map(e=>(0,x.jsxs)(`option`,{value:e,children:[`修订 `,e]},e))]})]}),E&&(0,x.jsxs)(`div`,{className:`revision`,"data-testid":`revision-preview`,children:[(0,x.jsx)(`p`,{children:String(E.content??``)}),(0,x.jsxs)(`small`,{children:[`相信程度 `,String(E.belief??e.belief),` · 重要度`,` `,String(E.importance??e.importance)]})]}),(0,x.jsx)(`p`,{className:`lifecycle-help`,children:`新建使用新标识,原记忆保持原状。正文和判断取所选修订,涉及人物、标签和来源沿用当前保存的关系;不继承置顶、遗忘时间或向量。`}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`primary`,disabled:w||!E,onClick:()=>void D(`recreate`,{source_revision:Number(S)}),children:`确认新建`}),(0,x.jsx)(`button`,{className:`secondary`,disabled:t,onClick:k,children:`取消新建`})]})]})]})}function Zt({version:e,openMemory:t,onChange:n}){let[r,i]=(0,l.useState)(0),a=y(`/memories/upcoming-deletion?limit=30&offset=${r}`),[o,s]=(0,l.useState)(null),[c,u]=(0,l.useState)(``),[d,p]=(0,l.useState)(``),[m,h]=(0,l.useState)(!1);(0,l.useEffect)(()=>{a.refresh()},[e,a.refresh]),(0,l.useEffect)(()=>{a.data&&r&&r>=a.data.total&&i(Math.max(0,Math.ceil(a.data.total/30)*30-30))},[a.data,r]);async function b(e){if(!(o!==null||m||a.loading||a.error)){s(e.id),u(``),p(``);try{await g(`/memories/${e.id}/restore`,_(`POST`,{expected_revision:e.revision})),p(`已恢复记忆 #${e.id}`),a.refresh(),n()}catch(e){e instanceof f&&(e.status===409||e.status===404)?(h(!0),u(`这条记忆已变化或已被删除,请刷新列表后再操作。`)):u(v(e))}finally{s(null)}}}return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:`即将删除`}),(0,x.jsx)(`button`,{className:`secondary`,disabled:o!==null,onClick:()=>{h(!1),u(``),a.refresh()},children:`刷新列表`})]}),(0,x.jsx)(`p`,{className:`learning-intro`,children:`包括遗忘期将满和已到期等待维护的记忆;置顶记忆不自动删除。到期后由维护执行删除,可以在此提前恢复。`}),(c||a.error)&&(0,x.jsx)(A,{error:!0,children:c||a.error}),d&&(0,x.jsx)(A,{children:d}),!a.data&&!a.error&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取即将删除的记忆…`}),a.data&&!a.data.enabled&&(0,x.jsxs)(A,{children:[`自动删除已关闭,当前没有即将删除的记忆。`,(0,x.jsx)(`a`,{href:`#/settings`,children:`前往生命周期设置`})]}),a.data?.enabled&&!a.data.items.length&&(0,x.jsx)(j,{title:`暂无即将删除的记忆`}),(0,x.jsx)(`div`,{className:`memory-grid`,children:a.data?.items.map(e=>(0,x.jsxs)(`article`,{className:`panel upcoming-card`,children:[(0,x.jsxs)(`div`,{className:`memory-card-top`,children:[(0,x.jsx)(M,{children:`已遗忘`}),(0,x.jsxs)(`span`,{className:`muted`,children:[`#`,e.id,` · 保留强度 `,e.retention]})]}),(0,x.jsx)(`button`,{className:`memory-preview`,onClick:()=>t(e.id),children:e.content}),(0,x.jsxs)(`p`,{children:[`遗忘时间:`,w(e.forgotten_at)]}),(0,x.jsxs)(`p`,{children:[`删除到期时间:`,w(e.delete_after)]}),(0,x.jsx)(`button`,{className:`secondary`,"aria-label":`恢复记忆 #${e.id}`,disabled:o!==null||m||a.loading||!!a.error,onClick:()=>void b(e),children:o===e.id?`正在恢复…`:`恢复记忆`})]},e.id))}),a.data&&(0,x.jsx)(T,{total:a.data.total,offset:r,change:i})]})}var Qt=[`事件`,`事实`,`偏好`,`关系`,`观点`,`计划`,`自我`,`其他`];function $t({openMemory:e,version:t,onChange:n,initialQuery:r}){let[i,a]=(0,l.useState)(`all`);return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{className:`page-heading`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`p`,{className:`eyebrow`,children:`留下的经历,有迹可循`}),(0,x.jsx)(`h1`,{children:`记忆`}),(0,x.jsx)(`p`,{children:`查看内容、追溯来源,管理记忆的保留与遗忘。`})]})}),(0,x.jsxs)(`div`,{className:`learning-tabs`,"aria-label":`记忆视图`,children:[(0,x.jsx)(`button`,{"aria-pressed":i===`all`,onClick:()=>a(`all`),children:`记忆列表`}),(0,x.jsx)(`button`,{"aria-pressed":i===`upcoming`,onClick:()=>a(`upcoming`),children:`即将删除`})]}),i===`all`?(0,x.jsx)(en,{openMemory:e,version:t,initialQuery:r}):(0,x.jsx)(Zt,{openMemory:e,version:t,onChange:n})]})}function en({openMemory:e,version:t,initialQuery:n=``}){let r=y(`/catalog`),i=new URLSearchParams(n),[a,o]=(0,l.useState)({text:``,person_id:i.get(`person_id`)||``,kind:``,entry_id:``,time_from:``,time_to:``,lifecycle:i.get(`lifecycle`)===`all`?`all`:`active`,pinned:``,sort:`time`}),[s,c]=(0,l.useState)(()=>new URLSearchParams(Object.entries(a).filter(([,e])=>!!e)).toString()),[u,d]=(0,l.useState)(0),[f,p]=(0,l.useState)(``),m=y(`/memories?${s}&limit=30&offset=${u}`);(0,l.useEffect)(()=>{m.refresh()},[t,m.refresh]),(0,l.useEffect)(()=>{m.data&&u&&u>=m.data.total&&d(Math.max(0,Math.ceil(m.data.total/30)*30-30))},[m.data,u]);function h(e){if(e.preventDefault(),a.time_from&&a.time_to&&a.time_from>a.time_to){p(`开始日期不能晚于结束日期`);return}p(``),d(0),c(new URLSearchParams(Object.entries(a).filter(([,e])=>!!e)).toString()),m.refresh()}let g=(e,t)=>o({...a,[e]:t});return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`section`,{className:`panel`,children:(0,x.jsxs)(`form`,{className:`memory-filters`,onSubmit:h,children:[(0,x.jsxs)(`div`,{className:`search-row`,children:[(0,x.jsxs)(`label`,{className:`search-field`,children:[`搜索记忆`,(0,x.jsx)(`input`,{value:a.text,maxLength:1e3,placeholder:`输入正文或标签中的词…`,onChange:e=>g(`text`,e.target.value)})]}),(0,x.jsx)(`button`,{className:`primary`,type:`submit`,children:`搜索`})]}),(0,x.jsxs)(`div`,{className:`filter-grid`,children:[(0,x.jsxs)(`label`,{children:[`涉及的人`,(0,x.jsxs)(`select`,{value:a.person_id,onChange:e=>g(`person_id`,e.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`全部人物`}),r.data?.people.map(e=>(0,x.jsxs)(`option`,{value:e.id,children:[e.name,(r.data?.people.filter(t=>t.name===e.name).length||0)>1?` · ${e.id.slice(0,6)}`:``]},e.id))]})]}),(0,x.jsxs)(`label`,{children:[`记忆类型`,(0,x.jsxs)(`select`,{value:a.kind,onChange:e=>g(`kind`,e.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`全部类型`}),Qt.map(e=>(0,x.jsx)(`option`,{children:e},e))]})]}),(0,x.jsxs)(`label`,{children:[`出处入口`,(0,x.jsxs)(`select`,{value:a.entry_id,onChange:e=>g(`entry_id`,e.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`全部入口`}),r.data?.entries.map(e=>(0,x.jsx)(`option`,{value:e.id,children:e.name},e.id))]})]}),(0,x.jsxs)(`label`,{children:[`状态`,(0,x.jsxs)(`select`,{value:a.lifecycle,onChange:e=>g(`lifecycle`,e.target.value),children:[(0,x.jsx)(`option`,{value:`active`,children:`有效`}),(0,x.jsx)(`option`,{value:`forgotten`,children:`已遗忘`}),(0,x.jsx)(`option`,{value:`deleted`,children:`已删除(历史)`}),(0,x.jsx)(`option`,{value:`all`,children:`全部状态`})]})]}),(0,x.jsxs)(`label`,{children:[`置顶筛选`,(0,x.jsxs)(`select`,{"aria-label":`置顶筛选`,value:a.pinned,onChange:e=>g(`pinned`,e.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`全部`}),(0,x.jsx)(`option`,{value:`true`,children:`已置顶`}),(0,x.jsx)(`option`,{value:`false`,children:`未置顶`})]})]}),(0,x.jsxs)(`label`,{children:[`开始日期`,(0,x.jsx)(`input`,{type:`date`,value:a.time_from,onChange:e=>g(`time_from`,e.target.value)})]}),(0,x.jsxs)(`label`,{children:[`结束日期`,(0,x.jsx)(`input`,{type:`date`,value:a.time_to,onChange:e=>g(`time_to`,e.target.value)})]}),(0,x.jsxs)(`label`,{children:[`排序方式`,(0,x.jsxs)(`select`,{value:a.sort,onChange:e=>g(`sort`,e.target.value),children:[(0,x.jsx)(`option`,{value:`time`,children:`更新时间 · 从新到旧`}),(0,x.jsx)(`option`,{value:`relevance`,children:`文本相关度`}),(0,x.jsx)(`option`,{value:`retention`,children:`保留强度 · 从高到低`})]})]})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`日期按事件时间筛选;没有事件时间时使用创建时间。`})]})}),f&&(0,x.jsx)(A,{error:!0,children:f}),(m.error||r.error)&&(0,x.jsx)(A,{error:!0,children:m.error||r.error}),(0,x.jsxs)(`div`,{className:`list-heading`,children:[(0,x.jsx)(`span`,{children:m.data?`共 ${m.data.total} 条`:`正在读取…`}),(0,x.jsx)(`span`,{children:`浏览列表不会增加召回或使用次数`})]}),m.data?.items.length===0&&(0,x.jsx)(`section`,{className:`panel`,children:(0,x.jsx)(j,{title:`没有找到记忆`,children:`尝试换一个词,或调整筛选条件。`})}),(0,x.jsx)(`div`,{className:`memory-grid`,children:m.data?.items.map(t=>(0,x.jsxs)(`button`,{className:`memory-card panel`,onClick:()=>e(t.id),children:[(0,x.jsxs)(`div`,{className:`memory-card-top`,children:[(0,x.jsx)(M,{tone:`purple`,children:t.kind}),(0,x.jsx)(M,{tone:t.pinned?`purple`:``,children:t.pinned?`已置顶`:`未置顶`}),(0,x.jsxs)(`span`,{className:`muted`,children:[`#`,t.id,` · `,E(t.lifecycle)]})]}),(0,x.jsx)(`p`,{className:`memory-content`,children:t.content}),(0,x.jsx)(`div`,{className:`person-line`,children:t.about.map(e=>e.name).join(`、`)||`未标注涉及人物`}),(0,x.jsxs)(`div`,{className:`memory-card-bottom`,children:[(0,x.jsxs)(`span`,{children:[`相信 `,t.belief,` · 保留强度 `,t.retention]}),(0,x.jsx)(`time`,{children:S(t.updated_at)}),(0,x.jsx)(`span`,{"aria-hidden":!0,children:`↗`})]})]},t.id))}),m.data&&(0,x.jsx)(T,{total:m.data.total,offset:u,change:d})]})}function tn({id:e,onClose:t,onChange:n,openMemory:r}){let i=y(`/memories/${e}`),a=y(`/catalog`),[o,s]=(0,l.useState)(null),[c,u]=(0,l.useState)(!1),[d,p]=(0,l.useState)(``),[m,h]=(0,l.useState)(!1),[b,C]=(0,l.useState)(``),[T,D]=(0,l.useState)(!1),[O,k]=(0,l.useState)(!1),[j,N]=(0,l.useState)(null),[P,F]=(0,l.useState)(0),I=j?null:o||i.data,te=e=>{O||r(e)};function L(e){e instanceof f&&e.code===`revision_conflict`?(D(!0),C(`其他操作已更新了这条记忆。草稿暂时保留;请刷新并载入最新修订,再核对后操作。载入会替换当前草稿。`)):e instanceof f&&e.status===404?(D(!0),C(`这条记忆已删除或已彻底清除,请刷新或返回列表查看。`)):C(v(e))}async function ne(t){if(t.preventDefault(),!(!I||O||T)){k(!0),C(``);try{s(await g(`/memories/${e}`,_(`PATCH`,{expected_revision:I.revision,content:d}))),u(!1),D(!1),n()}catch(e){L(e)}finally{k(!1)}}}async function R(){if(!(!I||O||T)){k(!0),C(``);try{s(await g(`/memories/${e}`,_(`DELETE`,{expected_revision:I.revision}))),h(!1),F(e=>e+1),u(!1),n()}catch(e){L(e)}finally{k(!1)}}}async function re(){k(!0);try{let t=await g(`/memories/${e}`);s(t),p(t.content),F(e=>e+1),D(!1),C(``),h(!1)}catch(e){L(e)}finally{k(!1)}}return(0,x.jsxs)(ee,{title:`记忆 #${e}`,onClose:t,closeDisabled:O,children:[(b||i.error)&&(0,x.jsx)(A,{error:!0,children:b||i.error}),T&&(0,x.jsx)(`button`,{className:`secondary`,disabled:O,onClick:re,children:`载入最新修订`}),j&&(0,x.jsx)(Yt,{result:j}),!I&&!j&&!i.error&&(0,x.jsx)(`p`,{className:`quiet`,children:`正在读取详情…`}),I&&(0,x.jsxs)(`div`,{className:`memory-detail`,children:[(0,x.jsxs)(`div`,{className:`detail-badges`,children:[(0,x.jsx)(M,{tone:`purple`,children:I.kind}),(0,x.jsx)(M,{children:I.stance}),(0,x.jsx)(M,{tone:I.lifecycle===`deleted`?`danger`:``,children:E(I.lifecycle)}),(0,x.jsx)(M,{tone:I.pinned?`purple`:``,children:I.pinned?`已置顶`:`未置顶`}),(0,x.jsxs)(`span`,{className:`muted`,children:[`修订 `,I.revision]})]}),I.merged_into!=null&&(0,x.jsxs)(A,{children:[(0,x.jsxs)(`button`,{className:`text-button`,disabled:O,onClick:()=>te(I.merged_into),children:[`已合并到 #`,I.merged_into]}),(0,x.jsx)(`p`,{children:`全部来源已归入保留记忆;此处是原记忆占位,不能恢复为有效记忆。`})]}),I.lifecycle===`deleted`&&I.merged_into==null&&(0,x.jsx)(A,{children:`此标识已撤销,不再参与召回;来源和修订历史仍然保留。`}),c&&I.lifecycle!==`deleted`?(0,x.jsxs)(`form`,{onSubmit:ne,children:[(0,x.jsxs)(`label`,{children:[`记忆正文`,(0,x.jsx)(`textarea`,{value:d,maxLength:1e3,rows:5,onChange:e=>p(e.target.value)})]}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`primary`,disabled:O||T||!d.trim(),children:`保存修改`}),(0,x.jsx)(`button`,{type:`button`,className:`secondary`,disabled:O,onClick:()=>u(!1),children:`取消编辑`}),(0,x.jsxs)(`small`,{children:[d.length,` / 1000 字`]})]})]}):(0,x.jsx)(`p`,{className:`detail-content`,children:I.content}),(0,x.jsxs)(`div`,{className:`score-grid`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`strong`,{children:I.belief}),(0,x.jsx)(`span`,{children:`相信程度`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`strong`,{children:I.importance}),(0,x.jsx)(`span`,{children:`重要度`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`strong`,{children:I.retention}),(0,x.jsx)(`span`,{children:`保留强度`})]})]}),(0,x.jsx)(Xt,{detail:I,busy:O,blocked:T||c||m,setBusy:k,failed:L,saved:e=>{s(e),C(``),n()},purged:e=>{N(e),s(null),C(``),n()},recreated:e=>{n(),r(e)}},`${I.id}:${I.revision}:${P}`),(0,x.jsxs)(`dl`,{className:`metadata`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`记忆可见范围`}),(0,x.jsx)(`dd`,{children:Qe(I.visibility,a.data?.entries||[])})]}),I.lifecycle===`forgotten`&&(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`遗忘时间`}),(0,x.jsx)(`dd`,{children:w(I.forgotten_at)})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`说话人`}),(0,x.jsx)(`dd`,{children:I.speaker.name})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`涉及的人`}),(0,x.jsx)(`dd`,{children:I.about.map(e=>e.name).join(`、`)||`未标注`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`事件时间`}),(0,x.jsx)(`dd`,{children:I.event_time||`未标注`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`更新时间`}),(0,x.jsx)(`dd`,{children:S(I.updated_at)})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`被召回`}),(0,x.jsxs)(`dd`,{children:[I.recall_count,` 次`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`被使用`}),(0,x.jsxs)(`dd`,{children:[I.used_count,` 次`]})]})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`被召回不等于被使用;使用次数不代表内容可信度。`}),!!I.tags.length&&(0,x.jsx)(`div`,{className:`tag-list`,children:I.tags.map(e=>(0,x.jsxs)(M,{children:[`# `,e]},e))}),(0,x.jsx)(Kt,{detail:I,busy:O,blocked:T||c||m,setBusy:k,saved:e=>{s(e),C(``),n()},failed:L,openMemory:te,close:t},`suggestions-${I.id}:${I.revision}:${P}`),(0,x.jsxs)(`section`,{className:`detail-section`,children:[(0,x.jsx)(`h3`,{children:`来源与前后文`}),I.sources.length?I.sources.map(e=>(0,x.jsx)(nn,{source:e,openMemory:te},e.id)):(0,x.jsx)(`p`,{className:`quiet`,children:`没有保存的来源消息。`})]}),(0,x.jsxs)(`section`,{className:`detail-section`,children:[(0,x.jsx)(`h3`,{children:`基于它形成的记忆`}),I.derived_memories.length?I.derived_memories.map(e=>(0,x.jsxs)(`button`,{className:`memory-preview`,disabled:O,onClick:()=>te(e.id),children:[(0,x.jsxs)(`span`,{children:[`#`,e.id,` · `,e.content]}),(0,x.jsxs)(`small`,{children:[E(e.lifecycle),e.needs_review?` · 来源已变化,待复核`:``]})]},e.id)):(0,x.jsx)(`p`,{className:`quiet`,children:`暂无派生记忆。`})]}),(0,x.jsxs)(`details`,{className:`history`,children:[(0,x.jsxs)(`summary`,{children:[`修订历史 `,(0,x.jsx)(M,{children:I.revisions.length})]}),I.revisions.length?I.revisions.map(e=>(0,x.jsx)(rn,{revision:e},e.id)):(0,x.jsx)(`p`,{className:`quiet`,children:`还没有修订记录。`})]}),(0,x.jsx)(`a`,{className:`operation-link`,href:`#/operations?object_type=memory&object_id=${e}`,onClick:e=>{O?e.preventDefault():t()},children:`查看此记忆的操作记录`}),I.lifecycle!==`deleted`&&(0,x.jsx)(`div`,{className:`detail-footer`,children:m?(0,x.jsxs)(`div`,{className:`delete-confirm`,children:[(0,x.jsx)(`p`,{children:`确认删除这条记忆?此标识将永久撤销,共享的来源消息与其他记忆保留。`}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`danger-button`,disabled:O||T,onClick:R,children:`确认删除`}),(0,x.jsx)(`button`,{className:`secondary`,disabled:O,onClick:()=>h(!1),children:`取消`})]})]}):(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`secondary`,disabled:O||T||c,onClick:()=>{u(!0),p(I.content),C(``)},children:`编辑正文`}),(0,x.jsx)(`button`,{className:`text-button danger-text`,disabled:O||T||c,onClick:()=>h(!0),children:`删除记忆`})]})})]})]})}function nn({source:e,openMemory:t,initiallyOpen:n=!1,speakerNames:r={}}){return(0,x.jsxs)(`details`,{className:`source`,open:n||void 0,children:[(0,x.jsx)(`summary`,{children:e.kind===`message`?`来源消息 · ${e.message?.sender_name||`原文已不可用`}`:e.kind===`memory`?`来源记忆 #${e.memory?.id||``}`:`初始背景`}),e.message&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{className:`muted`,children:[e.message.entry_name||e.message.entry_id,` ·`,` `,S(e.message.occurred_at)]}),(0,x.jsx)(`blockquote`,{children:e.message.content}),e.message.quote_content&&(0,x.jsxs)(`blockquote`,{children:[`转引原话(原作者:`,r[e.message.quote_author_subject_id||``]||e.message.quote_author_subject_id||`未记录`,`):`,e.message.quote_content]}),(0,x.jsx)(Ue,{media:e.message.media}),(0,x.jsxs)(`details`,{className:`source-context`,children:[(0,x.jsx)(`summary`,{children:`查看前后文`}),e.context?.map(t=>(0,x.jsxs)(`div`,{className:`context-message ${t.id===e.message_id?`highlight`:``}`,children:[(0,x.jsxs)(`small`,{children:[t.sender_name,` · `,S(t.occurred_at)]}),(0,x.jsx)(`p`,{children:t.content}),(0,x.jsx)(Ue,{media:t.media})]},t.id))]})]}),e.memory&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`button`,{className:`memory-preview`,onClick:()=>t(e.memory.id),children:e.memory.content}),(0,x.jsxs)(`p`,{className:`fine-print`,children:[`依据修订 `,e.source_revision,` · `,E(e.memory.lifecycle),e.needs_review?` · 来源已变化,待复核`:``]})]}),e.kind===`initial_setting`&&(0,x.jsx)(`p`,{children:e.note||`角色初始背景材料`})]})}function rn({revision:e}){return(0,x.jsxs)(`article`,{className:`revision`,children:[(0,x.jsxs)(`small`,{children:[S(e.created_at),` ·`,` `,{admin:`管理员`,learning:`学习`,maintenance:`维护`,entry_profile:`画像学习`}[e.actor]||e.actor,` `,`· 修订 `,e.revision_before,` → `,e.revision_after]}),(0,x.jsxs)(`p`,{children:[(0,x.jsx)(`span`,{className:`muted`,children:`修改前`}),` `,String(e.before.content||``)]}),(0,x.jsxs)(`p`,{className:`muted`,children:[`相信程度 `,String(e.before.belief??`—`),` →`,` `,String(e.after.belief??`—`),` · 重要度`,` `,String(e.before.importance??`—`),` →`,` `,String(e.after.importance??`—`)]}),(0,x.jsxs)(`p`,{children:[(0,x.jsx)(`span`,{className:`muted`,children:`修改后`}),` `,e.after.lifecycle===`deleted`?`已删除(撤销对象)`:String(e.after.content||``)]})]})}function an({goal:e,openMemory:t}){let[n,r]=(0,l.useState)(0),i=y(`/goals/${e.id}/sources?limit=30&offset=${n}`);return(0,x.jsxs)(`section`,{className:`panel goals-panel`,"aria-label":`来源消息`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:`来源消息`}),(0,x.jsx)(`button`,{className:`text-button`,onClick:i.refresh,children:`刷新来源消息`})]}),(0,x.jsx)(`p`,{className:`goal-help`,children:`前后文来自同一入口的相邻消息,只读查看不会成为新经历。`}),i.error&&(0,x.jsxs)(A,{error:!0,children:[i.error,(0,x.jsx)(`button`,{onClick:i.refresh,children:`重试来源消息`})]}),!i.data&&!i.error&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取来源消息…`}),i.data?.total===0&&(0,x.jsx)(`p`,{className:`goal-help`,children:`没有关联来源消息。宿主和管理员创建的目标可以没有对话依据。`}),i.data?.items.map(e=>(0,x.jsx)(`div`,{children:e.missing||!e.message?(0,x.jsxs)(`div`,{className:`source`,children:[(0,x.jsxs)(`p`,{children:[`来源消息 #`,e.message_id]}),(0,x.jsx)(`p`,{className:`goal-help`,children:e.notice||`来源消息已清理或不可用`})]}):(0,x.jsx)(nn,{source:{id:e.id,kind:`message`,message_id:e.message_id,message:e.message,context:e.context},openMemory:t})},e.id)),i.data&&(0,x.jsx)(T,{total:i.data.total,offset:n,change:r})]})}var on={content:`正文`,deadline:`截止时间`,deadline_at:`截止时刻`,reminder_minutes:`提醒提前量`,state:`状态`,kind:`类型`,origin:`来源`,entry_id:`产生入口`,people:`涉及的人`,closed_at:`结束时间`,closed_by:`结束操作者`,merged_into:`合并到目标`,source_message_ids:`来源消息`,promise_memories:`承诺记忆及依据修订`,merged_goal_ids:`合并进来的目标`,duplicates:`可能重复关系`,basis_annotations:`依据复核标注`},sn={create:`创建目标`,update:`更新目标`,merge:`合并目标`,duplicate_dismiss:`驳回重复`,possible_duplicate:`标记可能重复`,basis_clear:`清除依据标注`,basis_review:`复核目标依据`,dedup:`目标去重判断`},cn={"goal created":`创建目标`,"goal updated":`更新目标`,"goals merged":`合并目标`,"possible duplicate identified":`发现可能重复的目标`,"possible duplicate dismissed":`驳回可能重复关系`,"goal basis reviewed":`复核目标依据`,"basis warning cleared by administrator":`管理员清除依据标注`},ln={possible:`可能重复`,dismissed:`已驳回`,merged:`已合并`,active:`生效`,cleared:`已清除`,superseded:`已被新标注替代`,resolved:`依据已恢复或移除`};function un({field:e,value:t,catalog:n}){return t===void 0?(0,x.jsx)(x.Fragment,{children:`未记录`}):t===null?(0,x.jsx)(x.Fragment,{children:e===`reminder_minutes`?`使用默认值`:`未设置`}):(e===`deadline`||e===`closed_at`)&&typeof t==`string`?(0,x.jsx)(N,{value:t}):e===`reminder_minutes`?(0,x.jsxs)(x.Fragment,{children:[String(t),` 分钟`]}):e===`people`&&Array.isArray(t)?(0,x.jsx)(x.Fragment,{children:t.map(e=>ht(String(e),n)).join(`、`)||`无`}):e===`entry_id`?(0,x.jsx)(x.Fragment,{children:gt(String(t),n)}):e===`state`?(0,x.jsx)(x.Fragment,{children:lt[t]||String(t)}):e===`kind`?(0,x.jsx)(x.Fragment,{children:ut[t]||String(t)}):e===`origin`?(0,x.jsx)(x.Fragment,{children:dt[t]||String(t)}):e===`closed_by`?(0,x.jsx)(x.Fragment,{children:ve[String(t)]||String(t)}):Array.isArray(t)?(0,x.jsx)(x.Fragment,{children:t.map(e=>typeof e==`object`&&e&&`memory_id`in e?`记忆 #${e.memory_id}(依据修订 ${e.memory_revision})`:`#${e}`).join(`、`)||`无`}):typeof t==`object`?(0,x.jsx)(x.Fragment,{children:Object.entries(t).map(([e,t])=>`#${e}:${ln[String(t)]||String(t)}`).join(`;`)||`无`}):(0,x.jsx)(x.Fragment,{children:String(t)})}function dn({id:e,catalog:t}){let[n,r]=(0,l.useState)(0),[i,a]=(0,l.useState)(0),o=y(`/goals/${e}/revisions?limit=30&offset=${n}`),s=y(`/operations?object_type=goal&object_id=${e}&limit=30&offset=${i}`);return(0,x.jsxs)(`section`,{className:`panel goals-panel`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:`修订与操作记录`}),(0,x.jsx)(`button`,{className:`text-button`,onClick:()=>{o.refresh(),s.refresh()},children:`刷新目标记录`})]}),(0,x.jsxs)(`section`,{"aria-label":`修订历史`,children:[(0,x.jsx)(`h3`,{children:`修订历史`}),(0,x.jsx)(`p`,{className:`goal-help`,children:`每次仅展示发生变化的字段;依据标注和重复关系的变化也会留下修订。`}),o.error&&(0,x.jsxs)(A,{error:!0,children:[o.error,(0,x.jsx)(`button`,{onClick:o.refresh,children:`重试修订历史`})]}),!o.data&&!o.error&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取修订历史…`}),o.data?.history_status===`pre_migration_no_snapshot`&&(0,x.jsxs)(A,{children:[`迁移前无快照:截至修订 `,o.data.missing_through_revision,` `,`的历史值无法还原。`]}),o.data?.items.length===0&&(0,x.jsx)(`p`,{className:`goal-help`,children:`暂无修订快照。`}),o.data?.items.map(e=>(0,x.jsxs)(`article`,{className:`goal-operation`,children:[(0,x.jsxs)(`h4`,{children:[sn[e.action]||_e[`goal_${e.action}`]||e.action,` `,`·`,` `,e.revision_before==null?`新建`:`修订 ${e.revision_before}`,` `,`→ `,e.revision_after]}),(0,x.jsxs)(`p`,{children:[(0,x.jsx)(N,{value:e.created_at}),` ·`,` `,ve[e.actor]||e.actor]}),(0,x.jsx)(`p`,{className:`report-text`,children:cn[e.reason]||e.reason}),(0,x.jsx)(`dl`,{className:`revision-values`,children:Array.from(new Set([...Object.keys(e.before),...Object.keys(e.after)])).map(n=>(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:on[n]||n}),(0,x.jsxs)(`dd`,{children:[(0,x.jsx)(`span`,{className:`muted`,children:`修改前`}),(0,x.jsx)(`p`,{children:(0,x.jsx)(un,{field:n,value:e.before[n],catalog:t})})]}),(0,x.jsxs)(`dd`,{children:[(0,x.jsx)(`span`,{className:`muted`,children:`修改后`}),(0,x.jsx)(`p`,{children:(0,x.jsx)(un,{field:n,value:e.after[n],catalog:t})})]})]},n))})]},e.id)),o.data&&(0,x.jsx)(T,{total:o.data.total,offset:n,change:r})]}),(0,x.jsxs)(`details`,{className:`goal-operations`,children:[(0,x.jsx)(`summary`,{children:`操作记录`}),s.error&&(0,x.jsx)(A,{error:!0,children:s.error}),!s.data&&!s.error&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取操作记录…`}),s.data?.items.length===0&&(0,x.jsx)(`p`,{className:`goal-help`,children:`暂无操作记录。`}),s.data?.items.map(e=>(0,x.jsxs)(`article`,{className:`goal-operation`,children:[(0,x.jsx)(`h3`,{children:_e[e.action]||e.action}),(0,x.jsxs)(`p`,{children:[(0,x.jsx)(N,{value:e.created_at}),` ·`,` `,ve[e.actor]||e.actor]}),typeof e.details.revision_before==`number`&&(0,x.jsxs)(`p`,{children:[`修改前修订 `,e.details.revision_before]}),Array.isArray(e.details.fields)&&(0,x.jsxs)(`p`,{children:[`修改字段:`,e.details.fields.map(e=>on[String(e)]||String(e)).join(`、`)]}),typeof e.details.merged_id==`number`&&(0,x.jsxs)(`p`,{children:[`合并进来的目标 #`,e.details.merged_id]}),typeof e.details.other_id==`number`&&(0,x.jsxs)(`p`,{children:[`驳回与目标 #`,e.details.other_id,` 的可能重复关系`]}),e.action===`goal_create`&&(0,x.jsx)(`p`,{children:`已创建目标。`})]},e.id)),s.data&&(0,x.jsx)(T,{total:s.data.total,offset:i,change:a})]}),(0,x.jsx)(`a`,{className:`text-button`,href:`#/operations?object_type=goal&object_id=${e}`,children:`查看完整操作记录`})]})}function fn({goal:e,otherId:t,locked:n,catalog:r,openGoal:i,merge:a,dismiss:o}){let s=y(`/goals/${t}`);return(0,x.jsxs)(`article`,{className:`goal-duplicate`,children:[(0,x.jsxs)(`h3`,{children:[`可能重复的目标 #`,t]}),s.error&&(0,x.jsxs)(A,{error:!0,children:[s.error,(0,x.jsx)(`button`,{onClick:s.refresh,children:`重试读取重复目标`})]}),!s.data&&!s.error&&(0,x.jsx)(`p`,{children:`正在读取…`}),s.data&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`p`,{className:`goal-content`,children:s.data.content}),(0,x.jsx)(_t,{goal:s.data}),(0,x.jsx)(yt,{goal:s.data,catalog:r}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsxs)(`button`,{className:`secondary`,onClick:()=>i(t),children:[`查看目标 #`,t]}),(0,x.jsxs)(`button`,{disabled:n||s.loading||!!s.error||e.state!==`open`||s.data.state!==`open`||!!s.data.merged_into,onClick:()=>a(s.data),children:[`合并目标 #`,t]}),(0,x.jsxs)(`button`,{disabled:n||s.loading||!!s.error||!!s.data.merged_into,onClick:()=>o(s.data),children:[`驳回重复 #`,t]})]})]})]})}function pn({id:e,catalog:t,openMemory:n,openGoal:r,onBack:i,onChange:a}){let[o,s]=(0,l.useState)(null),[c,u]=(0,l.useState)(null),[d,p]=(0,l.useState)(!1),[m,h]=(0,l.useState)(!1),[b,S]=(0,l.useState)(``),[C,w]=(0,l.useState)(``),T=y(`/goals/${e}`,o||c||m?0:2e3),D=T.data,O=d||m||T.loading||!!T.error;function k(){s(null),u(null),S(``),w(``),h(!1),T.refresh()}async function j(e,t,n=`PATCH`){if(!(d||m)){p(!0),S(``),w(``);try{let i=await g(e,_(n,t));s(null),u(null),T.refresh(),a(),e.endsWith(`/merge`)?(w(`已合并,以下为保留目标。`),r(i.id)):w(e.endsWith(`/dismiss`)?`已驳回可能重复关系`:`目标已更新`)}catch(e){S(v(e)),e instanceof f&&e.status===409&&(h(!0),u(null))}finally{p(!1)}}}return(0,x.jsxs)(`div`,{className:`goal-detail`,children:[(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`text-button`,disabled:d,onClick:i,children:`← 返回目标列表`}),(0,x.jsx)(`button`,{className:`secondary`,disabled:d,onClick:k,children:m?`载入最新目标`:`刷新目标详情`})]}),!c&&(b||T.error)&&(0,x.jsxs)(A,{error:!0,children:[b||T.error,m&&`。请载入最新目标后重新核对;重新加载会放弃当前编辑草稿。`]}),C&&(0,x.jsx)(A,{children:C}),!D&&!T.error&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取目标详情…`}),D&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`section`,{className:`panel goals-panel`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsxs)(`h2`,{children:[`目标 #`,D.id]}),(0,x.jsxs)(`span`,{className:`muted`,children:[`修订 `,D.revision]})]}),(0,x.jsx)(_t,{goal:D}),D.merged_into&&(0,x.jsxs)(A,{children:[`此目标已合并到 #`,D.merged_into,`,原记录与依据保留。`,(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>r(D.merged_into),children:[`查看保留目标 #`,D.merged_into]})]}),o?(0,x.jsx)(wt,{goal:o,catalog:t,busy:d,locked:m||!!T.error,cancel:()=>s(null),submit:t=>void j(`/goals/${e}`,{...t,expected_revision:o.revision})}):(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`p`,{className:`goal-content goal-detail-content`,children:D.content}),(0,x.jsx)(yt,{goal:D,catalog:t}),(0,x.jsxs)(`div`,{className:`goal-time-lines`,children:[(0,x.jsxs)(`p`,{children:[`创建时间:`,(0,x.jsx)(N,{value:D.created_at})]}),(0,x.jsxs)(`p`,{children:[`最后更新:`,(0,x.jsx)(N,{value:D.updated_at})]}),D.state!==`open`&&(0,x.jsxs)(`p`,{children:[`结束时间:`,(0,x.jsx)(N,{value:D.closed_at}),` ·`,` `,D.closed_by?ve[D.closed_by]||D.closed_by:`操作者未知`]})]}),D.overdue&&(0,x.jsx)(`p`,{className:`goal-help`,children:`已过期只是标记,目标仍未结束。可修改截止时间,或明确完成、放弃。`}),!D.merged_into&&(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`secondary`,disabled:O,onClick:()=>{s(D),w(``)},children:`编辑目标`}),D.state===`open`&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`button`,{disabled:O,onClick:()=>u({kind:`completed`,goal:D}),children:`完成目标`}),(0,x.jsx)(`button`,{className:`danger-text`,disabled:O,onClick:()=>u({kind:`abandoned`,goal:D}),children:`放弃目标`})]})]})]})]}),(0,x.jsx)(xt,{goal:D,locked:O||!!o||!!c,openMemory:n,clear:e=>u({kind:`basis_clear`,goal:D,annotation:e})}),(0,x.jsx)(St,{goal:D,openGoal:r}),!D.merged_into&&D.possible_duplicate_ids.length>0&&(0,x.jsxs)(`section`,{className:`panel goals-panel`,children:[(0,x.jsx)(`h2`,{children:`可能重复`}),(0,x.jsx)(`p`,{className:`goal-help`,children:`相似不代表同一件事。核对双方内容、人物和时间后,再决定合并或驳回。`}),D.possible_duplicate_ids.map(n=>(0,x.jsx)(fn,{goal:D,otherId:n,locked:O||!!o,catalog:t,openGoal:r,merge:e=>u({kind:`merge`,goal:D,other:e}),dismiss:t=>void j(`/goals/${e}/duplicates/${t.id}/dismiss`,{expected_revision:D.revision,other_revision:t.revision},`POST`)},`${D.revision}-${n}`))]}),(0,x.jsx)(an,{goal:D,catalog:t,openMemory:n},`sources-${D.revision}`),(0,x.jsxs)(`section`,{className:`panel goals-panel`,children:[(0,x.jsx)(`h2`,{children:`同证据的承诺记忆`}),(0,x.jsx)(`p`,{className:`goal-help`,children:`与目标使用同一来源消息的角色记忆,保留当时依据修订。目标完成不会自动改写记忆。`}),!D.promise_memories.length&&(0,x.jsx)(`p`,{children:`暂无关联记忆。`}),D.promise_memories.map(e=>(0,x.jsxs)(`article`,{className:`goal-operation`,children:[(0,x.jsx)(`p`,{className:`goal-content`,children:e.content}),(0,x.jsxs)(`p`,{className:`muted`,children:[`依据修订 `,e.revision,` · 当前修订`,` `,e.current_revision,` · `,E(e.lifecycle),e.revision===e.current_revision?``:` · 依据已变化`]}),(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>n(e.id),children:[`查看记忆 #`,e.id]})]},e.id))]}),(0,x.jsxs)(`section`,{className:`panel goals-panel`,children:[(0,x.jsx)(`h2`,{children:`合并进来的目标`}),!D.merged_goals.length&&(0,x.jsx)(`p`,{className:`goal-help`,children:`暂无合并记录。`}),D.merged_goals.map(e=>(0,x.jsxs)(`article`,{className:`goal-operation`,children:[(0,x.jsx)(`p`,{className:`goal-content`,children:e.content}),(0,x.jsx)(yt,{goal:e,catalog:t}),(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>r(e.id),children:[`查看原目标 #`,e.id]})]},e.id))]}),(0,x.jsx)(Et,{goalId:D.id,openGoal:r}),(0,x.jsx)(`section`,{className:`panel goals-panel`,children:(0,x.jsxs)(`details`,{children:[(0,x.jsxs)(`summary`,{children:[`提醒计划 · `,D.reminder_plans.length,` 条`]}),(0,x.jsx)(`p`,{className:`goal-help`,children:`计划到点才发布提醒,尚未发布的计划不属于“待取走”提醒。`}),D.reminder_plans.map(e=>(0,x.jsxs)(`div`,{className:`goal-operation`,children:[(0,x.jsxs)(`p`,{children:[ft[e.reminder_kind],` ·`,` `,{scheduled:`待发布`,published:`已发布`,skipped:`已跳过`,cancelled:`已取消`}[e.status]||e.status]}),(0,x.jsx)(N,{value:e.scheduled_at})]},e.id))]})}),(0,x.jsx)(dn,{id:D.id,catalog:t},`operations-${D.revision}`)]}),c&&(0,x.jsxs)(ee,{title:c.kind===`basis_clear`?`清除目标依据标注`:c.kind===`merge`?`确认合并目标`:c.kind===`completed`?`完成目标`:`放弃目标`,closeDisabled:d,onClose:()=>u(null),children:[b&&(0,x.jsx)(A,{error:!0,children:b}),c.kind===`basis_clear`?(0,x.jsxs)(`div`,{className:`goal-confirm`,children:[(0,x.jsx)(`p`,{children:c.annotation.text}),(0,x.jsx)(`p`,{children:`清除只撤下这次观察的标注并保留修订记录,不改变目标正文、状态、截止时间或提醒;依据再次变化时仍可能出现新标注。`}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`primary`,disabled:d||m,onClick:()=>void j(`/goals/${e}/basis-annotations/${c.annotation.id}`,{expected_revision:c.goal.revision},`DELETE`),children:`确认清除依据标注`}),(0,x.jsx)(`button`,{disabled:d,onClick:()=>u(null),children:`取消`})]})]}):c.kind===`merge`?(0,x.jsxs)(`div`,{className:`goal-confirm`,children:[(0,x.jsxs)(`p`,{children:[`保留较早的目标 #`,[c.goal,c.other].sort((e,t)=>Date.parse(e.created_at)-Date.parse(t.created_at)||e.id-t.id)[0].id,`,另一条保留为指向它的合并记录。`]}),(0,x.jsx)(`p`,{children:`来源与待取提醒归入保留目标,重复提醒可能取消;已取走的记录仍保留。保留目标的正文不自动拼接;明确截止时间补入空值,两方都设提前量时采用较大的分钟数。`}),[c.goal,c.other].map(e=>(0,x.jsxs)(`div`,{children:[(0,x.jsxs)(`h3`,{children:[`目标 #`,e.id,` · 修订 `,e.revision]}),(0,x.jsx)(`p`,{className:`goal-content`,children:e.content}),(0,x.jsx)(yt,{goal:e,catalog:t})]},e.id)),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`primary`,disabled:d||m,onClick:()=>void j(`/goals/${e}/duplicates/${c.other.id}/merge`,{expected_revision:c.goal.revision,other_revision:c.other.revision},`POST`),children:`确认合并`}),(0,x.jsx)(`button`,{className:`secondary`,disabled:d,onClick:()=>u(null),children:`取消`})]})]}):(0,x.jsxs)(`div`,{className:`goal-confirm`,children:[(0,x.jsx)(`p`,{children:c.goal.content}),(0,x.jsxs)(`p`,{children:[`确认`,c.kind===`completed`?`完成`:`放弃`,`后,尚未取走的提醒会取消,已取走的记录保留。这是明确改变目标状态。`]}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`primary`,disabled:d||m,onClick:()=>void j(`/goals/${e}`,{state:c.kind,expected_revision:c.goal.revision}),children:c.kind===`completed`?`确认完成`:`确认放弃`}),(0,x.jsx)(`button`,{className:`secondary`,disabled:d,onClick:()=>u(null),children:`取消`})]})]})]})]})}var mn={state:`open`,kind:``,overdue:``,due_soon:``,possible_duplicate:``,entry_id:``,deadline_from:``,deadline_to:``},hn=e=>new URLSearchParams(Object.entries(e).filter(([,e])=>e!==``)).toString();function gn({initialId:e=null,openMemory:t}){let n=y(`/catalog`),[r,i]=(0,l.useState)(e),[a,o]=(0,l.useState)(mn),[s,c]=(0,l.useState)(hn(mn)),[u,d]=(0,l.useState)(0),[f,p]=(0,l.useState)(``),[m,h]=(0,l.useState)(!1),[b,S]=(0,l.useState)(!1),[C,w]=(0,l.useState)(``),[E,D]=(0,l.useState)(null),O=y(r===null?`/goals?${s}&limit=30&offset=${u}`:null,u===0?2e3:0),k=(e,t)=>o(n=>({...n,[e]:t}));function M(e){if(e.preventDefault(),a.deadline_from&&a.deadline_to&&a.deadline_from>a.deadline_to){p(`开始日期不能晚于结束日期`);return}p(``),d(0),c(hn(a)),O.refresh()}async function N(e){if(!b){S(!0),w(``);try{let t=await g(`/goals`,_(`POST`,e));D(t),h(!1),O.refresh()}catch(e){w(v(e))}finally{S(!1)}}}return(0,x.jsxs)(`div`,{className:`goal-workspace`,children:[n.error&&(0,x.jsxs)(A,{error:!0,children:[`人物与入口名称读取失败:`,n.error,(0,x.jsx)(`button`,{className:`text-button`,onClick:n.refresh,children:`重试人物与入口`})]}),r===null?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`section`,{className:`panel goals-panel`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:`目标与询问`}),(0,x.jsx)(`button`,{className:`primary`,onClick:()=>{w(``),h(!0)},children:`创建目标或询问`})]}),(0,x.jsx)(`p`,{className:`goal-help`,children:`所有入口共享目标。管理员创建的目标不自动合并,相似项仅标为“可能重复”。已过期只是标记,需要明确完成或放弃。`}),(0,x.jsxs)(`form`,{className:`goal-filters`,onSubmit:M,children:[(0,x.jsxs)(`label`,{children:[`目标状态`,(0,x.jsxs)(`select`,{value:a.state,onChange:e=>k(`state`,e.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`全部状态`}),Object.entries(lt).map(([e,t])=>(0,x.jsx)(`option`,{value:e,children:t},e))]})]}),(0,x.jsxs)(`label`,{children:[`目标类型`,(0,x.jsxs)(`select`,{value:a.kind,onChange:e=>k(`kind`,e.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`全部类型`}),Object.entries(ut).map(([e,t])=>(0,x.jsx)(`option`,{value:e,children:t},e))]})]}),[[`overdue`,`是否过期`],[`due_soon`,`是否临近`],[`possible_duplicate`,`是否可能重复`]].map(([e,t])=>(0,x.jsxs)(`label`,{children:[t,(0,x.jsxs)(`select`,{value:a[e],onChange:t=>k(e,t.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`全部`}),(0,x.jsx)(`option`,{value:`true`,children:`是`}),(0,x.jsx)(`option`,{value:`false`,children:`否`})]})]},e)),(0,x.jsxs)(`label`,{children:[`产生的入口`,(0,x.jsxs)(`select`,{value:a.entry_id,onChange:e=>k(`entry_id`,e.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`全部入口`}),n.data?.entries.map(e=>(0,x.jsx)(`option`,{value:e.id,children:e.name||e.id},e.id))]})]}),(0,x.jsxs)(`label`,{children:[`截止日期从`,(0,x.jsx)(`input`,{type:`date`,value:a.deadline_from,onChange:e=>k(`deadline_from`,e.target.value)})]}),(0,x.jsxs)(`label`,{children:[`截止日期至`,(0,x.jsx)(`input`,{type:`date`,value:a.deadline_to,onChange:e=>k(`deadline_to`,e.target.value)})]}),(0,x.jsx)(`p`,{className:`goal-help full-width`,children:`日期范围按角色时区解释,结束日期包含当天。临近范围包含已过期目标;选择“是否过期:否”可排除。`}),(0,x.jsxs)(`div`,{className:`actions full-width`,children:[(0,x.jsx)(`button`,{className:`primary`,children:`筛选目标`}),(0,x.jsx)(`button`,{type:`button`,className:`secondary`,onClick:O.refresh,children:`刷新目标`}),(0,x.jsx)(`button`,{type:`button`,className:`text-button`,onClick:()=>{o(mn),c(hn(mn)),d(0),p(``),O.refresh()},children:`重置筛选`})]})]})]}),E&&(0,x.jsx)(bt,{receipt:E,openGoal:i}),(f||O.error)&&(0,x.jsxs)(A,{error:!0,children:[f||O.error,O.error&&O.data&&`。以下为上次读取结果,可能尚未更新。`]}),(0,x.jsx)(`div`,{className:`list-heading`,children:(0,x.jsx)(`span`,{children:O.data?`共 ${O.data.total} 个目标与询问`:O.error?`目标暂不可读取`:`正在读取目标…`})}),O.data?.items.length===0&&(0,x.jsx)(j,{title:`当前范围没有目标或询问`,children:`可以创建目标,或在试用对话中让角色答应一件事,学习后在这里查看。`}),(0,x.jsx)(`div`,{className:`goal-grid`,children:O.data?.items.map(e=>(0,x.jsxs)(`article`,{className:`panel goals-panel`,children:[(0,x.jsx)(_t,{goal:e}),(0,x.jsx)(`h3`,{className:`goal-content`,children:e.content}),(0,x.jsx)(yt,{goal:e,catalog:n.data}),(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>i(e.id),children:[`查看目标 #`,e.id]})]},e.id))}),O.data&&(0,x.jsx)(T,{total:O.data.total,offset:u,change:d})]}):(0,x.jsx)(pn,{id:r,catalog:n.data,openMemory:t,openGoal:i,onBack:()=>i(null),onChange:O.refresh},r),m&&(0,x.jsxs)(ee,{title:`创建目标或询问`,onClose:()=>h(!1),closeDisabled:b,children:[(0,x.jsx)(`p`,{className:`goal-help`,children:`手动创建只会标记可能重复,保留每一条目标供你核对。`}),C&&(0,x.jsx)(A,{error:!0,children:C}),(0,x.jsx)(wt,{catalog:n.data,busy:b,submit:e=>void N(e),cancel:()=>h(!1)})]})]})}var _n={host:`宿主提供`,first_report:`自首次报告起`},vn={start:`开始活动`,replace:`更换活动`,update:`更新状态`,heartbeat:`心跳`,end:`结束活动`},yn={activity:`活动`,mood:`情绪`,started_at:`开始时间`,start_time_basis:`开始时间依据`};function bn(e){let t=Math.max(0,Math.floor(e));return[[Math.floor(t/86400),`天`],[Math.floor(t/3600)%24,`小时`],[Math.floor(t/60)%60,`分钟`],[t%60,`秒`]].filter(([e])=>e!==0).map(([e,t])=>`${e} ${t}`).join(` `)||`0 秒`}function xn(e,t=!1){return e===null?`无`:typeof e==`boolean`?e?`是(true)`:`否(false)`:e===``?`空文本`:t&&typeof e==`string`?`“${e}”`:String(e)}function Sn({state:e}){return(0,x.jsx)(x.Fragment,{children:e.mood===null?e.mood_updated_at?`已清空`:`未报告`:xn(e.mood)})}function Cn({error:e,retained:t}){return e?(0,x.jsxs)(A,{error:!0,children:[`当前状态读取失败:`,e,`。`,t&&`以下为上次读取结果,可能尚未更新。`]}):null}function wn({state:e}){return(0,x.jsxs)(x.Fragment,{children:[e.possibly_stale&&(0,x.jsxs)(`div`,{className:`state-stale`,children:[(0,x.jsx)(M,{tone:`warning`,children:`可能过时`}),(0,x.jsxs)(`p`,{children:[`超过 `,e.stale_after_minutes,` `,`分钟未收到报告,保留宿主最后报告的活动。`]})]}),(0,x.jsxs)(`dl`,{className:`state-fields`,children:[(0,x.jsxs)(`div`,{className:`full-width`,children:[(0,x.jsx)(`dt`,{children:`当前活动`}),(0,x.jsx)(`dd`,{className:`state-activity`,children:e.activity}),(0,x.jsxs)(`dd`,{className:`state-field-time`,children:[`活动更新时间:`,(0,x.jsx)(N,{value:e.activity_updated_at})]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`情绪`}),(0,x.jsx)(`dd`,{children:(0,x.jsx)(Sn,{state:e})}),(0,x.jsxs)(`dd`,{className:`state-field-time`,children:[`情绪更新时间:`,(0,x.jsx)(N,{value:e.mood_updated_at})]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`活动持续时长`}),(0,x.jsx)(`dd`,{children:bn(e.duration_seconds)})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`开始时间`}),(0,x.jsx)(`dd`,{children:(0,x.jsx)(N,{value:e.started_at})})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`开始时间依据`}),(0,x.jsx)(`dd`,{children:_n[e.start_time_basis]})]}),(0,x.jsxs)(`div`,{className:`full-width`,children:[(0,x.jsx)(`dt`,{children:`最后更新时间`}),(0,x.jsx)(`dd`,{children:(0,x.jsx)(N,{value:e.updated_at})})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`最后报告宿主`}),(0,x.jsx)(`dd`,{children:e.host??`未知`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`最后报告入口`}),(0,x.jsx)(`dd`,{children:e.entry_id??`未知`})]})]}),(0,x.jsx)(`h3`,{children:`细节`}),Object.keys(e.details).length?(0,x.jsx)(`dl`,{className:`state-fields state-detail-fields`,children:Object.entries(e.details).map(([e,t])=>(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:e}),(0,x.jsx)(`dd`,{children:xn(t.value)}),(0,x.jsxs)(`dd`,{className:`state-field-time`,children:[`更新时间:`,(0,x.jsx)(N,{value:t.updated_at})]})]},e))}):(0,x.jsx)(`p`,{className:`quiet`,children:`暂无细节报告`})]})}function Tn(){let e=y(`/state`,2e3),t=e.data;return(0,x.jsxs)(`div`,{className:`state-summary`,children:[(0,x.jsx)(Cn,{error:e.error,retained:t!==null}),e.error&&(0,x.jsx)(`button`,{className:`text-button`,onClick:e.refresh,children:`重试当前状态`}),!t&&!e.error&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取当前状态…`}),t&&(t.activity?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`p`,{className:`state-summary-activity`,children:t.activity}),t.possibly_stale&&(0,x.jsx)(M,{tone:`warning`,children:`可能过时`}),(0,x.jsxs)(`dl`,{className:`state-summary-fields`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`情绪`}),(0,x.jsx)(`dd`,{children:(0,x.jsx)(Sn,{state:t})})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`活动持续时长`}),(0,x.jsx)(`dd`,{children:bn(t.duration_seconds)})]})]}),t.start_time_basis===`first_report`&&(0,x.jsx)(`p`,{className:`muted`,children:`持续时长自首次报告起计算。`})]}):(0,x.jsx)(`p`,{className:`quiet`,children:`暂无宿主报告的当前活动`})),(0,x.jsx)(`a`,{className:`text-button`,href:`#/state`,children:`查看状态与报告历史`})]})}function En({report:e}){let t=[...Object.entries(yn).flatMap(([t,n])=>{let r=e.changes[t];return r?[{key:t,label:n,...r}]:[]}),...Object.entries(e.changes.details||{}).map(([e,t])=>({key:`details.${e}`,label:`细节 · ${e}`,...t}))],n=(e,t)=>t===null?`无`:e===`started_at`?(0,x.jsx)(N,{value:String(t)}):e===`start_time_basis`?_n[t]||String(t):xn(t,!0);return(0,x.jsxs)(`article`,{className:`state-report`,"aria-label":`报告 #${e.id}`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsxs)(`h3`,{children:[vn[e.action],` · `,e.action]}),(0,x.jsxs)(`span`,{className:`muted`,children:[`报告 #`,e.id,` · `,e.method]})]}),(0,x.jsx)(`p`,{className:`state-report-time`,children:(0,x.jsx)(N,{value:e.reported_at})}),(0,x.jsxs)(`dl`,{className:`state-report-source`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`宿主`}),(0,x.jsx)(`dd`,{children:e.host??`未知`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`入口`}),(0,x.jsx)(`dd`,{children:e.entry_id??`未知`})]})]}),t.length?(0,x.jsx)(`dl`,{className:`state-changes`,children:t.map(e=>(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:e.label}),(0,x.jsxs)(`dd`,{children:[(0,x.jsx)(`span`,{className:`muted`,children:`原值`}),(0,x.jsx)(`span`,{children:n(e.key,e.before)})]}),(0,x.jsxs)(`dd`,{children:[(0,x.jsx)(`span`,{className:`muted`,children:`现值`}),(0,x.jsx)(`span`,{children:n(e.key,e.after)})]})]},e.key))}):(0,x.jsx)(`p`,{className:`muted`,children:`无字段值变化,本次报告仍已记录。`})]})}function Dn(){let e=y(`/state`,2e3),[t,n]=(0,l.useState)(0),r=y(`/state/reports?limit=30&offset=${t}`,t===0?2e3:0);return(0,x.jsx)(x.Fragment,{children:(0,x.jsxs)(`div`,{className:`state-page`,children:[(0,x.jsxs)(`section`,{className:`panel state-panel`,"aria-labelledby":`current-state-title`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{id:`current-state-title`,children:`当前状态`}),(0,x.jsx)(`button`,{className:`text-button`,disabled:e.loading,onClick:e.refresh,children:`刷新当前状态`})]}),(0,x.jsx)(`p`,{className:`state-help`,children:`活动持续时长与情绪、细节的更新时间分别记录。时间按角色时区显示,保留 UTC 偏移。`}),(0,x.jsx)(Cn,{error:e.error,retained:e.data!==null}),!e.data&&!e.error&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取当前状态…`}),e.data&&(e.data.activity?(0,x.jsx)(wn,{state:e.data}):(0,x.jsx)(j,{title:`暂无宿主报告的当前活动`,children:`宿主开始活动后会显示在这里;结束活动后,报告历史仍会保留。`}))]}),(0,x.jsxs)(`section`,{className:`panel state-panel`,"aria-labelledby":`state-reports-title`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsxs)(`h2`,{id:`state-reports-title`,children:[`报告历史`,r.data?` · ${r.data.total} 条`:``]}),(0,x.jsx)(`button`,{className:`text-button`,disabled:r.loading,onClick:()=>t===0?r.refresh():n(0),children:`刷新报告历史`})]}),(0,x.jsxs)(`p`,{className:`state-help`,children:[`按报告顺序从新到旧排列,列出字段值的实际变化。心跳也会保留记录。`,t===0?`最新一页自动刷新。`:`较早报告暂停自动刷新;刷新历史可回到最新一页。`]}),r.error&&(0,x.jsxs)(A,{error:!0,children:[`报告历史读取失败:`,r.error,`。`,r.data&&`以下为上次读取的报告。`]}),!r.data&&!r.error&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取报告历史…`}),r.data?.items.length===0&&(0,x.jsx)(j,{title:`暂无报告历史`}),r.data?.items.map(e=>(0,x.jsx)(En,{report:e},e.id)),r.data&&(0,x.jsx)(T,{total:r.data.total,offset:t,limit:30,change:n})]})]})})}function On({initialQuery:e=``,openMemory:t=()=>{}}){let n=new URLSearchParams(e),r=Number(n.get(`id`)),[i,a]=(0,l.useState)(Number.isSafeInteger(r)&&r>0?r:null),o=n.get(`tab`),[s,c]=(0,l.useState)(o===`goals`||o===`notifications`?o:`state`);function u(e){a(e),c(`goals`)}return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{className:`page-heading`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`p`,{className:`eyebrow`,children:`此刻与接下来的事`}),(0,x.jsx)(`h1`,{children:`状态与目标`}),(0,x.jsx)(`p`,{children:`当前状态完全由宿主报告,管理员不能编辑。状态与目标由所有入口共享。`})]})}),(0,x.jsxs)(`nav`,{className:`learning-tabs`,"aria-label":`状态与目标分区`,children:[(0,x.jsx)(`button`,{"aria-pressed":s===`state`,onClick:()=>c(`state`),children:`当前状态`}),(0,x.jsx)(`button`,{"aria-pressed":s===`goals`,onClick:()=>{a(null),c(`goals`)},children:`目标与询问`}),(0,x.jsx)(`button`,{"aria-pressed":s===`notifications`,onClick:()=>c(`notifications`),children:`提醒`})]}),s===`state`?(0,x.jsx)(Dn,{}):s===`goals`?(0,x.jsx)(gn,{initialId:i,openMemory:t},i):(0,x.jsx)(Et,{openGoal:u})]})}function kn({goals:e,error:t=``}){let n=y(`/notifications?status=pending&limit=1&offset=0`,2e3),r=e?.filter(e=>e.state===`open`&&!e.merged_into).slice(0,10);return(0,x.jsxs)(`section`,{className:`panel trial-goals`,"aria-labelledby":`trial-goals-title`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{id:`trial-goals-title`,children:`未结束的目标与询问`}),(0,x.jsx)(M,{children:r?.length??`—`})]}),(0,x.jsx)(`p`,{className:`goal-help`,children:`角色答应一件事 → 学习形成目标 → 到点发布提醒。可在学习结束后点击目标查看来源;全部入口共享,优先展示临近、过期的目标,最多 10 个。`}),t&&(0,x.jsxs)(A,{error:!0,children:[`目标暂不可读取:`,t,`。`,r&&`以下为上次读取结果。`]}),!r&&!t&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取目标…`}),r?.length===0&&(0,x.jsx)(`p`,{className:`quiet`,children:`暂无未结束的目标或询问`}),r?.map(e=>(0,x.jsxs)(`a`,{className:`trial-goal-link`,href:`#/state?tab=goals&id=${e.id}`,children:[(0,x.jsx)(_t,{goal:e}),(0,x.jsx)(`p`,{className:`goal-content`,children:e.content}),(0,x.jsx)(`small`,{children:(0,x.jsx)(vt,{goal:e})}),(0,x.jsx)(`span`,{className:`text-button`,children:`查看目标与来源 ↗`})]},e.id)),n.error&&(0,x.jsxs)(`p`,{className:`danger-text`,children:[`提醒暂不可读取:`,n.error,(0,x.jsx)(`button`,{className:`text-button`,onClick:n.refresh,children:`重试提醒`})]}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`a`,{className:`text-button`,href:`#/state?tab=goals`,children:`查看全部目标与询问`}),(0,x.jsxs)(`a`,{className:`text-button`,href:`#/state?tab=notifications`,children:[`查看提醒`,n.data?.total===void 0?``:` · ${n.data.total} 条待取走`]})]}),(0,x.jsx)(`p`,{className:`goal-help`,children:`提醒被宿主取走不代表已送达或目标完成。这里的自动刷新不会取走提醒。`})]})}function An(e){let t=y(`/trial`),[n,r]=(0,l.useState)(``),[i,a]=(0,l.useState)(!1),[o,s]=(0,l.useState)(``),[c,u]=(0,l.useState)(`group`),[d,f]=(0,l.useState)(``),[p,m]=(0,l.useState)(!1),h=t.data?.entries||[],b=(0,l.useMemo)(()=>{if(!t.data)return null;let e=new Map;for(let n of t.data.speakers){let t=e.get(n.id);e.set(n.id,{...n,is_default:!!(n.is_default||t?.is_default)})}return{...t.data,speakers:[...e.values()]}},[t.data]);(0,l.useEffect)(()=>{!n&&h.length&&r(h[0].id)},[n,h]);async function S(n){n.preventDefault(),m(!0),f(``);try{let n=await g(`/trial/entries`,_(`POST`,{name:o,kind:c}));r(n.id),a(!1),s(``),t.refresh(),e.refreshStatus()}catch(e){f(v(e))}finally{m(!1)}}return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`page-heading`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`p`,{className:`eyebrow`,children:`在相处中,慢慢记住`}),(0,x.jsx)(`h1`,{children:`试用对话`}),(0,x.jsx)(`p`,{children:`聊一件小事,看看它如何成为记忆。`})]}),(0,x.jsx)(M,{tone:`purple`,children:h.find(e=>e.id===n)?`${tt(h.find(e=>e.id===n).pace)}学习`:`试用入口`})]}),(t.error||d)&&(0,x.jsx)(A,{error:!0,children:t.error||d}),(0,x.jsxs)(`div`,{className:`entry-bar`,children:[(0,x.jsxs)(`label`,{children:[`当前入口`,(0,x.jsxs)(`select`,{"aria-label":`当前入口`,value:n,onChange:e=>r(e.target.value),children:[(0,x.jsx)(`option`,{value:``,disabled:!0,children:`选择试用入口`}),h.map(e=>(0,x.jsx)(`option`,{value:e.id,children:e.name},e.id))]})]}),(0,x.jsx)(`button`,{className:`secondary`,onClick:()=>a(!i),children:`+ 新建入口`}),(0,x.jsx)(`span`,{className:`muted entry-tip`,children:`记忆共同积累,近期消息各自保留`})]}),(i||t.data&&!h.length)&&(0,x.jsxs)(`form`,{className:`inline-form panel`,onSubmit:S,children:[(0,x.jsxs)(`label`,{children:[`入口名称`,(0,x.jsx)(`input`,{value:o,onChange:e=>s(e.target.value),placeholder:`如:试用群聊 A`,required:!0,maxLength:100})]}),(0,x.jsxs)(`label`,{children:[`入口类型`,(0,x.jsxs)(`select`,{value:c,onChange:e=>u(e.target.value),children:[(0,x.jsx)(`option`,{value:`group`,children:`群聊`}),(0,x.jsx)(`option`,{value:`private`,children:`私聊`})]})]}),(0,x.jsx)(`button`,{className:`primary`,disabled:p||!o.trim(),children:`创建入口`})]}),!t.data&&!t.error&&(0,x.jsx)(`p`,{className:`muted`,children:`正在读取试用入口…`}),n&&b&&(0,x.jsx)(jn,{entryId:n,catalog:b,refreshCatalog:t.refresh,...e},n)]})}function jn({entryId:e,catalog:t,refreshCatalog:n,status:r,openMemory:i,refreshStatus:a}){let o=y(`/trial/entries/${e}`,2e3),[s,c]=(0,l.useState)(t.speakers.find(e=>e.is_default)?.id||``);(0,l.useEffect)(()=>{s||c(t.speakers.find(e=>e.is_default)?.id||``)},[s,t.speakers]);let[u,d]=(0,l.useState)(!1),[p,m]=(0,l.useState)(``),[h,b]=(0,l.useState)(``),C=`iris.trial.replies.${e}`,[w,T]=(0,l.useState)(()=>{try{return window.localStorage.getItem(C)===`true`}catch{return!1}});function E(e){T(e);try{window.localStorage.setItem(C,String(e))}catch{}}let[D,ee]=(0,l.useState)(!1),[N,P]=(0,l.useState)(``),[F,I]=(0,l.useState)(``),[te,L]=(0,l.useState)(``),[ne,R]=(0,l.useState)(null),[re,ie]=(0,l.useState)(null),[ae,oe]=(0,l.useState)(null),[se,ce]=(0,l.useState)(``),[le,ue]=(0,l.useState)([]),[de,z]=(0,l.useState)(null),[B,V]=(0,l.useState)(!1),[fe,pe]=(0,l.useState)(null),me=qe(),he=(0,l.useRef)(null);(0,l.useEffect)(()=>()=>he.current?.abort(),[]);function H(e){if(!D){I(``);try{me.add(e)}catch(e){I(v(e))}}}let U=o.data,ge=r?.entries.find(t=>t.entry_id===e),_e=[...new Map([...le,...U?.messages||[]].map(e=>[e.id,e])).values()].sort((e,t)=>e.id-t.id),ve=(0,l.useRef)(null),ye=(0,l.useRef)(!0),be=_e.at(-1)?.id;(0,l.useEffect)(()=>{ye.current&&ve.current&&(ve.current.scrollTop=ve.current.scrollHeight)},[be]);async function xe(e){e.preventDefault(),I(``);try{let e=await g(`/trial/speakers`,_(`POST`,{name:p}));n(),c(e.id),d(!1),m(``)}catch(e){I(v(e))}}async function Se(t,n){P(n?`角色正在回复…`:`正在准备回复材料…`),ce(``),oe(null),ie(null);try{if(n){R(t);let n=await g(`/trial/entries/${e}/reply`,_(`POST`,{message_id:t}));ie(n.prepared),oe(n.diagnostic||null),n.reused&&ce(n.diagnostic?`已复用回复 #${n.diagnostic.reply_message_id};以下诊断来自发布该回复时的准备。`:`已复用已发布回复;原诊断未记录或已按保留期限清理,无法还原当时的判断。`),R(null)}else ie(await g(`/trial/entries/${e}/prepare`,_(`POST`)))}catch(e){let t=e instanceof f&&e.code===`reply_failed`?e.result:void 0;throw t?.diagnostic?(oe(t.diagnostic),ce(`角色回复失败;以下为本次已经完成的回复准备诊断。`)):ce(`本次回复准备结果未返回,无法展示召回判断状态。`),e}}async function Ce(t){if(t.preventDefault(),!h.trim()&&!me.images.length||D||!s)return;let n=new AbortController;he.current=n,ee(!0),I(``),L(``),ie(null),oe(null),ce(``),R(null),P(`正在发送…`);let r=me.images.map(e=>e.key).join(`,`),i=fe?.content===h&&fe.speaker===s&&fe.imageKeys===r?fe:{content:h,speaker:s,imageKeys:r,key:crypto.randomUUID()};pe(i);try{let t=await me.upload(n.signal,P);n.signal.throwIfAborted(),P(`正在发送…`);let r=await g(`/trial/entries/${e}/messages`,{..._(`POST`,{speaker_id:s,content:h,dedupe_key:i.key,media_ids:t}),signal:n.signal});n.signal.throwIfAborted(),b(``),me.clear(),pe(null),L(`消息已接收,学习结果请看右侧批次。`),o.refresh(),a(),await Se(r.message_id,w)}catch(e){n.signal.aborted||I(v(e))}finally{n.signal.aborted||(ee(!1),P(``),o.refresh(),a())}}async function we(){if(ne){ee(!0),I(``);try{await Se(ne,!0)}catch(e){I(v(e))}finally{ee(!1),P(``),o.refresh(),a()}}}async function Te(){I(``);try{let t=await g(`/trial/entries/${e}/learn`,_(`POST`));L(t.paused?`已请求立即学习;模型暂停中,恢复后处理。`:`已请求立即学习,完成情况请看批次状态。`),a()}catch(e){I(v(e))}}async function Ee(){V(!0);try{let t=await g(`/trial/entries/${e}?before=${_e[0].id}`);ue([...t.messages,...le]),z(t.has_older)}catch(e){I(v(e))}finally{V(!1)}}return(0,x.jsxs)(`div`,{className:`trial-grid`,children:[(0,x.jsxs)(`section`,{className:`panel conversation`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:U?.entry.name||`正在读取对话…`}),(0,x.jsxs)(`span`,{className:`muted`,children:[U?.entry.kind===`private`?`私聊`:`群聊`,` · 图文试用`]})]}),(0,x.jsxs)(`span`,{className:`live-label`,children:[(0,x.jsx)(`i`,{}),` `,o.error?`连接中断`:U?`入口已就绪`:`正在连接`]})]}),(0,x.jsxs)(`div`,{className:`messages`,"aria-label":`对话记录`,ref:ve,onScroll:e=>{let t=e.currentTarget;ye.current=t.scrollHeight-t.scrollTop-t.clientHeight<60},children:[(de??U?.has_older)&&(0,x.jsx)(`button`,{className:`text-button older`,onClick:Ee,disabled:B,children:`查看更早消息`}),!_e.length&&(0,x.jsx)(j,{title:`从一句话开始`,children:`例如「我下周三去上海出差」。实时节奏会在短暂停顿后开始学习。`}),_e.map(e=>(0,x.jsxs)(`article`,{className:`message ${e.kind===`self_output`?`role`:`user`}`,children:[(0,x.jsxs)(`div`,{className:`message-meta`,children:[(0,x.jsx)(`strong`,{children:e.kind===`self_output`?t.role_name:e.sender_name}),(0,x.jsx)(`time`,{children:S(e.received_at)})]}),(0,x.jsxs)(`div`,{className:`bubble`,children:[e.content,(0,x.jsx)(Ue,{media:e.media})]}),(0,x.jsxs)(`div`,{className:`message-state ${[`abandoned`,`refused`].includes(e.learning_state)?`danger-text`:``}`,children:[O(e.learning_state),e.batch_id&&` · 批次 #${e.batch_id}`,e.kind===`self_output`?` · 角色实际输出`:``]})]},e.id))]}),(0,x.jsxs)(`div`,{className:`composer`,children:[(F||o.error)&&(0,x.jsx)(A,{error:!0,children:F||o.error}),te&&(0,x.jsx)(`p`,{className:`receipt`,role:`status`,children:te}),ne&&!D&&(0,x.jsx)(`button`,{className:`secondary`,onClick:we,children:`重试角色回复`}),u&&(0,x.jsxs)(`form`,{className:`inline-form compact`,onSubmit:xe,children:[(0,x.jsxs)(`label`,{children:[`虚拟发言人姓名`,(0,x.jsx)(`input`,{value:p,maxLength:100,required:!0,onChange:e=>m(e.target.value)})]}),(0,x.jsx)(`button`,{className:`secondary`,disabled:!p.trim(),children:`添加发言人`})]}),(0,x.jsxs)(`form`,{onSubmit:Ce,children:[(0,x.jsxs)(`div`,{className:`composer-controls`,children:[(0,x.jsxs)(`label`,{className:`speaker-label`,children:[`发言人`,(0,x.jsx)(`select`,{"aria-label":`发言人`,disabled:D,value:s,onChange:e=>c(e.target.value),children:t.speakers.map(e=>(0,x.jsxs)(`option`,{value:e.id,children:[e.name,t.speakers.filter(t=>t.name===e.name).length>1?` · ${e.id.slice(0,6)}`:``]},e.id))})]}),(0,x.jsx)(`button`,{type:`button`,className:`text-button`,onClick:()=>d(!u),children:`+ 添加`}),(0,x.jsxs)(`label`,{className:`switch`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:w,disabled:D,onChange:e=>E(e.target.checked)}),(0,x.jsx)(`span`,{children:`角色回复`})]})]}),(0,x.jsx)(`textarea`,{"aria-label":`消息内容`,placeholder:`说说正在发生的事…`,value:h,onChange:e=>b(e.target.value),onPaste:e=>{let t=Array.from(e.clipboardData.files);t.length&&(e.preventDefault(),H(t))},rows:3,disabled:D}),(0,x.jsx)(Je,{images:me.images,busy:D,add:H,remove:me.remove}),(0,x.jsxs)(`div`,{className:`composer-bottom`,children:[(0,x.jsx)(`span`,{className:`muted`,children:N||`接收后自动排队学习`}),(0,x.jsxs)(`button`,{className:`primary`,disabled:D||!h.trim()&&!me.images.length||!s,"aria-label":`发送消息`,children:[D?`处理中…`:`发送`,` `,(0,x.jsx)(`span`,{"aria-hidden":!0,children:`↑`})]})]})]})]})]}),(0,x.jsxs)(`aside`,{className:`trial-aside`,"aria-label":`学习与回复上下文`,children:[(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:`学习动态`}),(0,x.jsx)(`button`,{className:`text-button`,onClick:Te,children:`立即学习`})]}),(0,x.jsxs)(`div`,{className:`queue-summary`,children:[(0,x.jsx)(`strong`,{children:ge?.pending_count??`—`}),(0,x.jsx)(`span`,{children:`条待学习`}),(0,x.jsx)(M,{tone:ge?.current_batch?`purple`:``,children:ge?.current_batch?`批次 #${ge.current_batch.id}`:`等待新消息`})]}),ge?.current_batch&&(0,x.jsxs)(`p`,{className:`batch-state`,children:[k(ge.current_batch),ge.current_batch.next_retry_at&&(0,x.jsxs)(`small`,{children:[`下次尝试:`,S(ge.current_batch.next_retry_at)]})]}),ge?.latest_batch&&(0,x.jsxs)(`div`,{className:`batch-result`,children:[(0,x.jsxs)(`span`,{className:`muted`,children:[`最近结束 · #`,ge.latest_batch.id]}),(0,x.jsx)(`p`,{children:k(ge.latest_batch)}),ge.latest_batch.last_error&&(0,x.jsx)(`small`,{children:ge.latest_batch.last_error})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`学习成功也可能没有值得记住的内容。`}),(0,x.jsx)(rt,{value:ge?.queue_wait})]}),(0,x.jsx)(kn,{goals:U?.goals,error:o.error}),(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:`新形成与更新`}),(0,x.jsx)(M,{children:U?.recent_memories.length||0})]}),(0,x.jsx)(`p`,{className:`muted section-help`,children:`本入口最近 12 条,点击查看来源`}),U?.recent_memories.length?U.recent_memories.map(e=>(0,x.jsxs)(`button`,{className:`memory-preview`,onClick:()=>i(e.id),children:[(0,x.jsxs)(`span`,{className:`tiny-label`,children:[e.kind,` · #`,e.id]}),(0,x.jsx)(`span`,{children:e.content}),(0,x.jsxs)(`small`,{children:[S(e.updated_at),` `,(0,x.jsx)(`span`,{"aria-hidden":!0,children:`↗`})]})]},e.id)):(0,x.jsx)(`p`,{className:`quiet`,children:`暂时还没有形成记忆。`})]}),(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:`这次回复准备`}),(0,x.jsx)(`span`,{className:`muted`,children:re?`${re.memories.length} 条召回`:ae?`当次诊断`:se?`未返回材料`:D?`准备中`:`等待发送`})]}),!re&&!ae?(0,x.jsx)(`p`,{className:`quiet`,children:se||(D?`正在准备回复材料…`:`发送消息后展示召回结果。`)}):(0,x.jsxs)(x.Fragment,{children:[se&&(0,x.jsx)(A,{children:se}),(0,x.jsx)(st,{value:ae?.judgment||re?.judgment}),ae&&(0,x.jsx)(Be,{value:ae,openMemory:i}),re?.memories.length===0&&(0,x.jsx)(`p`,{className:`quiet`,children:`没有额外召回记忆,近期原文仍在对话上下文中。`}),re?.memories.map(e=>(0,x.jsxs)(`div`,{children:[(0,x.jsxs)(`button`,{className:`memory-preview`,onClick:()=>i(e.id),children:[(0,x.jsx)(M,{tone:`purple`,children:e.reason===`person_highlight`?`人物要点`:`与当前内容相关`}),(0,x.jsx)(`span`,{children:e.content})]}),(0,x.jsx)(ct,{value:e.subject_annotations})]},e.id)),(0,x.jsx)(`p`,{className:`fine-print`,children:`被召回不等于被使用,也不代表内容已证实。`}),re?.hints.filter(e=>e.code!==`recall_judgment`).map((e,t)=>(0,x.jsx)(`p`,{className:`fine-print`,children:e.message},t))]})]}),(0,x.jsxs)(`section`,{className:`panel context-panel`,children:[(0,x.jsx)(`h2`,{children:`角色上下文`}),(0,x.jsx)(Ye,{}),(0,x.jsxs)(`details`,{open:!0,children:[(0,x.jsx)(`summary`,{children:`当前状态`}),(0,x.jsx)(Tn,{})]})]})]})]})}function Mn({value:e}){return e?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`table`,{className:`image-usage`,children:[(0,x.jsx)(`caption`,{children:`图片理解用量`}),(0,x.jsx)(`thead`,{children:(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`th`,{scope:`col`,children:`指标`}),(0,x.jsx)(`th`,{scope:`col`,children:`今日`}),(0,x.jsx)(`th`,{scope:`col`,children:`本周`})]})}),(0,x.jsx)(`tbody`,{children:[[`调用次数`,e=>e.calls],[`token(输入+输出)`,e=>e.tokens.toLocaleString()],[`累计耗时`,e=>C(e.duration_ms)],[`失败调用`,e=>e.failures],[`其中被拒绝`,e=>e.refusals],[`超时调用`,e=>e.timeouts],[`未返回 token 用量的调用`,e=>e.calls_without_usage]].map(([t,n])=>(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`th`,{scope:`row`,children:t}),(0,x.jsx)(`td`,{children:n(e.today)}),(0,x.jsx)(`td`,{children:n(e.week)})]},t))})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`按角色时区统计,本周自周一开始。含重试、连接测试和恢复探测;未返回的 token 用量不作推算。`})]}):(0,x.jsx)(`p`,{children:`暂时无法读取图片用量。`})}var Nn={manual:`手动维护`,scheduled:`定时维护`,catchup:`启动补跑`},Pn={decay:`衰减与状态转换`,expiry:`到期删除`,dependency:`依据失效扣减`,messages:`消息清理`,retry:`批次重试`,consolidation:`模型整理`,persona:`persona 更新`,goals:`目标依据复核`},Fn={decayed:`衰减`,forgotten:`遗忘`,restored:`恢复`,deleted:`删除`,dependencies_weakened:`依据扣减`,messages_deleted:`清理消息`,batches_retried:`重试批次`,questions_expired:`询问到期结束`,checked:`检查项目`,skipped:`跳过`,failed:`失败`,merged:`合并`,conflicts:`待核对建议(矛盾或合并)`,dependencies_reviewed:`依赖复核建议`,persona_published:`persona 已发布`,persona_pending:`persona 待确认`,person_summary:`人物摘要处理`,goals_reviewed:`目标依据标注变化`,model_calls:`模型调用`},In={pinned:`已置顶`,revision_conflict:`修订冲突`,forgotten:`已遗忘`,deleted:`已删除`,no_longer_due:`尚未到期`,already_applied:`已经扣减`,dependency_removed:`依据关系已移除`,no_longer_eligible:`不再符合清理条件`,referenced:`仍有引用`,batch_state_changed:`批次状态已变化`,already_retried:`已自动重试过`,batch_date_changed:`批次日期已变化`,target_messages_cleared:`目标消息已清理`};function Ln({summary:e}){return(0,x.jsx)(`dl`,{className:`maintenance-counts`,children:Object.entries(e).filter(([e])=>![`model_step_budget`,`backlog_trimmed`].includes(e)).map(([e,t])=>(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:Fn[e]||e}),(0,x.jsx)(`dd`,{children:t.count})]},e))})}function Rn({run:e}){return(0,x.jsxs)(`div`,{className:`lifecycle-stack`,children:[(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(M,{tone:e.state===`completed`?`green`:`purple`,children:e.state===`completed`?`已完成`:`运行中`}),(0,x.jsx)(`span`,{children:Nn[e.trigger]||e.trigger}),(0,x.jsxs)(`span`,{className:`muted`,children:[`#`,e.id]})]}),(0,x.jsxs)(`p`,{children:[`开始:`,w(e.created_at),` · 完成:`,e.finished_at?w(e.finished_at):`尚未完成`]})]})}function zn({openMemory:e,initialRun:t}){let n=y(`/maintenance?limit=1&offset=0`,5e3),[r,i]=(0,l.useState)(!1),[a,o]=(0,l.useState)(0),s=y(r?`/maintenance?limit=10&offset=${a}`:null,5e3),[c,u]=(0,l.useState)(t||null),[d,f]=(0,l.useState)(!1),[p,m]=(0,l.useState)(!1),[h,b]=(0,l.useState)(``),S=n.data?.items[0];(0,l.useEffect)(()=>{let e=()=>{let e=location.hash;if(e.split(`?`)[0]!==`#/status`)return;let t=Number(new URLSearchParams(e.split(`?`)[1]||``).get(`run`));Number.isSafeInteger(t)&&t>0&&u(t)};return addEventListener(`hashchange`,e),()=>removeEventListener(`hashchange`,e)},[]);async function C(){if(!p){m(!0),b(``);try{let e=await g(`/maintenance`,_(`POST`,{}));f(!1),u(e.run_id),n.refresh(),s.refresh()}catch(e){b(v(e))}finally{m(!1)}}}return(0,x.jsxs)(`section`,{className:`panel maintenance-panel`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:`梦境整理与记忆维护`}),(0,x.jsx)(`button`,{className:`secondary`,disabled:p,onClick:()=>f(!0),children:`手动维护`})]}),(h||n.error||s.error)&&(0,x.jsxs)(A,{error:!0,children:[h||n.error||s.error,(0,x.jsx)(`button`,{className:`text-button`,onClick:()=>{n.refresh(),s.refresh()},children:`刷新维护记录`})]}),d&&(0,x.jsxs)(`div`,{className:`delete-confirm`,children:[(0,x.jsx)(`p`,{children:`手动维护也计一次衰减,并执行遗忘、到期删除、消息清理和批次重试。还会按本次设置调用模型进行整理与 persona 与人物摘要更新,并复核目标依据。已有未完成的维护时继续该次运行。`}),(0,x.jsxs)(`div`,{className:`actions`,children:[(0,x.jsx)(`button`,{className:`primary`,disabled:p,onClick:()=>void C(),children:p?`正在请求…`:`确认运行维护`}),(0,x.jsx)(`button`,{className:`secondary`,disabled:p,onClick:()=>f(!1),children:`取消维护`})]})]}),!n.data&&!n.error&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取维护记录…`}),n.data&&!S&&(0,x.jsx)(j,{title:`尚无维护记录`}),S&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`h3`,{className:`maintenance-subheading`,children:`最近一次维护`}),(0,x.jsx)(Rn,{run:S}),Object.keys(S.summary).length?(0,x.jsx)(Ln,{summary:S.summary}):(0,x.jsx)(`p`,{className:`quiet`,children:`维护进行中,可在报告中查看当前数量。`}),(0,x.jsx)(`button`,{className:`text-button`,onClick:()=>u(S.id),children:`查看最近维护报告`})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`维护不中断接收和学习。报告逐项保留实际变化、模型建议和失败;检查及跳过数量按阶段和原因汇总。`}),(0,x.jsx)(`button`,{className:`text-button`,"aria-expanded":r,onClick:()=>i(e=>!e),children:`历史维护`}),r&&(0,x.jsxs)(`div`,{className:`lifecycle-stack`,children:[!s.data&&!s.error&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取历史维护…`}),s.data?.items.length===0&&(0,x.jsx)(`p`,{className:`quiet`,children:`没有历史维护。`}),s.data?.items.map(e=>(0,x.jsxs)(`div`,{className:`maintenance-history-row`,children:[(0,x.jsxs)(`span`,{children:[`#`,e.id,` · `,w(e.created_at),` ·`,` `,Nn[e.trigger]||e.trigger,` ·`,` `,e.state===`completed`?`已完成`:`运行中`]}),(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>u(e.id),children:[`查看报告 #`,e.id]})]},e.id)),s.data&&(0,x.jsx)(T,{total:s.data.total,limit:10,offset:a,change:o})]}),c!==null&&(0,x.jsx)(Bn,{id:c,close:()=>{u(null),t&&(location.hash=`#/status`)},openMemory:t=>{u(null),location.hash.startsWith(`#/status?`)&&window.history.replaceState(null,``,`#/status`),e(t)}},c)]})}function Bn({id:e,close:t,openMemory:n}){let[r,i]=(0,l.useState)(3e3),a=y(`/maintenance/${e}`,r),o=a.data;(0,l.useEffect)(()=>{o?.state===`completed`&&i(0)},[o?.state]);let s=o?[[`变化的记忆`,o.items.filter(e=>e.memory_id!=null&&e.outcome!==`failed`&&e.phase!==`consolidation`)],[`清理的消息`,o.items.filter(e=>e.outcome===`messages_deleted`)],[`重试的批次`,o.items.filter(e=>e.outcome===`batches_retried`)],[`失败项`,o.items.filter(e=>e.outcome===`failed`)]]:[];return(0,x.jsxs)(ee,{title:`维护报告 #${e}`,onClose:t,children:[a.error&&(0,x.jsxs)(A,{error:!0,children:[a.error,(0,x.jsx)(`button`,{className:`text-button`,onClick:a.refresh,children:`重新读取报告`})]}),!o&&!a.error&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取维护报告…`}),o&&(0,x.jsxs)(`div`,{className:`lifecycle-stack`,children:[(0,x.jsx)(Rn,{run:o}),(0,x.jsxs)(`p`,{className:`muted`,children:[`角色时区:`,o.timezone,` · 当前阶段:`,o.state===`completed`?`已结束`:Object.values(Pn)[o.phase]||`生成报告`]}),(0,x.jsx)(Ln,{summary:o.summary}),(0,x.jsxs)(`details`,{children:[(0,x.jsx)(`summary`,{children:`检查阶段与跳过原因`}),Object.entries(o.summary.checked?.by_phase||{}).map(([e,t])=>(0,x.jsxs)(`p`,{children:[Pn[e]||e,`:`,t]},e)),Object.entries(o.summary.skipped?.reasons||{}).map(([e,t])=>(0,x.jsxs)(`p`,{children:[In[e]||B(e),`:`,t]},e))]}),(0,x.jsx)(Gt,{data:o,openMemory:n}),s.map(([t,r])=>(0,x.jsx)(Vn,{name:t,items:r,openMemory:n},`${e}:${t}`))]})]})}function Vn({name:e,items:t,openMemory:n}){let[r,i]=(0,l.useState)(0);return(0,x.jsxs)(`section`,{className:`detail-section`,"aria-label":e,children:[(0,x.jsxs)(`h3`,{children:[e,` `,(0,x.jsx)(M,{children:t.length})]}),!t.length&&(0,x.jsx)(`p`,{className:`quiet`,children:`暂无记录。`}),t.slice(r,r+30).map(e=>(0,x.jsxs)(`article`,{className:`maintenance-item`,children:[e.memory_id==null?(0,x.jsxs)(`strong`,{children:[e.phase===`messages`?`消息`:e.phase===`persona`?`persona 任务`:e.phase===`goals`?`目标`:`批次`,` `,`#`,e.object_id]}):(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>n(e.memory_id),children:[`记忆 #`,e.memory_id]}),(0,x.jsxs)(`p`,{children:[Pn[e.phase]||e.phase,` ·`,` `,Fn[e.outcome]||e.outcome]}),typeof e.details.before==`number`&&(0,x.jsxs)(`p`,{children:[`保留强度:`,e.details.before,` → `,e.details.after]}),e.details.transition&&(0,x.jsxs)(`p`,{children:[`状态变为:`,E(e.details.transition)]}),e.details.source_memory_id!==void 0&&(0,x.jsxs)(`p`,{children:[`失效依据:记忆 #`,e.details.source_memory_id]}),e.reason&&(0,x.jsx)(`p`,{className:`danger-text`,children:In[e.reason]||B(e.reason)}),(0,x.jsx)(`small`,{children:w(e.created_at)})]},`${e.phase}:${e.item_key}`)),(0,x.jsx)(T,{total:t.length,offset:r,change:i})]})}var Hn={learning:`学习`,learning_repair:`学习 JSON 修正`,trial_reply:`试用回复`,trial_reply_repair:`回复 JSON 修正`,embedding:`向量生成`,image_understanding:`图片理解`,retrieval_query:`召回查询`,health_probe:`健康探测`,recall_judge:`召回判断`,goal_dedup_judge:`目标去重判断`,consolidation_merge:`整理合并判断`,consolidation_merge_repair:`整理合并 JSON 修正`,consolidation_conflict:`整理矛盾建议`,consolidation_conflict_repair:`整理矛盾 JSON 修正`,consolidation_dependency:`整理依赖复核`,consolidation_dependency_repair:`整理依赖 JSON 修正`,persona_generate:`persona 生成`,persona_check:`persona 检查`,connection_check:`连接测试`};function Un({data:e,openMemory:t,initialQuery:n=``}){let r=y(`/catalog`),i=y(`/settings`,5e3);if(!e)return(0,x.jsx)(j,{title:`正在读取运行状态`});let a=Number(new URLSearchParams(n).get(`run`)),o=e.learning_latency_24h,s=e.models.find(e=>e.purpose===`image_understanding`),c=e.models.filter(e=>e.result_category!==`success`),l=new Map(r.data?.entries.map(e=>[e.id,e.name]));return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`page-heading`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`p`,{className:`eyebrow`,children:`每一步,都看得见`}),(0,x.jsx)(`h1`,{children:`运行状态`}),(0,x.jsx)(`p`,{children:`服务、模型和学习队列的当前情况。`})]}),(0,x.jsx)(M,{tone:e.scheduler.running?`green`:`danger`,children:e.scheduler.running?`调度运行中`:`调度未运行`})]}),(0,x.jsxs)(`div`,{className:`stat-grid`,children:[(0,x.jsxs)(`section`,{className:`panel metric`,children:[(0,x.jsx)(`span`,{children:`待学习消息`}),(0,x.jsx)(`strong`,{children:e.entries.reduce((e,t)=>e+t.pending_count,0)}),(0,x.jsxs)(`small`,{children:[e.scheduler.max_concurrent,` 个学习批次可同时运行`]})]}),(0,x.jsxs)(`section`,{className:`panel metric`,children:[(0,x.jsx)(`span`,{children:`今日 token 用量`}),(0,x.jsx)(`strong`,{children:e.usage.today.tokens.toLocaleString()}),(0,x.jsxs)(`small`,{children:[e.usage.today.calls,` 次请求 ·`,` `,e.usage.today.reasoning_tokens.toLocaleString(),` 推理 token(包含在总量内)`]})]}),(0,x.jsxs)(`section`,{className:`panel metric`,children:[(0,x.jsx)(`span`,{children:`近 24 小时学习 P95`}),(0,x.jsx)(`strong`,{children:C(o.p95_ms)}),(0,x.jsxs)(`small`,{children:[o.count,` 次学习调用`]})]}),(0,x.jsxs)(`section`,{className:`panel metric`,children:[(0,x.jsx)(`span`,{children:`近 24 小时学习超时`}),(0,x.jsx)(`strong`,{children:o.timeouts}),(0,x.jsxs)(`small`,{children:[`共享学习总预算 `,(0,x.jsxs)(`b`,{children:[e.timeouts_seconds.learning,` 秒`]})]})]})]}),(0,x.jsx)(zn,{openMemory:t,initialRun:Number.isSafeInteger(a)&&a>0?a:void 0}),(0,x.jsxs)(`div`,{className:`status-grid`,children:[(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:`模型用途`}),(0,x.jsx)(`span`,{className:`muted`,children:`实时健康状态`})]}),Object.entries(e.model_health).map(([t,n])=>(0,x.jsxs)(`div`,{className:`model-row`,children:[(0,x.jsxs)(`div`,{className:`model-title`,children:[(0,x.jsx)(`strong`,{children:Se[t]||t}),(0,x.jsx)(M,{tone:n.state===`normal`?`green`:`danger`,children:D(n.state)})]}),(0,x.jsx)(`p`,{className:`muted`,children:t===`chat`?`用于学习与角色回复`:t===`recall_judge`?`判断相关候选能否回答当前请求`:t===`goal_dedup_judge`?`跨入口判断目标是否为同一件事`:t===`image_understanding`?`为没有宿主说明的图片补充理解;失败时使用占位继续学习`:`用于记忆向量与语义检索`}),t===`recall_judge`&&(0,x.jsxs)(x.Fragment,{children:[e.timeouts_seconds.recall_judge!=null&&(0,x.jsxs)(`p`,{children:[`总预算 `,e.timeouts_seconds.recall_judge,` 秒(含排队)`]}),i.error&&(0,x.jsxs)(`p`,{className:`muted`,children:[`判断开关状态暂时无法读取。`,(0,x.jsx)(`button`,{onClick:i.refresh,children:`重新读取`})]}),i.data?.recall_judge?.enabled===!1?(0,x.jsx)(`p`,{children:`召回判断已关闭,保留基础召回。`}):n.state!==`normal`&&(0,x.jsx)(`p`,{children:`召回判断暂停或退避时降级,保留仍有效的原召回。`}),n.retry_at&&(0,x.jsxs)(`p`,{children:[`退避截止:`,S(n.retry_at)]}),(0,x.jsx)(`a`,{href:`#/settings`,children:`管理召回判断设置`})]}),t===`goal_dedup_judge`&&(0,x.jsxs)(x.Fragment,{children:[i.error&&(0,x.jsxs)(`p`,{className:`muted`,children:[`判断设置暂时无法读取。`,(0,x.jsx)(`button`,{onClick:i.refresh,children:`重新读取`})]}),i.data?.goal_dedup_judge&&(0,x.jsxs)(`p`,{children:[`判断预算 `,i.data.goal_dedup_judge.budget_seconds,` `,`秒(含排队) · 并发`,` `,i.data.goal_dedup_judge.concurrency,` · 排队上限`,` `,i.data.goal_dedup_judge.queue_limit]}),i.data?.goal_dedup_judge?.enabled===!1?(0,x.jsx)(`p`,{children:`目标去重判断已关闭,使用确定性规则。`}):(0,x.jsx)(`p`,{children:`模型暂停、退避或判断失败时先保留目标,等待复核。管理员创建的目标不会自动合并。`}),n.retry_at&&(0,x.jsxs)(`p`,{children:[`退避截止:`,S(n.retry_at)]}),(0,x.jsx)(`a`,{href:`#/settings`,children:`管理目标去重判断设置`})]}),t===`image_understanding`&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{children:[n.inherited?`沿用对话模型`:`使用独立图片理解配置`,` · 健康状态按图片理解用途独立记录。`]}),n.timeout_seconds!=null&&(0,x.jsxs)(`p`,{children:[`整批图片理解预算 `,n.timeout_seconds,` 秒(含排队与重试)`]}),n.retry_at&&(0,x.jsxs)(`p`,{children:[`退避截止:`,S(n.retry_at)]}),(0,x.jsx)(`a`,{href:`#/settings`,children:`管理图片理解设置`})]}),n.last_error&&(0,x.jsxs)(`p`,{className:`error-summary`,children:[`最近错误:`,n.last_error]}),n.next_probe_at&&(0,x.jsxs)(`small`,{children:[`下次探测:`,S(n.next_probe_at)]})]},t)),!e.model_health.image_understanding&&i.data?.models?.image_understanding?.enabled===!1&&(0,x.jsx)(`p`,{children:`图片理解未启用,没有宿主说明的图片以“未理解”占位继续学习。`}),(e.model_health.image_understanding||s||e.usage.by_purpose?.image_understanding)&&(0,x.jsxs)(`div`,{className:`model-row`,children:[(0,x.jsx)(`h3`,{children:`图片理解调用与用量`}),(0,x.jsx)(Mn,{value:e.usage.by_purpose?.image_understanding}),s&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{children:[`最近调用:`,s.model,` ·`,` `,C(s.duration_ms),` ·`,` `,s.result_category===`success`?`成功`:`未成功`]}),(0,x.jsx)(`p`,{className:`muted`,children:S(s.created_at)})]})]})]}),(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsx)(`h2`,{children:`用量与学习`}),(0,x.jsxs)(`dl`,{className:`status-facts`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`每日 token 上限`}),(0,x.jsx)(`dd`,{children:e.budget.limit==null?`不限`:e.budget.limit.toLocaleString()})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`未报告 token 的调用`}),(0,x.jsxs)(`dd`,{children:[e.usage.today.calls_without_usage,` 次`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`学习耗时 P50 / 最大`}),(0,x.jsxs)(`dd`,{children:[C(o.p50_ms),` / `,C(o.max_ms)]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`缺少向量的记忆`}),(0,x.jsxs)(`dd`,{children:[e.missing_vectors,` 条`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`记忆缺口`}),(0,x.jsxs)(`dd`,{children:[e.memory_gap_count,` 段`]})]})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`今日按角色时区统计。服务商未报告的用量和在途调用不计入已知总量;未配置价格,暂不估算费用。`})]})]}),(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:`入口队列`}),(0,x.jsx)(`span`,{className:`muted`,children:`接收、学习和形成记忆分别记录`})]}),e.entries.length?(0,x.jsx)(`div`,{className:`table-scroll`,children:(0,x.jsxs)(`table`,{children:[(0,x.jsx)(`thead`,{children:(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`th`,{children:`入口`}),(0,x.jsx)(`th`,{children:`待学习`}),(0,x.jsx)(`th`,{children:`当前批次`}),(0,x.jsx)(`th`,{children:`过滤与等待`}),(0,x.jsx)(`th`,{children:`最近结束的批次`}),(0,x.jsx)(`th`,{children:`未记住的消息`})]})}),(0,x.jsx)(`tbody`,{children:e.entries.map(e=>(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`td`,{children:l.get(e.entry_id)||e.entry_id}),(0,x.jsx)(`td`,{children:e.pending_count}),(0,x.jsx)(`td`,{children:k(e.current_batch)}),(0,x.jsx)(`td`,{children:(0,x.jsx)(rt,{value:e.queue_wait})}),(0,x.jsx)(`td`,{children:k(e.latest_batch)}),(0,x.jsx)(`td`,{children:e.gap_message_count||0})]},e.entry_id))})]})}):(0,x.jsx)(`p`,{className:`quiet`,children:`暂无入口。`})]}),(0,x.jsxs)(`div`,{className:`status-grid`,children:[(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsx)(`h2`,{children:`最近学习调用`}),e.learning_calls_24h.length?(0,x.jsx)(`div`,{className:`call-list`,children:e.learning_calls_24h.slice(0,12).map((e,t)=>(0,x.jsxs)(`div`,{className:`call`,children:[(0,x.jsxs)(`span`,{children:[`批次 #`,e.batch_id,` · `,Hn[e.purpose]||e.purpose]}),(0,x.jsx)(`strong`,{children:C(e.duration_ms)}),e.timed_out?(0,x.jsx)(M,{tone:`danger`,children:`超时`}):e.error_summary?(0,x.jsx)(M,{tone:`danger`,children:`失败`}):(0,x.jsx)(M,{tone:`green`,children:`调用完成`}),e.error_summary&&(0,x.jsx)(`small`,{children:e.error_summary})]},t))}):(0,x.jsx)(`p`,{className:`quiet`,children:`近 24 小时没有学习调用。`}),(0,x.jsx)(`p`,{className:`fine-print`,children:`模型调用完成不等于批次成功;JSON 校验和记忆写入结果请看批次。`})]}),(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsx)(`h2`,{children:`错误摘要`}),(0,x.jsx)(`p`,{className:`muted section-help`,children:`来自现有状态接口的最近用途错误与调度错误`}),e.scheduler.last_error&&(0,x.jsx)(A,{error:!0,children:e.scheduler.last_error}),c.map(e=>(0,x.jsxs)(`div`,{className:`error-entry`,children:[(0,x.jsxs)(`strong`,{children:[Hn[e.purpose]||e.purpose,` · `,e.model]}),(0,x.jsx)(`p`,{children:e.error_summary||e.result_category}),(0,x.jsx)(`small`,{children:S(e.created_at)})]},e.purpose)),!c.length&&!e.scheduler.last_error&&(0,x.jsx)(`p`,{className:`quiet`,children:`最近的用途调用没有错误。`})]})]})]})}var Wn=e=>e.execution_state===`split`||e.state===`split`,Gn=e=>({full:`完整`,target_only:`仅目标`})[e||``]||`未记录`;function Kn(e,t){return Wn(e)?[`waiting`,`running`].includes(e.state)?`拆小重学中`:e.state===`succeeded`?`拆小重学已完成`:e.state===`split`?`历史请求被拒绝 · 已拆分`:`拆小重学结束 · 仍有缺口`:e.parent_batch_id&&[`waiting`,`running`].includes(e.state)?`拆小重学中`:e.state===`refused`&&(t===1||t===void 0&&e.parent_batch_id)?`该单消息的学习请求被拒绝`:e.relearning?`重新学习中`:k(e)}function qn(e){return new Set([...e.attempts.flatMap(e=>e.calls.map(e=>e.id)),...e.unassigned_calls.map(e=>e.id)]).size}function Jn({batch:e}){let t=e.split;if(!t)return null;let n=t.waiting_messages+t.running_messages,r=t.refused_messages+t.abandoned_messages,i=n+r+t.succeeded_messages,a=e.state===`succeeded`&&n===0&&r===0&&t.gap_count===0;return(0,x.jsxs)(`div`,{className:`split-progress`,children:[(0,x.jsxs)(`div`,{className:`split-metrics`,"aria-label":`子树消息进度`,children:[(0,x.jsxs)(`span`,{children:[e.parent_batch_id?`本子树目标`:`原目标`,` `,i,` 条`]}),(0,x.jsxs)(`span`,{children:[`已成功 `,t.succeeded_messages,` 条`]}),(0,x.jsxs)(`span`,{children:[`仍在补学 `,n,` 条`]}),(0,x.jsxs)(`span`,{children:[`最终被拒绝 `,t.refused_messages,` 条`]}),(0,x.jsxs)(`span`,{children:[`最终失败 `,r,` 条`]}),(0,x.jsxs)(`span`,{children:[`剩余缺口 `,t.gap_count,` 处`]})]}),(0,x.jsxs)(`p`,{children:[`批次树节点 `,t.node_count,` 个`]}),(0,x.jsx)(`p`,{className:`muted`,children:`消息结果仅统计末端子批次;最终失败包含拒绝与尝试用尽。父批次的历史拒绝单独保留。`}),a&&(0,x.jsx)(`p`,{className:`split-complete`,children:`全部成功,无缺口`}),!a&&(0,x.jsx)(`p`,{children:`缺口在对应子批次成功后消失;每处缺口可能包含多条消息。`})]})}function Yn({batch:e,onOpen:t}){return e.parent_batch_id?(0,x.jsxs)(`div`,{className:`batch-links`,children:[e.root_batch_id&&(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>t(e.root_batch_id),"aria-label":`查看原始批次 #${e.root_batch_id}`,children:[`原始批次 #`,e.root_batch_id,` →`]}),e.parent_batch_id!==e.root_batch_id&&(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>t(e.parent_batch_id),"aria-label":`查看父批次 #${e.parent_batch_id}`,children:[`父批次 #`,e.parent_batch_id,` →`]}),(0,x.jsxs)(`span`,{children:[`路径 `,e.split_path]})]}):null}function Xn(e){return e.count?`第 ${e.start+1}${e.count>1?`–${e.end}`:``} 条 · 共 ${e.count} 条`:`没有目标消息`}function Zn({id:e}){let t=y(`/batches/${e}/tree?limit=1&offset=0`,3e3),n=t.data?.items.find(t=>t.id===e);return(0,x.jsxs)(x.Fragment,{children:[t.error&&(0,x.jsxs)(A,{error:!0,children:[t.error,(0,x.jsx)(`button`,{onClick:t.refresh,children:`重试读取目标范围`})]}),n&&(0,x.jsxs)(`p`,{children:[`原始目标范围:`,Xn(n.target_range)]})]})}function Qn({batch:e}){let t=Wn(e);return(0,x.jsxs)(`div`,{className:`batch-node-facts`,children:[(0,x.jsxs)(`p`,{children:[`上下文模式:`,Gn(e.context_mode)]}),t?(0,x.jsxs)(`p`,{children:[`拆分前已计 `,e.attempt_count??0,` 次尝试;执行已交给子批次。`]}):(0,x.jsxs)(`p`,{children:[`当前额度:已用 `,e.attempt_count??0,` / 4,剩余`,` `,e.attempts_remaining??Math.max(0,4-(e.attempt_count??0)),` `,`次`]}),e.state===`waiting`&&!t&&(0,x.jsx)(`p`,{children:`排队原因未提供;请结合入口和运行状态查看。`}),!t&&(0,x.jsxs)(`p`,{children:[`下次重试:`,e.next_retry_at?S(e.next_retry_at):`无定时时间`]})]})}function $n({id:e}){let t=y(`/batches/${e}`,3e3);return(0,x.jsxs)(x.Fragment,{children:[t.error&&(0,x.jsxs)(A,{error:!0,children:[t.error,(0,x.jsx)(`button`,{onClick:t.refresh,children:`重试读取历史`})]}),t.data?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{children:[`历史尝试编号:`,t.data.attempts.length?t.data.attempts.map(e=>e.number).join(`、`):`暂无已完成尝试`]}),(0,x.jsxs)(`p`,{children:[`本节点实际模型调用 `,qn(t.data),` 次`]}),(0,x.jsx)(`p`,{className:`muted`,children:`含学习与 JSON 修正请求及未归入尝试的调用;不等于本轮已用额度。`})]}):(0,x.jsx)(`p`,{children:`正在读取历史…`})]})}function er({id:e}){let[t,n]=(0,l.useState)(!1);return(0,x.jsxs)(`details`,{className:`node-history`,onToggle:e=>n(e.currentTarget.open),children:[(0,x.jsxs)(`summary`,{children:[`历史尝试与调用 · #`,e]}),t&&(0,x.jsx)($n,{id:e})]})}function tr({id:e,onOpen:t}){let[n,r]=(0,l.useState)(!1),[i,a]=(0,l.useState)(0),[o,s]=(0,l.useState)([]),c=y(n?`/batches/${e}/tree?limit=100&offset=${i}`:null,3e3),u=c.data;return(0,x.jsxs)(`div`,{className:`split-tree`,children:[(0,x.jsx)(`button`,{className:`secondary`,"aria-expanded":n,"aria-controls":`split-tree-${e}`,"aria-label":`${n?`收起`:`展开`}拆分树 #${e}`,onClick:()=>r(!n),children:n?`收起拆分树`:`展开拆分树`}),n&&(0,x.jsxs)(`section`,{id:`split-tree-${e}`,"aria-label":`拆分树 #${e}`,children:[(0,x.jsx)(`p`,{className:`muted`,children:`范围按原始批次的目标消息顺序,从第 1 条开始;路径中 0 为左支、1 为右支。节点可展开历史尝试,或进入详情查看消息与调用。`}),c.error&&(0,x.jsxs)(A,{error:!0,children:[c.error,(0,x.jsx)(`button`,{onClick:c.refresh,children:`重试读取拆分树`})]}),u?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{children:[`显示节点 `,u.total?u.offset+1:0,`–`,u.offset+u.items.length,` / `,u.total]}),(0,x.jsx)(`ol`,{className:`batch-tree-nodes`,children:u.items.filter(e=>!o.some(t=>e.split_path!==t&&e.split_path?.startsWith(t))).map(n=>{let r=Wn(n),i=n.split_path||``,a=n.target_range,c=o.includes(i);return(0,x.jsxs)(`li`,{className:`batch-tree-node`,style:{"--tree-depth":Math.min(i.length,3)},children:[(0,x.jsxs)(`div`,{className:`section-title`,children:[(0,x.jsxs)(`strong`,{children:[`#`,n.id,` · `,r?`拆分父批次`:`子批次`]}),(0,x.jsx)(M,{children:Kn(n,a.count)})]}),(0,x.jsx)(`p`,{children:Xn(a)}),(0,x.jsxs)(`p`,{children:[`路径 `,i||`根`]}),n.parent_batch_id&&(0,x.jsxs)(`button`,{className:`text-button`,"aria-label":`查看父批次 #${n.parent_batch_id}`,onClick:()=>t(n.parent_batch_id),children:[`父批次 #`,n.parent_batch_id,` →`]}),(0,x.jsx)(Qn,{batch:n}),n.gap&&(0,x.jsxs)(`p`,{children:[`仍有记忆缺口`,[`waiting`,`running`].includes(n.state)?` · 拆小重学中`:``]}),n.relearn_blocked_reason&&!r&&(0,x.jsx)(`p`,{children:n.relearn_blocked_reason}),(0,x.jsxs)(`div`,{className:`batch-links`,children:[r&&(0,x.jsx)(`button`,{className:`text-button`,"aria-expanded":!c,"aria-label":`${c?`展开`:`折叠`}子批次 #${n.id}`,onClick:()=>s(c?o.filter(e=>e!==i):[...o,i]),children:c?`展开子批次`:`折叠子批次`}),n.id!==e&&(0,x.jsxs)(`button`,{className:`text-button`,"aria-label":`查看批次 #${n.id}`,onClick:()=>t(n.id),children:[`查看详情`,n.can_relearn&&!r?` / 重新学习`:``,` `,`→`]})]}),(0,x.jsx)(er,{id:n.id})]},n.id)})}),u.total>u.limit&&(0,x.jsxs)(`div`,{className:`learning-pagination tree-pagination`,children:[(0,x.jsx)(`button`,{disabled:u.offset===0,onClick:()=>{a(Math.max(0,u.offset-u.limit)),s([])},children:`上一页节点`}),(0,x.jsx)(`button`,{disabled:u.offset+u.items.length>=u.total,onClick:()=>{a(u.offset+u.limit),s([])},children:`下一页节点`})]}),(0,x.jsx)(`p`,{className:`muted`,children:`分页统计的是批次树节点;实际模型调用次数在各节点历史中单独显示。`})]}):(0,x.jsx)(`p`,{children:`正在读取拆分树…`})]})]})}var nr={topic:`常聊话题`,saying:`群内说法`,rule:`明确群规`};function rr({value:e}){return e.kind?(0,x.jsxs)(`div`,{className:`profile-item-content`,children:[(0,x.jsxs)(`p`,{children:[(0,x.jsx)(M,{children:nr[e.kind]||e.kind}),` `,(0,x.jsx)(`strong`,{children:e.label})]}),e.meaning&&(0,x.jsxs)(`p`,{children:[`含义:`,e.meaning]}),e.quotes?.map((e,t)=>(0,x.jsxs)(`blockquote`,{children:[e.text,(0,x.jsxs)(`footer`,{children:[`消息 #`,e.message_id,` ·`,` `,e.field===`content`?`消息正文`:e.field===`quote`?`转引原话`:`原话归属未记录`,` `,`· 原作者:`,e.speaker_name||e.speaker||`未记录`]})]},t))]}):(0,x.jsx)(`p`,{className:`entry-profile-content`,children:e.text})}var ir=e=>({small:`小`,medium:`中`,large:`大`})[e]||e,ar=e=>({periodic:`定期更新`,regenerate:`重新生成`,edit:`管理员编辑`,rollback:`回滚`})[e]||e,or=e=>({published:`已发布`,candidate:`待确认`,rejected:`被拒绝`,failed:`失败`,conflict:`版本冲突`,skipped:`已跳过`})[e]||e,sr={message_cleaned:`原消息已清理`,message_changed:`原消息已变化`,memory_unavailable:`记忆已失效或删除`,memory_changed:`记忆已修改`,visibility_changed:`记忆可见范围已变化`,memory_sources_changed:`记忆来源已变化`,disabled:`本入口画像已关闭`,entry_kind:`私聊入口不生成画像`,daily_limit:`今天已经尝试过生成,请在下一个角色本地日期重试`,insufficient_messages:`首次生成需要最近 14 天至少 50 条消息`,no_evidence:`没有可用的本入口依据`,unconfigured:`尚未配置对话模型`,daily_token_limit:`达到今日 token 上限`,current_version_changed:`当前已发布版本已变化,结果未发布`,settings_changed:`画像设置已变化,结果未发布`,evidence_changed:`依据在生成期间发生变化,结果未发布`,interrupted:`服务中断,任务未完成`,unexpected_error:`生成失败,请查看运行状态`,timeout:`模型调用超时`,invalid_output:`模型输出格式无效,未发布`,invalid_sentence:`候选句格式无效`,too_many_deleted:`检查删除了超过 30% 的候选句`,too_short:`正文低于旧版摘要的最少字数要求`,too_long:`正文超过该版本的字数上限`,superseded:`已被新候选或编辑取代`,paused:`对话用途已暂停`,invalid_items:`候选条目列表格式无效`,invalid_item:`条目类型、名称或含义格式无效`,invalid_quotes:`每个模型条目需要 1—3 条引语`,invalid_quote:`引语格式无效或超过 100 字`,invalid_quote_reference:`引语消息编号不在本入口材料中`,quote_not_found:`引语不是消息正文或转引原话的连续片段`,invalid_evidence_reference:`含义引用的记忆依据无效`,duplicate_item:`条目重复`,account_identifier:`包含账号标识或长数字号段`,insufficient_topic_recurrence:`常聊话题缺少跨日期的独立消息正文依据`,too_many_items:`条目数超过 6 条(包含手写条目)`,token_budget:`超过画像的估算 token 预算`,empty:`检查后没有可保留内容`,administrator_rejected:`管理员拒绝`},cr=(e,t)=>e===`too_many_deleted`?t===2?`检查累计删除了超过 50% 的模型条目`:t===1?`检查删除了超过 30% 的候选句`:`检查删除比例超出该版本上限,请查看版本检查记录`:sr[e]||e,lr=e=>e.memory_id?`记忆 #${e.memory_id} · 修订 ${e.revision}`:`消息 #${e.message_id}`,ur={evidence_budget_exceeded:`必要依据超出单次检查预算,暂不能完成这次检查`,basis_changed:`依据已变化,需要重新检查`,reject:`本次自动检查未通过`,invalid_output:`模型返回的检查结果格式无效,未据此准入`,timeout:`本次模型调用超时,已保留此前处理结果`,rule_scope_not_established:`尚未建立这条群规的适用范围依据`,bundle_rejected:`同组检查已有页面未通过,后续页已取消`,stale_check:`检查所用的正文或依据已变化,需要重新检查`,call_budget:`本轮调用额度已用完,剩余工作留待后续处理`,purged:`相关内容已彻底清除,本项停止处理`,merged_basis:`合并后的依据需要重新检查`,no_new_evidence:`没有新依据,本次跳过;不会重复增加保留强度。`,snapshot_changed:`依据或画像已变化,本次结果未写入。`},dr=e=>e.startsWith(`unbound_entities:`)?`相关对象缺少绑定依据:${e.slice(17).split(`,`).join(`、`)}`:ur[e]||cr(e),fr=e=>({manual:`人工条目`,candidate:`候选`,pending:`等待自动检查`,accepted:`已准入`,rejected:`检查未通过`})[e]||e;function pr({base:e,openMemory:t}){let[n,r]=(0,l.useState)(0),i=y(`${e}/versions?limit=10&offset=${n}`),[a,o]=(0,l.useState)(null),s=(0,l.useRef)(null),c=y(a===null?null:`${e}/versions/${a}`),[u,d]=(0,l.useState)(`1`),[f,p]=(0,l.useState)(`2`),[m,h]=(0,l.useState)(null),g=y(m),_=e=>{o(e),requestAnimationFrame(()=>s.current?.scrollIntoView?.({behavior:`smooth`,block:`start`}))};return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`section`,{className:`entry-profile-section`,"aria-label":`历史(旧形式)`,children:[(0,x.jsx)(`h3`,{children:`历史(旧形式)`}),(0,x.jsx)(`p`,{className:`muted`,children:`旧版本只读,保留原有依据与检查记录;不能回滚,也不再确认或拒绝候选。这里的版本号与宿主投影版本无关。`}),i.error&&(0,x.jsxs)(A,{error:!0,children:[i.error,(0,x.jsx)(`button`,{onClick:i.refresh,children:`重试历史`})]}),i.data?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`ul`,{className:`entry-profile-history`,children:i.data.items.map(e=>(0,x.jsxs)(`li`,{children:[(0,x.jsxs)(`div`,{children:[(0,x.jsxs)(`strong`,{children:[`v`,e.version]}),` · `,or(e.status),` ·`,` `,ar(e.source),` · 变化`,ir(e.change_degree),(0,x.jsx)(`p`,{className:`muted`,children:w(e.generated_at)})]}),(0,x.jsxs)(`button`,{className:`secondary`,onClick:()=>_(e.version),children:[`查看旧版 v`,e.version]})]},e.version))}),!i.data.items.length&&(0,x.jsx)(`p`,{children:`还没有版本记录。`}),(0,x.jsx)(T,{total:i.data.total,offset:n,limit:10,change:r})]}):(0,x.jsx)(`p`,{children:`正在读取历史…`}),(0,x.jsxs)(`form`,{className:`entry-profile-compare`,onSubmit:t=>{t.preventDefault(),h(`${e}/diff?before_version=${Number(u)}&after_version=${Number(f)}`),g.refresh()},children:[(0,x.jsxs)(`label`,{children:[`对比起始版本`,(0,x.jsx)(`input`,{type:`number`,required:!0,min:1,max:2**53-1,value:u,onChange:e=>d(e.target.value)})]}),(0,x.jsxs)(`label`,{children:[`对比目标版本`,(0,x.jsx)(`input`,{type:`number`,required:!0,min:1,max:2**53-1,value:f,onChange:e=>p(e.target.value)})]}),(0,x.jsx)(`button`,{children:`逐句对比`})]}),g.error&&(0,x.jsx)(A,{error:!0,children:g.error}),g.data&&(0,x.jsxs)(`div`,{"aria-label":`逐句差异`,children:[!g.data.changed&&(0,x.jsx)(`p`,{children:`两版内容与依据相同。`}),g.data.sentences.map((e,t)=>(0,x.jsxs)(`div`,{className:`entry-profile-diff ${e.op}`,children:[(0,x.jsx)(`strong`,{children:{equal:JSON.stringify(e.before)===JSON.stringify(e.after)?`保留`:`依据或手写标记变化`,replace:`改写`,insert:`新增`,delete:`删除`}[e.op]||e.op}),e.op===`equal`&&JSON.stringify(e.before)===JSON.stringify(e.after)?e.after.map((e,t)=>(0,x.jsx)(hr,{value:e},t)):(0,x.jsxs)(`div`,{className:`entry-profile-diff-columns`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h4`,{children:`起始版本`}),e.before.map((e,t)=>(0,x.jsx)(hr,{value:e},t))]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h4`,{children:`目标版本`}),e.after.map((e,t)=>(0,x.jsx)(hr,{value:e},t))]})]})]},t))]})]}),a!==null&&(0,x.jsxs)(`section`,{ref:s,className:`entry-profile-section`,"aria-label":`旧版详情`,children:[(0,x.jsxs)(`h3`,{children:[`旧版 v`,a,` 的依据与检查`]}),(0,x.jsx)(M,{children:`只读历史`}),c.error?(0,x.jsxs)(A,{error:!0,children:[c.error,(0,x.jsx)(`button`,{onClick:c.refresh,children:`重试版本详情`})]}):c.data?(0,x.jsx)(mr,{value:c.data,openMemory:t}):(0,x.jsx)(`p`,{children:`正在读取版本…`})]})]})}function mr({value:e,openMemory:t}){let n=e.checks,r=n.model,i=n.format_version||1,a=n.reason!==`invalid_output`&&r&&typeof r.reason==`string`&&Array.isArray(r.sentences)&&r.sentences.length===n.checked_sentences?.length&&r.sentences.every((e,t)=>e&&typeof e==`object`&&e.index===t+1&&typeof e.supported==`boolean`&&typeof e.scene_qualified==`boolean`&&typeof e.reason==`string`&&Array.isArray(e.violations)&&e.violations.every(e=>typeof e==`string`));return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{children:[or(e.status),` · `,ar(e.source),` · 变化`,ir(e.change_degree),` · `,w(e.generated_at)]}),i===1&&(0,x.jsx)(M,{children:`旧版摘要`}),e.redacted&&(0,x.jsxs)(A,{children:[`此旧版本的相关内容已彻底清除。`,e.redaction_reason&&`原因:${e.redaction_reason}`]}),e.possibly_stale&&(0,x.jsx)(A,{children:`此版本依据可能过时。`}),(0,x.jsx)(`ol`,{className:`entry-profile-sentences`,children:e.sentences.map((e,n)=>(0,x.jsxs)(`li`,{children:[(0,x.jsx)(rr,{value:e}),(0,x.jsx)(M,{children:e.admin_written?`管理员手写 · 受保护`:`模型生成`}),e.admin_written&&!e.basis.length&&(0,x.jsx)(`p`,{className:`muted`,children:`管理员直接提供,无模型依据。`}),e.basis.map((e,n)=>(0,x.jsxs)(`div`,{className:`entry-profile-evidence`,children:[e.memory_id?(0,x.jsx)(`button`,{className:`text-button`,onClick:()=>t(e.memory_id),children:lr(e)}):(0,x.jsx)(`strong`,{children:lr(e)}),e.evidence?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`p`,{children:e.evidence.content}),e.evidence.occurred_at&&(0,x.jsx)(`small`,{children:w(e.evidence.occurred_at)}),e.evidence.source_messages?.map(e=>(0,x.jsxs)(`blockquote`,{children:[e.content,(0,x.jsxs)(`footer`,{children:[`本入口原消息 #`,e.message_id,` ·`,` `,w(e.occurred_at)]})]},e.message_id))]}):(0,x.jsx)(`p`,{children:`此版本未保存来源摘录,可按依据编号核对历史。`}),e.memory&&(0,x.jsxs)(`small`,{children:[`当前修订 `,e.memory.revision,` ·`,` `,{active:`有效`,forgotten:`已遗忘`,deleted:`已删除`}[e.memory.lifecycle]||e.memory.lifecycle]})]},n))]},n))}),(0,x.jsxs)(`h4`,{children:[`检查结果:`,n.passed?`通过`:`未通过`]}),n.reason&&(0,x.jsx)(`p`,{children:cr(n.reason,i)}),n.quote_validation&&(0,x.jsxs)(`p`,{children:[`引用原话核对:`,n.quote_validation.passed,` /`,` `,n.quote_validation.total,` `,`条通过(含被删条目的引语;不代表语义支持)`]}),!!n.quote_validation_items?.length&&(0,x.jsxs)(`details`,{children:[(0,x.jsx)(`summary`,{children:`逐条引用核对`}),(0,x.jsx)(`ul`,{children:n.quote_validation_items.map(e=>(0,x.jsxs)(`li`,{children:[`候选第 `,e.index,` 项:`,e.passed,` / `,e.total,` 条原话通过`,e.quotes.filter(e=>!e.passed).map(e=>(0,x.jsxs)(`p`,{children:[`引语 `,e.index,`:`,cr(e.reason||`invalid_quote`,i)]},e.index))]},e.index))})]}),n.deterministic?.characters!=null&&(0,x.jsxs)(`p`,{children:[`正文 `,n.deterministic.characters,` 字 ·`,` `,n.deterministic.tokens??`未记录`,` 估算 token`]}),(0,x.jsxs)(`p`,{children:[`确定性检查:`,n.deterministic?.passed?`通过`:`存在删句或错误,见下方记录`]}),n.errors?.length?(0,x.jsx)(`ul`,{children:n.errors.map((e,t)=>(0,x.jsx)(`li`,{children:cr(e,i)},t))}):null,a&&r?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{children:[`模型判断:`,r.reason]}),(0,x.jsx)(`ol`,{children:r.sentences.map((e,t)=>(0,x.jsxs)(`li`,{children:[(0,x.jsx)(`p`,{children:n.checked_sentences?.[t]?.text}),(0,x.jsxs)(`p`,{children:[`依据`,e.supported?`支持`:`不支持`,` · 场景限定`,e.scene_qualified?`通过`:`未通过`,` ·`,` `,n.checked_sentences?.[t]?.meaning&&typeof e.meaning_supported==`boolean`?`含义${e.meaning_supported?`有依据`:`无依据,已移除`} · `:``,e.violations.length?e.violations.join(`、`):`未发现禁止内容`]}),(0,x.jsx)(`p`,{children:e.reason})]},e.index))})]}):(0,x.jsx)(`p`,{children:r?`模型检查输出格式无效,本版未通过检查。`:n.admin_edit?`管理员编辑只做确定性检查。`:`本版未执行模型检查。`}),!!n.removed_meanings?.length&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`h4`,{children:`已删含义记录`}),(0,x.jsx)(`p`,{children:`说法本身可以保留;没有含义不表示生成失败。`}),(0,x.jsx)(`ul`,{children:n.removed_meanings.map((e,t)=>(0,x.jsxs)(`li`,{children:[`候选第 `,e.index,` 项:`,e.meaning,(0,x.jsx)(`p`,{children:cr(e.reason,i)})]},t))})]}),!!n.admin_warnings?.length&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`h4`,{children:`手写条目检查提醒`}),(0,x.jsx)(`ul`,{children:n.admin_warnings.map((e,t)=>(0,x.jsxs)(`li`,{children:[`第 `,e.index,` 项:`,e.result.violations.join(`、`),` ·`,` `,e.result.reason]},t))})]}),!!n.deleted_sentences?.length&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`h4`,{children:i===2?`已删条目记录`:`已删句记录`}),(0,x.jsx)(`ul`,{children:n.deleted_sentences.map((e,t)=>(0,x.jsxs)(`li`,{children:[(0,x.jsx)(`p`,{children:typeof e.sentence?.text==`string`?e.sentence.text:`候选第 ${e.index} 项`}),(0,x.jsxs)(`p`,{children:[e.stage===`deterministic`?`引用与格式核对:`:e.stage===`model`?`模型检查:`:``,cr(e.reason,i)]})]},t))})]})]})}function hr({value:e}){return(0,x.jsxs)(`div`,{children:[(0,x.jsx)(rr,{value:e}),(0,x.jsxs)(`small`,{children:[e.author===`admin`?`管理员手写`:`模型生成`,e.basis?.length?` · ${e.basis.map(lr).join(`;`)}`:``]})]})}var gr={topic:`话题`,saying:`说法`,rule:`群规`},_r=e=>e?gr[e]:`管理员说明`;function vr({entry:e,blocked:t,busy:n,write:r,cancel:i,created:a}){let[o,s]=(0,l.useState)(`rule`),[c,u]=(0,l.useState)(``),[d,f]=(0,l.useState)(``);return(0,x.jsxs)(`form`,{className:`profile-memory-card`,"aria-label":`人工新建画像记忆`,onSubmit:async n=>{if(n.preventDefault(),!(t||!c.trim()||Array.from(c).length>1e3)){f(``);try{await r(`/memories`,`POST`,{kind:`入口画像`,owner_entry_id:e.id,category:o,content:c}),a()}catch(e){f(v(e))}}},children:[(0,x.jsx)(`h4`,{children:`人工新建画像记忆`}),(0,x.jsxs)(`p`,{children:[`仅用于入口“`,e.name,`”。人工内容无需模型依据。`]}),d&&(0,x.jsx)(A,{error:!0,children:d}),(0,x.jsxs)(`label`,{children:[`子类`,(0,x.jsxs)(`select`,{"aria-label":`子类`,value:o||``,disabled:n,onChange:e=>s(e.target.value||null),children:[Object.entries(gr).map(([e,t])=>(0,x.jsx)(`option`,{value:e,children:t},e)),(0,x.jsx)(`option`,{value:``,children:`管理员说明`})]})]}),(0,x.jsxs)(`label`,{children:[`新画像正文`,(0,x.jsx)(`textarea`,{"aria-label":`新画像正文`,rows:4,maxLength:1e3,value:c,disabled:n,onChange:e=>u(e.target.value)})]}),(0,x.jsxs)(`p`,{className:`fine-print`,children:[Array.from(c).length,` / 1000 字`]}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{disabled:t||!c.trim()||Array.from(c).length>1e3,children:`创建画像记忆`}),(0,x.jsx)(`button`,{type:`button`,className:`secondary`,disabled:n,onClick:i,children:`取消新建`})]})]})}function yr({id:e,revision:t,message:n,openMemory:r,speakerNames:i,pendingSources:a}){let o=y(`/memories/${e}`),s=(0,l.useRef)(null);return(0,l.useEffect)(()=>{o.refresh()},[t,o.refresh]),(0,l.useEffect)(()=>{o.data&&n!==null&&(s.current?.scrollIntoView?.({behavior:`smooth`,block:`start`}),s.current?.focus({preventScroll:!0}))},[o.data,n]),(0,x.jsxs)(`div`,{className:`profile-memory-evidence`,children:[o.error&&(0,x.jsxs)(A,{error:!0,children:[o.error,(0,x.jsx)(`button`,{onClick:o.refresh,children:`重试来源与修订`})]}),o.data?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`h4`,{children:`来源消息与前后文`}),!o.data.sources.length&&(0,x.jsx)(`p`,{children:`没有保存的来源消息。`}),o.data.sources.map(e=>(0,x.jsxs)(`section`,{ref:e.message_id===n?s:null,tabIndex:-1,className:e.message_id===n?`profile-source-target`:``,"aria-label":e.message_id?`来源消息 #${e.message_id}`:`来源 #${e.id}`,children:[e.message_id&&(0,x.jsxs)(`h5`,{children:[`消息 #`,e.message_id]}),a.some(t=>t.message.position===e.message_id)&&(0,x.jsx)(A,{children:`该消息含待审引文,请以上方已审/待审分区为准`}),(0,x.jsx)(nn,{source:e,openMemory:r,initiallyOpen:e.message_id===n,speakerNames:i},`${e.id}:${e.message_id===n}`)]},e.id)),n!==null&&!o.data.sources.some(e=>e.message_id===n)&&(0,x.jsx)(A,{children:`该来源已变化或不可用,请刷新画像核对。`}),(0,x.jsxs)(`h4`,{children:[`修订历史 · `,o.data.revisions.length]}),o.data.revisions.length?o.data.revisions.map(e=>(0,x.jsx)(rn,{revision:e},e.id)):(0,x.jsx)(`p`,{children:`还没有修订记录。`})]}):!o.error&&(0,x.jsx)(`p`,{children:`正在读取来源与修订…`})]})}function br({memory:e,speakerNames:t,displayed:n,blocked:r,busy:i,write:a,refresh:o,openMemory:s}){let[c,u]=(0,l.useState)(null),[d,p]=(0,l.useState)(null),[m,h]=(0,l.useState)(!1),[g,_]=(0,l.useState)(``),[y,b]=(0,l.useState)(``),[S,C]=(0,l.useState)(!1),[T,D]=(0,l.useState)(null),O=!!c&&c.revision!==e.revision,k=e.lifecycle===`deleted`;function j(e){e instanceof f&&e.status===409?(h(!0),_(`这条画像记忆已变化,草稿已保留。请核对最新正文与修订后继续。`)):e instanceof f&&e.status===404?(h(!0),_(`这条画像记忆已不可用,草稿已保留。请复制需要保留的内容后关闭。`)):_(v(e))}async function ee(t,n,i,o){if(!r){_(``),b(``);try{await a(`/memories/${e.memory_id}${n}`,t,i),u(null),p(null),h(!1),b(o)}catch(e){j(e)}}}return(0,x.jsxs)(`article`,{id:`profile-memory-${e.memory_id}`,className:`profile-memory-card`,"aria-label":`画像记忆 #${e.memory_id}`,children:[(0,x.jsxs)(`div`,{className:`detail-badges`,children:[(0,x.jsx)(M,{tone:`purple`,children:_r(e.category)}),(0,x.jsx)(M,{children:e.author===`admin`?`人工`:`模型`}),(0,x.jsx)(M,{children:fr(e.admission_state)}),e.manual_protected&&(0,x.jsx)(M,{children:`人工保护`}),(0,x.jsx)(M,{tone:k?`danger`:``,children:E(e.lifecycle)}),(0,x.jsxs)(`span`,{className:`muted`,children:[`#`,e.memory_id,` · 修订 `,e.revision]})]}),(0,x.jsx)(`p`,{className:`entry-profile-content`,children:e.body}),e.admission_state===`candidate`&&(0,x.jsx)(A,{children:`还在等待更多独立讨论,暂不给宿主看`}),e.admission_state===`pending`&&(0,x.jsx)(A,{children:`正在排队或自动检查,全部检查页通过前暂不给宿主看。`}),e.admission_state===`rejected`&&(0,x.jsx)(A,{children:`自动检查未通过,暂不给宿主看;后续由系统继续处理新依据。`}),e.admission_reason&&(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`p`,{children:dr(e.admission_reason)}),e.admission_state===`manual`&&(0,x.jsx)(`p`,{className:`fine-print`,children:`这是自动依据检查记录,不影响人工正文的使用。`}),e.admission_state===`accepted`&&(0,x.jsx)(`p`,{className:`fine-print`,children:`后续检查记录不代表已准入正文被撤下,是否展示请看宿主投影。`})]}),(0,x.jsxs)(`dl`,{className:`profile-memory-metadata`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`保留强度`}),(0,x.jsxs)(`dd`,{children:[e.retention,e.pinned?` · 已置顶`:``]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`最近确认时间`}),(0,x.jsx)(`dd`,{children:e.last_confirmed_at?w(e.last_confirmed_at):`暂无确认记录`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`独立日期`}),(0,x.jsxs)(`dd`,{children:[e.independent_days,` 天`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`独立依据`}),(0,x.jsxs)(`dd`,{children:[e.independent_uses,` 次`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`宿主投影`}),(0,x.jsx)(`dd`,{children:n?`已加入`:e.usable?`当前未加入`:`当前不可用`})]})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`独立日期按角色时区统计;独立依据已排除转引、复述等重复讨论,不等于消息总数。`}),(0,x.jsxs)(`div`,{"aria-label":`依据原话`,children:[(0,x.jsxs)(`h4`,{children:[`已审依据 · `,e.sources.length,` 条`]}),e.sources.map((e,n)=>(0,x.jsxs)(`blockquote`,{children:[(0,x.jsx)(`p`,{children:e.excerpt}),(0,x.jsxs)(`footer`,{children:[e.field===`quote`?`转引原话`:`消息正文`,` · 原作者:`,t[e.speaker]||e.speaker,` ·`,` `,w(e.message.occurred_at)]}),(0,x.jsxs)(`button`,{className:`text-button`,disabled:i,onClick:()=>{D(e.message.position),C(!0)},children:[`跳转来源消息 #`,e.message.position]})]},`${e.ref}:${n}`)),!e.sources.length&&(0,x.jsx)(`p`,{className:`muted`,children:e.author===`admin`?`管理员手写,无需模型依据。`:`当前没有可用的绑定原话,可在来源与修订历史中核对。`})]}),!!e.pending_sources.length&&(0,x.jsxs)(`section`,{"aria-label":`待审来源`,className:`profile-pending-sources`,children:[(0,x.jsxs)(`h4`,{children:[`待审来源 · `,e.pending_sources.length,` 条`]}),(0,x.jsxs)(`p`,{className:`fine-print`,children:[`这些引文尚未完成自动准入检查,不作为已审依据。`,e.admission_state===`manual`?`人工正文照常可用,无需等待这些引文。`:`通过检查后才可能成为可展示画像的依据。`]}),e.pending_sources.map((e,n)=>(0,x.jsxs)(`blockquote`,{children:[(0,x.jsx)(`p`,{children:e.excerpt}),(0,x.jsxs)(`footer`,{children:[e.field===`quote`?`转引原话`:`消息正文`,` · 原作者:`,t[e.speaker]||e.speaker,` ·`,` `,w(e.message.occurred_at)]}),(0,x.jsxs)(`button`,{className:`text-button`,disabled:i,onClick:()=>{D(e.message.position),C(!0)},children:[`跳转来源消息 #`,e.message.position]})]},`${e.ref}:${n}`))]}),g&&(0,x.jsxs)(A,{error:!0,children:[g,(0,x.jsx)(`button`,{className:`text-button`,disabled:i,onClick:()=>{o(),!c&&d===null&&(h(!1),_(``))},children:`刷新画像记忆`})]}),y&&(0,x.jsx)(A,{children:y}),c&&(0,x.jsxs)(`form`,{onSubmit:e=>{e.preventDefault(),!r&&!m&&!O&&!k&&c.content.trim()&&ee(`PATCH`,``,{expected_revision:c.revision,content:c.content},`修改已保存。`)},children:[(0,x.jsxs)(`label`,{children:[`画像正文`,(0,x.jsx)(`textarea`,{"aria-label":`画像正文`,value:c.content,disabled:i,rows:4,maxLength:1e3,onChange:e=>u({...c,content:e.target.value})})]}),(0,x.jsxs)(`p`,{className:`fine-print`,children:[`草稿基于修订 `,c.revision,` · `,Array.from(c.content).length,` / 1000 字`]}),(O||m)&&(0,x.jsxs)(A,{children:[`草稿未被替换。上方显示当前修订 `,e.revision,` `,`的正文,请核对后继续。`,(0,x.jsx)(`button`,{type:`button`,disabled:r||k||m&&!O,onClick:()=>{u({...c,revision:e.revision}),h(!1),_(``)},children:`已核对最新修订,保留草稿继续`})]}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{disabled:r||m||O||k||!c.content.trim()||Array.from(c.content).length>1e3,children:`保存修改`}),(0,x.jsx)(`button`,{className:`secondary`,type:`button`,disabled:i,onClick:()=>{u(null),h(!1),_(``)},children:`取消编辑`})]})]}),d!==null&&(0,x.jsxs)(`div`,{className:`delete-confirm`,children:[(0,x.jsx)(`p`,{children:`确认删除这条画像记忆?该标识将永久撤销,不能恢复;来源和修订历史保留。`}),d!==e.revision&&(0,x.jsx)(A,{children:`这条记忆已变化,请取消并核对最新正文后重新操作。`}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{className:`danger-button`,disabled:r||m||k||d!==e.revision,onClick:()=>void ee(`DELETE`,``,{expected_revision:d},`画像记忆已删除,历史仍保留。`),children:`确认删除`}),(0,x.jsx)(`button`,{className:`secondary`,disabled:i,onClick:()=>{p(null),h(!1),_(``)},children:`取消删除`})]})]}),k&&(0,x.jsx)(`p`,{className:`muted`,children:`已删除的记忆标识不可恢复。需要重新手写时,请使用人工新建。`}),(0,x.jsxs)(`div`,{className:`button-row`,children:[!k&&(0,x.jsx)(`button`,{className:`secondary`,disabled:r||!!c||d!==null,onClick:()=>{u({content:e.body,revision:e.revision}),h(!1),_(``),b(``)},children:`编辑`}),!k&&(0,x.jsx)(`button`,{className:`text-button danger-text`,disabled:r||!!c||d!==null,onClick:()=>{p(e.revision),h(!1),_(``),b(``)},children:`删除`}),e.lifecycle===`forgotten`&&(0,x.jsx)(`button`,{className:`secondary`,disabled:r||!!c||d!==null||m,onClick:()=>void ee(`POST`,`/restore`,{expected_revision:e.revision},`画像记忆已恢复。`),children:`恢复`}),(0,x.jsx)(`button`,{className:`text-button`,"aria-expanded":S,disabled:i,onClick:()=>{C(!S),D(null)},children:S?`收起来源与修订历史`:`来源与修订历史`}),(0,x.jsx)(`button`,{className:`text-button`,disabled:i||!!c,onClick:()=>s(e.memory_id),children:`打开记忆详情`})]}),S&&(0,x.jsx)(yr,{id:e.memory_id,speakerNames:t,revision:e.revision,pendingSources:e.pending_sources,message:T,openMemory:s})]})}function xr({progress:e}){return e?(0,x.jsxs)(`section`,{"aria-label":`当前入口进度与积压`,children:[(0,x.jsx)(`h4`,{children:`当前入口进度与积压`}),(0,x.jsxs)(`dl`,{className:`profile-progress-grid`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`已完成观察分块`}),(0,x.jsxs)(`dd`,{children:[e.completed_chunks,` / `,e.observation_chunks,` 块`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`待检查`}),(0,x.jsxs)(`dd`,{children:[e.pending_checks,` 页`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`检查失败`}),(0,x.jsxs)(`dd`,{children:[e.failed_checks,` 页`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`检查未通过`}),(0,x.jsxs)(`dd`,{children:[e.rejected_checks,` 页`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`未准入画像`}),(0,x.jsxs)(`dd`,{children:[e.waiting_candidates,` 条`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`待扫描`}),(0,x.jsxs)(`dd`,{children:[e.unscanned_messages,` 条消息`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`观察缺口`}),(0,x.jsxs)(`dd`,{children:[e.observation_gaps,` 块`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`最早积压时间`}),(0,x.jsx)(`dd`,{children:e.oldest_pending_at?w(e.oldest_pending_at):`无`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`已排队至`}),(0,x.jsxs)(`dd`,{children:[`消息 #`,e.scan_cursor]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`已连续完成至`}),(0,x.jsxs)(`dd`,{children:[`消息 #`,e.applied_cursor]})]})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`页数和记忆条目数分别统计;未准入不等于失败。消息编号表示处理位置,不是发生时间;连续完成位置不会越过观察缺口。`})]}):null}function Sr(e){return e.state===`applied`?e.kind===`admit`?`本页通过`:`已完成`:e.state===`rejected`?e.kind===`admit`?`本页未通过`:`未通过`:{queued:`排队中`,running:`处理中`,failed:`本次失败`,cancelled:`已取消`,deferred:`稍后重试`}[e.state]||e.state}function Cr({work:e}){return e?.length?(0,x.jsxs)(`details`,{className:`history profile-work-list`,children:[(0,x.jsxs)(`summary`,{children:[`本次任务分块与检查 · `,e.length,` 项`]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`每页单独检查;全部页通过后才可能准入,还需核对最终正文与依据。宿主是否能看到,以每条画像的投影状态为准。`}),e.map(e=>(0,x.jsxs)(`article`,{"aria-label":`工作项 #${e.id}`,className:`profile-work-card`,children:[(0,x.jsxs)(`div`,{className:`detail-badges`,children:[(0,x.jsx)(`strong`,{children:e.kind===`observe`?`观察消息分块`:`画像准入检查`}),(0,x.jsx)(M,{tone:e.state===`failed`||e.state===`rejected`?`danger`:``,children:Sr(e)}),(0,x.jsxs)(`span`,{className:`muted`,children:[`工作项 #`,e.id]})]}),e.memory_id!=null&&(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>document.getElementById(`profile-memory-${e.memory_id}`)?.scrollIntoView?.({behavior:`smooth`,block:`start`}),children:[`画像记忆 #`,e.memory_id]}),e.kind===`admit`&&(0,x.jsx)(`p`,{children:e.check_page!=null&&e.check_pages!=null?`检查第 ${e.check_page} / ${e.check_pages} 页`:`检查页码未记录`}),e.kind===`admit`&&e.state===`applied`&&(0,x.jsx)(`p`,{className:`fine-print`,children:`全部页通过后才可能准入,本页通过不代表整条已展示。`}),(0,x.jsxs)(`dl`,{className:`profile-work-metadata`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`所属日期(角色时区)`}),(0,x.jsx)(`dd`,{children:e.local_day||`未记录`})]}),e.kind===`observe`&&(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`消息编号范围`}),(0,x.jsxs)(`dd`,{children:[`#`,e.cursor_before,` 之后至 #`,e.cursor_after]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`执行次数`}),(0,x.jsxs)(`dd`,{children:[e.attempts,` 次`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`下次重试`}),(0,x.jsx)(`dd`,{children:e.retry_at?w(e.retry_at):`未安排`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`入队时间`}),(0,x.jsx)(`dd`,{children:w(e.created_at)})]}),e.finished_at&&(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`结束时间`}),(0,x.jsx)(`dd`,{children:w(e.finished_at)})]})]}),e.reason&&(0,x.jsx)(`p`,{children:dr(e.reason)})]},e.id))]}):null}function wr({base:e,initial:t,settled:n,progress:r}){let[i,a]=(0,l.useState)(t.state===`running`),o=y(`${e}/attempts/${t.id}`,i?1500:0),s=(0,l.useRef)(!1);(0,l.useEffect)(()=>{o.data&&o.data.state!==`running`&&!s.current&&(s.current=!0,a(!1),n(o.data))},[o.data,n]);let c=i&&o.data||t;return(0,x.jsxs)(`section`,{className:`entry-profile-task`,"aria-label":`画像更新任务`,children:[(0,x.jsxs)(`h3`,{children:[`更新任务 #`,c.id]}),o.error&&(0,x.jsxs)(A,{error:!0,children:[o.error,(0,x.jsx)(`button`,{onClick:o.refresh,children:`重试任务状态`})]}),(0,x.jsx)(`p`,{role:`status`,children:c.state===`running`?c.stage===`checking`?`正在检查画像条目…`:`正在观察消息分块…`:c.state===`published`?`本轮已提交处理结果,仍以逐条准入状态为准。`:or(c.state)}),c.reason&&(0,x.jsx)(`p`,{children:dr(c.reason)}),(0,x.jsxs)(`p`,{className:`fine-print`,children:[`开始:`,w(c.started_at),c.finished_at&&` · 结束:${w(c.finished_at)}`]}),(0,x.jsx)(xr,{progress:c.progress||r}),(0,x.jsx)(Cr,{work:c.work}),c.version!=null&&(0,x.jsxs)(`p`,{children:[`任务完成时的宿主投影版本:v`,c.version]})]})}function Tr({entry:e,onClose:t,openMemory:n}){let r=`/entries/${encodeURIComponent(e.id)}/profile`,i=y(r,5e3),a=y(`/catalog`),o=Object.fromEntries((a.data?.people||[]).map(e=>[e.id,e.name])),[s,c]=(0,l.useState)(!1),[u,d]=(0,l.useState)(``),[p,m]=(0,l.useState)(``),[h,b]=(0,l.useState)(!1),[S,C]=(0,l.useState)(null),[T,E]=(0,l.useState)(null),D=(0,l.useRef)(!1),O=(0,l.useRef)(!0);(0,l.useEffect)(()=>(O.current=!0,()=>{O.current=!1}),[]);let k=async(e,t,n)=>{if(D.current)throw new f(`busy`,`正在保存,请稍候。`,409);D.current=!0,c(!0),d(``),m(``);try{return await g(e,_(t,n))}finally{D.current=!1,O.current&&(c(!1),i.refresh())}},j=(0,l.useCallback)(e=>{E(e),i.refresh()},[i.refresh]),N=i.data,P=N?.latest_attempt&&(!T||N.latest_attempt.id>T.id||N.latest_attempt.id===T.id&&(T.state===`running`||N.latest_attempt.state!==`running`))?N.latest_attempt:T||N?.latest_attempt,F=s||i.loading||!!i.error,I=P?.state===`running`,te=e=>{s||(t(),n(e))};async function L(){if(S&&!F)try{await k(`${r}/settings`,`PATCH`,S),C(null),m(`画像设置已保存。`)}catch(e){d(e instanceof f&&e.status===409?`画像已变化,设置草稿已保留;请核对最新投影后重新确认。`:v(e))}}async function ne(){if(!(!N||F||I))try{let e=await k(`${r}/regenerate`,`POST`,{expected_version:N.settings.current_version});E(e.attempt),m(`更新请求已提交,可关闭面板后再查看任务结果。`)}catch(e){d(v(e))}}return(0,x.jsx)(ee,{title:`入口画像 · ${e.name}`,onClose:t,closeDisabled:s,children:(0,x.jsxs)(`div`,{className:`entry-profile`,children:[(0,x.jsx)(`p`,{className:`muted`,children:`每条画像都是本入口的记忆,自动更新。手写内容按人工记忆保护。`}),(i.error||u)&&(0,x.jsxs)(A,{error:!0,children:[u||i.error,(0,x.jsx)(`button`,{className:`text-button`,disabled:s,onClick:i.refresh,children:`刷新画像`})]}),p&&(0,x.jsx)(A,{children:p}),N?N.supported?N.mode===`memory`?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`section`,{className:`entry-profile-section`,"aria-label":`画像设置`,children:[(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(M,{children:N.settings.enabled?`已开启`:`已关闭`}),(0,x.jsx)(`span`,{children:`自动更新,无需确认候选`})]}),!N.global_enabled&&(0,x.jsx)(A,{children:`全局画像开关已关闭,当前不会生成或加入回复准备。`}),S?(0,x.jsxs)(`form`,{onSubmit:e=>{e.preventDefault(),L()},children:[(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:S.enabled,disabled:s,onChange:e=>C({...S,enabled:e.target.checked})}),`启用本入口画像`]}),S.expected_version!==N.settings.current_version&&(0,x.jsxs)(A,{children:[`投影已更新为 v`,N.settings.current_version,`,请先核对下方预览。`,(0,x.jsx)(`button`,{type:`button`,disabled:F,onClick:()=>C({...S,expected_version:N.settings.current_version}),children:`已核对,保留设置草稿`})]}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{disabled:F||S.expected_version!==N.settings.current_version,children:`保存画像设置`}),(0,x.jsx)(`button`,{type:`button`,className:`secondary`,disabled:s,onClick:()=>C(null),children:`取消设置`})]})]}):(0,x.jsx)(`button`,{className:`secondary`,disabled:F,onClick:()=>C({enabled:N.settings.enabled,expected_version:N.settings.current_version}),children:`修改画像设置`})]}),(0,x.jsxs)(`section`,{className:`entry-profile-section`,"aria-label":`宿主投影预览`,children:[(0,x.jsxs)(`h3`,{children:[`宿主投影预览 · v`,N.settings.current_version]}),(0,x.jsx)(`p`,{className:`muted`,children:`以下为回复准备提供的原文;宿主传入已知记忆时会排除相应条目。投影版本独立于每条记忆的修订号。`}),N.projection?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`p`,{className:`entry-profile-content profile-projection`,children:N.projection.text}),(0,x.jsxs)(`p`,{className:`fine-print`,children:[`version:`,N.projection.version,` · 更新于`,` `,w(N.projection.generated_at)]}),(0,x.jsx)(`div`,{className:`button-row`,children:N.projection.memory_ids.map(e=>(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>document.getElementById(`profile-memory-${e}`)?.scrollIntoView?.({behavior:`smooth`,block:`start`}),children:[`画像记忆 #`,e]},e))}),N.projection.possibly_stale&&(0,x.jsx)(A,{children:`投影可能过时:还有未处理消息、观察缺口、待检查或待重建的内容。`})]}):(0,x.jsx)(`p`,{children:`当前不向宿主提供画像(entry_profile 为 null)。`}),!!N.diagnostics.omitted_memory_ids?.length&&(0,x.jsxs)(A,{children:[`受展示预算限制,以下记忆未加入投影:`,N.diagnostics.omitted_memory_ids.map(e=>(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>document.getElementById(`profile-memory-${e}`)?.scrollIntoView?.({behavior:`smooth`,block:`start`}),children:[`#`,e]},e)),(0,x.jsx)(`p`,{children:`这些记忆仍然保留;人工内容不会因展示预算被隐藏。`})]}),N.rebuild_pending&&(0,x.jsx)(A,{children:`画像正在等待新任务重建或继续处理消息。`})]}),(0,x.jsxs)(`section`,{className:`entry-profile-section`,"aria-label":`每日增量进度`,children:[(0,x.jsx)(`h3`,{children:`每日增量进度`}),(0,x.jsx)(`p`,{className:`muted`,children:`自动任务按角色时区处理已结束日期;立即运行也处理当日尾块。准入由系统自动检查,无需审批。`}),(0,x.jsx)(`button`,{disabled:F||I||!N.settings.enabled||!N.global_enabled,onClick:()=>void ne(),children:`立即运行`}),(0,x.jsx)(`p`,{className:`fine-print`,children:`继续处理新消息和排队的检查;没有新依据时不会重复确认。`}),!P&&(0,x.jsx)(xr,{progress:N.progress}),P&&(0,x.jsx)(wr,{base:r,initial:P,settled:j,progress:N.progress},P.id)]}),(0,x.jsxs)(`section`,{className:`entry-profile-section`,"aria-label":`画像记忆`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsxs)(`h3`,{children:[`画像记忆 · `,N.memories.length,` 条`]}),(0,x.jsx)(`button`,{disabled:F||h,onClick:()=>b(!0),children:`人工新建`})]}),h&&(0,x.jsx)(vr,{entry:e,blocked:F,busy:s,write:k,cancel:()=>b(!1),created:()=>{b(!1),m(`已创建本入口的画像记忆。`)}}),!N.memories.length&&(0,x.jsx)(`p`,{children:`暂无画像记忆。可手写补充,也可等待新消息形成画像。`}),(0,x.jsx)(`div`,{className:`profile-memory-list`,children:N.memories.map(e=>(0,x.jsx)(br,{memory:e,speakerNames:o,displayed:!!N.projection?.memory_ids.includes(e.memory_id),blocked:F,busy:s,write:k,refresh:i.refresh,openMemory:te},e.memory_id))})]})]}):(0,x.jsx)(A,{children:`入口画像尚未切换为记忆形式,请更新服务后刷新。旧版历史仍可只读查看。`}):(0,x.jsx)(A,{children:`私聊入口不生成入口画像。`}):(0,x.jsx)(`p`,{role:`status`,children:`正在读取入口画像…`}),N?.supported&&(0,x.jsxs)(x.Fragment,{children:[!!N.migration?.length&&(0,x.jsxs)(`details`,{className:`history`,children:[(0,x.jsx)(`summary`,{children:`旧画像迁移记录`}),(0,x.jsx)(`ul`,{children:N.migration.map(e=>(0,x.jsxs)(`li`,{children:[`旧版 v`,e.legacy_version,` · 原条目序号`,` `,e.sentence_index,`:`,{manual_imported:`已转为人工画像记忆`,manual_unclassified:`已转为管理员说明`,model_rebuild_pending:`原模型条目待按依据重建`,cleared_history:`原内容已清空`}[e.disposition]||e.disposition,e.memory_id!=null&&(0,x.jsxs)(`button`,{className:`text-button`,disabled:s,onClick:()=>te(e.memory_id),children:[`查看记忆 #`,e.memory_id]})]},`${e.legacy_version}:${e.sentence_index}`))})]}),(0,x.jsx)(pr,{base:r,openMemory:te})]})]})})}var Er={forget:`遗忘`,delete:`删除`,purge:`彻底清除`},Dr={memory_source:`仍是其他记忆的来源`,batch_segment:`等待或运行中的批次仍在使用`,goal_source:`仍是目标的来源`,subject_alias:`仍是主体别名的证据`,subject_link:`仍是主体联系的证据`,learning_request:`立即学习请求仍在使用`};function Or({scope:e,name:t,onClose:n,onChanged:r}){let[i,a]=(0,l.useState)(`forget`),[o,s]=(0,l.useState)(!1),[c,u]=(0,l.useState)(null),[d,p]=(0,l.useState)(null),[m,h]=(0,l.useState)(!1),[y,b]=(0,l.useState)(``),[S,C]=(0,l.useState)(!1),[w,T]=(0,l.useState)(!1),D=d?.status===`completed`,O=()=>{u(null),b(``),C(!1),T(!1)};async function k(){h(!0),O();try{u(await g(`/memories/bulk/preview`,_(`POST`,{...e,action:i,include_pinned:o})))}catch(e){b(v(e))}finally{h(!1)}}async function j(){if(c&&!m&&c.applicable_count&&(i!==`purge`||w)){h(!0),b(``);try{p(await g(`/memories/bulk/apply`,_(`POST`,{snapshot_token:c.snapshot_token,action:i,confirm:i===`purge`&&w}))),u(null),C(!1),r()}catch(e){e instanceof f&&e.status===409?(O(),e.result&&(p(e.result),r()),b(e.message)):b(`${v(e)}。执行结果尚未确认,可使用当前预览重试;若服务已重启,请先查看操作记录。`)}finally{h(!1)}}}return(0,x.jsx)(ee,{title:`批量遗忘/删除`,onClose:n,closeDisabled:m,children:(0,x.jsxs)(`div`,{className:`lifecycle-stack bulk-memory`,children:[(0,x.jsxs)(`p`,{children:[(0,x.jsx)(`strong`,{children:t}),` ·`,` `,`subject_id`in e?`人物 ${e.subject_id}`:`入口 ${e.entry_id}`]}),(0,x.jsx)(`p`,{className:`muted`,children:`subject_id`in e?`范围:说话人或涉及人物为此人的记忆。`:`范围:至少一条直接来源消息属于此入口的记忆。`}),y&&(0,x.jsx)(A,{error:!0,children:y}),d&&(0,x.jsxs)(`section`,{"aria-label":`批量操作结果`,children:[(0,x.jsx)(A,{error:!D,children:D?`已批量${Er[i]} ${d.count} 条记忆。`:`操作未全部完成,已处理 ${d.count} 条记忆。`}),(0,x.jsx)(qt,{notice:d.backup_notice}),d.skipped_count>0&&(0,x.jsxs)(`p`,{children:[`跳过已删除的 `,d.skipped_count,` 条记忆。`]}),(0,x.jsxs)(`details`,{children:[(0,x.jsxs)(`summary`,{children:[`已处理记忆 ID(`,d.memory_ids.length,` 条)`]}),(0,x.jsx)(`p`,{className:`bulk-ids`,children:d.memory_ids.map(e=>`#${e}`).join(`、`)||`无`})]}),i===`purge`&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{children:[`已删除来源消息 `,d.deleted_message_ids.length,` 条;保留`,` `,d.retained_messages.length,` 条。`]}),(0,x.jsxs)(`details`,{children:[(0,x.jsx)(`summary`,{children:`来源消息处理明细`}),(0,x.jsxs)(`p`,{className:`bulk-ids`,children:[`已删除:`,d.deleted_message_ids.map(e=>`#${e}`).join(`、`)||`无`]}),d.retained_messages.map(e=>(0,x.jsxs)(`p`,{children:[`消息 #`,e.message_id,`:`,e.reasons.map(e=>Dr[e]||e).join(`;`)]},e.message_id))]})]})]}),!D&&(0,x.jsxs)(x.Fragment,{children:[!S&&(0,x.jsxs)(`fieldset`,{disabled:m,className:`bulk-options`,children:[(0,x.jsxs)(`label`,{children:[`目标操作`,(0,x.jsxs)(`select`,{value:i,onChange:e=>{a(e.target.value),O()},children:[(0,x.jsx)(`option`,{value:`forget`,children:`遗忘(可恢复)`}),(0,x.jsx)(`option`,{value:`delete`,children:`删除(撤销对象)`}),(0,x.jsx)(`option`,{value:`purge`,children:`彻底清除(不可撤销)`})]})]}),(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:o,onChange:e=>{s(e.target.checked),O()}}),`包含置顶记忆`]}),(0,x.jsx)(`p`,{children:i===`forget`?`遗忘会降低保留强度并取消置顶;仍可深度召回及恢复。`:i===`delete`?`删除会撤销记忆对象,保留来源与历史;普通和深度召回均不再返回。`:`彻底清除会清除正文、修订历史,以及没有其他受保护引用的来源消息。`}),(0,x.jsx)(`button`,{className:`secondary`,onClick:()=>void k(),children:m?`正在处理…`:`预览范围`})]}),c&&(0,x.jsxs)(`section`,{"aria-label":`批量操作预览`,children:[(0,x.jsxs)(`h3`,{children:[`范围内 `,c.total,` 条,本次处理 `,c.applicable_count,` `,`条`]}),(0,x.jsxs)(`p`,{children:[`有效 `,c.counts.active,` · 遗忘 `,c.counts.forgotten,` `,`· 已删除 `,c.counts.deleted]}),(0,x.jsxs)(`p`,{children:[`包含置顶 `,c.pinned_count,` 条;排除置顶`,` `,c.excluded_pinned_count,` 条。`]}),(0,x.jsx)(`p`,{className:`muted`,children:`已删除对象只参加彻底清除。预览有效期 15 分钟,记忆变化后需重新预览。`}),(0,x.jsx)(`ul`,{className:`bulk-examples`,children:c.examples.map(e=>(0,x.jsxs)(`li`,{children:[(0,x.jsxs)(`span`,{className:`muted`,children:[`#`,e.id,` · `,E(e.lifecycle),e.pinned?` · 置顶`:``]}),(0,x.jsx)(`p`,{children:e.content})]},e.id))}),i===`purge`&&(0,x.jsx)(qt,{notice:c.backup_notice}),S?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(A,{error:!0,children:[`即将彻底清除 `,c.applicable_count,` `,`条记忆,此操作不可撤销。同时清空可关联的模型原始输出等正文副本。`]}),(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,disabled:m,checked:w,onChange:e=>T(e.target.checked)}),`我理解此操作不可撤销`]}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{className:`danger-button`,disabled:m||!w,onClick:()=>void j(),children:`再次确认并彻底清除`}),(0,x.jsx)(`button`,{className:`secondary`,disabled:m,onClick:()=>{C(!1),T(!1)},children:`返回预览`})]})]}):(0,x.jsxs)(`button`,{className:`danger-button`,disabled:m||!c.applicable_count,onClick:()=>i===`purge`?C(!0):void j(),children:[`确认批量`,Er[i]]})]})]}),m&&(0,x.jsx)(`p`,{role:`status`,children:`正在处理,请等待结果…`}),!m&&(0,x.jsx)(`a`,{href:`#/operations?object_type=memory_bulk`,onClick:n,children:`查看批量操作记录`}),D&&(0,x.jsx)(`button`,{className:`primary`,onClick:n,children:`完成`})]})})}var kr=e=>({group:`群聊`,private:`私聊`,live:`直播`})[e]||e,Ar=e=>({message:`消息`,self_output:`角色实际输出`,action_result:`行动结果`,event:`场景事件`})[e]||e,jr=e=>({attempts_exhausted:`尝试用尽,未学习`,content_rejection:`内容拒绝,未学习`,interrupted:`学习中断`})[e]||e,Mr=e=>typeof e==`string`?e:JSON.stringify(e,null,2);function Nr({openMemory:e}){let[t,n]=(0,l.useState)(`entries`),[r,i]=(0,l.useState)(null),[a,o]=(0,l.useState)(null),[s,c]=(0,l.useState)(null),[u,d]=(0,l.useState)(null),[f,p]=(0,l.useState)(``),[m,h]=(0,l.useState)({entry_id:``,time_from:``,time_to:``}),[g,_]=(0,l.useState)(m),[v,b]=(0,l.useState)(0),C=y(`/entries`,5e3),w=new URLSearchParams({limit:`30`,offset:String(v)});for(let[e,t]of Object.entries(g))t&&w.set(e,t);let T=y(t===`batches`&&r===null?`/batches?${w}`:null,3e3),E=y(t===`gaps`&&r===null?`/memory-gaps?${w}`:null,3e3),D=t===`batches`?T:E,O=()=>{C.refresh(),T.refresh(),E.refresh()};function k(e){n(e),i(null),b(0)}function ee(e){let t={entry_id:e,time_from:``,time_to:``};h(t),_(t),k(`batches`)}return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{className:`page-heading`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`p`,{className:`eyebrow`,children:`从消息到记忆`}),(0,x.jsx)(`h1`,{children:`入口与学习`}),(0,x.jsx)(`p`,{children:`查看每个入口的学习进度,追溯批次结果与尚未记住的消息。`})]})}),(0,x.jsx)(`div`,{className:`learning-tabs`,role:`group`,"aria-label":`入口与学习视图`,children:[[`entries`,`入口列表`],[`batches`,`学习批次`],[`gaps`,`记忆缺口`]].map(([e,n])=>(0,x.jsx)(`button`,{"aria-pressed":t===e,onClick:()=>k(e),children:n},e))}),C.error&&(0,x.jsxs)(A,{error:!0,children:[C.error,(0,x.jsx)(`button`,{onClick:C.refresh,children:`重试`})]}),f&&(0,x.jsx)(A,{children:f}),a&&(0,x.jsx)(Or,{scope:{entry_id:a.id},name:a.name,onClose:()=>o(null),onChanged:O}),u&&(0,x.jsx)(Tr,{entry:u,onClose:()=>d(null),openMemory:e},u.id),s&&(0,x.jsx)(it,{entry:s,entries:C.data?.items||[],onClose:()=>c(null),onSaved:()=>{c(null),p(`入口设置已保存`),O()}}),r===null?t===`entries`?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`p`,{className:`learning-intro`,children:`已接收的消息可能仍在等待学习;批次结束后,也可能没有形成记忆。`}),C.data?C.data.items.length?(0,x.jsx)(`div`,{className:`entry-grid`,children:C.data.items.map(e=>(0,x.jsxs)(`article`,{className:`panel learning-entry`,children:[(0,x.jsxs)(`div`,{className:`section-title`,children:[(0,x.jsx)(`h2`,{children:e.name}),(0,x.jsx)(M,{children:kr(e.kind)})]}),(0,x.jsx)(`p`,{className:`muted`,children:e.platform===`iris-trial`?`试用入口`:`宿主入口 · ${e.platform}`}),(0,x.jsxs)(`div`,{className:`learning-entry-meta`,children:[(0,x.jsx)(M,{children:tt(e.pace)}),(0,x.jsxs)(`strong`,{children:[`待学习 `,e.pending_count,` 条`]})]}),(0,x.jsxs)(`p`,{className:`entry-filter-summary`,children:[`记忆可见范围:`,Ze(e,C.data?.items||[])]}),(0,x.jsx)(nt,{value:e.filters}),(0,x.jsx)(rt,{value:e.queue_wait}),(0,x.jsxs)(`p`,{children:[`最近批次`,e.latest_batch?` #${e.latest_batch.id}`:``]}),(0,x.jsx)(`p`,{children:e.latest_batch?Kn(e.latest_batch):`暂无批次`}),e.current_batch&&e.current_batch.id!==e.latest_batch?.id&&(0,x.jsxs)(`p`,{children:[`当前处理 #`,e.current_batch.id,` ·`,` `,Kn(e.current_batch)]}),(0,x.jsx)(`button`,{className:`secondary`,"aria-label":`修改入口设置 · ${e.name}`,onClick:()=>{p(``),c(e)},children:`修改入口设置`}),(0,x.jsx)(`button`,{className:`secondary`,"aria-label":`入口画像 · ${e.name}`,onClick:()=>d(e),children:`入口画像`}),(0,x.jsx)(`button`,{className:`secondary`,"aria-label":`批量遗忘/删除 · ${e.name}`,onClick:()=>o(e),children:`批量遗忘/删除`}),(0,x.jsx)(`button`,{className:`text-button`,"aria-label":`查看批次 · ${e.name}`,onClick:()=>ee(e.id),children:`查看批次 →`})]},e.id))}):(0,x.jsx)(j,{title:`还没有入口`,children:`可在试用对话页创建入口,或由宿主发送消息。`}):(0,x.jsx)(`p`,{children:`正在读取入口…`})]}):(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`p`,{className:`learning-intro`,children:t===`gaps`?`放弃或内容拒绝的批次留下记忆缺口。重新学习成功后才会消失;模型暂停期间的普通积压不算缺口。`:`批次保留冻结的三段消息。成功可以形成零条记忆;失败重试和放弃、拒绝会分别显示。`}),(0,x.jsxs)(`form`,{className:`learning-filters`,onSubmit:e=>{e.preventDefault(),_({...m}),b(0)},children:[(0,x.jsxs)(`label`,{children:[`筛选入口`,(0,x.jsxs)(`select`,{value:m.entry_id,onChange:e=>h({...m,entry_id:e.target.value}),children:[(0,x.jsx)(`option`,{value:``,children:`全部入口`}),C.data?.items.map(e=>(0,x.jsx)(`option`,{value:e.id,children:e.name},e.id))]})]}),(0,x.jsxs)(`label`,{children:[`开始日期`,(0,x.jsx)(`input`,{type:`date`,value:m.time_from,onChange:e=>h({...m,time_from:e.target.value})})]}),(0,x.jsxs)(`label`,{children:[`结束日期`,(0,x.jsx)(`input`,{type:`date`,value:m.time_to,min:m.time_from||void 0,onChange:e=>h({...m,time_to:e.target.value})})]}),(0,x.jsx)(`button`,{className:`secondary`,type:`submit`,children:`筛选`})]}),(0,x.jsxs)(`p`,{className:`muted learning-date-help`,children:[`日期按角色时区;`,t===`gaps`?`显示与日期范围重叠的消息区间。`:`按批次组成时间筛选。`]}),D.error&&(0,x.jsxs)(A,{error:!0,children:[D.error,(0,x.jsx)(`button`,{onClick:D.refresh,children:`重试`})]}),t===`batches`&&T.data?.entry_waits?.filter(e=>e.queue_wait.reason).map(e=>(0,x.jsxs)(`div`,{className:`panel`,children:[(0,x.jsxs)(`strong`,{children:[C.data?.items.find(t=>t.id===e.entry_id)?.name||e.entry_id,` `,`· 当前入口等待`]}),(0,x.jsx)(rt,{value:e.queue_wait})]},e.entry_id)),D.data?(0,x.jsxs)(x.Fragment,{children:[D.data.total===0?(0,x.jsx)(j,{title:t===`gaps`?`当前范围没有记忆缺口`:`当前范围没有批次`}):(0,x.jsx)(`div`,{className:`learning-list`,children:t===`batches`?T.data?.items.map(e=>(0,x.jsxs)(`article`,{className:`panel learning-batch-card`,children:[(0,x.jsxs)(`div`,{className:`learning-row`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsxs)(`strong`,{children:[`#`,e.id,` · `,e.entry_name]}),(0,x.jsx)(`p`,{children:Kn(e)}),(0,x.jsxs)(`small`,{children:[S(e.created_at),` ·`,` `,Wn(e)?`拆分前`:`本轮`,`已计`,` `,e.attempt_count,` 次尝试`]})]}),(0,x.jsx)(`button`,{className:`text-button`,"aria-label":`查看批次 #${e.id}`,onClick:()=>i(e.id),children:`查看详情 →`})]}),(0,x.jsx)(Yn,{batch:e,onOpen:i}),Wn(e)&&(0,x.jsxs)(`div`,{className:`learning-batch-tree`,children:[(0,x.jsx)(Jn,{batch:e}),(0,x.jsx)(tr,{id:e.id,onOpen:i})]})]},e.id)):E.data?.items.map(e=>(0,x.jsxs)(`article`,{className:`panel learning-row`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsxs)(`strong`,{children:[e.entry_name,` · 批次 #`,e.batch_id]}),(0,x.jsxs)(`p`,{children:[S(e.started_at),` — `,S(e.ended_at)]}),(0,x.jsx)(`p`,{children:jr(e.reason)}),e.relearning&&(0,x.jsx)(M,{children:`重新学习中`})]}),(0,x.jsx)(`button`,{className:`text-button`,"aria-label":`查看批次 #${e.batch_id}`,onClick:()=>i(e.batch_id),children:`查看详情 →`})]},e.batch_id))}),(0,x.jsxs)(`div`,{className:`learning-pagination`,children:[(0,x.jsxs)(`span`,{children:[`共 `,D.data.total,` `,t===`batches`?`个批次节点(含子批次)`:`处缺口`]}),(0,x.jsx)(`button`,{disabled:v===0,onClick:()=>b(Math.max(0,v-30)),children:`上一页`}),(0,x.jsx)(`button`,{disabled:v+30>=D.data.total,onClick:()=>b(v+30),children:`下一页`})]})]}):(0,x.jsx)(`p`,{children:`正在读取…`})]}):(0,x.jsx)(Ir,{id:r,openMemory:e,onBack:()=>i(null),onRelearn:O,onOpen:i},r)]})}function Pr({calls:e}){return e.length?(0,x.jsx)(`div`,{className:`learning-calls`,children:e.map(e=>(0,x.jsxs)(`div`,{children:[(0,x.jsxs)(`strong`,{children:[e.purpose===`learning_repair`?`JSON 修正请求`:`学习请求`,` `,`· `,e.model]}),(0,x.jsxs)(`dl`,{children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`请求结果`}),(0,x.jsxs)(`dd`,{children:[e.result_category===`success`?`已返回正文`:e.result_category,e.timed_out?` · 超时`:``]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`耗时`}),(0,x.jsx)(`dd`,{children:C(e.duration_ms)})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`结束原因(finish_reason)`}),(0,x.jsx)(`dd`,{children:e.finish_reason||`未提供`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`推理档位`}),(0,x.jsx)(`dd`,{children:e.reasoning_effort||`未记录 / 服务商默认`})]})]}),e.error_summary&&(0,x.jsx)(`p`,{children:e.error_summary})]},e.id))}):(0,x.jsx)(`p`,{className:`muted`,children:`没有可关联的调用记录;结束原因与推理档位未知。`})}function Fr({label:e,value:t}){return t==null?(0,x.jsxs)(`p`,{className:`muted`,children:[e,`:没有记录`]}):(0,x.jsxs)(`details`,{className:`learning-output`,children:[(0,x.jsx)(`summary`,{children:e}),(0,x.jsx)(`pre`,{children:t||`(空正文)`})]})}function Ir({id:e,onBack:t,openMemory:n,onRelearn:r,onOpen:i}){let a=y(`/batches/${e}`,3e3),[o,s]=(0,l.useState)(!1),[c,u]=(0,l.useState)(``),[d,f]=(0,l.useState)(``),p=a.data;async function m(){if(!o&&p?.can_relearn&&!Wn(p)&&[`abandoned`,`refused`].includes(p.state)){s(!0),f(``),u(``);try{await g(`/batches/${e}/relearn`,_(`POST`,{})),u(`已重新排队,尚未记住。模型恢复且本入口在途批次结束后开始学习。`),r()}catch(e){f(v(e))}finally{s(!1),a.refresh()}}}return(0,x.jsxs)(`section`,{"aria-label":`批次 #${e}`,className:`batch-detail`,children:[(0,x.jsx)(`button`,{className:`text-button`,onClick:t,children:`← 返回列表`}),(a.error||d)&&(0,x.jsx)(A,{error:!0,children:d||a.error}),c&&(0,x.jsx)(A,{children:c}),p?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`panel batch-overview`,children:[(0,x.jsxs)(`div`,{className:`section-title`,children:[(0,x.jsxs)(`h2`,{children:[`批次 #`,e,` · `,p.entry.name]}),(0,x.jsx)(M,{children:Kn(p,p.segments.target.length)})]}),(0,x.jsx)(Yn,{batch:p,onOpen:i}),(0,x.jsxs)(`p`,{className:`muted`,children:[`组成于 `,S(p.created_at),p.finished_at?` · 结束于 ${S(p.finished_at)}`:``,` `,`· `,Wn(p)?`拆分前`:`本轮`,`已计`,` `,p.attempt_count,` / 4 次尝试`]}),p.parent_batch_id&&(0,x.jsx)(Zn,{id:e}),(0,x.jsx)(Qn,{batch:p}),Wn(p)&&(0,x.jsx)(Jn,{batch:p}),!Wn(p)&&p.gap&&(0,x.jsx)(`p`,{children:`仍有记忆缺口;成功学习后才会消失。`}),p.last_error&&(0,x.jsxs)(`p`,{children:[Wn(p)?`子批次最近错误`:`最近错误`,`:`,p.last_error]}),p.relearn_blocked_reason&&!Wn(p)&&(0,x.jsx)(`p`,{children:p.relearn_blocked_reason}),p.can_relearn&&!Wn(p)&&[`abandoned`,`refused`].includes(p.state)&&(0,x.jsxs)(`div`,{className:`relearn-action`,children:[(0,x.jsx)(`button`,{className:`primary`,disabled:o,onClick:m,children:o?`正在提交…`:`重新学习`}),(0,x.jsx)(`p`,{children:`保留原批次范围和历史记录,重新获得 4 次尝试;成功前缺口持续存在。`})]}),p.state===`succeeded`&&!p.memories.length&&(0,x.jsx)(`p`,{children:`本批已学习,形成或更新了 0 条记忆。这是正常的成功结果。`}),!Wn(p)&&p.state!==`succeeded`&&(0,x.jsx)(`p`,{children:`尚未成功学习,不能把这些消息当作已经记住。`})]}),Wn(p)&&(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsx)(`h2`,{children:`子批次结果`}),(0,x.jsx)(`p`,{children:`本节点的历史请求曾被拒绝,已拆分交给子批次。请进入失败子批次详情重新学习。`}),(0,x.jsx)(tr,{id:e,onOpen:i})]}),(0,x.jsxs)(`section`,{children:[(0,x.jsx)(`h2`,{children:Wn(p)?`拆分前冻结的三段消息`:`三段消息`}),(0,x.jsxs)(`details`,{className:`panel`,children:[(0,x.jsx)(`summary`,{children:`组成批次时的入口设置`}),p.entry_settings?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{children:[`学习节奏:`,tt(p.entry_settings.pace)]}),(0,x.jsx)(nt,{value:p.entry_settings.filters})]}):(0,x.jsx)(`p`,{children:`该批次没有保存入口设置快照。`})]}),(0,x.jsx)(`p`,{className:`muted`,children:`三段范围已冻结;历史与后续只帮助理解,只有目标段可以形成记忆。这里保留消息原文。`}),p.context_mode===`target_only`&&(0,x.jsx)(`p`,{className:`notice`,children:`当前仅目标模式:下方历史段与后续段保留供追溯,不会作为可选前后文发送;仍保留目标引用、附件及既有相关记忆等材料。`}),(0,x.jsx)(`div`,{className:`batch-segments`,children:[[`history`,`历史段`,`只帮助理解`],[`target`,`目标段`,`只从这里学习`],[`future`,`后续段`,`以后再学习`]].map(([e,t,n])=>(0,x.jsxs)(`section`,{className:`panel segment segment-${e}`,children:[(0,x.jsxs)(`div`,{className:`section-title`,children:[(0,x.jsxs)(`h3`,{children:[t,` · `,p.segments[e].length,` 条`]}),(0,x.jsx)(`small`,{children:n})]}),!p.segments[e].length&&(0,x.jsx)(`p`,{className:`muted`,children:`本段为空`}),p.segments[e].map(e=>(0,x.jsx)(`article`,{className:`batch-message`,children:e.missing?(0,x.jsxs)(`p`,{children:[`消息 #`,e.id,` 已不可用`]}):(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`strong`,{children:e.sender_name||e.sender_subject_id}),` `,(0,x.jsx)(M,{children:Ar(e.kind)})]}),(0,x.jsxs)(`small`,{children:[`#`,e.id,` · `,S(e.occurred_at),e.scene_identity?` · ${e.scene_identity}`:``]}),e.content.length>600?(0,x.jsxs)(`details`,{children:[(0,x.jsxs)(`summary`,{children:[e.content.slice(0,120),`…(展开原文)`]}),(0,x.jsx)(`p`,{className:`message-body`,children:e.content})]}):(0,x.jsx)(`p`,{className:`message-body`,children:e.content}),(0,x.jsx)(Ue,{media:e.media}),e.quote_content&&(0,x.jsxs)(`blockquote`,{children:[e.quote_author_name||`引用`,`:`,e.quote_content]}),(0,x.jsx)(`small`,{children:O(e.learning_state)})]})},e.id))]},e))})]}),(0,x.jsxs)(`section`,{children:[(0,x.jsx)(`h2`,{children:Wn(p)?`本节点历史尝试(拆分前)`:`每次尝试`}),Wn(p)&&(0,x.jsx)(`p`,{children:`以下只记录本节点拆分前的请求;这些历史拒绝不等于子批次最终失败。`}),(0,x.jsxs)(`p`,{children:[`本节点实际模型调用 `,qn(p),` 次`]}),(0,x.jsx)(`p`,{className:`muted`,children:`含学习、JSON 修正和未归入尝试的调用;不包含子批次调用,不等于树节点数或尝试额度。`}),(0,x.jsx)(`p`,{className:`muted`,children:`历次尝试持续编号;服务暂停时的失败记录不一定扣除尝试额度。模型返回正文不代表已经写入记忆。`}),!p.attempts.length&&(0,x.jsx)(j,{title:p.state===`running`?`本次尝试仍在进行`:`尚无已完成的尝试`}),p.attempts.map(e=>(0,x.jsxs)(`article`,{className:`panel batch-attempt`,children:[(0,x.jsxs)(`div`,{className:`section-title`,children:[(0,x.jsxs)(`h3`,{children:[`第 `,e.number,` 次尝试`]}),(0,x.jsx)(M,{children:e.parse_status===`failed`?`失败 · 未写入`:`学习成功`})]}),(0,x.jsxs)(`p`,{children:[S(e.started_at),` — `,S(e.finished_at),` · 总耗时 `,C(e.duration_ms)]}),(0,x.jsxs)(`p`,{children:[`解析结果:`,{direct:`直接解析`,repaired:`修正后解析`,failed:`失败`}[e.parse_status]||e.parse_status]}),(0,x.jsxs)(`p`,{children:[`本次上下文模式:`,Gn(e.context_mode)]}),e.error&&(0,x.jsxs)(`p`,{children:[`诊断:`,e.error]}),(0,x.jsx)(Pr,{calls:e.calls}),(0,x.jsx)(Fr,{label:`模型原始正文`,value:e.raw_output}),(0,x.jsx)(Fr,{label:`JSON 修正后的正文`,value:e.repair_output})]},e.id)),!!p.unassigned_calls.length&&(0,x.jsxs)(`details`,{className:`panel batch-attempt`,children:[(0,x.jsxs)(`summary`,{children:[`尚未归入已完成尝试的调用 · `,p.unassigned_calls.length,` 条`]}),(0,x.jsx)(Pr,{calls:p.unassigned_calls})]})]}),(0,x.jsxs)(`div`,{className:`batch-results`,children:[(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsxs)(`h2`,{children:[`规整记录 · `,p.result.normalizations?.length||0,` 条`]}),!p.result.normalizations?.length&&(0,x.jsx)(`p`,{className:`muted`,children:`没有规整记录。`}),p.result.normalizations?.map((e,t)=>(0,x.jsxs)(`article`,{className:`result-item`,children:[(0,x.jsx)(`strong`,{children:e.field}),(0,x.jsx)(`p`,{children:e.reason}),(0,x.jsxs)(`small`,{children:[e.section,e.index==null?``:` · 第 ${e.index+1} 项`]}),(0,x.jsxs)(`pre`,{children:[Mr(e.before),` → `,Mr(e.after)]})]},t))]}),(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsxs)(`h2`,{children:[`被丢弃的条目 · `,p.result.dropped?.length||0,` 条`]}),!p.result.dropped?.length&&(0,x.jsx)(`p`,{className:`muted`,children:`没有已记录的丢弃条目;批次失败时请查看原始输出和错误。`}),p.result.dropped?.map((e,t)=>(0,x.jsxs)(`article`,{className:`result-item`,children:[(0,x.jsx)(`strong`,{children:e.reason}),(0,x.jsx)(`small`,{children:e.section}),(0,x.jsx)(`pre`,{children:Mr(e.item)})]},t))]})]}),(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsxs)(`h2`,{children:[Wn(p)?`成功子批次的记忆结果`:`记忆结果`,` ·`,` `,p.memories.length,` 条`]}),(0,x.jsx)(`p`,{className:`muted`,children:`下列正文为记忆当前版本;详情中可查看修订历史。`}),!p.memories.length&&(0,x.jsx)(`p`,{children:p.state===`succeeded`?`本批没有新增、更新或确认记忆。`:`尚无成功写入的记忆。`}),p.memories.map(e=>(0,x.jsxs)(`div`,{className:`learning-row`,children:[(0,x.jsx)(M,{children:{created:`新增`,updated:`更新`,confirmed:`再次确认`}[e.change]||e.change}),e.missing?(0,x.jsxs)(`span`,{children:[`记忆 #`,e.id,` 已不可用`]}):(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>n(e.id),children:[`#`,e.id,` · `,e.content]}),(0,x.jsxs)(`small`,{children:[E(e.lifecycle),` · 修订 `,e.revision]})]},`${e.change}-${e.id}`))]})]}):(0,x.jsx)(`p`,{children:`正在读取批次…`})]})}function Lr(e){if(!e||typeof e!=`object`)return null;let t=e;return typeof t.reason!=`string`||!Array.isArray(t.items)||!t.items.every(e=>{if(!e||typeof e!=`object`)return!1;let t=e;return Number.isInteger(t.index)&&typeof t.supported==`boolean`&&typeof t.scene_qualified==`boolean`&&typeof t.reason==`string`&&Array.isArray(t.violations)&&t.violations.every(e=>typeof e==`string`)})?null:t}function Rr(e){if(!e||typeof e!=`object`)return`原条目格式无效或未保存`;let t=e.text;return typeof t==`string`?t:`原条目格式无效或未保存`}function zr({value:e,openMemory:t}){return e.length?(0,x.jsxs)(A,{children:[(0,x.jsx)(`strong`,{children:`可能过时`}),(0,x.jsx)(`ul`,{children:e.map((e,n)=>(0,x.jsxs)(`li`,{children:[e.memory_id!=null&&(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>t(e.memory_id),children:[`记忆 #`,e.memory_id]}),e.revision!=null&&`(依据修订 ${e.revision})`,e.sentence_index!=null&&`第 ${e.sentence_index+1} 条:`,jt(e.reason||``)]},n))})]}):null}function Br({item:e,openMemory:t}){return(0,x.jsxs)(`div`,{className:`summary-item`,children:[(0,x.jsxs)(`p`,{children:[e.kind&&(0,x.jsx)(M,{children:kt[e.kind]||e.kind}),` `,(0,x.jsx)(M,{children:e.admin_written||e.author===`admin`?`管理员手写`:`模型生成`})]}),(0,x.jsx)(`p`,{className:`entry-profile-content`,children:e.body||e.text}),e.time_range&&(0,x.jsxs)(`p`,{children:[`时间范围:`,e.time_range]}),e.valid_until&&(0,x.jsxs)(`p`,{children:[`有效至:`,e.valid_until]}),e.expires_at&&(0,x.jsxs)(`p`,{children:[`到期时间:`,w(e.expires_at)]}),(0,x.jsxs)(`details`,{className:`source`,children:[(0,x.jsxs)(`summary`,{children:[`记忆依据 · `,e.basis.length,` 条`]}),!e.basis.length&&(0,x.jsx)(`p`,{children:`此条没有模型记忆依据;管理员手写内容由管理员负责核对。`}),e.basis.map((e,n)=>(0,x.jsxs)(`div`,{className:`entry-profile-evidence`,children:[(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>t(e.memory_id),children:[`记忆 #`,e.memory_id]}),` `,`· 依据修订 `,e.revision,e.evidence?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`p`,{className:`entry-profile-content`,children:e.evidence.content}),(0,x.jsxs)(`small`,{children:[`依据快照 ·`,` `,w(e.evidence.event_time||e.evidence.created_at),e.evidence.truncated&&` · 摘录已截短`]})]}):(0,x.jsx)(`p`,{className:`muted`,children:`没有保存的依据正文快照。`}),e.memory?(0,x.jsxs)(`details`,{children:[(0,x.jsxs)(`summary`,{children:[`当前记忆 · 修订 `,e.memory.revision]}),(0,x.jsx)(`p`,{children:e.memory.content})]}):(0,x.jsx)(`p`,{className:`muted`,children:`当前记忆已不可用。`})]},n))]})]})}function Vr({value:e}){return(0,x.jsxs)(`p`,{className:`muted`,children:[`v`,e.version,` · `,At[e.status]||e.status,` ·`,` `,{periodic:`定期更新`,regenerate:`管理员重新生成`,edit:`管理员编辑`,rollback:`回滚`}[e.source]||e.source,` `,`· 生成于 `,w(e.generated_at),` · 变化程度:`,{small:`小`,medium:`中`,large:`大`}[e.change_degree]||e.change_degree]})}function Hr({value:e,openMemory:t}){let n=e.checks,r=Lr(n.model);return e.cleared_at?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(Vr,{value:e}),(0,x.jsxs)(A,{children:[`因彻底清除而清空 · `,w(e.cleared_at),`。此版本不能回滚。`]})]}):(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(Vr,{value:e}),e.invalidated_reason&&(0,x.jsxs)(A,{children:[jt(e.invalidated_reason),`,此版本不可回滚。`]}),(0,x.jsx)(zr,{value:e.stale_basis,openMemory:t}),e.sentences.map((e,n)=>(0,x.jsx)(Br,{item:e,openMemory:t},n)),!e.sentences.length&&(0,x.jsx)(`p`,{children:`此版本没有摘要条目。`}),(0,x.jsxs)(`details`,{className:`source`,children:[(0,x.jsx)(`summary`,{children:`检查与删条记录`}),(0,x.jsxs)(`p`,{children:[`检查结果:`,n.passed?`通过`:`未通过`,n.admin_edit&&`(管理员编辑,未调用模型检查)`]}),n.reason&&(0,x.jsx)(`p`,{children:jt(n.reason)}),n.errors?.map((e,t)=>(0,x.jsx)(`p`,{children:jt(e)},t)),n.deterministic&&(0,x.jsxs)(`p`,{children:[`规则检查:`,n.deterministic.passed?`通过`:`未通过`,n.deterministic.characters!=null&&` · ${n.deterministic.characters} 字`,n.deterministic.tokens!=null&&` · ${n.deterministic.tokens} token`]}),r?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{children:[`模型检查:`,r.reason]}),r.items.map((e,t)=>(0,x.jsxs)(`div`,{className:`entry-profile-evidence`,children:[(0,x.jsxs)(`strong`,{children:[`检查条目 `,e.index]}),(0,x.jsx)(`p`,{children:n.checked_sentences?.[t]?.text}),(0,x.jsxs)(`p`,{children:[`依据支持:`,e.supported?`是`:`否`,` · 场景限定:`,e.scene_qualified?`充分`:`不足`]}),(0,x.jsx)(`p`,{children:e.reason}),!!e.violations.length&&(0,x.jsxs)(`p`,{children:[`问题:`,e.violations.join(`、`)]})]},e.index))]}):(0,x.jsx)(`p`,{children:n.model==null?`没有模型检查记录。`:`模型检查记录格式无效,无法逐条展示。`}),!!n.deleted_sentences?.length&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`h4`,{children:`已删条目`}),n.deleted_sentences.map((e,t)=>(0,x.jsxs)(`div`,{children:[(0,x.jsxs)(`p`,{children:[`第 `,e.index,` 条 ·`,` `,e.stage===`references`?`引用核对`:`模型检查`]}),(0,x.jsx)(`p`,{children:e.sentence?.text||Rr(e.item)}),(0,x.jsx)(`p`,{children:jt(e.reason)}),!!e.violations?.length&&(0,x.jsx)(`p`,{children:e.violations.join(`、`)})]},t))]}),n.admin_warnings?.map((e,t)=>(0,x.jsxs)(A,{children:[`手写条目 `,e.index,` 的检查提醒:`,e.reason,` ·`,` `,e.violations.join(`、`)]},t)),n.rollback_from!=null&&(0,x.jsxs)(`p`,{children:[`从 v`,n.rollback_from,` 回滚新建。`]})]})]})}function Ur(e){let t=Array.from(e),n=0,r=0,i=0;for(;ie.kind).map(e=>e.text))].sort((e,t)=>t.length-e.length),r=0,i=0;if(n.length){let t=RegExp(`^(?:`+n.map(e=>e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)).join(`|`)+`)`,`gm`);for(let n of e.matchAll(t))r+=Ur(e.slice(i,n.index))+1,i=n.index+n[0].length}r+=Ur(e.slice(i));let a=Array.from(e),o=a.filter(e=>/[\u4e00-\u9fff]/u.test(e)).length;return{items:r,characters:a.length,tokens:Math.max(1,o+Math.floor((a.length-o+2)/3))}}function Gr({base:e,initial:t,onSettled:n,view:r}){let[i,a]=(0,l.useState)(t.state===`running`),o=y(`${e}/attempts/${t.id}`,i?1500:0),s=(0,l.useRef)(!1);(0,l.useEffect)(()=>{o.data&&o.data.state!==`running`&&!s.current&&(s.current=!0,a(!1),n())},[o.data,n]);let c=o.data||t;return(0,x.jsxs)(`section`,{className:`entry-profile-section`,"aria-label":`摘要生成任务`,children:[(0,x.jsxs)(`h3`,{children:[`生成任务 #`,c.id]}),o.error&&(0,x.jsxs)(A,{error:!0,children:[o.error,(0,x.jsx)(`button`,{onClick:o.refresh,children:`重试任务状态`})]}),(0,x.jsx)(`p`,{role:`status`,children:c.state===`running`?c.stage===`checking`?`正在检查候选…`:`正在生成候选…`:At[c.state]||c.state}),c.reason&&(0,x.jsx)(`p`,{children:jt(c.reason)}),(0,x.jsxs)(`p`,{className:`fine-print`,children:[`开始:`,w(c.started_at),c.finished_at&&` · 结束:${w(c.finished_at)}`]}),c.state===`rejected`&&(0,x.jsx)(`p`,{children:`当前发布版保持不变。确定性拒绝后自动整理等待新依据;管理员仍可主动重新生成。`}),c.cleared_at&&(0,x.jsx)(`p`,{children:`任务关联内容因彻底清除而清空。`}),c.version!=null&&(0,x.jsxs)(`button`,{onClick:()=>r(c.version),children:[`查看任务版本 v`,c.version]})]})}function Kr({subjectId:e,initialVersion:t,openMemory:n}){let r=`/people/${encodeURIComponent(e)}/summary`,i=y(r,5e3),[a,o]=(0,l.useState)(0),[s,c]=(0,l.useState)(t||null),u=y(`${r}/versions?limit=10&offset=${a}`),d=y(i.data?.current?`${r}/versions/${i.data.current.version}`:null),p=y(s?`${r}/versions/${s}`:null),[h,g]=(0,l.useState)(null),b=y(h),[S,C]=(0,l.useState)(`1`),[E,D]=(0,l.useState)(`2`),[O,k]=(0,l.useState)(null),[j,N]=(0,l.useState)(null),[P,F]=(0,l.useState)(null),[I,te]=(0,l.useState)(``),[L,ne]=(0,l.useState)(null),[R,re]=(0,l.useState)(!1),[ie,ae]=(0,l.useState)(``),[oe,se]=(0,l.useState)(``),[ce,le]=(0,l.useState)(!1),ue=(0,l.useRef)(!1),de=(0,l.useRef)(!0);(0,l.useEffect)(()=>(de.current=!0,()=>{de.current=!1}),[]);let z=(0,l.useCallback)(()=>{i.refresh(),u.refresh(),d.refresh(),p.refresh(),b.refresh()},[i.refresh,u.refresh,d.refresh,p.refresh,b.refresh]),B=i.data,V=B?.settings.current_version??0,fe=JSON.stringify(B?.stale_basis||[]);(0,l.useEffect)(()=>{u.refresh(),d.refresh(),p.refresh()},[V,B?.current?.cleared_at,fe,B?.pending?.version,B?.latest_attempt?.state,u.refresh,d.refresh,p.refresh]);let pe=e=>{c(e),ae(``)},me=B?.latest_attempt,he=me&&(!L||me.id>=L.id)?me:L,H=he?.state===`running`,U=R||i.loading||!!i.error||ce,ge=!B?.current||d.data?.version===V&&!d.loading&&!d.error,_e=Wr(O?.content||``,O?.original),ve=B?.edit_limits||{max_items:5,max_chars:200,max_tokens:250},ye=!O?.content.trim()||_e.characters>ve.max_chars||_e.tokens>ve.max_tokens||_e.items>ve.max_items;async function be(e,t,n,i){if(ue.current)return!1;ue.current=!0,re(!0),ae(``),se(``);try{let a=await m(r+e,_(t,n));return de.current&&(e===`/regenerate`&&a.status===202&&a.data.attempt&&ne(a.data.attempt),se(i),F(null),z()),!0}catch(e){if(de.current){let t=e instanceof f&&e.status===409;le(t),ae(t?`当前摘要、设置、依据或生成任务已变化。已刷新版本;请核对后再操作,编辑草稿已保留。`:v(e)),t&&F(null),z()}return!1}finally{ue.current=!1,de.current&&re(!1)}}let xe=(e,t)=>{C(String(e)),D(String(t)),g(`${r}/diff?before_version=${e}&after_version=${t}`)};return(0,x.jsxs)(`section`,{className:`panel person-summary`,"aria-label":`人物摘要`,children:[(0,x.jsxs)(`div`,{className:`panel-heading`,children:[(0,x.jsx)(`h2`,{children:`人物摘要`}),(0,x.jsx)(`button`,{disabled:R,onClick:z,children:`刷新人物摘要`})]}),(0,x.jsx)(`p`,{className:`muted`,children:`从与此人物相关、全部入口共享的有效记忆提炼。查看与轮询不会召回或增加使用次数。`}),(i.error||ie)&&(0,x.jsx)(A,{error:!0,children:ie||i.error}),oe&&(0,x.jsx)(A,{children:oe}),B?(0,x.jsxs)(x.Fragment,{children:[!B.supported&&(0,x.jsx)(A,{children:`此主体类型或已合并人物不支持摘要写操作,可查阅已有历史。`}),!B.global_enabled&&(0,x.jsx)(A,{children:`全局人物摘要开关已关闭,不会生成或加入回复准备。`}),ce&&(0,x.jsx)(`button`,{disabled:R||i.loading||!!i.error||!ge,onClick:()=>{le(!1),ae(``),k(e=>e?{...e,expected_version:V,original:d.data?.sentences||[]}:null),N(e=>e?{...e,expected_version:V}:null)},children:`已核对最新版本,继续操作`}),(0,x.jsxs)(`p`,{children:[(0,x.jsx)(M,{children:B.settings.enabled?`此人摘要已开启`:`此人摘要已关闭`}),` `,`·`,` `,B.settings.publish_mode===`all_manual`?`全部人工确认`:`检查通过自动发布`,` `,`·`,` `,(0,x.jsxs)(M,{tone:B.pending_count?`amber`:``,children:[`待确认 `,B.pending_count]})]}),B.supported&&(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{disabled:U||!ge,onClick:()=>k({content:B.current?.content||``,expected_version:V,original:d.data?.sentences||[]}),children:`编辑摘要`}),(0,x.jsx)(`button`,{disabled:U,onClick:()=>N({enabled:B.settings.enabled,publish_mode:B.settings.publish_mode,expected_version:V}),children:`人物摘要设置`}),(0,x.jsx)(`button`,{disabled:U||H||!B.global_enabled||!B.settings.enabled,onClick:()=>void be(`/regenerate`,`POST`,{expected_version:V},`已接受重新生成,请查看任务进度。`),children:H?`摘要生成中…`:`重新生成摘要`})]}),(0,x.jsx)(`p`,{className:`fine-print`,children:`重新生成至少需要 8 条相关全局有效记忆,并受开关、版本检查与模型预算限制。`}),j&&(0,x.jsxs)(`form`,{className:`entry-profile-section`,"aria-label":`人物摘要设置`,onSubmit:async e=>{e.preventDefault(),!(U||j.expected_version!==V)&&await be(`/settings`,`PATCH`,j,`人物摘要设置已保存`)&&N(null)},children:[(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,disabled:R,checked:j.enabled,onChange:e=>N({...j,enabled:e.target.checked})}),`启用此人的摘要`]}),(0,x.jsxs)(`label`,{children:[`摘要发布方式`,(0,x.jsxs)(`select`,{disabled:R,value:j.publish_mode,onChange:e=>N({...j,publish_mode:e.target.value}),children:[(0,x.jsx)(`option`,{value:`check_auto`,children:`检查通过自动发布`}),(0,x.jsx)(`option`,{value:`all_manual`,children:`全部人工确认`})]})]}),(0,x.jsx)(`p`,{children:`关闭后保留历史;发布方式只影响之后的候选,不会发布已有待确认版本。`}),j.expected_version!==V&&(0,x.jsx)(A,{children:`设置基于旧版本,请取消后重新打开设置。`}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{disabled:U||j.expected_version!==V,children:`保存人物摘要设置`}),(0,x.jsx)(`button`,{type:`button`,disabled:R,onClick:()=>N(null),children:`取消设置`})]})]}),O&&(0,x.jsxs)(`form`,{className:`entry-profile-section`,"aria-label":`编辑人物摘要`,onSubmit:async e=>{e.preventDefault(),!(U||ye||O.expected_version!==V)&&await be(``,`PUT`,{content:O.content,expected_version:O.expected_version},`摘要编辑已发布`)&&k(null)},children:[(0,x.jsx)(`h3`,{children:`编辑并直接发布`}),(0,x.jsx)(`p`,{children:`新增或改动条目标为管理员手写,之后生成会保留;未改条目保留原依据。按句号或换行分条。`}),(0,x.jsxs)(`label`,{children:[`人物摘要正文`,(0,x.jsx)(`textarea`,{rows:6,disabled:R,value:O.content,onChange:e=>k({...O,content:e.target.value})})]}),(0,x.jsxs)(`p`,{children:[_e.items,` / `,ve.max_items,` 条 · `,_e.characters,` /`,` `,ve.max_chars,` 字 · `,_e.tokens,` / `,ve.max_tokens,` `,`估算 token(无最低字数) · 基于 v`,O.expected_version]}),O.expected_version!==V&&(0,x.jsxs)(A,{children:[`当前版本已变化,草稿已保留。请核对最新摘要后更新草稿版本。`,(0,x.jsx)(`button`,{type:`button`,disabled:!ge||U,onClick:()=>k({...O,expected_version:V,original:d.data?.sentences||[]}),children:`更新草稿版本`})]}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{disabled:U||ye||O.expected_version!==V,children:`发布摘要编辑`}),(0,x.jsx)(`button`,{type:`button`,disabled:R,onClick:()=>k(null),children:`取消编辑摘要`})]})]}),(0,x.jsxs)(`section`,{className:`entry-profile-section`,"aria-label":`当前人物摘要`,children:[(0,x.jsx)(`h3`,{children:`当前摘要`}),B.current?d.error?(0,x.jsxs)(A,{error:!0,children:[d.error,(0,x.jsx)(`button`,{onClick:d.refresh,children:`重试当前摘要`})]}):!d.data||d.data.version!==V?(0,x.jsx)(`p`,{children:`正在读取当前摘要…`}):(0,x.jsx)(Hr,{value:d.data,openMemory:n}):(0,x.jsx)(`p`,{children:`尚无已发布的人物摘要。`}),!d.data&&(0,x.jsx)(zr,{value:B.stale_basis,openMemory:n})]}),B.pending&&(0,x.jsxs)(`section`,{className:`entry-profile-section`,"aria-label":`待确认人物摘要`,children:[(0,x.jsxs)(`h3`,{children:[`待确认候选 · v`,B.pending.version]}),(0,x.jsx)(`p`,{className:`entry-profile-content`,children:B.pending.content}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsxs)(`button`,{onClick:()=>pe(B.pending.version),children:[`审阅候选 v`,B.pending.version]}),B.current&&(0,x.jsx)(`button`,{onClick:()=>xe(V,B.pending.version),children:`对比当前与候选`})]})]}),he&&(0,x.jsx)(Gr,{base:r,initial:he,onSettled:z,view:pe},he.id),(0,x.jsxs)(`section`,{className:`entry-profile-section`,"aria-label":`人物摘要历史`,children:[(0,x.jsx)(`h3`,{children:`版本历史`}),u.error&&(0,x.jsxs)(A,{error:!0,children:[u.error,(0,x.jsx)(`button`,{onClick:u.refresh,children:`重试摘要历史`})]}),u.data?.items.map(e=>(0,x.jsxs)(`div`,{className:`entry-profile-evidence`,children:[(0,x.jsxs)(`button`,{onClick:()=>pe(e.version),children:[`查看摘要 v`,e.version]}),` `,(0,x.jsx)(M,{children:e.is_current?`当前版本`:At[e.status]||e.status}),e.cleared_at&&(0,x.jsx)(M,{tone:`warning`,children:`因彻底清除而清空`}),(0,x.jsx)(`p`,{children:w(e.generated_at)})]},e.version)),u.data&&!u.data.total&&(0,x.jsx)(`p`,{children:`暂无历史版本。`}),u.data&&(0,x.jsx)(T,{total:u.data.total,offset:a,change:o,limit:10})]}),s!=null&&(0,x.jsxs)(`section`,{className:`entry-profile-section`,"aria-label":`人物摘要版本详情`,children:[(0,x.jsxs)(`h3`,{children:[`摘要 v`,s,` 的依据与检查`]}),p.error?(0,x.jsxs)(A,{error:!0,children:[p.error,(0,x.jsx)(`button`,{onClick:p.refresh,children:`重试摘要版本`})]}):p.data?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(Hr,{value:p.data,openMemory:n}),B.supported&&p.data.status===`candidate`&&(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsxs)(`button`,{disabled:U||!!p.data.cleared_at||!p.data.checks.passed,onClick:()=>F({kind:`confirm`,version:s,expected_version:V}),children:[`确认发布摘要 v`,s]}),(0,x.jsxs)(`button`,{disabled:U,onClick:()=>{te(``),F({kind:`reject`,version:s,expected_version:V})},children:[`拒绝摘要 v`,s]})]}),B.supported&&p.data.status===`published`&&!p.data.is_current&&(0,x.jsxs)(`button`,{disabled:U||!!p.data.cleared_at||!!p.data.invalidated_reason||!p.data.content.trim(),onClick:()=>F({kind:`rollback`,version:s,expected_version:V}),children:[`回滚到摘要 v`,s]})]}):(0,x.jsx)(`p`,{children:`正在读取版本…`})]}),(0,x.jsxs)(`section`,{className:`entry-profile-section`,"aria-label":`摘要版本对比`,children:[(0,x.jsx)(`h3`,{children:`任意两版对比`}),(0,x.jsxs)(`form`,{className:`button-row`,onSubmit:e=>{e.preventDefault(),Number.isSafeInteger(+S)&&+S>0&&Number.isSafeInteger(+E)&&+E>0&&xe(+S,+E)},children:[(0,x.jsxs)(`label`,{children:[`较早版本`,(0,x.jsx)(`input`,{type:`number`,min:1,required:!0,value:S,onChange:e=>C(e.target.value)})]}),(0,x.jsxs)(`label`,{children:[`较晚版本`,(0,x.jsx)(`input`,{type:`number`,min:1,required:!0,value:E,onChange:e=>D(e.target.value)})]}),(0,x.jsx)(`button`,{children:`对比摘要版本`})]}),b.error&&(0,x.jsxs)(A,{error:!0,children:[b.error,(0,x.jsx)(`button`,{onClick:b.refresh,children:`重试摘要对比`})]}),b.data&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{children:[`v`,b.data.before,` → v`,b.data.after,!b.data.changed&&` · 条目没有变化`]}),b.data.sentences.map((e,t)=>(0,x.jsxs)(`div`,{className:`persona-diff-row`,children:[(0,x.jsx)(`strong`,{children:{equal:`保留`,replace:`修改`,insert:`新增`,delete:`删除`}[e.op]||e.op}),(0,x.jsxs)(`div`,{className:`persona-diff-columns`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`small`,{children:`之前`}),e.before.map((e,t)=>(0,x.jsx)(`p`,{className:`entry-profile-content`,children:e.text},t))]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`small`,{children:`之后`}),e.after.map((e,t)=>(0,x.jsx)(`p`,{className:`entry-profile-content`,children:e.text},t))]})]})]},t))]})]}),(0,x.jsx)(`a`,{href:`#/operations?object_type=person_summary&object_id=${encodeURIComponent(e)}`,children:`查看人物摘要操作记录`}),P&&(0,x.jsxs)(ee,{title:P.kind===`confirm`?`确认发布人物摘要`:P.kind===`reject`?`拒绝人物摘要`:`回滚人物摘要`,onClose:()=>F(null),closeDisabled:R,children:[(0,x.jsx)(`p`,{children:P.kind===`rollback`?`将复制 v${P.version},新建并发布一个版本;历史版本保持原记录。`:P.kind===`confirm`?`将发布候选 v${P.version},替换当前摘要。`:`将拒绝候选 v${P.version},保留当前发布版。`}),P.kind===`reject`&&(0,x.jsxs)(`label`,{children:[`拒绝摘要原因`,(0,x.jsx)(`input`,{maxLength:1e3,value:I,onChange:e=>te(e.target.value),disabled:R})]}),(0,x.jsx)(`p`,{children:`请核对条目、依据和检查记录后再次确认。`}),ie&&(0,x.jsx)(A,{error:!0,children:ie}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{disabled:R,onClick:()=>F(null),children:`取消操作`}),(0,x.jsxs)(`button`,{className:`primary`,disabled:U||P.expected_version!==V,onClick:()=>void be(`/versions/${P.version}/${P.kind}`,`POST`,{expected_version:P.expected_version,...P.kind===`reject`?{reason:I.trim()||`管理员拒绝`}:{}},P.kind===`rollback`?`已新建并发布回滚版本`:P.kind===`confirm`?`候选已确认发布`:`候选已拒绝`),children:[`确认`,P.kind===`rollback`?`回滚`:P.kind===`confirm`?`发布`:`拒绝`]})]})]})]}):(0,x.jsx)(`p`,{role:`status`,children:`正在读取人物摘要…`})]})}function qr({initialQuery:e=``,onChange:t,openMemory:n=()=>{}}){let r=new URLSearchParams(e),[i,a]=(0,l.useState)(r.get(`id`)),[o,s]=(0,l.useState)(``),[c,u]=(0,l.useState)({text:``,pending_only:r.get(`pending_only`)===`true`,include_merged:!1}),[d,f]=(0,l.useState)(c),[p,m]=(0,l.useState)(0),h=new URLSearchParams({text:d.text,pending_only:String(d.pending_only),include_merged:String(d.include_merged),limit:`30`,offset:String(p)}),g=y(i?null:`/people?${h}`,5e3);return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`page-heading`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`p`,{className:`eyebrow`,children:`名字背后的人`}),(0,x.jsx)(`h1`,{children:`人物`}),(0,x.jsx)(`p`,{children:`核对身份与证据,再决定是否为同一个人。`})]}),(0,x.jsx)(`a`,{className:`button`,href:`#/people-graph`,children:`人物关系图 →`})]}),o&&(0,x.jsx)(A,{children:o}),i?(0,x.jsx)(Yr,{id:i,summaryVersion:i===r.get(`id`)&&Number(r.get(`summary_version`))||void 0,openMemory:n,openPerson:a,onBack:()=>a(null),onChange:()=>{g.refresh(),t()},onMerged:e=>{s(`已确认联系并完成人物合并,以下为保留人物的资料。`),a(e)}},i):(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`form`,{className:`panel people-filters`,onSubmit:e=>{e.preventDefault(),f({...c}),m(0),g.refresh()},children:[(0,x.jsxs)(`label`,{children:[`搜索名字或别名`,(0,x.jsx)(`input`,{maxLength:100,value:c.text,onChange:e=>u({...c,text:e.target.value})})]}),(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:c.pending_only,onChange:e=>u({...c,pending_only:e.target.checked})}),`只看待确认`]}),(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:c.include_merged,onChange:e=>u({...c,include_merged:e.target.checked})}),`包含已合并人物`]}),(0,x.jsx)(`button`,{className:`primary`,children:`搜索人物`})]}),g.error&&(0,x.jsxs)(A,{error:!0,children:[g.error,(0,x.jsx)(`button`,{onClick:g.refresh,children:`重新加载`})]}),g.data?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{className:`muted`,children:[`共 `,g.data.total,` 位人物`]}),!g.data.items.length&&(0,x.jsx)(j,{title:`当前范围没有人物`}),(0,x.jsx)(`div`,{className:`entry-grid`,children:g.data.items.map(e=>(0,x.jsxs)(`article`,{className:`panel person-card`,children:[(0,x.jsx)(`h2`,{children:e.name}),(0,x.jsxs)(`small`,{className:`muted`,children:[`人物标识:`,e.id]}),!!e.pending_links&&(0,x.jsx)(`p`,{children:(0,x.jsxs)(M,{tone:`purple`,children:[`可能是同一人 · `,e.pending_links,` 条待确认`]})}),e.merged_into&&(0,x.jsx)(`p`,{children:(0,x.jsx)(M,{children:`已合并`})}),(0,x.jsxs)(`p`,{children:[`别名:`,e.aliases.map(e=>e.alias).join(`、`)||`暂无`]}),(0,x.jsxs)(`p`,{children:[`相关记忆 `,e.memory_count,` 条`]}),(0,x.jsx)(`button`,{className:`text-button`,onClick:()=>a(e.id),"aria-label":`查看人物 ${e.name}`,children:`查看人物 →`})]},e.id))}),(0,x.jsx)(T,{total:g.data.total,offset:p,change:m})]}):(0,x.jsx)(`p`,{role:`status`,children:`正在读取人物…`})]})]})}function Jr({messages:e}){return(0,x.jsxs)(`details`,{className:`person-evidence`,open:!0,children:[(0,x.jsxs)(`summary`,{children:[`证据消息 · `,e.length,` 条`]}),!e.length&&(0,x.jsx)(`p`,{className:`muted`,children:`没有可展示的证据消息。`}),e.map(e=>(0,x.jsxs)(`blockquote`,{children:[(0,x.jsxs)(`small`,{children:[e.sender_name||e.sender_subject_id,` ·`,` `,e.entry_name||e.entry_id,` · #`,e.id,` ·`,` `,w(e.occurred_at||e.received_at)]}),(0,x.jsx)(`p`,{children:e.content}),e.quote_content&&(0,x.jsxs)(`div`,{className:`evidence-quote`,children:[(0,x.jsxs)(`small`,{children:[`引用`,e.quote_author_subject_id?` · 作者标识 ${e.quote_author_subject_id}`:``]}),(0,x.jsx)(`p`,{children:e.quote_content})]})]},e.id))]})}function Yr({id:e,summaryVersion:t,openMemory:n,openPerson:r,onBack:i,onChange:a,onMerged:o}){let s=y(`/people/${encodeURIComponent(e)}`),[c,u]=(0,l.useState)(!1),[d,p]=(0,l.useState)(``),[m,h]=(0,l.useState)(null),[b,S]=(0,l.useState)(``),[C,w]=(0,l.useState)(``),[T,D]=(0,l.useState)(!1),[O,k]=(0,l.useState)(!1),j=s.data,N=T||O||s.loading||!!s.error,P=()=>{h(null),S(``),k(!1),s.refresh()},F=e=>{let t=e instanceof f&&e.status===409;k(t),S(t?`资料或联系已变化,请刷新人物资料后重新核对。`:v(e))},I=e=>{h(null),w(e),S(``),s.refresh(),a()};async function te(t){if(t.preventDefault(),!j||N)return;let n=d.trim();if(!n||Array.from(n).length>100){S(`别名需为 1 至 100 个字符`);return}if(n.toLocaleLowerCase()===j.name.trim().toLocaleLowerCase()){S(`别名不能与人物名字相同`);return}D(!0),S(``),w(``);try{await g(`/people/${encodeURIComponent(e)}/aliases`,_(`POST`,{alias:n,expected_revision:j.revision})),p(``),I(`已添加别名`)}catch(e){F(e)}finally{D(!1)}}async function L(){if(j&&m&&m.kind!==`merge`&&!N){D(!0),S(``),w(``);try{m.kind===`deny`?await g(`/people/links/${m.link.id}/deny`,_(`POST`,{expected_revision:m.link.revision})):await g(`/people/${encodeURIComponent(e)}/aliases/${m.alias.id}`,_(`DELETE`,{expected_revision:j.revision})),I(m.kind===`deny`?`联系已否认,后续学习不会重新提出这对人物的同一人联系。`:`已删除别名,后续学习不会自动加回。必要时可手动添加。`)}catch(e){F(e)}finally{D(!1)}}}return(0,x.jsxs)(`section`,{className:`person-detail`,children:[(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{className:`text-button`,onClick:i,children:`← 返回人物列表`}),(0,x.jsx)(`button`,{disabled:T||s.loading,onClick:P,children:`刷新人物资料`})]}),(s.error||b)&&!m&&(0,x.jsx)(A,{error:!0,children:b||s.error}),C&&(0,x.jsx)(A,{children:C}),j?(0,x.jsxs)(x.Fragment,{children:[c&&(0,x.jsx)(Or,{scope:{subject_id:j.id},name:j.name,onClose:()=>u(!1),onChanged:()=>{s.refresh(),a()}}),(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsx)(`h2`,{children:j.name}),!j.merged_into&&(0,x.jsx)(`button`,{className:`secondary`,disabled:N,onClick:()=>u(!0),children:`批量遗忘/删除`}),(0,x.jsxs)(`p`,{className:`muted`,children:[`人物标识:`,j.id,` · 资料修订 `,j.revision]}),j.merged_into&&(0,x.jsxs)(A,{children:[`此人物已合并,原标识保留用于追溯。`,(0,x.jsx)(`button`,{onClick:()=>r(j.canonical_id),children:`查看合并后的人物`})]}),(0,x.jsx)(Kr,{subjectId:e,initialVersion:t,openMemory:n}),(0,x.jsx)(`h3`,{children:`平台身份`}),!j.platform_identities.length&&(0,x.jsx)(`p`,{className:`muted`,children:`暂无平台身份。`}),j.platform_identities.map(e=>(0,x.jsxs)(`dl`,{className:`identity-facts`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`平台`}),(0,x.jsx)(`dd`,{children:e.platform===`iris-trial`?`试用`:e.platform})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`账号`}),(0,x.jsx)(`dd`,{children:e.account_id})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`显示名`}),(0,x.jsx)(`dd`,{children:e.display_name})]})]},`${e.platform}:${e.account_id}`)),(0,x.jsxs)(`h3`,{children:[`相关记忆 · `,j.memory_count,` 条`]}),(0,x.jsx)(`p`,{children:Object.entries(j.memory_counts).map(([e,t])=>`${E(e)} ${t} 条`).join(` · `)||`暂无相关记忆`}),(0,x.jsx)(`a`,{href:`#/memories?${new URLSearchParams({person_id:j.canonical_id,lifecycle:`all`})}`,children:`查看关于此人的记忆`})]}),(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsx)(`h3`,{children:`别名`}),!j.aliases.length&&(0,x.jsx)(`p`,{className:`muted`,children:`暂无别名。`}),(0,x.jsx)(`ul`,{className:`alias-list`,children:j.aliases.map(e=>(0,x.jsxs)(`li`,{children:[(0,x.jsx)(`span`,{children:e.alias}),!!e.evidence_message_ids.length&&(0,x.jsxs)(`small`,{className:`muted`,children:[`证据消息`,` `,e.evidence_message_ids.map(e=>`#${e}`).join(`、`)]}),!j.merged_into&&(0,x.jsx)(`button`,{disabled:N,className:`text-button danger-text`,"aria-label":`删除别名 ${e.alias}`,onClick:()=>{S(``),h({kind:`alias`,alias:e})},children:`删除`})]},e.id))}),!j.merged_into&&(0,x.jsxs)(`form`,{className:`inline-form`,onSubmit:te,noValidate:!0,children:[(0,x.jsxs)(`label`,{children:[`新别名`,(0,x.jsx)(`input`,{value:d,maxLength:100,disabled:N,onChange:e=>p(e.target.value)})]}),(0,x.jsx)(`button`,{disabled:N,className:`secondary`,children:`添加别名`})]})]}),(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsx)(`h3`,{children:`可能是同一人`}),!j.same_as.length&&(0,x.jsx)(`p`,{className:`muted`,children:`暂无身份联系。`}),j.same_as.map(t=>(0,x.jsxs)(`article`,{className:`person-link`,children:[(0,x.jsx)(`h4`,{children:t.subjects.map(e=>e.name).join(` ↔ `)}),(0,x.jsxs)(`p`,{children:[(0,x.jsx)(M,{tone:t.status===`possible`?`purple`:``,children:t.status===`possible`?`待确认`:t.status===`denied`?`已否认`:`已确认`}),` `,`相信程度 `,t.belief,` / 100`]}),(0,x.jsx)(`div`,{className:`button-row`,children:t.subjects.filter(t=>t.id!==e).map(e=>(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>r(e.id),children:[`查看 `,e.name,` 的资料`]},e.id))}),(0,x.jsx)(Jr,{messages:t.evidence_messages}),t.status===`possible`&&!j.merged_into&&(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{disabled:N,className:`primary`,onClick:()=>{S(``),h({kind:`merge`,link:t})},children:`确认并合并`}),(0,x.jsx)(`button`,{disabled:N,onClick:()=>{S(``),h({kind:`deny`,link:t})},children:`否认联系`})]})]},t.id))]}),(0,x.jsxs)(`section`,{className:`panel`,children:[(0,x.jsx)(`h3`,{children:`扮演关系`}),!j.roleplay.length&&(0,x.jsx)(`p`,{className:`muted`,children:`暂无扮演关系。`}),j.roleplay.map(e=>(0,x.jsxs)(`article`,{className:`person-link`,children:[(0,x.jsxs)(`h4`,{children:[e.actor.name,` 扮演 `,e.character.name]}),(0,x.jsxs)(`p`,{children:[(0,x.jsx)(M,{children:`虚构角色`}),` · 相信程度 `,e.belief,` / 100`]}),(0,x.jsxs)(`p`,{children:[`所属场景:`,e.worlds.map(e=>e??`场景未知`).join(`、`)]}),(0,x.jsx)(`p`,{className:`muted`,children:`扮演关系不代表同一人,角色经历不归入现实人物。`}),(0,x.jsx)(Jr,{messages:e.evidence_messages})]},e.id))]}),m?.kind===`merge`?(0,x.jsx)(Xr,{link:m.link,initialTarget:e,onClose:()=>h(null),onRefresh:P,onSuccess:e=>{I(``),o(e)}}):m&&(0,x.jsxs)(ee,{title:m.kind===`deny`?`否认人物联系`:`删除别名`,onClose:()=>h(null),closeDisabled:T,children:[m.kind===`deny`?(0,x.jsxs)(`p`,{children:[`否认 `,m.link.subjects.map(e=>e.name).join(`与`),` `,`是同一人。否认后,后续学习不会改回待确认,也不会再次提出这对人物的同一人联系。`]}):(0,x.jsxs)(`p`,{children:[`删除别名“`,m.alias.alias,`”及其别名证据记录,后续学习不会自动加回。管理员仍可手动添加。`]}),b&&(0,x.jsxs)(A,{error:!0,children:[b,O&&(0,x.jsx)(`button`,{onClick:P,children:`刷新人物资料`})]}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{onClick:()=>h(null),disabled:T,children:`取消`}),(0,x.jsx)(`button`,{className:`danger-button`,disabled:N,onClick:L,children:m.kind===`deny`?`确认否认`:`确认删除别名`})]})]})]}):(0,x.jsx)(`p`,{role:`status`,children:`正在读取人物资料…`})]})}function Xr({link:e,initialTarget:t,onClose:n,onRefresh:r,onSuccess:i}){let a=y(`/people/${encodeURIComponent(e.subjects[0].id)}`),o=y(`/people/${encodeURIComponent(e.subjects[1].id)}`),[s,c]=(0,l.useState)(t),[u,d]=(0,l.useState)(!1),[p,m]=(0,l.useState)(!1),[h,b]=(0,l.useState)(!1),[S,C]=(0,l.useState)(``),w=a.data&&o.data?[a.data,o.data]:null,T=w?.find(e=>e.id===s),E=w?.find(e=>e.id!==s),D=!!a.error||!!o.error||a.loading||o.loading||w?.some(e=>!!e.merged_into);async function O(){if(T&&E&&!p&&!h&&!D&&u){m(!0),C(``);try{i((await g(`/people/links/${e.id}/confirm`,_(`POST`,{target_id:T.id,expected_revision:e.revision,expected_source_revision:E.revision,expected_target_revision:T.revision}))).target_id)}catch(e){let t=e instanceof f&&e.status===409;b(t),C(t?`资料或联系已变化,请刷新人物资料后重新核对。`:v(e))}finally{m(!1)}}}return(0,x.jsxs)(ee,{title:`确认并合并人物`,onClose:n,closeDisabled:p,children:[(S||a.error||o.error)&&(0,x.jsxs)(A,{error:!0,children:[S||a.error||o.error,(0,x.jsx)(`button`,{disabled:p,onClick:r,children:`刷新人物资料`})]}),w?(0,x.jsxs)(x.Fragment,{children:[w.some(e=>e.merged_into)&&(0,x.jsxs)(A,{error:!0,children:[`人物已合并,请刷新后核对。`,(0,x.jsx)(`button`,{onClick:r,children:`刷新人物资料`})]}),(0,x.jsxs)(`fieldset`,{className:`lifecycle-fieldset`,disabled:p||h||!!D,children:[(0,x.jsxs)(`label`,{children:[`保留的人物`,(0,x.jsx)(`select`,{value:s,onChange:e=>{c(e.target.value),d(!1)},children:w.map(e=>(0,x.jsxs)(`option`,{value:e.id,children:[e.name,` · `,e.id]},e.id))})]}),(0,x.jsxs)(`div`,{className:`purge-confirm`,children:[(0,x.jsxs)(`strong`,{children:[`将“`,E?.name,`”合并到“`,T?.name,`”`]}),(0,x.jsx)(`p`,{children:`平台身份、有效别名、记忆的涉及人和说话人、人物联系及从属人物会转到保留方。被合并方的名字成为别名,原人物保留为合并占位。`}),(0,x.jsx)(`p`,{children:`记忆正文、修订号与分数保持原值。联系冲突时否认优先。M2 不提供撤销合并,请先核对双方账号与证据。`}),(0,x.jsxs)(`p`,{children:[E?.name,`:`,E?.platform_identities.length,` `,`个平台身份,`,E?.memory_count,` 条相关记忆。`]}),(0,x.jsxs)(`p`,{children:[T?.name,`:`,T?.platform_identities.length,` 个平台身份,`,T?.memory_count,` 条相关记忆。`]}),w.map(e=>(0,x.jsxs)(`div`,{className:`merge-identity`,children:[(0,x.jsxs)(`strong`,{children:[e.name,` · `,e.id]}),(0,x.jsxs)(`p`,{children:[`账号:`,e.platform_identities.map(e=>`${e.platform} / ${e.account_id}`).join(`;`)||`未绑定平台账号`]}),(0,x.jsxs)(`p`,{children:[`别名:`,e.aliases.map(e=>e.alias).join(`、`)||`暂无`]})]},e.id)),(0,x.jsxs)(`label`,{className:`check-label`,children:[(0,x.jsx)(`input`,{type:`checkbox`,checked:u,onChange:e=>d(e.target.checked)}),`我已核对身份,理解合并后无法在界面撤销`]})]})]}),(0,x.jsxs)(`div`,{className:`button-row`,children:[(0,x.jsx)(`button`,{disabled:p,onClick:n,children:`取消`}),(0,x.jsx)(`button`,{className:`danger-button`,disabled:p||h||!!D||!u,onClick:O,children:p?`正在合并…`:`确认合并`})]})]}):(0,x.jsx)(`p`,{role:`status`,children:`正在核对双方资料…`})]})}var Zr=e=>JSON.stringify([e.source,e.target]),Qr=e=>`${e.links.some(e=>e.kind===`same_as`)?`可能同一人`:e.links.some(e=>e.kind===`roleplay`)?`扮演`:e.relationship_count?`关系`:`共现`} · ${e.memory_count}`;function $r(e,t=900){let n=t<560,r=n?48:88,i=n?104:180,a=n?110:135,o=n?24:36,s=n?64:80,c=Math.max(1,Math.ceil(Math.sqrt(e*(n?1:1.7)))),l=Math.max(260,t,e>12?r*2+(c-1)*i:0),u=Math.min(c,Math.max(1,Math.floor((l-r*2)/i)+1)),d=Math.max(1,Math.ceil(e/u));return{width:l,height:Math.max(e<=3?220:n?330:400,o+s+(d-1)*a),compact:n,marginX:r,top:o,bottom:s,rows:d}}function ei(e,t,n=900){if(!e.length)return{};let r=$r(e.length,n),i=e.map((t,n)=>({x:200*Math.cos(n*2*Math.PI/e.length),y:200*Math.sin(n*2*Math.PI/e.length)})),a=new Map(e.map((e,t)=>[e.id,t]));for(let e=0;e<90;e++){let n=i.map(e=>({x:-e.x*.009,y:-e.y*.009}));for(let e=0;e{e.x+=Math.max(-r,Math.min(r,n[t].x)),e.y+=Math.max(-r,Math.min(r,n[t].y))})}let o=[];for(let t=0;te.x),c=i.map(e=>e.y),l=Math.min(...s),u=Math.min(...c),d=Math.max(...s)-l,f=Math.max(...c)-u;return Object.fromEntries(e.map((e,t)=>{let n=d>.001?r.marginX+(i[t].x-l)/d*(r.width-r.marginX*2):r.width/2,a=f>.001?r.top+(i[t].y-u)/f*(r.height-r.top-r.bottom):(r.top+r.height-r.bottom)/2,s=0;for(let e=1;ee.leftt.left&&e.topt.top;function ni(e,t,n,r){let i=e.map(e=>{let t=n[e.id];return{left:t.x-(r.compact?48:84),right:t.x+(r.compact?48:84),top:t.y-(r.compact?22:33),bottom:t.y+(r.compact?57:70)}}),a={};for(let e of t){let t=n[e.source],o=n[e.target],s=o.x-t.x,c=o.y-t.y,l=Math.max(1,Math.hypot(s,c)),u=r.compact?11:12,d=Array.from(Qr(e)).reduce((e,t)=>e+u*(t.charCodeAt(0)>255?1:.65),12),f=u+10,p=!1;for(let n of[.5,.35,.65,.2,.8]){for(let o of[-16,16,-32,32,-48,48]){let u={x:t.x+s*n-c/l*o,y:t.y+c*n+s/l*o},m={left:u.x-d/2,right:u.x+d/2,top:u.y-f/2,bottom:u.y+f/2};if(!(m.left<4||m.right>r.width-4||m.top<4||m.bottom>r.height-4||i.some(e=>ti(m,e)))){a[Zr(e)]=u,i.push(m),p=!0;break}}if(p)break}}return a}var ri=(e,t)=>Array.from(e).length>t?Array.from(e).slice(0,t).join(``)+`…`:e,ii=e=>`#/memories?person_id=${encodeURIComponent(e)}&lifecycle=active`,ai=e=>new URLSearchParams(Object.entries(e).filter(([,e])=>e)).toString();function oi({edge:e}){return(0,x.jsxs)(`span`,{className:`graph-kinds`,children:[e.memory_count>0&&(0,x.jsxs)(M,{children:[`共同涉及 `,e.memory_count]}),e.relationship_count>0&&(0,x.jsxs)(M,{tone:`purple`,children:[`关系记忆 `,e.relationship_count]}),e.links.some(e=>e.kind===`same_as`)&&(0,x.jsx)(M,{tone:`purple`,children:`可能同一人 · 未确认`}),e.links.some(e=>e.kind===`roleplay`)&&(0,x.jsx)(M,{children:`扮演 · 虚构角色`})]})}function si({data:e,onEdge:t}){let n=(0,l.useRef)(null),[r,i]=(0,l.useState)(900),[a,o]=(0,l.useState)(null),[s,c]=(0,l.useState)(null),u=(0,l.useId)();(0,l.useEffect)(()=>{let e=n.current;if(!e)return;let t=()=>{let t=Math.floor(e.getBoundingClientRect().width);t>0&&i(t)};if(t(),typeof ResizeObserver>`u`)return;let r=new ResizeObserver(t);return r.observe(e),()=>r.disconnect()},[]);let d=(0,l.useMemo)(()=>$r(e.nodes.length,r),[e.nodes.length,r]),f=(0,l.useMemo)(()=>ei(e.nodes,e.edges,r),[e,r]),p=(0,l.useMemo)(()=>ni(e.nodes,e.edges,f,d),[e,f,d]),m=new Map(e.nodes.map(e=>[e.id,e.name])),h=e.edges.find(e=>Zr(e)===(s||a));return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{ref:n,className:`graph-scroll`,tabIndex:0,"aria-label":`关系图画布,可横向滚动`,children:(0,x.jsxs)(`svg`,{viewBox:`0 0 ${d.width} ${d.height}`,style:{minWidth:d.width},role:`group`,"aria-label":`人物关系图`,className:`people-graph-svg${d.compact?` compact`:``}`,children:[(0,x.jsx)(`title`,{children:`人物关系图`}),(0,x.jsx)(`desc`,{children:`点击节点打开人物的全部有效记忆,点击连线查看依据。悬停或聚焦连线查看摘要,也可使用画布下方的人物和连线列表。`}),e.edges.map(e=>{let n=f[e.source],r=f[e.target],i=`查看${m.get(e.source)}与${m.get(e.target)}的连线依据`,a=Zr(e),s=p[a],l=e.links.some(e=>e.kind===`same_as`)?`possible`:e.links.length?`roleplay`:e.relationship_count?`relationship`:`cooccurrence`;return(0,x.jsxs)(`g`,{className:`graph-edge ${l}`,role:`button`,tabIndex:0,"aria-label":i,"aria-describedby":h===e?u:void 0,onMouseEnter:()=>o(a),onMouseLeave:()=>o(null),onFocus:()=>c(a),onBlur:()=>c(null),onClick:()=>t(e),onKeyDown:n=>{(n.key===`Enter`||n.key===` `)&&(n.preventDefault(),t(e))},children:[(0,x.jsxs)(`title`,{children:[i,`;`,e.memory_count,` 条共同涉及记忆`]}),(0,x.jsx)(`line`,{x1:n.x,y1:n.y,x2:r.x,y2:r.y,className:`graph-edge-hit`}),(0,x.jsx)(`line`,{x1:n.x,y1:n.y,x2:r.x,y2:r.y,strokeWidth:Math.min(7,1.5+Math.log2(1+e.memory_count))}),s&&(0,x.jsx)(`text`,{x:s.x,y:s.y,textAnchor:`middle`,dominantBaseline:`middle`,children:Qr(e)})]},a)}),e.nodes.map(e=>(0,x.jsxs)(`a`,{href:ii(e.id),"aria-label":`查看${e.name}的有效记忆`,className:`graph-node ${e.kind===`self`?`self`:``}`,children:[(0,x.jsxs)(`title`,{children:[e.name,`;别名:`,e.aliases.join(`、`)||`暂无`,`;`,e.account_count,` 个账号;`,e.memory_count,` 条有效记忆`]}),(0,x.jsx)(`circle`,{cx:f[e.id].x,cy:f[e.id].y,r:d.compact?14:Math.min(27,18+Math.log2(1+e.memory_count))}),(0,x.jsx)(`text`,{x:f[e.id].x,y:f[e.id].y+5,textAnchor:`middle`,className:`graph-node-mark`,children:e.kind===`self`?`我`:Array.from(e.name)[0]}),(0,x.jsx)(`rect`,{className:`graph-node-label-background`,x:f[e.id].x-(d.compact?44:78),y:f[e.id].y+(d.compact?20:30),width:d.compact?88:156,height:d.compact?33:38,rx:`4`}),(0,x.jsx)(`text`,{x:f[e.id].x,y:f[e.id].y+(d.compact?32:44),textAnchor:`middle`,children:ri(e.name,d.compact?6:10)}),(0,x.jsxs)(`text`,{x:f[e.id].x,y:f[e.id].y+(d.compact?48:63),textAnchor:`middle`,className:`graph-node-count`,children:[e.memory_count,` 条记忆`]})]},e.id))]})}),(0,x.jsx)(`div`,{className:`graph-preview`,children:h?(0,x.jsxs)(`div`,{id:u,role:`tooltip`,children:[(0,x.jsxs)(`strong`,{children:[m.get(h.source),` · `,m.get(h.target)]}),(0,x.jsxs)(`p`,{children:[Qr(h),`(数字为共同涉及的有效记忆数)`]}),h.relationship_summaries.map(e=>(0,x.jsx)(`p`,{children:e.summary},e.id)),!h.relationship_summaries.length&&(0,x.jsx)(`p`,{children:`点击连线查看联系记录与支撑记忆。`})]}):(0,x.jsx)(`p`,{children:`悬停或用键盘聚焦连线可查看摘要;数字为共同涉及的有效记忆数。拥挤处省略标签,完整内容见下方列表。`})})]})}function ci({edge:e,names:t,entryId:n,onClose:r,openMemory:i}){let[a,o]=(0,l.useState)(0),s=y(`/people-graph/edge?${ai({source_id:e.source,target_id:e.target,entry_id:n,limit:`30`,offset:String(a)})}`);return(0,x.jsxs)(ee,{title:`连线依据:${t.get(e.source)} · ${t.get(e.target)}`,onClose:r,children:[(0,x.jsx)(`p`,{children:`这里只显示当前仍有效的记忆。身份/扮演联系来自独立联系记录;同来源记忆不等于确认身份,也不把角色经历归给扮演者。`}),s.error&&(0,x.jsxs)(A,{error:!0,children:[s.error,(0,x.jsx)(`button`,{onClick:s.refresh,children:`重新读取依据`})]}),s.loading&&(0,x.jsx)(`p`,{role:`status`,children:`正在读取连线依据…`}),s.data&&(0,x.jsxs)(x.Fragment,{children:[s.data.links.map(e=>(0,x.jsxs)(`article`,{className:`graph-link-record`,children:[(0,x.jsx)(`h3`,{children:e.kind===`same_as`?`可能同一人 · 未确认`:`扮演 · 虚构角色`}),(0,x.jsxs)(`p`,{children:[t.get(e.source),` `,e.kind===`roleplay`?`→`:`↔`,` `,t.get(e.target),` · 相信程度 `,e.belief]}),e.kind===`roleplay`&&(0,x.jsxs)(`p`,{children:[`场景:`,e.worlds.map(e=>e||`场景未记录`).join(`、`)]}),(0,x.jsxs)(`p`,{children:[`联系 #`,e.id,` · `,e.evidence_message_count,` 条来源消息`]}),(0,x.jsx)(`a`,{href:`#/people?id=${encodeURIComponent(e.source)}`,onClick:r,children:`到人物详情核对联系与消息`})]},e.id)),(0,x.jsxs)(`p`,{children:[`共 `,s.data.total,` 条支撑/同来源记忆`]}),!s.data.items.length&&(0,x.jsx)(j,{title:`没有可展示的有效支撑记忆`,children:`联系记录可能只有来源消息;遗忘、删除或清除的记忆不会在这里显示。`}),(0,x.jsx)(`div`,{className:`graph-evidence-list`,children:s.data.items.map(e=>(0,x.jsxs)(`article`,{children:[(0,x.jsxs)(`p`,{children:[(0,x.jsx)(M,{children:e.kind}),` #`,e.id,` · 修订`,` `,e.revision]}),(0,x.jsx)(`p`,{className:`memory-content`,children:e.content}),(0,x.jsxs)(`p`,{children:[e.cooccurrence&&(0,x.jsx)(M,{children:`共同涉及两人`}),` `,e.link_evidence&&(0,x.jsx)(M,{children:`同来源联系证据`})]}),(0,x.jsxs)(`button`,{onClick:()=>{r(),i(e.id)},children:[`查看记忆 #`,e.id]})]},e.id))}),(0,x.jsx)(T,{total:s.data.total,offset:a,change:o})]})]})}function li({initialQuery:e=``,openMemory:t}){let n=new URLSearchParams(e),[r,i]=(0,l.useState)({entry_id:n.get(`entry_id`)||``,person_id:n.get(`person_id`)||``,hops:`1`,min_memories:`1`,node_limit:`60`,edge_limit:`100`}),[a,o]=(0,l.useState)(r),[s,c]=(0,l.useState)(null),u=y(`/catalog`),d=y(`/people-graph?${ai(a)}`),f=new Map(d.data?.nodes.map(e=>[e.id,e.name])||[]),p=e=>{c(null),o({...e}),ai(e)===ai(a)&&d.refresh()};return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`page-heading`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`p`,{className:`eyebrow`,children:`从已有经历看人物联系`}),(0,x.jsx)(`h1`,{children:`人物关系图`}),(0,x.jsx)(`p`,{children:`点击人物查看记忆,点击连线追溯依据。`})]}),(0,x.jsx)(`a`,{href:`#/people`,className:`button`,children:`返回人物列表`})]}),(0,x.jsxs)(`form`,{className:`panel graph-filters`,onSubmit:e=>{e.preventDefault(),p(r)},children:[(0,x.jsxs)(`label`,{children:[`来源入口`,(0,x.jsxs)(`select`,{value:r.entry_id,onChange:e=>i({...r,entry_id:e.target.value}),children:[(0,x.jsx)(`option`,{value:``,children:`全部入口`}),u.data?.entries.map(e=>(0,x.jsx)(`option`,{value:e.id,children:e.name},e.id))]})]}),(0,x.jsxs)(`label`,{children:[`聚焦人物`,(0,x.jsxs)(`select`,{value:r.person_id,onChange:e=>i({...r,person_id:e.target.value}),children:[(0,x.jsx)(`option`,{value:``,children:`所有人物`}),u.data?.people.filter(e=>e.id!==`scene`).map(e=>(0,x.jsxs)(`option`,{value:e.id,children:[e.name,e.id===`self`?`(角色)`:``,` · `,e.id]},e.id))]})]}),(0,x.jsxs)(`label`,{children:[`范围`,(0,x.jsxs)(`select`,{value:r.hops,disabled:!r.person_id,onChange:e=>i({...r,hops:e.target.value}),children:[(0,x.jsx)(`option`,{value:`1`,children:`一跳联系`}),(0,x.jsx)(`option`,{value:`2`,children:`两跳联系`})]})]}),(0,x.jsxs)(`label`,{children:[`共现最少记忆数`,(0,x.jsx)(`input`,{type:`number`,min:`1`,max:`1000000`,required:!0,value:r.min_memories,onChange:e=>i({...r,min_memories:e.target.value})})]}),(0,x.jsxs)(`label`,{children:[`节点上限`,(0,x.jsx)(`input`,{type:`number`,min:`2`,max:`100`,required:!0,value:r.node_limit,onChange:e=>i({...r,node_limit:e.target.value})})]}),(0,x.jsxs)(`label`,{children:[`连线上限`,(0,x.jsx)(`input`,{type:`number`,min:`1`,max:`200`,required:!0,value:r.edge_limit,onChange:e=>i({...r,edge_limit:e.target.value})})]}),(0,x.jsx)(`button`,{className:`primary`,disabled:d.loading,children:`生成关系图`})]}),u.error&&(0,x.jsxs)(A,{error:!0,children:[`筛选目录:`,u.error,(0,x.jsx)(`button`,{onClick:u.refresh,children:`重新读取目录`})]}),(0,x.jsxs)(`details`,{className:`panel graph-explanation`,children:[(0,x.jsx)(`summary`,{children:`数据口径与图例`}),(0,x.jsx)(`p`,{children:`只统计 active 且未彻底清除的记忆。共现按同一记忆的 about 涉及人两两计数,每条只算一次;共现不等于关系事实。“关系”类记忆另外显示正文摘要。`}),(0,x.jsx)(`p`,{children:`入口筛选只认至少一条直接来源消息在该入口的记忆,不沿派生依据扩大范围。身份/扮演联系按其来源消息筛选,可没有支撑记忆;共现阈值不隐藏这些独立联系。`}),(0,x.jsx)(`p`,{children:`节点记忆数包括作为涉及人或说话人的有效记忆,别名与账号数为当前主体资料。self 显示为角色节点,scene 不作为人物;已合并主体只显示保留人物。点击人物打开其全部入口的有效记忆列表。`}),(0,x.jsx)(`p`,{children:`线条越粗,共同涉及记忆越多;紫色为关系记忆,虚线为可能同一人,绿色为扮演。位置和距离只用于排布,没有关系强弱含义。图中读数不调用模型,不产生召回或使用记录。`})]}),d.error&&(0,x.jsxs)(A,{error:!0,children:[d.error,(0,x.jsx)(`button`,{onClick:d.refresh,children:`重新读取关系图`})]}),d.loading&&(0,x.jsx)(`p`,{role:`status`,children:`正在生成只读关系图…`}),d.data&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{"aria-live":`polite`,children:[`当前显示 `,d.data.nodes.length,` 个节点、`,d.data.edges.length,` `,`条连线。`]}),d.data.truncated&&(0,x.jsxs)(A,{children:[`筛选后共有 `,d.data.total_nodes,` 个节点、`,d.data.total_edges,` `,`条连线,超过显示上限。按共同涉及记忆数从高到低保留,关系记忆数和主体标识用于同权重排序;聚焦人物优先保留。可缩小入口或聚焦范围后重新查看。`]}),d.data.nodes.length?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`section`,{className:`panel graph-panel`,"aria-label":`关系图与图例`,children:[(0,x.jsxs)(`div`,{className:`graph-legend`,children:[(0,x.jsx)(`span`,{children:`实线:共现`}),(0,x.jsx)(`span`,{children:`紫色:关系记忆`}),(0,x.jsx)(`span`,{children:`虚线:可能同一人`}),(0,x.jsx)(`span`,{children:`绿色:扮演`})]}),(0,x.jsx)(si,{data:d.data,onEdge:c}),(0,x.jsx)(`p`,{className:`muted`,children:`窄屏可横向滚动画布。下方列表提供相同的跳转和证据操作。`})]}),(0,x.jsxs)(`section`,{"aria-label":`图中人物`,children:[(0,x.jsx)(`h2`,{children:`图中人物`}),(0,x.jsx)(`div`,{className:`graph-node-list`,children:d.data.nodes.map(e=>(0,x.jsxs)(`article`,{className:`panel`,children:[(0,x.jsxs)(`h3`,{children:[(0,x.jsx)(`a`,{href:ii(e.id),"aria-label":`查看${e.name}的有效记忆`,children:e.name}),` `,e.kind===`self`&&(0,x.jsx)(M,{children:`角色`})]}),(0,x.jsx)(`small`,{className:`muted`,children:e.id}),(0,x.jsxs)(`p`,{children:[`别名:`,e.aliases.join(`、`)||`暂无`]}),(0,x.jsxs)(`p`,{children:[e.account_count,` 个账号 · `,e.memory_count,` `,`条有效记忆`]}),(0,x.jsx)(`button`,{className:`text-button`,"aria-label":`聚焦${e.name}`,onClick:()=>{let t={...r,person_id:e.id};i(t),p(t)},children:`以此人为中心`})]},e.id))})]}),(0,x.jsxs)(`section`,{"aria-label":`图中连线`,children:[(0,x.jsx)(`h2`,{children:`图中连线`}),!d.data.edges.length&&(0,x.jsx)(`p`,{className:`muted`,children:`当前阈值和范围没有连线。`}),(0,x.jsx)(`div`,{className:`graph-edge-list`,children:d.data.edges.map(e=>(0,x.jsxs)(`article`,{className:`panel`,children:[(0,x.jsxs)(`h3`,{children:[f.get(e.source),` · `,f.get(e.target)]}),(0,x.jsx)(oi,{edge:e}),(0,x.jsxs)(`p`,{children:[e.memory_count,` 条共同涉及记忆`]}),e.relationship_summaries.map(e=>(0,x.jsxs)(`p`,{children:[`关系记忆 #`,e.id,`:`,e.summary]},e.id)),e.relationship_count>e.relationship_summaries.length&&(0,x.jsx)(`small`,{children:`更多关系正文见连线依据。`}),(0,x.jsx)(`button`,{onClick:()=>c(e),"aria-label":`查看${f.get(e.source)}与${f.get(e.target)}的连线依据`,children:`查看连线依据`})]},JSON.stringify([e.source,e.target])))})]})]}):(0,x.jsx)(j,{title:`当前范围没有人物关系数据`,children:`可以改选入口或人物;遗忘、删除和清除的记忆不参与关系图。`})]}),s&&(0,x.jsx)(ci,{edge:s,names:f,entryId:a.entry_id,onClose:()=>c(null),openMemory:t},JSON.stringify([s.source,s.target,a.entry_id]))]})}function ui({initialVersion:e,initialComparison:t,currentID:n,catalog:r,openMemory:i,onAction:a,locked:o}){let[s,c]=(0,l.useState)(e),[u,d]=(0,l.useState)({status:``,source:``}),[f,p]=(0,l.useState)(``),[m,h]=(0,l.useState)(0),g=y(`/persona/versions?${f}limit=30&offset=${m}`,5e3),[_,v]=(0,l.useState)(t?.before.toString()||``),[b,S]=(0,l.useState)(t?.after.toString()||n?.toString()||``),[C,w]=(0,l.useState)(``),[E,D]=(0,l.useState)(t||null),[O,k]=(0,l.useState)(0);return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`section`,{className:`panel persona-history`,children:[(0,x.jsx)(`h2`,{children:`版本历史`}),(0,x.jsx)(`p`,{children:`可选择任意两个版本逐句对比。只有已经发布过的版本可以回滚;回滚会新建版本。`}),(0,x.jsxs)(`form`,{className:`persona-filters`,onSubmit:e=>{e.preventDefault();let t=new URLSearchParams;u.status&&t.set(`status`,u.status),u.source&&t.set(`source`,u.source),p(t.size?`${t}&`:``),h(0),g.refresh()},children:[(0,x.jsxs)(`label`,{children:[`版本状态`,(0,x.jsxs)(`select`,{value:u.status,onChange:e=>d({...u,status:e.target.value}),children:[(0,x.jsx)(`option`,{value:``,children:`全部状态`}),Object.entries(ne).map(([e,t])=>(0,x.jsx)(`option`,{value:e,children:t},e))]})]}),(0,x.jsxs)(`label`,{children:[`版本来源`,(0,x.jsxs)(`select`,{value:u.source,onChange:e=>d({...u,source:e.target.value}),children:[(0,x.jsx)(`option`,{value:``,children:`全部来源`}),Object.entries(L).map(([e,t])=>(0,x.jsx)(`option`,{value:e,children:t},e))]})]}),(0,x.jsx)(`button`,{children:`筛选版本`})]}),g.error&&(0,x.jsxs)(A,{error:!0,children:[g.error,(0,x.jsx)(`button`,{onClick:g.refresh,children:`重试版本列表`})]}),g.loading&&(0,x.jsx)(`p`,{children:`正在读取版本…`}),g.data?.items.map(e=>(0,x.jsxs)(`article`,{className:`persona-history-row`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsxs)(`strong`,{children:[`v`,e.id]}),` `,(0,x.jsx)(M,{children:ne[e.status]}),` ·`,` `,L[e.source],` · 变化`,` `,e.change_degree?R[e.change_degree]:`未记录`,(0,x.jsx)(`p`,{className:`muted`,children:(0,x.jsx)(N,{value:e.generated_at})}),(0,x.jsx)(`p`,{className:`persona-content`,children:e.content})]}),(0,x.jsxs)(`div`,{className:`persona-actions`,children:[(0,x.jsxs)(`button`,{onClick:()=>c(e.id),children:[`查看版本 v`,e.id]}),(0,x.jsxs)(`button`,{onClick:()=>v(String(e.id)),children:[`v`,e.id,` 作为对比前版`]}),(0,x.jsxs)(`button`,{onClick:()=>S(String(e.id)),children:[`v`,e.id,` 作为对比后版`]})]})]},e.id)),g.data?.total===0&&(0,x.jsx)(j,{title:`没有符合筛选的版本`}),g.data&&(0,x.jsx)(T,{total:g.data.total,offset:m,change:h})]}),(0,x.jsxs)(`section`,{className:`panel persona-comparison`,children:[(0,x.jsx)(`h2`,{children:`对比任意版本`}),(0,x.jsx)(`p`,{children:`从列表选择,或输入版本 ID;可以跨页选择,也可以查看被拒绝的候选。`}),(0,x.jsxs)(`form`,{noValidate:!0,className:`persona-filters`,onSubmit:e=>{if(e.preventDefault(),!/^\d+$/.test(_)||!/^\d+$/.test(b)||!Number.isSafeInteger(Number(_))||!Number.isSafeInteger(Number(b))||Number(_)<1||Number(b)<1){w(`请输入有效的正整数版本 ID`);return}w(``),D({before:Number(_),after:Number(b)}),k(e=>e+1)},children:[(0,x.jsxs)(`label`,{children:[`对比前版本 ID`,(0,x.jsx)(`input`,{type:`number`,min:1,step:1,value:_,onChange:e=>v(e.target.value)})]}),(0,x.jsxs)(`label`,{children:[`对比后版本 ID`,(0,x.jsx)(`input`,{type:`number`,min:1,step:1,value:b,onChange:e=>S(e.target.value)})]}),(0,x.jsx)(`button`,{children:`对比版本`})]}),C&&(0,x.jsx)(A,{error:!0,children:C}),E&&(0,x.jsx)(Bt,{...E},O)]}),s&&(0,x.jsx)(Rt,{id:s,title:`版本详情`,catalog:r,openMemory:i,onAction:a,locked:o,currentID:n,history:!0},s)]})}function di({openMemory:e}){let[t,n]=(0,l.useState)(0),r=y(`/persona/self-memories?limit=30&offset=${t}`);return(0,x.jsxs)(`section`,{className:`panel persona-memories`,children:[(0,x.jsx)(`h2`,{children:`自我记忆`}),(0,x.jsx)(`p`,{children:`有效的自我设定与经历是 persona 的材料;打开或翻页不会触发召回。`}),r.error&&(0,x.jsxs)(A,{error:!0,children:[r.error,(0,x.jsx)(`button`,{onClick:r.refresh,children:`重试自我记忆`})]}),r.loading&&(0,x.jsx)(`p`,{children:`正在读取自我记忆…`}),r.data?.items.map(t=>(0,x.jsxs)(`article`,{className:`persona-history-row`,children:[(0,x.jsx)(`p`,{className:`persona-content`,children:t.content}),(0,x.jsxs)(`p`,{className:`muted`,children:[`#`,t.id,` · 修订 `,t.revision,` · `,t.stance,` ·`,` `,E(t.lifecycle),` · `,(0,x.jsx)(N,{value:t.created_at})]}),(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>e(t.id),children:[`查看自我记忆 #`,t.id]})]},t.id)),r.data?.total===0&&(0,x.jsx)(j,{title:`暂无有效自我记忆`,children:`在持续对话中积累经历,或在设置中完善初始背景。`}),r.data&&(0,x.jsx)(T,{total:r.data.total,offset:t,change:n})]})}function fi(){let[e,t]=(0,l.useState)(0),n=y(`/persona/attempts?limit=30&offset=${e}`,2e3);return(0,x.jsxs)(`section`,{className:`panel persona-attempts`,children:[(0,x.jsx)(`h2`,{children:`生成记录`}),(0,x.jsx)(`p`,{children:`包括未生成版本的跳过、冲突与失败;生成被拒绝不改变当前 persona。`}),n.error&&(0,x.jsxs)(A,{error:!0,children:[n.error,(0,x.jsx)(`button`,{onClick:n.refresh,children:`重试生成记录`})]}),n.loading&&(0,x.jsx)(`p`,{children:`正在读取生成记录…`}),n.data?.items.map(e=>(0,x.jsxs)(`article`,{className:`persona-history-row`,children:[(0,x.jsxs)(`h3`,{children:[`任务 #`,e.id,` · `,se(e.state,e.stage)]}),(0,x.jsxs)(`p`,{children:[L[e.source]||e.source,` · 基于 v`,e.base_version_id]}),(0,x.jsxs)(`p`,{className:`muted`,children:[`接受:`,(0,x.jsx)(N,{value:e.created_at}),` · 结束:`,(0,x.jsx)(N,{value:e.finished_at})]}),e.reason&&(0,x.jsx)(`p`,{children:ae(e.reason)}),e.version_id&&(0,x.jsxs)(`a`,{href:`#/persona?tab=history&version=${e.version_id}`,children:[`查看版本 v`,e.version_id]}),(0,x.jsx)(`p`,{children:(0,x.jsx)(`a`,{href:`#/operations?object_type=persona_attempt&object_id=${e.id}`,children:`查看任务操作记录`})})]},e.id)),n.data?.total===0&&(0,x.jsx)(j,{title:`暂无生成任务`}),n.data&&(0,x.jsx)(T,{total:n.data.total,offset:e,change:t})]})}function pi({initial:e,path:t,onFinish:n}){let[r,i]=(0,l.useState)(e),[a,o]=(0,l.useState)(``),[s,c]=(0,l.useState)(0),u=(0,l.useRef)(n);u.current=n;let d=oe(e.state);(0,l.useEffect)(()=>{if(!d){i(e),o(``);return}let n=new AbortController,r=!0,a,s=async()=>{let c=!0;try{let a=await g(t||`/persona/attempts/${e.id}`,{signal:n.signal});if(!r)return;i(a),o(``),oe(a.state)||(c=!1,u.current(a))}catch(e){r&&!n.signal.aborted&&o(v(e))}r&&c&&(a=setTimeout(s,2e3))};return s(),()=>{r=!1,n.abort(),clearTimeout(a)}},[e.id,d,t,s]);let f=y(r.state===`rejected`&&r.version_id?`/persona/versions/${r.version_id}`:null);return(0,x.jsxs)(`section`,{className:`panel persona-task`,"aria-label":`最近生成任务`,children:[(0,x.jsxs)(`h2`,{children:[`生成任务 #`,r.id]}),(0,x.jsxs)(`p`,{role:`status`,children:[se(r.state,r.stage),r.state===`current`&&r.version_id?` · v${r.version_id}`:``]}),oe(r.state)&&(0,x.jsx)(`p`,{children:`请求已接受,尚未发布。页面会持续查询生成与检查结果;离开后任务仍在服务端运行。`}),r.reason&&(0,x.jsx)(A,{error:r.state===`failed`||r.state===`conflict`,children:ae(r.reason)}),(0,x.jsxs)(`p`,{className:`muted`,children:[`基于 v`,r.base_version_id,` · 接受时间:`,(0,x.jsx)(N,{value:r.created_at}),r.finished_at&&(0,x.jsxs)(x.Fragment,{children:[` `,`· 结束时间:`,(0,x.jsx)(N,{value:r.finished_at})]})]}),a&&(0,x.jsxs)(A,{error:!0,children:[a,`。任务结果尚未获知,将继续查询。`,(0,x.jsx)(`button`,{onClick:()=>c(e=>e+1),children:`立即查询任务`})]}),f.error&&(0,x.jsxs)(A,{error:!0,children:[f.error,(0,x.jsx)(`button`,{onClick:f.refresh,children:`重试拒绝原因`})]}),f.data&&(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h3`,{children:`拒绝原因`}),f.data.rejection_reasons.length?(0,x.jsx)(`ul`,{children:f.data.rejection_reasons.map((e,t)=>(0,x.jsx)(`li`,{children:ae(e)},t))}):(0,x.jsx)(`p`,{children:`未记录拒绝原因,请查看版本检查结果。`})]}),r.version_id&&(0,x.jsxs)(`a`,{href:`#/persona?tab=history&version=${r.version_id}`,children:[`查看结果版本 v`,r.version_id]}),(0,x.jsx)(`p`,{children:(0,x.jsx)(`a`,{href:`#/operations?object_type=persona_attempt&object_id=${r.id}`,children:`查看生成操作记录`})})]})}var mi={edit:`编辑并发布 persona`,confirm:`确认发布候选`,reject:`拒绝候选`,rollback:`回滚 persona`},hi={edit:`发布编辑`,confirm:`确认发布`,reject:`确认拒绝`,rollback:`确认回滚`},gi={current:`当前与候选`,history:`版本历史`,memories:`自我记忆`,attempts:`生成记录`};function _i({openMemory:e,initialQuery:t=``}){let n=new URLSearchParams(t),r=Number(n.get(`version`)),[i,a]=(0,l.useState)(n.get(`focus`)===`pending`),o=(0,l.useRef)(null),[s,c]=(0,l.useState)(Object.hasOwn(gi,n.get(`tab`)||``)?n.get(`tab`):`current`),u=y(`/persona`,2e3),d=y(`/catalog`),[p,h]=(0,l.useState)(null),[b,S]=(0,l.useState)(``),[C,w]=(0,l.useState)(``),[T,E]=(0,l.useState)(``),[D,O]=(0,l.useState)(``),[k,N]=(0,l.useState)(!1),[P,F]=(0,l.useState)(!1),[I,te]=(0,l.useState)(0),[L,ne]=(0,l.useState)(null),R=u.data,re=R?.current,ie=R?.pending;(0,l.useEffect)(()=>{i&&s===`current`&&ie&&o.current&&(o.current.focus(),o.current.scrollIntoView?.({block:`start`}),a(!1))},[i,s,ie]);let se=R?.latest_attempt,ce=se&&(!L||se.id>L.attempt.id||se.id===L.attempt.id&&oe(L.attempt.state)&&!oe(se.state))?{attempt:se,path:L?.attempt.id===se.id?L.path:void 0}:L,le=k||P||!!u.error||u.loading;function ue(e,t){re&&!le&&(h({kind:e,version:t,expectedVersion:re.id}),S(t.content),w(``),E(``),O(``))}function de(){h(null),F(!1),E(``),O(``),u.refresh(),te(e=>e+1)}function z(e){E(v(e)),e instanceof f&&e.code===`persona_conflict`&&F(!0)}async function B(){if(p&&!le){if(p.kind===`edit`&&(!b.trim()||[...b].length>800)){E(`persona 正文须为 1—800 字,不能只含空白`);return}if(p.kind===`reject`&&[...C.trim()].length>1e3){E(`拒绝原因不能超过 1000 字`);return}N(!0),E(``);try{let e={expected_version:p.expectedVersion,...p.kind===`edit`?{content:b}:p.kind===`reject`&&C.trim()?{reason:C.trim()}:{}},t=await g(p.kind===`edit`?`/persona`:`/persona/versions/${p.version.id}/${p.kind}`,_(p.kind===`edit`?`PUT`:`POST`,e));O(p.kind===`reject`?`已拒绝候选 v${t.id},当前版本仍保留。`:`已发布 persona v${t.id}${p.kind===`rollback`?`,回滚自 v${p.version.id}`:``}。`),h(null),c(`current`),u.refresh(),te(e=>e+1)}catch(e){z(e)}finally{N(!1)}}}async function V(){if(!(!re||le||oe(ce?.attempt.state))){N(!0),E(``),O(``);try{let e=await m(`/persona/regenerate`,_(`POST`,{expected_version:re.id}));if(e.status!==202||!e.data.accepted)throw new f(`invalid_response`,`生成请求返回了意外结果,请刷新查看任务记录;不要重复提交。`,e.status);let t=e.data.attempt,n=e.headers.get(`Location`),r=n===`/admin/api/persona/attempts/${t.id}`?n.slice(10):`/persona/attempts/${t.id}`;ne({attempt:t,path:r}),u.refresh()}catch(e){z(e),u.refresh()}finally{N(!1)}}}let fe=(0,x.jsx)(`button`,{disabled:k,onClick:de,children:`重新加载当前版本`});return(0,x.jsxs)(`div`,{className:`persona-page`,children:[(0,x.jsxs)(`div`,{className:`page-heading`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`span`,{className:`eyebrow`,children:`自我与未来`}),(0,x.jsx)(`h1`,{children:`persona 与自我`}),(0,x.jsx)(`p`,{children:`从持续经历中认识自己,逐句查看变化的依据。`})]}),(0,x.jsxs)(`div`,{className:`persona-actions`,children:[(0,x.jsx)(`button`,{disabled:k,onClick:u.refresh,children:`刷新 persona`}),re&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`button`,{disabled:le,onClick:()=>ue(`edit`,re),children:`编辑并发布`}),(0,x.jsx)(`button`,{className:`primary`,disabled:le||oe(ce?.attempt.state),onClick:()=>void V(),children:`重新生成`})]})]})]}),u.error&&(0,x.jsxs)(A,{error:!0,children:[u.error,`。数据可能尚未更新,写操作暂不可用。`]}),d.error&&(0,x.jsxs)(A,{error:!0,children:[`入口类型暂不可用。`,d.error,(0,x.jsx)(`button`,{onClick:d.refresh,children:`重试入口信息`})]}),!p&&T&&(0,x.jsxs)(A,{error:!0,children:[T,P&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`p`,{children:`请重新加载后核对当前版本,再决定是否操作。`}),fe]})]}),D&&(0,x.jsx)(A,{children:D}),R?.needs_update&&(0,x.jsxs)(`section`,{className:`notice persona-stale`,"aria-label":`失效依据`,children:[(0,x.jsxs)(`h2`,{children:[(0,x.jsx)(M,{tone:`warning`,children:`待更新`}),` `,R.stale_basis_count,` `,`条依据失效`]}),(0,x.jsx)(`p`,{children:`当前 persona 仍在使用。重新生成会重新提炼与检查;失效依据不等于已有待确认候选。`}),(0,x.jsx)(`ul`,{children:R.stale_basis.map((t,n)=>(0,x.jsxs)(`li`,{children:[`记忆 #`,t.memory_id,` · 记录修订 `,t.expected_revision,` ·`,` `,t.current_revision==null?`当前不可用`:`当前修订 ${t.current_revision}`,`:`,ae(t.reason),t.memory&&(0,x.jsxs)(`button`,{className:`text-button`,onClick:()=>e(t.memory_id),children:[`查看失效依据 #`,t.memory_id]})]},`${t.memory_id}-${n}`))})]}),ie&&(0,x.jsxs)(A,{children:[(0,x.jsx)(M,{tone:`warning`,children:`待确认`}),` 候选 v`,ie.id,` `,`等待决定,当前版本仍在使用。`,(0,x.jsx)(`button`,{className:`text-button`,onClick:()=>{c(`current`),a(!0)},children:`查看候选与差异`})]}),R&&!ie&&n.get(`focus`)===`pending`&&(0,x.jsx)(A,{children:`当前没有待确认的 persona 候选。`}),ce&&(0,x.jsx)(pi,{initial:ce.attempt,path:ce.path,onFinish:e=>{ne({attempt:e,path:ce.path}),u.refresh(),te(e=>e+1)}},ce.attempt.id),(0,x.jsx)(me,{}),(0,x.jsx)(`div`,{className:`tabs persona-tabs`,role:`tablist`,"aria-label":`persona 内容`,children:Object.entries(gi).map(([e,t])=>(0,x.jsx)(`button`,{id:`persona-tab-${e}`,role:`tab`,"aria-selected":s===e,tabIndex:s===e?0:-1,onKeyDown:t=>{let n=Object.keys(gi),r=n.indexOf(e),i=t.key===`ArrowRight`?(r+1)%n.length:t.key===`ArrowLeft`?(r+n.length-1)%n.length:t.key===`Home`?0:t.key===`End`?n.length-1:null;i!==null&&(t.preventDefault(),c(n[i]),document.getElementById(`persona-tab-${n[i]}`)?.focus())},"aria-controls":`persona-tab-panel`,className:s===e?`active`:``,onClick:()=>c(e),children:t},e))}),(0,x.jsxs)(`div`,{role:`tabpanel`,id:`persona-tab-panel`,"aria-labelledby":`persona-tab-${s}`,children:[s===`current`&&(0,x.jsxs)(x.Fragment,{children:[!R&&!u.error&&(0,x.jsx)(`p`,{children:`正在读取 persona…`}),R&&!re&&(0,x.jsx)(j,{title:`暂无 persona 版本`,children:`请先在设置中完成角色初始设定。`}),re&&(0,x.jsx)(Rt,{id:re.id,title:`当前 persona`,catalog:d.data,openMemory:e},`current-${re.id}-${I}`),ie&&(0,x.jsxs)(`div`,{ref:o,role:`region`,"aria-label":`待确认候选与差异`,tabIndex:-1,children:[(0,x.jsx)(Rt,{id:ie.id,title:`待确认候选`,catalog:d.data,openMemory:e,onAction:ue,currentID:re?.id,locked:le},`pending-${ie.id}-${I}`),re&&(0,x.jsx)(`div`,{className:`panel`,children:(0,x.jsx)(Bt,{before:re.id,after:ie.id},`${re.id}-${ie.id}-${I}`)})]})]}),s===`history`&&(0,x.jsx)(ui,{initialComparison:(()=>{let e=Number(n.get(`before`)),t=Number(n.get(`after`));return Number.isSafeInteger(e)&&e>0&&Number.isSafeInteger(t)&&t>0?{before:e,after:t}:void 0})(),initialVersion:Number.isSafeInteger(r)&&r>0?r:void 0,currentID:re?.id,catalog:d.data,openMemory:e,onAction:ue,locked:le}),s===`memories`&&(0,x.jsx)(di,{openMemory:e}),s===`attempts`&&(0,x.jsx)(fi,{})]}),p&&(0,x.jsx)(ee,{title:mi[p.kind],closeDisabled:k,onClose:()=>h(null),children:(0,x.jsxs)(`form`,{noValidate:!0,className:`persona-action-form`,onSubmit:e=>{e.preventDefault(),B()},children:[p.kind===`edit`?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{children:[`发布会替换当前 v`,p.expectedVersion,` `,`并新建版本;新增或改动的句子会标为手写。待确认候选会被替代。`]}),(0,x.jsx)(`p`,{children:`之后的自动候选若删去手写内容,按“大变化”处理:默认方式需人工确认;“全部自动”模式下,检查通过仍会直接发布。`}),(0,x.jsxs)(`label`,{children:[`persona 正文`,(0,x.jsx)(`textarea`,{rows:9,disabled:k,value:b,onChange:e=>S(e.target.value)})]}),(0,x.jsxs)(`small`,{children:[[...b].length,` / 800 字`]})]}):p.kind===`confirm`?(0,x.jsxs)(`p`,{children:[`发布候选 v`,p.version.id,` 会替换当前 v`,p.expectedVersion,`。旧版本保留在历史中,可在之后回滚;服务会再次核对版本和依据。`]}):p.kind===`reject`?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`p`,{children:[`拒绝候选 v`,p.version.id,`,保留当前 v`,p.expectedVersion,`。拒绝记录与原因会保存;采用新候选需要再次生成。`]}),(0,x.jsxs)(`label`,{children:[`拒绝原因(可选)`,(0,x.jsx)(`textarea`,{rows:3,maxLength:1e3,disabled:k,value:C,onChange:e=>w(e.target.value)})]})]}):(0,x.jsxs)(`p`,{children:[`使用 v`,p.version.id,` 的正文与依据新建一个版本,替换当前 v`,p.expectedVersion,`;历史版本保持不变。待确认候选会被替代,旧依据失效时新版本仍会标为待更新。`]}),T&&(0,x.jsxs)(A,{error:!0,children:[T,P&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`p`,{children:`重新加载会放弃本次未保存草稿。可先复制草稿,再核对最新版本。`}),(0,x.jsx)(`button`,{type:`button`,onClick:de,children:`重新加载当前版本`})]})]}),(0,x.jsxs)(`div`,{className:`persona-actions`,children:[(0,x.jsx)(`button`,{type:`button`,disabled:k,onClick:()=>h(null),children:`取消`}),(0,x.jsx)(`button`,{className:`primary`,disabled:le,children:k?`正在提交…`:hi[p.kind]})]})]})})]})}var vi=[{id:`trial`,name:`试用对话`,icon:`chat`},{id:`memories`,name:`记忆`,icon:`memory`},{id:`people`,name:`人物`,icon:`people`},{id:`learning`,name:`入口与学习`,icon:`learning`},{id:`persona`,name:`persona 与自我`,icon:`people`},{id:`state`,name:`状态与目标`,icon:`state`},{id:`status`,name:`运行状态`,icon:`status`},{id:`operations`,name:`操作记录`,icon:`memory`},{id:`connections`,name:`接入与数据`,icon:`learning`},{id:`settings`,name:`设置`,icon:`settings`}];function yi({name:e}){return(0,x.jsx)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`1.7`,strokeLinecap:`round`,strokeLinejoin:`round`,"aria-hidden":!0,children:e===`chat`?(0,x.jsx)(`path`,{d:`M20 11.5a8 8 0 0 1-8 8H5l-3 2 1.5-5A8 8 0 1 1 20 11.5ZM7 10h8M7 14h5`}):e===`people`?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`circle`,{cx:`9`,cy:`7`,r:`3`}),(0,x.jsx)(`path`,{d:`M3 21v-3a6 6 0 0 1 12 0v3M16 4a3 3 0 0 1 0 6M18 14a5 5 0 0 1 3 4v3`})]}):e===`learning`?(0,x.jsx)(x.Fragment,{children:(0,x.jsx)(`path`,{d:`M4 4h16v5H4zM4 14h7v6H4zM16 14h4v6h-4M8 9v5M18 9v5`})}):e===`state`?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`circle`,{cx:`12`,cy:`12`,r:`9`}),(0,x.jsx)(`path`,{d:`M12 7v5l3 2`})]}):e===`memory`?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`rect`,{x:`5`,y:`3`,width:`14`,height:`18`,rx:`3`}),(0,x.jsx)(`path`,{d:`M9 8h6M9 12h6M9 16h3`})]}):(0,x.jsx)(x.Fragment,{children:(0,x.jsx)(`path`,{d:`M3 13h4l3-7 4 13 3-7h4`})})})}function bi(){return(0,x.jsx)(Me,{children:e=>(0,x.jsx)(xi,{refreshSession:e})})}function xi({refreshSession:e}){let[t,n]=(0,l.useState)(location.hash.slice(2)||`trial`),[r,i]=(0,l.useState)(null),[a,o]=(0,l.useState)(0),s=y(`/status`,2e3),c=y(`/people?pending_only=true&limit=1&offset=0`,5e3),u=t.split(`?`)[0],d=()=>{o(e=>e+1),s.refresh()};(0,l.useEffect)(()=>{let e=()=>{n(location.hash.slice(2)||`trial`),i(null)};return addEventListener(`hashchange`,e),()=>removeEventListener(`hashchange`,e)},[]);let f=(0,l.useCallback)(e=>i(e),[]),p=(0,l.useCallback)(()=>i(null),[]),m=s.data?.model_health.chat;return(0,x.jsxs)(`div`,{className:`app`,children:[(0,x.jsx)(`a`,{className:`skip-link`,href:`#main`,onClick:e=>{e.preventDefault(),document.getElementById(`main`)?.focus()},children:`跳到主内容`}),(0,x.jsxs)(`header`,{className:`app-header`,children:[(0,x.jsxs)(`a`,{href:`#/trial`,className:`brand`,"aria-label":`Iris 首页`,children:[(0,x.jsx)(`span`,{className:`brand-symbol`,"aria-hidden":!0,children:`✳`}),(0,x.jsxs)(`span`,{children:[`Iris`,(0,x.jsx)(`small`,{children:`相处与记忆`})]})]}),(0,x.jsx)(`nav`,{"aria-label":`主导航`,children:vi.map(e=>(0,x.jsxs)(`a`,{href:`#/${e.id}`,"aria-current":u===e.id||u===`people-graph`&&e.id===`people`?`page`:void 0,children:[(0,x.jsx)(yi,{name:e.icon}),e.name,e.id===`people`&&!!c.data?.total&&(0,x.jsx)(`span`,{className:`nav-dot`,"aria-label":`有待确认的人物联系`})]},e.id))}),(0,x.jsx)(`button`,{className:`text-button logout-button`,onClick:async()=>{await g(`/logout`,_(`POST`,{})),e()},children:`退出登录`}),(0,x.jsxs)(`span`,{className:`local-badge`,children:[(0,x.jsx)(`span`,{"aria-hidden":!0,children:`◉`}),` 仅本机`]})]}),(0,x.jsx)(`main`,{id:`main`,tabIndex:-1,children:(0,x.jsxs)(`div`,{className:`content-wrap`,children:[!!c.data?.total&&u===`trial`&&(0,x.jsxs)(A,{children:[c.data.total,` 位人物有待确认的“可能是同一人”联系。`,(0,x.jsx)(`a`,{href:`#/people?pending_only=true`,children:`查看待确认联系`})]}),c.error&&u===`trial`&&(0,x.jsxs)(A,{error:!0,children:[`人物联系提示暂时无法更新。`,(0,x.jsx)(`button`,{onClick:c.refresh,children:`重试人物提示`})]}),s.error&&(0,x.jsxs)(A,{error:!0,children:[s.error,`。以下数据可能尚未更新。`,(0,x.jsx)(`button`,{className:`text-button`,onClick:s.refresh,children:`重新连接`})]}),m&&m.state!==`normal`&&(0,x.jsxs)(A,{error:!0,children:[`对话模型:`,D(m.state),`。`,m.last_error?.includes(`未配置`)?`未配置模型,暂不学习。`:`学习已暂停。`,`消息仍可接收。`,(0,x.jsx)(`a`,{href:`#/status`,children:`查看运行状态`})]}),u===`settings`?(0,x.jsx)(ke,{}):u===`memories`?(0,x.jsx)($t,{initialQuery:t.split(`?`)[1],version:a,openMemory:f,onChange:d},t):u===`people-graph`?(0,x.jsx)(li,{initialQuery:t.split(`?`)[1],openMemory:f},t):u===`people`?(0,x.jsx)(qr,{openMemory:f,initialQuery:t.split(`?`)[1],onChange:()=>{c.refresh(),d()}},t):u===`operations`?(0,x.jsx)(be,{initialQuery:t.split(`?`)[1]},t):u===`learning`?(0,x.jsx)(Nr,{openMemory:f}):u===`state`?(0,x.jsx)(On,{initialQuery:t.split(`?`)[1],openMemory:f},t):u===`persona`?(0,x.jsx)(_i,{initialQuery:t.split(`?`)[1],openMemory:f},t):u===`connections`?(0,x.jsx)(ze,{}):u===`status`?(0,x.jsx)(Un,{initialQuery:t.split(`?`)[1]||``,data:s.data,openMemory:f},t):(0,x.jsx)(An,{status:s.data,openMemory:f,refreshStatus:s.refresh})]})}),(0,x.jsx)(`footer`,{className:`app-footer`,children:`Iris · 记忆有来源,相处有连续`}),r!==null&&(0,x.jsx)(tn,{id:r,onClose:p,openMemory:f,onChange:d},r)]})}(0,c.createRoot)(document.getElementById(`root`)).render((0,x.jsx)(l.StrictMode,{children:(0,x.jsx)(bi,{})})); \ No newline at end of file diff --git a/src/iris/web/index.html b/src/iris/web/index.html index cd7fc402..63e150eb 100644 --- a/src/iris/web/index.html +++ b/src/iris/web/index.html @@ -1,6 +1,6 @@ - Iris · 相处与记忆 + Iris · 相处与记忆
diff --git a/tests/test_limits_partial_settings.py b/tests/test_limits_partial_settings.py new file mode 100644 index 00000000..39ce65ee --- /dev/null +++ b/tests/test_limits_partial_settings.py @@ -0,0 +1,72 @@ +"""Limits PATCH preserves omitted values, runtime settings and audit scope.""" +import json +from unittest.mock import Mock + +import pytest +from fastapi.testclient import TestClient + +from conftest import login_admin +from iris.api import create_app + + +PATH = '/admin/api/settings/limits' +ORIGINAL = { + 'daily_token_limit': 12000, + 'learning_concurrency': 5, + 'learning_image_limit': 4, + 'native_image_learning': True, + 'media_retention_days': 21, +} + + +@pytest.fixture +def client(store, monkeypatch): + with TestClient(create_app(store=store, configs={}), base_url='http://127.0.0.1', + client=('127.0.0.1', 1000)) as client: + client.app.state.scheduler.stop() + login_admin(client) + assert client.patch(PATH, json=ORIGINAL).status_code == 200 + health = client.app.state.health + scheduler = client.app.state.scheduler + monkeypatch.setattr(health, 'set_daily_token_limit', Mock(wraps=health.set_daily_token_limit)) + monkeypatch.setattr(scheduler, 'set_concurrency', Mock(wraps=scheduler.set_concurrency)) + yield client + + +@pytest.mark.parametrize('changes', [ + {'media_retention_days': 14}, + {'daily_token_limit': None}, + {'learning_concurrency': 3}, + {'learning_image_limit': 0}, + {'native_image_learning': False}, + {}, + {'daily_token_limit': 9000, 'learning_concurrency': 4, 'learning_image_limit': 2, + 'native_image_learning': False, 'media_retention_days': 30}, +]) +def test_partial_limits_preserve_omissions_and_sync_only_submitted_fields(client, store, changes): + with store.read() as conn: + before = conn.execute("SELECT COUNT(*) FROM admin_operations WHERE action='limits_saved'").fetchone()[0] + response = client.patch(PATH, json=changes) + assert response.status_code == 200 + expected = {**ORIGINAL, **changes} + for key, value in expected.items(): + assert response.json()[key] == value + assert store.setting(key) == value + health = client.app.state.health + scheduler = client.app.state.scheduler + assert health.budget()['limit'] == expected['daily_token_limit'] + status = client.get('/admin/api/status').json() + assert status['budget']['limit'] == expected['daily_token_limit'] + assert status['scheduler']['max_concurrent'] == expected['learning_concurrency'] + if 'daily_token_limit' in changes: + health.set_daily_token_limit.assert_called_once_with(changes['daily_token_limit']) + else: + health.set_daily_token_limit.assert_not_called() + if 'learning_concurrency' in changes: + scheduler.set_concurrency.assert_called_once_with(changes['learning_concurrency']) + else: + scheduler.set_concurrency.assert_not_called() + with store.read() as conn: + rows = conn.execute("SELECT details_json FROM admin_operations WHERE action='limits_saved' ORDER BY id").fetchall() + assert len(rows) == before + 1 + assert json.loads(rows[-1][0]) == changes