# Agent 模块：扩展点与提醒

> agent-runtime 的扩展 SPI 怎样把功能挂进 pi 的回合循环，agent-modules 十二个子包各管什么，以及系统提醒、失控守卫、会话报告与引用溯源的实现。

- 作者：David（道雾轩）
- 专栏：MiniMax Code 源码解读（https://daiw.org/manual/minimax-code.md）
- 最后更新：2026-09-19
- 原文：https://daiw.org/manual/minimax-code/agent-modules
- 转载与引用：请注明出处并附原文链接（https://daiw.org/about/copyright）

pi 的 `Agent` 加上 agent-core 的 `PiTurnRunner`，只管“调模型、跑工具、再调模型”（见[pi 的 Agent 循环与回合执行器](https://daiw.org/manual/minimax-code/pi-agent)）。提醒注入、上下文压缩、失控检测、工具输出预算、Plan 模式、目标这些横切功能，MiniMax Code 都做成挂在循环上的模块，分三层：

| 层 | 位置 | 规模 | 职责 |
| --- | --- | --- | --- |
| 领域模块 | `packages/agent-modules/*` | 12 个子包，39383 行 | 纯领域逻辑，依赖由宿主注入，不 import 运行时包 |
| 适配层 | `packages/agent-extension` | 5395 行 | 把领域模块包装成 `AgentExtension` |
| 扩展 SPI | `packages/agent-runtime` | 1417 行 | 定义 `ExtensionAPI`，每个回合把所有扩展的贡献组装起来 |

适配层的自我定位写在入口文件的注释里（`packages/agent-extension/src/index.ts:4`）：

> This package owns only SPI glue. It does not construct module instances, choose a host profile, or provide a default extension list.

装哪些扩展由宿主 local-runtime-v2 决定。后面会看到，公开版本里有好几个适配器导出了却没有挂上。

## 怎么用

普通用户不直接写扩展，接触到的是这些开关和命令：

- 失控守卫：`~/.minimax-code/config.yaml`（数据目录可用 `MINIMAX_DATA_DIR` 改，`packages/tui/src/runtime/data-dir.ts:21`）里的 `runawayGuard.enabled`，缺省为 `true`，远程下发的值优先（`packages/config/src/runaway-guard-config.ts:17`）。
- 工具输出预算：`toolResultCompaction.maxInlineKiB` 等，见[上下文管理与压缩](https://daiw.org/manual/minimax-code/context-management)。
- `/feedback`：只在命令搜索里出现（`packages/tui/src/tui/commands/catalog.ts:347`），提交反馈时会附带一份从会话报告统计出来的诊断摘要。
- `beta.mcodeTools`：开启后，模型 ID 以 `MiniMax-M2.7` 开头时，系统提醒里多一段 `mcode-tools-master-reminder`（`packages/agent-modules/system-reminder/src/mcode-tools-master-reminder.ts:1`）。
- `beta.desktopPlanModeAgentEntry`：决定模型能不能主动调用 `EnterPlanMode`，见[Plan 模式与目标](https://daiw.org/manual/minimax-code/plan-and-goal)。

`contextManagement.disableSystemReminderModels` 在配置里有定义，注释说列出的模型会跳过每轮提醒（`packages/config/src/config.ts:873`）；但本地宿主构造 `SystemReminderService` 时没有传这个集合（`packages/local-runtime/src/api/host-memory.ts:79`），在 CLI 里不起作用。

## 扩展 SPI：五种贡献、九个事件

一个扩展就是 `{ id, description?, init(pi) }`（`packages/agent-runtime/src/types.ts:308`）。`init` 里能用的 `ExtensionAPI`（`types.ts:263`）只有五类调用：`registerTool`（静态工具或每回合求值的工具工厂）、`contributeSystemPrompt`、`contributeUserPromptPrefix`、`registerReminderProvider`，以及用 `on(event, handler)` 订阅 `HOOK_NAMES` 里的九个事件（`types.ts:162`）。

注册表 `Registry` 有几条硬规矩：注册只能发生在 `init` 期间，事后再调直接抛错，防止扩展把 `pi` 存起来以后用（`packages/agent-runtime/src/registry.ts:307`）；两个扩展贡献同名工具时组装失败（`agent-runtime/src/registry.ts:461`）；每回合收集的提醒按 `priority` 降序排列（`agent-runtime/src/registry.ts:413`）；扩展还可以按会话单独启停（`agent-runtime/src/registry.ts:189`）。

九个事件里有七个落在 step 级，由一张表映射成 agent-core 的 `PiTurnHooks` 字段（`agent-runtime/src/registry.ts:126`）：

```ts
const HOOK_MAPPINGS = [
  { pi: 'onLlmCallPreparedHook', event: 'on_llm_call_prepared', adapter: 'context' },
  { pi: 'beforeLlmCallHook', event: 'before_llm_call', adapter: 'context' },
  { pi: 'afterLlmCallHook', event: 'after_llm_call', adapter: 'context' },
  { pi: 'beforeToolCallHook', event: 'before_tool_call', adapter: 'tool-context' },
  { pi: 'afterToolCallHook', event: 'after_tool_call', adapter: 'tool-context' },
  { pi: 'onHistoryChangedHook', event: 'on_history_changed', adapter: 'context' },
  { pi: 'onStepEndHook', event: 'on_step_end', adapter: 'context' },
] as const satisfies readonly {
  pi: keyof PiTurnHooks;
  event: HookName;
  adapter: 'context' | 'tool-context';
}[];
```

另外两个 `turn_start`、`turn_end` 不进 pi，由宿主在回合前后直接调用（`packages/local-runtime-v2/src/service/turn-system/agent-host/local-agent-host.ts:240`）。术语要注意：pi 的 “turn” 指一次模型回答加上它引出的工具执行，在 MiniMax 这边叫 step；MiniMax 的回合由若干 step 组成（`packages/agent-core/src/pi-turn-runner/hooks.ts:241`）。

| 事件 | 在 pi 上的落点 | 时机 | 能做什么 |
| --- | --- | --- | --- |
| `before_llm_call` | `Agent.transformContext` | 每次模型请求前 | 放行、跳过、直接给回答、只改本次请求、持久替换历史、追加隐藏消息、中止 |
| `on_llm_call_prepared` | 包在 `streamFn` 外 | 请求定型、发出之前 | 只读观察 |
| `after_llm_call` | `message_end` 事件 | 回答完整、工具未执行 | 改写文本、要求重答、判失败 |
| `before_tool_call` / `after_tool_call` | `Agent.beforeToolCall` / `afterToolCall` | 每个工具调用前后 | 拦截调用、改写结果 |
| `on_history_changed` | 历史落盘时 | 消息增量或整段替换后 | 观察 |
| `on_step_end` | pi 的 `turn_end` 事件 | 每个 step 结束 | 观察，可往 `agent` 里塞转向消息 |

对应实现在 agent-core 的 pi-turn-runner 里：`transformContext` 在 `packages/agent-core/src/pi-turn-runner/llm.ts:37` 设置，只读观察者包在 `packages/agent-core/src/pi-turn-runner/turn.ts:273`，`after_llm_call` 在 `packages/agent-core/src/pi-turn-runner/events.ts:87`，工具钩子在 `packages/agent-core/src/pi-turn-runner/tools.ts:79` 与 `pi-turn-runner/tools.ts:104`。`transformContext`、`beforeToolCall`、`afterToolCall` 是 pi 上游 `Agent` 自带的回调；runner 另外用到的 `onToolExecutionStart`，以及 `Agent` 上的 `shouldStopAfterTurn`，来自 MiniMax 的补丁（`third_party/pi-mono/MINIMAX_CHANGES.md:65`、`MINIMAX_CHANGES.md:191`）。几条语义契约：

- `before_llm_call` 的钩子按顺序执行，任何一个抛错都会中止这次模型调用（日志写明 fail-closed，`pi-turn-runner/llm.ts:212`）；有钩子返回 `appendMessage` 后，后面的钩子不再执行（`pi-turn-runner/llm.ts:290`），所以宿主把只改请求的提醒排在追加型提醒之前（`packages/local-runtime-v2/src/service/turn-system/agent-host/execution/executor.ts:752`）。
- `after_llm_call` 返回 `retry` 时，runner 先删掉这条回答里的工具调用，再用 `followUp` 追加一条用户消息让模型重答（`pi-turn-runner/events.ts:123`），被否决的回答不会产生副作用。
- `on_step_end` 的钩子出错只记降级指标，循环照常继续（`pi-turn-runner/events.ts:341`）。

## CLI 回合实际挂了什么

`AgentRuntime` 在宿主组装时创建一次（`packages/local-runtime-v2/src/service/turn-system/agent-host/native-production-dependencies.ts:131`），每个回合预检时调用 `assembleTurn`（`local-agent-host.ts:200`）。扩展清单来自三处，由 `mergeNormalExtensions` 合并（`packages/local-runtime-v2/src/service/turn-system/production-composition.ts:737`）：

| 来源 | 扩展 |
| --- | --- |
| 产品层（`packages/local-runtime-v2/src/application/agent/runtime-agent-product.ts:209`、`packages/local-runtime-v2/src/compat/v1/agent-host.ts:256`） | 浏览器工具、网站部署投影、目标预算守卫、`local-builtin-tool-hooks`（产品内置的工具前后处理）、代码审查 |
| 会话层（`packages/local-runtime-v2/src/services.ts:979`） | 引用溯源（受开关控制）、`plan-mode`、`local-goal-verifier-readonly`、`local-goal-budget-summary`、`miniapp-control`（有 Mini App 生命周期时才挂，`services.ts:687`） |
| 宿主内置（`production-composition.ts:510`） | `session-report`、`runaway-guard`、`tool-output-budget` |

宿主内置的三个总是排在最后，而且不能被同 ID 的扩展替换，注释给的理由是它们要看到前面所有扩展对工具结果的改写：

> Host-owned builtins establish terminal postconditions. They must observe every configured after_tool_call rewrite and cannot be replaced by a configured extension with the same id.

反过来，`@mavis/agent-extension` 还导出了 `systemReminderExtension`、`contextManagerExtension`、`permissionExtension`、`skillsExtension`、`terminalResponseRecoveryExtension`、`runawayGuardShadowExtension`，公开仓库里却没有生产代码挂载它们；`createNativeAgentHostProductionDependencies` 的注释也写明，工厂本身不会自动启用 agent-extension 的内置适配器，只装调用方显式传入的那些（`native-production-dependencies.ts:104`）。CLI 走的是别的路：系统提醒由宿主直接拼进用户消息（见下文），压缩由 v2 自己的压缩器负责，权限走 `LocalTurnPermissionGate`（见[权限模式与规则](https://daiw.org/manual/minimax-code/permission)）。

## 十二个子包

| 子包 | 行数 | 做什么 | 详见 |
| --- | --- | --- | --- |
| `system-reminder` | 3407 | `<system-reminder>` 块的提供者链与组装 | 本篇 |
| `conversation-contract` | 751 | 会话、队列、回合与压缩的运行时无关契约 | 本篇 |
| `session-report` | 620 | 模型调用环境记录与会话诊断包收集 | 本篇 |
| `runaway-guard` | 1438 | 回合内的打转检测与一次性提醒 | 本篇 |
| `context-manager` | 1511 | 压缩阈值公式、token 估算、共享的 `ContextManager` | [上下文管理与压缩](https://daiw.org/manual/minimax-code/context-management) |
| `goal` | 3090 | 线程目标的状态、工具、续跑提示与验证 | [Plan 模式与目标](https://daiw.org/manual/minimax-code/plan-and-goal) |
| `background-task` | 916 | 后台任务的领域模型与生命周期原语 | [子 Agent 与后台任务](https://daiw.org/manual/minimax-code/subagents) |
| `cron` | 2921 | 定时任务的调度与执行 | [定时任务](https://daiw.org/manual/minimax-code/cron) |
| `skills` | 1292 | 基于文件系统的技能注册表 | [技能](https://daiw.org/manual/minimax-code/skills) |
| `plugin-hooks` | 5194 | 插件 Hook 的解析、命令执行与会话生命周期协调 | [插件系统](https://daiw.org/manual/minimax-code/plugins) |
| `mcp` | 1644 | MCP 运行时底座 | [MCP](https://daiw.org/manual/minimax-code/mcp) |
| `permission` | 16599 | 工具调用的权限决策引擎 | [权限模式与规则](https://daiw.org/manual/minimax-code/permission) |

行数按全书统一口径统计（排除测试）。`permission` 一个子包就占了四成多。

## 系统提醒（system-reminder）

`SystemReminderRegistry`（`packages/agent-modules/system-reminder/src/registry.ts:25`）按注册顺序保存提供者，用 `appendCritical` 登记的“关键”提供者在某个模型被整体关掉提醒时仍然运行。`SystemReminderService.buildReminder`（`packages/agent-modules/system-reminder/src/service.ts:88`）每调用一次把会话轮数加一，让宿主实现的 `DataCollector` 收集数据，依次运行提供者，把非空输出拼成一个块（`service.ts:210`）：

```ts
      const fullText =
        blocks.length === 0
          ? null
          : `<system-reminder>\n${blocks.join('\n\n')}\n</system-reminder>`;
```

`createDefaultRegistry`（`packages/agent-modules/system-reminder/src/providers.ts:823`）装了 26 个提供者，其中 4 个是关键提供者（待投递的会话提醒、Todo 收尾提醒、媒体产出提醒、异步审计）。按内容大致分几类：`<agent-context>`（agent 名、会话 ID 等身份信息，第二轮起换精简版，`providers.ts:193`）、团队协作、十来个记忆相关的块、Todo 收尾提醒（有未完成的 Todo 时，距上次提醒满 5 轮再提醒，`providers.ts:425`）、冷启动检查、媒体与密钥环境提示、IM 渠道的入站元数据。每个提供者自己判断数据齐不齐，不满足就返回空。

CLI 里，这套服务由第一代运行时的宿主设施 `LocalSystemReminderService` 持有（`packages/local-runtime/src/api/host-memory.ts:65`），v2 在回合输入准备阶段通过 `reminders.buildSystem` 取回结果（`packages/local-runtime-v2/src/service/turn-system/agent-host/assembly/local-turn-input-preparation.ts:199`），校验它恰好是一个完整的 `<system-reminder>` 块或空串（`local-turn-input-preparation.ts:868`），再和附件提醒（`local-turn-input-preparation.ts:647`）、斜杠技能提醒（`local-turn-input-preparation.ts:831`）排成 `reminderBlocks`（`local-turn-input-preparation.ts:251`）。执行器把它们连同扩展贡献的提醒一起拼到用户消息正文前面（`executor.ts:502`）：

```ts
    const userPromptPrefix = joinUserPrompt(
      input.assembly.userPromptPrefix,
      renderAgentRuntimeReminders(input.assembly.reminders),
      joinPrompt(
        preparedExecution.reminderBlocks.join('\n\n'),
        input.pluginHookContext
          ? `<plugin-hook-context>\n${input.pluginHookContext}\n</plugin-hook-context>`
          : '',
      ),
      '',
    );
```

顺序是：扩展的用户提示前缀、扩展的提醒（如 Plan 模式提醒，按优先级排好）、宿主的提醒块与插件 Hook 上下文，最后才是用户输入；用户真正输入的那一段另用 `genuineUserQueryText` 标出。扩展提醒同样必须是完整的单个块，否则直接抛错（`packages/local-runtime-v2/src/service/turn-system/agent-host/execution/prompt.ts:6`）。

回合进行中还有几种只在请求前插入的提醒，都挂在 `before_llm_call` 上：带截止时间的回合会在每次请求末尾附上剩余秒数，只改本次请求、不进历史（`packages/local-runtime-v2/src/service/turn-system/agent-host/runner/execution-budget-reminder.ts:10`）；Todo 节奏提醒在距上次 `todowrite` 和上次提醒都满 15 次 assistant 迭代后，以隐藏消息追加进历史（`packages/local-runtime-v2/src/service/turn-system/execution/reminder/todo-cadence-reminder.ts:14`、`packages/local-runtime-v2/src/service/turn-system/compaction/compat.ts:10`）；后台任务提醒同理。追加前都要过 `fitsReminderInFinalRequest`，加上提醒会超出 provider 输入上限就放弃（`packages/local-runtime-v2/src/service/turn-system/execution/reminder/reminder-admission.ts:8`）。

## 会话契约（conversation-contract）

`RuntimeConversation`（`packages/agent-modules/conversation-contract/src/index.ts:516`）把运行时对外的会话能力收成四组：`query`（读会话与消息）、`lifecycle`（建、改、删会话）、`ingress`（提交、恢复用户输入、转向、队列的查询修改取消与重排、中止、派发，`conversation-contract/src/index.ts:451`）、`maintenance`（目前只有 `compact`，`conversation-contract/src/index.ts:510`）。local-runtime 和 local-runtime-v2 各有三十多个文件 import 这个包，它是两代运行时共用的会话接口。`ConversationSource`（`conversation-contract/src/index.ts:1`）列出回合的来源，如 `api`、`cron`、`thread-goal`、`channel:feishu`；`ConversationSession.runtime` 至今保留 `opencode` 这个取值（`conversation-contract/src/index.ts:91`），是旧底座留下的痕迹。`DeferredRuntimeConversation`（`conversation-contract/src/index.ts:580`）先把接口交出去，调用会等到真正的实现绑定之后再转发。

## 会话报告（session-report）

采集这一半是宿主内置扩展 `sessionReportExtension`（`packages/agent-extension/src/session-report.ts:13`）。它订阅 `on_llm_call_prepared`（`session-report.ts:64`），把一次模型调用里消息以外的部分——系统提示词、工具 schema、模型与 provider、思考级别、输出上限、缓存策略——写进会话目录下的 `llm-call.json`（`packages/agent-modules/session-report/src/llm-call-report-store.ts:12`）。内容不变就跳过写入（按 SHA-256 指纹比较），单个信封上限 4 MiB（`llm-call-report-store.ts:14`）；压缩完成时把它冻结到对应快照旁边（`llm-call-report-store.ts:57`），回退（rewind）后删掉失效的那份（`llm-call-report-store.ts:77`）。写入失败只上报，不打断模型调用。历史消息本来就落盘，缺的正是这部分“调用环境”，两者合起来才能复原一次请求。

打包这一半是 `SessionReportService.collect`（`packages/agent-modules/session-report/src/session-report-service.ts:47`）：遍历会话及其子会话的目录收集文件，跳过 `llm-context-inspector` 等目录（`session-report-service.ts:34`），task 会话额外附上 Agent 定义；读不到的文件记进 `session-report-collection.json`，不让整体失败。TUI 的 `/feedback` 经 `uploadTuiFeedbackDiagnostics`（`packages/tui/src/runtime/feedback/diagnostic-upload.ts:70`）读取这份清单和最近两天的日志，逐个文件压成计数、状态、错误码之类的摘要再打包上传（`diagnostic-upload.ts:120`），归档里的文件名一律换成不透明的编号（`diagnostic-upload.ts:100`）；提交前的预览会列出这些范围，并写明原文与文件名不上传（`packages/tui/src/runtime/feedback/service.ts:139`）。

## 失控守卫（runaway-guard）

失控守卫只管“同一回合里模型原地打转”，从不拦工具，也不中止回合。宿主这样创建它（`packages/local-runtime-v2/src/service/turn-system/runaway-guard/extension.ts:13`）：

```ts
export function createProductionRunawayGuardExtension(options: RunawayGuardHostOptions) {
  const emit = createRunawayGuardObserver(options);
  const local = readBestEffort(options.readLocalConfig);
  return runawayGuardExtension({
    toolPolicies: createProductionRunawayGuardToolPolicies(),
    readVerifiedProgress: options.readVerifiedProgress,
    isEnabled: () =>
      resolveRunawayGuardConfig(local, readBestEffort(options.readRemoteConfig)).enabled,
    shouldRemind: (ctx) => ctx.turnIntent?.kind !== 'goal-verifier',
    onSignal: (value) => emit('runaway_guard_signal', value),
    onReminder: (value) => emit('runaway_guard_reminder_injected', value),
    onTurnSummary: (value) => emit('runaway_guard_turn_summary', value),
  });
}
```

本地配置只在创建时读一次，远程值每次判定都重新读；目标验证子 Agent 的回合只观测不提醒。判定发生在每个 step 结束时：

1. 投影：本 step 的每个工具调用被投影成几种指纹——动作（工具名加参数，工具策略可以只挑稳定字段）、结果（工具名、内容、details、是否出错）、错误族（优先取 details 里的错误码，否则按正则归到 timeout、rate_limit 等八类，再不行取前 1024 个字符，`packages/agent-modules/runaway-guard/src/step-view.ts:388`）、进度（由工具策略或宿主提供的循环键与进度键）。指纹是用每回合随机 32 字节密钥算的 HMAC（`packages/agent-modules/runaway-guard/src/state.ts:101`），原始参数不会外泄。
2. 计数：同一个键在相邻 step 里连续出现就累加，断开即清零（`packages/agent-modules/runaway-guard/src/signals.ts:158`）。六种信号见 `RunawayGuardSignalKind`（`packages/agent-modules/runaway-guard/src/contracts.ts:3`）：重复动作、重复结果、同一错误族、ABAB 交替（看最近四个 step 的动作批次，`signals.ts:199`）、轮询无变化、进度无变化。
3. 阈值：计数到 2 发一次观测事件（`signals.ts:174`）；到提醒阈值（默认 3，也不许设得更小，`packages/agent-extension/src/runaway-guard.ts:69`、`packages/agent-modules/runaway-guard/src/guard.ts:31`）时，其中四种信号可以触发提醒，按“进度无变化、同一错误族、重复动作、轮询”的优先级取一个（`packages/agent-modules/runaway-guard/src/reminder.ts:10`）。
4. 提醒：每回合最多一次（`reminder.ts:26`），用 `event.agent.steer()` 作为一条用户消息放进 pi 的转向队列（`runaway-guard.ts:130`），在下一次模型请求前送达。

重复动作的提醒原文是：

> Do not repeat it unchanged. Inspect the results already available, then either change strategy with a concrete expected state change, or report the blocker.

每条提醒末尾还补一句，声明这只是本回合的临时提醒，不要写进记忆或技能（`reminder.ts:59`）。工具策略（`packages/local-runtime-v2/src/service/turn-system/runaway-guard/tool-policy.ts:7`）排除了常见误报：`bash`、`sh`、`shell`、`zsh` 里单独的 `rg`、`grep`、`git grep` 以退出码 1 结束算“没搜到”而不是出错，`grep` 工具的 “No matches found” 同理；`task_query`、`task_output` 按轮询处理，用任务状态和输出游标判断有没有进展。

## 空回答恢复（terminal-response-recovery）

`terminalResponseRecoveryExtension`（`packages/agent-extension/src/terminal-response-recovery.ts:36`）盯的是另一种卡住：工具全部成功之后，模型交回一条既没有工具调用、也没有可见文字的回答。它在 `on_step_end` 记下上一批工具是否全部成功，`after_llm_call` 遇到这种空回答就返回 `retry`，附上一句提示（`terminal-response-recovery.ts:28`）：

> The tools completed, but your response was empty. Provide a concise final response summarizing the result for the user.

再空一次就返回 `fail`，原因记为 `terminal_empty`（`terminal-response-recovery.ts:69`）。前面说过，公开版本的 CLI 没有挂这个扩展。

## 引用溯源（source-reference）

agent-extension 里最大的文件是 `packages/agent-extension/src/source-reference.ts`，2434 行，加上 files、web、utils、marker 四个辅助文件共 2944 行。扩展做两件事（`source-reference.ts:145`）：

- 工具调用之后（`source-reference.ts:155`）：MCP、App、文件三个适配器把一次成功的工具调用归一成 `ToolSourceReference`，写进工具结果的 `details.source_references`；App、MCP 与网页抓取的结果末尾再追加一个只给模型看的标记块。标记块由宿主创建并登记在一个 `WeakSet` 里（`packages/agent-extension/src/source-reference-marker.ts:5`），工具输出伪造不了；工具输出预算归档大结果时会保留这些标记（`packages/agent-extension/src/tool-output-budget.ts:79`）。
- 模型回答之后（`source-reference.ts:246`）：对不含工具调用的最终回答规范化引用写法；如果回答确实用了某个来源的内容却没标引用，就要求重答一次，原因 `missing_source_citation`（`source-reference.ts:337`），否则只改写文本。

宿主一侧已经接好（`packages/local-runtime-v2/src/application/agent/source-reference-extension.ts:12` 负责把附件与工作区文件解析成来源），能不能挂上取决于 `isLocalSourceProvenanceEnabled`；而它最终调用的 `resolveSourceProvenanceEnabled` 目前对所有环境都返回 `false`（`packages/shared/src/source-provenance.ts:10`），注释说是在排查疑似由溯源流程引发的主线程卡顿（`source-provenance.ts:4`）。

下一篇：[上下文管理与压缩](https://daiw.org/manual/minimax-code/context-management)——自动压缩何时触发、检查点摘要怎样生成，以及压缩后如何重算上下文用量。
