区块模型
一个区块就是 blocks 表里的一行。它有标题、Markdown 正文、一个类型、一个父区块,以及在兄弟节点之间的
位置。
| 字段 | 类型 | 说明 |
|---|---|---|
id |
text | 主键 |
title |
text | not null,默认空字符串 |
slug |
text | 规范化后的短名,未删除的区块之间唯一 |
content |
text | Markdown 正文 |
metadata |
text | JSON 字符串——图标、颜色、视图模式 |
type |
text | 下面七种之一 |
position |
text | fractional index key,决定兄弟之间的顺序 |
parent_id |
text | 为 null 时是顶层区块 |
ref_id |
text | 指向另一个区块:context 子区块用它记下自己引入了哪个区块 |
created_at / updated_at |
integer | |
deleted_at / is_deleted |
integer | 软删除 |
is_snapshot |
integer | 为 1 时,这一行保存的是某个区块的旧状态 |
索引是部分索引,条件里带 is_deleted = 0,所以回收站里的东西越多,扫描也不会越贵。
| 类型 | 谁创建 | 怎么渲染 |
|---|---|---|
note |
你 | Markdown 预览,CodeMirror 编辑 |
prompt |
你,或一次运行 | 提问,旁边挂着模型控件 |
completion |
一次运行 | 流式写入的答复 |
agent |
你 | 系统提示词,下面是它的运行记录 |
craft |
你 | 和 note 一样 |
script |
你 | JavaScript 源码编辑器 |
context |
你 | 指向另一个区块的引用 |
completion 是唯一不能手工新建的类型——它由模型写回。craft 的渲染和 note 相同,区分的是用途而不是
展示方式。script 现在还不能执行,只存储和高亮。
兄弟顺序来自 position,一个 fractional indexing 的键。要把一个区块插到另外两个中间,OneBook 生成一个
排在两者之间的键,于是这次移动只是一行 UPDATE。不管这一层有多少兄弟,别的区块都不用重新编号。
移动一棵子树时,只有最上面那个区块重新认父。子区块保留自己的 position,所以子树内部的顺序不变。
删除是设 is_deleted 和 deleted_at。这个区块和它的后代从树上消失,但行还在库里。回收站列出被删除子树
的根节点,恢复会把整棵子树连同位置键一起带回来。真正删掉行只有 purge 这一个操作。
提问让 agent 修改某个区块的正文时,OneBook 先把当前状态复制成一个快照子区块:is_snapshot = 1,排在
这个区块所有子区块的最后。旧文本从此就是一个普通区块,能读、能搜、能被链接。
slug 与链接
Section titled “slug 与链接”每个区块可以带一个 slug,由标题规范化而来:小写、空白变连字符、去掉标点,写入和读取用的是同一个函数。
正文里 [[slug]] 是链接,((block-id)) 是嵌入。保存时这些引用被抽进 block_links,类型是 block_link
或 block_embed,于是反链查询就是一条普通的 SELECT。