npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

event-chronicle

v0.2.2

Published

从 AI 对话中提取事件,构建可视编年史,形成长期记忆

Downloads

536

Readme

Event Chronicle

img

让对话不只是对话,而是一部持续书写的可视编年史

Event Chronicle 从 AI 对话中提取结构化事件,并以时间线形式长期保存。在未来对话中,这些历史事件会重新注入模型上下文,使 AI 基于已发生的事实而非压缩后的摘要进行理解与推理,从而形成连贯、可追溯的长期记忆

支持 Node.js浏览器 两种环境


Demo

假设有以下聊天信息

img

Event Chronicle 不会保存整段聊天,只会从中提取事件

[
  {
    "date": "2026-06-14",
    "event": "用户开始饲养一只三个月大的橘猫,取名为奶糖"
  },
  {
    "date": "2026-06-14",
    "event": "奶糖昨天进行了体检,结果正常"
  }
]

每个事件自动记录来源消息的引用(索引范围 + 预览),用于事件回溯和上下文查看,不重复存储原始消息

这些事件会被保存到编年史中。后续再次对话时,Event Chronicle 将完整编年史注入模型上下文:

Event Chronicle

2026-06
├─ 用户开始饲养一只三个月大的橘猫,取名为奶糖
├─ 奶糖昨天进行了体检,结果正常

AI 基于这些历史事件组织回复——它们构成了 AI 的长期记忆

要理解现在,必须追溯过去

安装

Node.js

npm install event-chronicle

环境要求:Node.js ≥ 18

SillyTavern 插件

插件安装 URL:

https://github.com/janfeise/st-event-chronicle

插件安装方式:

网页打开酒馆 → Extensions → Install from Git URL → 输入上述 URL

插件安装后的位置:

{ST目录}/data/default-user/extensions/st-event-chronicle/

数据存放位置

Node.js SDK

data/ 目录下的 JSON 文件,由 CHRONICLE_EVENT_ID 环境变量控制文件名

SillyTavern 插件

ST 存储位置: data/default-user/settings.json
          → extension_settings.event-chronicle._events

数据随 ST 的 settings.json 自动保存,无独立文件


快速开始

Node.js

在项目中安装依赖 event-chronicle

npm install event-chronicle
npm install -D tsx          # TypeScript 运行器,也可用 node + .js

配置 API Key:创建 .env 文件,填入你的 LLM API Key:

支持的 LLM 提供商:OpenAI、DeepSeek、以及任何兼容 OpenAI API 格式的服务

LLM_PROVIDER=openai
LLM_BASE_URL=https://api.openai.com/v1
LLM_API_KEY=sk-your-key
LLM_MODEL=gpt-4o

Browser SDK 不使用 .env——请在 API 调用方直接传入配置。

创建 chronicle.ts

import { startup, processMessages, exportMemory } from "event-chronicle";

// 1. 初始化(自动加载 .env 中的 LLM 配置)
await startup();

// 2. 传入聊天消息,自动提取事件
const result = await processMessages([
  { role: "Alice", content: "我们去图书馆查资料" },
  { role: "Bob", content: "好主意。那里的数据库很全。" },
  { role: "Alice", content: "我在历史区找到了关于失踪探险队的日志。" },
]);

console.log(result.events.length); // → 提取到的事件数

// 3. 导出为 AI 记忆 Prompt
const memory = await exportMemory("default", { highlightThreshold: 7 });

运行:

npx tsx chronicle.ts

预期输出:生成的数据将保存在项目 data/ 目录下

╔══════════════════════════════════════════╗
║          Event Chronicle 启动…           ║
╚══════════════════════════════════════════╝
[Event Chronicle] ✓  LLM 健康检查通过
[Event Chronicle] 🚀 启动完成

提取事件: 1 条
存储文件: my-story.json
触发合并: false

# Event Chronicle Memory
## Summary
1 events · importance range 6–6
...

💡 完整 Demo(6 轮 RPG 对话、自动合并触发)见 demo/

Browser

import { formatMessages, extractPrompt } from 'event-chronicle/browser';

// 浏览器 SDK 不含 LLM 客户端 —— 仅提供纯函数和 Prompt 模板
const msgs = [{ role: 'Alice', content: 'Hello' }, { role: 'Bob', content: 'Hi!' }];
const prompt = extractPrompt
  .replace('{{existingEvents}}', '')
  .replace('{{recentMessages}}', formatMessages(msgs));

// 自己调用 LLM API
const response = await fetch('https://api.openai.com/v1/chat/completions', { ... });
const data = await response.json();
const events = parseEvents(data.choices[0].message.content);

API 参考

Node.js SDK (event-chronicle)

第一层:一站式 API

大多数场景只需这两个函数

| 函数 | 说明 | | ------------------------------------- | ---------------------------------------------- | | startup(options?) | 加载 .env → 初始化 LLM → 预热提示词 → 健康检查 | | processMessages(messages, options?) | 完整管道:提取事件 → 持久化 → 自动合并检测 |

const result = await processMessages(messages, {
  eventId: "my-story", // 文件名
  autoMerge: true, // 累计事件达阈值自动合并(默认 true)
  existingEventId: "old", // 加载已有事件供 LLM 参考去重
});
// → { events: Event[], storedFile: string, merged: boolean }

| 导出函数 | 说明 | 输出 | | --------------------------------- | ------------- | ---------------------------------------------------- | | exportMemory(eventId, options?) | Memory Export | Markdown + Prompt 包裹,可直接注入 LLM system prompt | | exportRaw(eventId) | Raw Export | 完整 JSON 数组(数据迁移 / 调试) |

第二层:流程级 API

需要自定义流程时使用

| 函数 | 说明 | | ------------------------------------------------------ | ---------------------- | | extractEvents(messages, existingEvents?) | 仅提取事件,不持久化 | | mergeEvents(existing, newEvents) | 仅合并事件,不自动触发 | | applyInstructions(existing, newEvents, instructions) | 纯函数:执行合并指令 | | loadChronicle(eventId?) | 读取已存储的事件 | | saveChronicle(events) | 全量保存到新文件 | | appendEvents(events, eventId?) | 追加事件到已有文件 |

第三层:底层 API

需要完全控制时使用

| 函数 | 说明 | | ------------------------------------------ | -------------------------------- | | initLLM(config) | 手动初始化 LLM 客户端 | | loadMergeState(eventId) | 读取合并计数器状态 | | resetMergeCounter(eventId) | 重置合并计数器 | | getDataDir() / setDataDir(dir) | 获取/覆盖数据目录 | | loadEnv() | 手动加载 .env 到 process.env | | exportRawFromEvents(events) | 纯函数版 Raw Export | | exportMemoryFromEvents(events, options?) | 纯函数版 Memory Export | | PromptManager | 提示词管理器类(创建自定义实例) |

Browser SDK (event-chronicle/browser)

| 函数/常量 | 说明 | | ---------------------------------------------------- | -------------------------------------------------------------------- | | parseEvents(response) | LLM 响应 → Event[] | | formatMessages(messages) | ChatMessage[] → 文本 | | applyInstructions(events, newEvents, instructions) | 执行合并指令 | | extractPrompt | 事件提取 Prompt 模板(含 {{existingEvents}} {{recentMessages}}) | | mergePrompt | 事件合并 Prompt 模板(含 {{existingEvents}} {{newEvents}}) | | memoryPrompt | 记忆注入 Prompt 模板(含 {{memoryTimeline}}) |


Configuration

方式一:.env 文件(推荐)

| 变量 | 必填 | 默认值 | 说明 | | ------------------------- | ---- | --------------------------- | ----------------------------- | | LLM_API_KEY | ✓ | — | LLM API Key | | LLM_PROVIDER | | openai | LLM 提供商 | | LLM_BASE_URL | | https://api.openai.com/v1 | API 地址 | | LLM_MODEL | | gpt-4o | 模型名称 | | CHRONICLE_EVENT_ID | | — | 默认数据文件名 | | CHRONICLE_MERGE_TRIGGER | | 5 | 自动合并触发阈值 | | CHRONICLE_MERGE_WINDOW | | 20 | 合并时发送给 LLM 的已有事件数 |

方式二:代码传参

// 完全绕过 .env,纯代码配置
await startup({
  healthCheck: false,
  llmConfig: {
    provider: "openai",
    baseUrl: "https://api.openai.com/v1",
    apiKey: "sk-xxx",
    model: "gpt-4o",
  },
  dataDir: "./my-data", // 自定义数据目录
  promptsDir: "./my-prompts", // 自定义提示词目录
});

系统流程

                     ┌──────────────┐
                     │ Chat Messages│
                     └──────┬───────┘
                            │
                            ▼
                     ┌──────────────┐
                     │   Extractor   │  ← LLM 从对话中提取事件
                     │  事件提取      │
                     └──────┬───────┘
                            │ Event[]
                            ▼
                     ┌──────────────┐
                     │    Storage    │  ← JSON 文件持久化
                     │   事件存储     │
                     └──────┬───────┘
                            │
              ┌─────────────┼─────────────┐
              │             │             │
              ▼             ▼             ▼
       [counter < N]  [counter ≥ N]    Export
              │             │             │
              │             ▼             │
              │      ┌──────────┐         │
              │      │   Merge   │  ← LLM 去重/整理
              │      │  事件合并  │         │
              │      └────┬─────┘         │
              │           │               │
              │           ▼               │
              │      ┌──────────┐         │
              │      │  Storage  │        │
              │      │  保存结果  │        │
              │      └──────────┘         │
              │                           │
              ▼                           ▼
       ┌──────────┐              ┌──────────────┐
       │ Continue │              │   Exporter    │
       │  继续积累 │              │ Raw / Memory  │
       └──────────┘              └──────┬───────┘
                                       │
                                       ▼
                               ┌──────────────┐
                               │    LLM API   │  ← 注入记忆
                               │   下次对话     │
                               └──────────────┘

核心原则

  1. 事件是历史事实 — 只记录已经发生、明确决定、明确推进的事情
  2. 时间线是记忆结构 — 按时间组织的事件序列,保持因果关系
  3. 记忆不是摘要 — 摘要告诉你聊了什么;记忆告诉你在这些对话中发生了什么

史官,不创造事实,不推测事实,不补全事实。Event Chronicle 只记录聊天中明确发生、明确决定、明确推进的事件

副作用

  1. 每轮对话的 token 增加(记忆会注入到 LLM API 中)
  2. token 逐步递增:事件不断累积,记忆愈加厚重
  3. LLM API 请求次数增多:每 N 次对话触发一次提取,每 M 个事件触发一次合并(N、M 可配置)

更多资源

| 文档 | 说明 | | --------------------------------------------- | ------------------------------- | | ST 扩展用户文档 | 安装 + 功能 + 配置 | | ST 扩展开发文档 | 架构 + 设计决策 + 开发流程 | | 项目开发文档 | 核心模块详解 + Browser SDK 架构 | | Web Demo | 浏览器交互式演示 | | CLI Demo | 端到端命令行演示 |

扩展

若导入 TA 的"历史",AI 是否是 TA 的一种延续呢?

License

MIT