@chronoai/toolkit/history — HistoryFeature
HistoryFeature 从多条时间轴收集历史帧,按时间顺序组装为 { role, content }[] 消息数组。不包含 LLM 调用逻辑,只做数据收集与角色映射,适合作为 LLM 调用前的消息准备层。
快速上手
声明哪些时间轴参与历史收集,以及各自对应的角色:
import { Agent, defineFeature, useTimeline, useCommand } from 'chronoai';
import { HistoryFeature } from '@chronoai/toolkit/history';
import { LlmFeature, LlmCall } from '@chronoai/toolkit/llm';
const agent = new Agent();
// 自定义 Feature:声明问答时间轴
const QAFeature = defineFeature('qa', () => {
const question = useTimeline<string>({ name: 'question' });
useTimeline<string>({ name: 'answer' });
useCommand('ask', {
runAt: 'after-settle',
when({ read }) {
return !!read(question, 'current')?.value;
},
plan({ read }) {
// 从 history::messages 读取已组装好的历史消息
const history = read('history::messages', 'current')?.value ?? [];
return LlmCall.plan({
messages: [
{ role: 'system', content: '简洁回答。' },
...history,
],
target: 'qa::answer',
});
},
});
});
agent.use(LlmFeature, { apiKey: 'sk-xxx' });
agent.use(QAFeature);
// 指定哪些时间轴参与历史收集
agent.use(HistoryFeature, {
sources: [
{ timeline: 'qa::question', role: 'user' },
{ timeline: 'qa::answer', role: 'assistant' },
],
});
agent.initialize();
await agent.write('qa::question', '什么是时间轴?');
console.log(agent.read('qa::answer', 'current')?.value);
// 第二轮——历史消息自动包含上一轮的问答
await agent.write('qa::question', '能举个例子吗?');
多 Feature 时间轴混合收集
sources 中的时间轴可以来自不同 Feature,使用全限定名即可:
agent.use(HistoryFeature, {
sources: [
{ timeline: 'input::question', role: 'user' },
{ timeline: 'rag::context', role: 'system' },
{ timeline: 'llm-out::reply', role: 'assistant' },
],
});
所有帧按时间顺序排列,不区分来源 Feature。
快照策略(snapshot)
组装后的 history::messages 数组默认只保留最新一份(snapshot: 'latest'),因为完整的历史消息数组本身已包含所有历史帧,存多份会带来 $O(n^2)$ 的空间冗余。
如果需要回看每个时间点的消息快照(审计、调试等场景),可以设为 'all':
agent.use(HistoryFeature, {
sources: [...],
snapshot: 'all', // 每个时间点都保留一份完整快照
});
// 回看第 3 轮给 LLM 发了什么
const round3 = agent.read('history::messages', 3)?.value;
时间轴
外部时间轴
| 名称 | 值类型 | 方向 | 说明 |
|---|---|---|---|
history::messages | HistoryMessage[] | 输出 | 按时间顺序排列的消息数组,任一 source 时间轴更新时自动重算 |
const messages = agent.read('history::messages', 'current')?.value;
// => [{ role: 'user', content: '...' }, { role: 'assistant', content: '...' }, ...]
内部时间轴
无。
配置参数
agent.use(HistoryFeature, config) 的 config 支持以下参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
sources | HistorySource[] | 是 | 数据源列表,每个元素声明一条时间轴及其对应角色 |
snapshot | 'latest' | 'all' | 否 | 快照策略(默认 'latest')。'latest' 只保留最新一份,'all' 每个时间点都保留 |
HistorySource 字段
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
timeline | string | 是 | 时间轴名称,支持全限定名(如 'qa::question') |
role | 'system' | 'user' | 'assistant' | 是 | 该时间轴帧值映射到的消息角色 |