Liking cljdoc? Tell your friends :D

im.ttalk.agent.agui.event-store

会话事件存储的可替换挂点(designs/agui-borrow.md §8;对照 Keelson IAguiThreadEventStore / IAguiThreadSequenceRecorder 与卫星包 Keelson.Agui.Bitcask)。

本库只带一个实现:ring-store,即原来 runtime 内置的会话环形缓冲 (有界、进程内、不落库)。缺省行为与以前逐字相同。

为什么要有这个协议(2026-11-08 用户拍板):事件持久化本库不做—— docs/agent-runtime-design.md §8.1 / §8.2 的结论不变(对话真相在 ChatMemory, 暂停真相在 PauseStore,事件缓冲是传输设施)。但事件存储的逻辑要能整个换掉: 将来外部库(同 Keelson 的 Agui.Bitcask)实现本协议、经 runtime 的 :event-store 插进来,就能让 /threads/:id/events、/threads/:id/state 在 重启后仍有内容,:since / Last-Event-ID 跨进程续传。本库不需要为此改一行。

即便插了持久化实现,它仍然不是对话真相::since 补不上时 runtime 照旧以 ChatMemory 的消息快照 resync(§8.1),事件存储只是回放设施。

契约(实现方必须满足)

  • :seq 由 runtime 分配:会话内单调递增、跨 run 连续。存储按原样保存, 不改、不重排。
  • es-append! 在会话锁内同步调用:要快,不许抛(抛了 runtime 记日志吞掉, 不打断 run,但这条事件就没进存储)。慢存储请自己做写缓冲。
  • es-last-seq:会话新建条目时 runtime 用它接上序号(重启后 :seq 不从 0 重来——否则客户端拿着旧的 Last-Event-ID 会漏收)。没有记录返回 nil。
  • es-since:返回 {:events [...] :gap? bool};since 为 nil 返回空且不报 gap;gap? 为真表示存储起点已越过 since,中间那段补不回来,runtime 会走 resync。
  • es-release!:会话从 runtime 内存里被驱逐 / forget 时调。进程内实现借机 释放内存;持久化实现什么都不做(数据要留着给重启后的续传)。
  • es-delete!:线程被删除时调(rt/purge!)。持久化实现在这里真删。

事件是中立的 Clojure map(agui.event 的事件形状,含 :type :seq :ts 等), EDN 可往返;持久化实现自己决定编码(EDN / Transit / JSON)。

会话事件存储的**可替换挂点**(designs/agui-borrow.md §8;对照 Keelson
`IAguiThreadEventStore` / `IAguiThreadSequenceRecorder` 与卫星包
`Keelson.Agui.Bitcask`)。

**本库只带一个实现**:`ring-store`,即原来 runtime 内置的会话环形缓冲
(有界、进程内、不落库)。缺省行为与以前逐字相同。

**为什么要有这个协议**(2026-11-08 用户拍板):事件持久化本库**不做**——
`docs/agent-runtime-design.md` §8.1 / §8.2 的结论不变(对话真相在 ChatMemory,
暂停真相在 PauseStore,事件缓冲是传输设施)。但事件存储的逻辑要**能整个换掉**:
将来外部库(同 Keelson 的 `Agui.Bitcask`)实现本协议、经 runtime 的
`:event-store` 插进来,就能让 `/threads/:id/events`、`/threads/:id/state` 在
重启后仍有内容,`:since` / Last-Event-ID 跨进程续传。本库不需要为此改一行。

即便插了持久化实现,它仍然**不是**对话真相:`:since` 补不上时 runtime 照旧以
ChatMemory 的消息快照 resync(§8.1),事件存储只是回放设施。

## 契约(实现方必须满足)

- **`:seq` 由 runtime 分配**:会话内单调递增、跨 run 连续。存储按原样保存,
  不改、不重排。
- **`es-append!` 在会话锁内同步调用**:要快,**不许抛**(抛了 runtime 记日志吞掉,
  不打断 run,但这条事件就没进存储)。慢存储请自己做写缓冲。
- **`es-last-seq`**:会话新建条目时 runtime 用它接上序号(重启后 `:seq` 不从 0
  重来——否则客户端拿着旧的 Last-Event-ID 会漏收)。没有记录返回 nil。
- **`es-since`**:返回 `{:events [...] :gap? bool}`;`since` 为 nil 返回空且不报
  gap;`gap?` 为真表示存储起点已越过 `since`,中间那段补不回来,runtime 会走 resync。
- **`es-release!`**:会话从 runtime 内存里被驱逐 / forget 时调。进程内实现借机
  释放内存;持久化实现**什么都不做**(数据要留着给重启后的续传)。
- **`es-delete!`**:线程被删除时调(`rt/purge!`)。持久化实现在这里真删。

事件是中立的 Clojure map(`agui.event` 的事件形状,含 `:type :seq :ts` 等),
EDN 可往返;持久化实现自己决定编码(EDN / Transit / JSON)。
raw docstring

EventStorecljprotocol

es-append!clj

(es-append! s conv-id event)

追加一条(已带 :seq)。会话锁内同步调用:要快、不许抛。

追加一条(已带 `:seq`)。会话锁内同步调用:要快、不许抛。

es-delete!clj

(es-delete! s conv-id)

线程被删除:真删。

线程被删除:真删。

es-eventsclj

(es-events s conv-id)

现存的全部事件(只读端点用)。没有返回 []。

现存的全部事件(只读端点用)。没有返回 []。

es-last-seqclj

(es-last-seq s conv-id)

该会话最后一条事件的 :seq,没有返回 nil。

该会话最后一条事件的 `:seq`,没有返回 nil。

es-release!clj

(es-release! s conv-id)

会话被 runtime 驱逐 / forget:进程内实现释放内存,持久化实现不动数据。

会话被 runtime 驱逐 / forget:进程内实现释放内存,持久化实现不动数据。

es-sinceclj

(es-since s conv-id since)

since 之后的事件:{:events [...] :gap? bool}。

`since` 之后的事件:`{:events [...] :gap? bool}`。
source

ring-storeclj

(ring-store)
(ring-store {:keys [buffer-size] :or {buffer-size 512}})

进程内环形缓冲:每会话最多 :buffer-size 条(缺省 512),会话驱逐即丢、进程停即丢。 这就是 runtime 不配 :event-store 时用的那个。:buffer-size 必须是正整数(装配期抛)。

进程内环形缓冲:每会话最多 `:buffer-size` 条(缺省 512),会话驱逐即丢、进程停即丢。
这就是 runtime 不配 `:event-store` 时用的那个。`:buffer-size` 必须是正整数(装配期抛)。
sourceraw docstring

safe-append!clj

(safe-append! s conv-id event)
source

safe-last-seqclj

(safe-last-seq s conv-id)
source

safe-release!clj

(safe-release! s conv-id)
source

safe-sinceclj

(safe-since s conv-id since)
source

since-ofclj

(since-of events since)

对一串按 :seq 升序的事件做 es-since 的语义(实现方可直接复用)。

对一串按 `:seq` 升序的事件做 `es-since` 的语义(实现方可直接复用)。
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
←Move to previous article
→Move to next article
Ctrl+/Jump to the search field
× close