思源笔记内核 HTTP API 完全指南:从鉴权规范到数据库(属性视图)自动化操作
思源笔记(SiYuan)是一个开源、隐私优先、自托管的知识工作空间,其数据管理核心是运行在本地(默认 http://127.0.0.1:6806)的 Go 语言内核服务,前端界面、插件体系与外部自动化脚本都通过这套内核 HTTP API 与之通信。本文以 docs/API.zh-CN.md 为骨架,结合内核源码(kernel/api、kernel/model 等)展开,完整讲解从通用调用规范、鉴权机制,到笔记本、文档、块、属性、SQL、模板、文件、导出、转换、通知、网络代理、系统状态等接口,并重点剖析结构化数据库(内核中称为属性视图 Attribute View)的字段、条目、视图与过滤排序的自动化操作方法。读完本文,你将能够独立编写脚本,通过 API 对思源笔记工作空间进行增删改查、批量导入导出与数据库自动化管理。
一、通用调用规范:端点、参数与返回值
所有内核 API 都遵循统一约定,理解这一点后,其余接口几乎可以触类旁通。
1.1 端点与请求方式
- 端点(Endpoint):
http://127.0.0.1:6806,由内核进程监听,默认仅允许本机访问。 - 请求方法:绝大多数接口是 POST;少数接口(如
/api/system/bootProgress、/api/system/version)同时支持 GET 与 POST。 - 参数传递:需要带参的接口,参数为 JSON 字符串,放置到请求 body 中,标头
Content-Type设置为application/json。 - 个别接口例外:
/api/asset/upload(资源上传)与/api/file/putFile(文件写入)使用的是 HTTP Multipart 表单。
从源码看,路由统一在 kernel/api/router.go 的 ServeAPI 中注册,例如:
ginServer.Handle("POST", "/api/notebook/lsNotebooks", model.CheckAuth, lsNotebooks)
ginServer.Handle("POST", "/api/query/sql", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, SQL)
其中 model.CheckAuth 是鉴权中间件,model.CheckAdminRole 要求管理员角色,model.CheckReadonly 则在只读模式下拦截写操作(返回 code: -1)。可以看到几乎所有"写"接口都叠加了只读保护,这是内核保证数据安全的重要机制。
1.2 统一返回值结构
所有接口返回统一的 JSON 结构:
{
"code": 0,
"msg": "",
"data": {}
}
字段语义:
code:非 0 为异常情况,0 表示成功;msg:正常情况下是空字符串,异常情况下会返回错误文案;data:可能为{}、[]或NULL,根据不同接口而不同。
开发脚本时务必先判断 code 是否为 0,再解析 data。
1.3 鉴权:API Token
在思源笔记界面 设置 - 关于 中查看 API token,调用需要鉴权的接口时,在请求标头携带:
Authorization: Token xxx
从 kernel/model/session.go 的 CheckAuth 实现可以看到,内核支持的 token 传递方式远不止这一种:
- 请求标头
Authorization,前缀可为Token、token、Bearer、bearer(不区分大小写写法); - URL 查询参数
?token=xxx; - 已登录 Web 界面的会话(JWT 认证)也会被识别。
Token 值来自内核配置 kernel/conf/api.go 中的 API.Token 字段,首次启动时由 gulu.Rand.String(16) 随机生成 16 位字符串。注意:/api/system/bootProgress、/api/system/version、/api/system/currentTime 等少数接口无需鉴权(见 kernel/api/router.go)。
下面给出一个最小可用的 Python 调用示例:
import json
import urllib.request
API_URL = "http://127.0.0.1:6806"
TOKEN = "your-api-token" # 在 设置-关于 中查看
def call_api(path, payload=None):
req = urllib.request.Request(API_URL + path, method="POST")
req.add_header("Content-Type", "application/json")
req.add_header("Authorization", "Token " + TOKEN)
data = json.dumps(payload).encode("utf-8") if payload else b"{}"
with urllib.request.urlopen(req, data=data) as resp:
return json.loads(resp.read().decode("utf-8"))
二、笔记本(Notebook)管理
笔记本是工作空间中的顶层数据容器,对应工作空间 data/ 目录下的子文件夹,每个笔记本以 ID 命名,例如 20210808180117-czj9bvb/(仓库内置的用户指南笔记本即使用这种 ID 命名,参见 app/guide 目录下的文件夹)。
2.1 列出笔记本
POST /api/notebook/lsNotebooks,不带参。返回:
{
"code": 0,
"msg": "",
"data": {
"notebooks": [
{ "id": "20210817205410-2kvfpfn", "name": "测试笔记本", "icon": "1f41b", "sort": 0, "closed": false },
{ "id": "20210808180117-czj9bvb", "name": "思源笔记用户指南", "icon": "1f4d4", "sort": 1, "closed": false }
]
}
}
字段说明:id 为笔记本 ID;name 为显示名称;icon 为 Emoji 图标(Unicode 码点);sort 为排序值;closed 表示该笔记本是否处于关闭状态。
2.2 打开 / 关闭笔记本
POST /api/notebook/openNotebook:参数{"notebook": "20210831090520-7dvbdv0"},notebook为笔记本 ID;POST /api/notebook/closeNotebook:参数同上。
两者返回值均为 data: null。关闭状态会体现在 lsNotebooks 的 closed 字段中。
2.3 重命名笔记本
POST /api/notebook/renameNotebook,参数:
{ "notebook": "20210831090520-7dvbdv0", "name": "笔记本的新名称" }
2.4 创建笔记本
POST /api/notebook/createNotebook,参数 {"name": "笔记本的名称"}。返回新笔记本的完整信息:
{
"code": 0,
"msg": "",
"data": {
"notebook": { "id": "20220126215949-r1wvoch", "name": "笔记本的名称", "icon": "", "sort": 0, "closed": false }
}
}
2.5 删除笔记本
POST /api/notebook/removeNotebook,参数 {"notebook": "20210831090520-7dvbdv0"}。该操作不可恢复,脚本调用前应做好确认与备份。
2.6 获取与保存笔记本配置
POST /api/notebook/getNotebookConf,参数 {"notebook": "20210817205410-2kvfpfn"},返回:
{
"code": 0,
"msg": "",
"data": {
"box": "20210817205410-2kvfpfn",
"conf": {
"name": "测试笔记本",
"closed": false,
"refCreateSavePath": "",
"createDocNameTemplate": "",
"dailyNoteSavePath": "/daily note/{{now | date \"2006/01\"}}/{{now | date \"2006-01-02\"}}",
"dailyNoteTemplatePath": ""
},
"name": "测试笔记本"
}
}
配置字段语义:
name:笔记本名称;closed:是否关闭;refCreateSavePath:创建引用时默认保存路径(模板);createDocNameTemplate:新建文档名称模板;dailyNoteSavePath:日记存放路径模板,默认按/daily note/年/月/日组织,其中的{{now | date "2006/01"}}是 Go 模板语法(Go 的参考时间为 2006-01-02 15:04:05),渲染结果形如2023/03;dailyNoteTemplatePath:日记模板文件路径。
保存配置使用 POST /api/notebook/setNotebookConf,请求体为 {"notebook": "...", "conf": { ...完整配置对象... }},返回 data 为保存后的配置对象。写操作(设置类接口)在路由中均带有 model.CheckReadonly 中间件,当内核处于只读模式(如发布只读场景)时会拒绝执行。
三、文档(Document)管理
文档是笔记本内的叶子数据单元,存储为 *.sy 文件(JSON 格式,参见 docs/SY-FORMAT.zh-CN.md),文件名即文档 ID。文档在笔记本内通过路径组织,路径中既包含人类可读的标题层级,也包含 ID 目录,理解两类路径的转换是使用文档 API 的关键。
3.1 通过 Markdown 创建文档
POST /api/filetree/createDocWithMd,参数:
{
"notebook": "20210817205410-2kvfpfn",
"path": "/foo/bar",
"markdown": ""
}
notebook:笔记本 ID;path:文档路径,需要以/开头,中间使用/分隔层级(这里的 path 对应数据库 hpath 字段,即人类可读路径,如/foo/bar);markdown:GFM(GitHub Flavored Markdown)格式内容。
返回值 data 为创建好的文档 ID,如 "20210914223645-oj2vnx2"。如果使用同一个 path 重复调用该接口,不会覆盖已有文档,这一点对幂等性脚本非常友好。
3.2 重命名文档
按路径重命名:POST /api/filetree/renameDoc,参数:
{ "notebook": "20210831090520-7dvbdv0", "path": "/20210902210113-0avi12f.sy", "title": "文档新标题" }
按 ID 重命名:POST /api/filetree/renameDocByID,参数:
{ "id": "20210902210113-0avi12f", "title": "文档新标题" }
注意按路径重命名时,path 是存储路径(含 .sy 后缀);而 renameDocByID 的 id 是去掉 .sy 的文档 ID。
3.3 删除文档
- 按路径删除:
POST /api/filetree/removeDoc,参数{"notebook": "...", "path": "/20210902210113-0avi12f.sy"}; - 按 ID 删除:
POST /api/filetree/removeDocByID,参数{"id": "20210902210113-0avi12f"}。
3.4 移动文档
- 按路径移动:
POST /api/filetree/moveDocs,参数:
{
"fromPaths": ["/20210917220056-yxtyl7i.sy"],
"toNotebook": "20210817205410-2kvfpfn",
"toPath": "/"
}
fromPaths 为源路径数组;toNotebook 为目标笔记本 ID;toPath 为目标路径(/ 表示笔记本根)。
- 按 ID 移动:
POST /api/filetree/moveDocsByID,参数:
{ "fromIDs": ["20210917220056-yxtyl7i"], "toID": "20210817205410-2kvfpfn" }
fromIDs 为源文档 ID 数组;toID 为目标父文档 ID 或笔记本 ID。
3.5 路径转换四件套
这一组接口用于在"存储路径 / 人类可读路径 / ID"之间互相转换,是编写文档遍历与迁移脚本的核心工具。
| 接口 | 用途 | 关键参数 | 返回 |
|---|---|---|---|
POST /api/filetree/getHPathByPath |
根据存储路径获取人类可读路径 | notebook、path(如 /20210917220500-sz588nq/20210917220056-yxtyl7i.sy) |
data 为 /foo/bar |
POST /api/filetree/getHPathByID |
根据块 ID 获取人类可读路径 | id |
data 为 /foo/bar |
POST /api/filetree/getPathByID |
根据块 ID 获取存储路径 | id |
data 含 notebook 与 path(如 /20200812220555-lj3enxa/20210808180320-fqgskfj.sy) |
POST /api/filetree/getIDsByHPath |
根据人类可读路径获取 IDs | path、notebook |
data 为 ID 数组 |
从源码结构看,这些接口均注册于 kernel/api/router.go 的 filetree 路由组,配合 kernel/api/filetree.go 中的实现使用。
四、资源文件(Asset)上传
POST /api/asset/upload,参数为 HTTP Multipart 表单:
-
assetsDirPath:资源文件存放的文件夹路径,以data文件夹作为根路径:"/assets/":工作空间data/assets/文件夹;"/assets/sub/":工作空间data/assets/sub/文件夹。
常规情况下建议使用第一种,统一存放到工作空间资源文件夹下;放入子目录会带来一些副作用(如资源引用路径解析问题),具体可参考用户指南中的资源文件章节。
-
file[]:上传的文件列表。
返回值:
{
"code": 0,
"msg": "",
"data": {
"errFiles": [""],
"succMap": {
"foo.png": "assets/foo-20210719092549-9j5y79r.png"
}
}
}
errFiles:处理时遇到错误的文件名列表;succMap:处理成功的文件映射,key 为上传时的文件名,value 为assets/foo-id.png。上传后的文件名带时间戳与随机后缀以避免重名冲突。实际开发中常将已有 Markdown 内容中的资源文件链接地址替换为上传后的地址,即用succMap完成链接重写。
上传接口在 kernel/api/router.go 中对应 model.Upload 处理器。
五、块(Block)操作:内容自动化的核心
思源笔记是"块级"笔记应用,文档由内容块(段落、标题、列表、引用块等)构成,每个块有全局唯一的 ID(14 位时间戳 + - + 7 位随机字符,如 20211229114650-vrek5x6)。块的增删改查接口是内容自动化的核心。
5.1 插入块
POST /api/block/insertBlock,参数:
{
"dataType": "markdown",
"data": "foo**bar**{: style=\"color: var(--b3-font-color8);\"}baz",
"nextID": "",
"previousID": "20211229114650-vrek5x6",
"parentID": ""
}
dataType:待插入数据类型,可选markdown或dom;data:待插入的数据(markdown 或 DOM 字符串);nextID:后一个块的 ID,用于锚定插入位置;previousID:前一个块的 ID,用于锚定插入位置;parentID:父块 ID,用于锚定插入位置。
nextID、previousID、parentID 三个参数必须至少存在一个有值,优先级为 nextID > previousID > parentID。也就是说,当同时传入多个锚点时,nextID 优先生效。
返回值 data 为操作数组,其中 action.data 是新插入块生成的 DOM,action.id 是新插入块的 ID。例如:
{
"code": 0,
"msg": "",
"data": [
{
"doOperations": [
{
"action": "insert",
"data": "<div data-node-id=\"20211230115020-g02dfx0\" data-node-index=\"1\" data-type=\"NodeParagraph\" class=\"p\"><div contenteditable=\"true\" spellcheck=\"false\">foo<strong style=\"color: var(--b3-font-color8);\">bar</strong>baz</div><div class=\"protyle-attr\" contenteditable=\"false\"></div></div>",
"id": "20211230115020-g02dfx0",
"parentID": "",
"previousID": "20211229114650-vrek5x6",
"retData": null
}
],
"undoOperations": null
}
]
}
从返回结构可以看到,思源的内容操作采用事务操作(Operations)模型,doOperations 描述将执行的操作,undoOperations 描述对应的撤销操作——这与前端编辑器的撤销/重做机制(kernel/model/transaction.go 中实现的 performTransactions 体系)完全同构,也是思源支持细粒度撤销的基础。
5.2 插入前置子块 / 后置子块
POST /api/block/prependBlock:在parentID指定的父块开头插入子块;POST /api/block/appendBlock:在parentID指定的父块末尾追加子块。
两者参数相同:
{
"data": "foo**bar**{: style=\"color: var(--b3-font-color8);\"}baz",
"dataType": "markdown",
"parentID": "20220107173950-7f9m1nb"
}
返回结构与 insertBlock 相同,action.id 为新插入块的 ID。对比 prependBlock 与 appendBlock 的返回可以观察到,前置插入的 previousID 为空,而后置插入的 previousID 为父块内最后一个子块的 ID。
5.3 更新块
POST /api/block/updateBlock,参数:
{
"dataType": "markdown",
"data": "foobarbaz",
"id": "20211230161520-querkps"
}
id 为待更新块的 ID。返回 action 为 update,action.data 为更新块生成的 DOM。这是修改既有内容块的推荐方式,比"删除 + 插入"更安全(不会改变块的 ID,保留引用关系)。
5.4 删除块
POST /api/block/deleteBlock,参数 {"id": "20211230161520-querkps"},id 为待删除块的 ID。返回 action 为 delete。删除文档内的块会同时清理相关引用与索引。
5.5 移动块
POST /api/block/moveBlock,参数:
{
"id": "20230406180530-3o1rqkc",
"previousID": "20230406152734-if5kyx6",
"parentID": "20230404183855-woe52ko"
}
id:待移动块的 ID;previousID:前一个块的 ID,用于锚定插入位置;parentID:父块的 ID,用于锚定插入位置。
previousID 和 parentID 不能同时为空,同时存在时优先使用 previousID。返回 action 为 move,包含 parentID、previousID、nextID 等定位信息。
5.6 折叠与展开
POST /api/block/foldBlock,参数{"id": "20231224160424-2f5680o"},折叠指定块;POST /api/block/unfoldBlock,参数同上,展开指定块。
两者返回 data: null,可用于自动折叠/展开标题下方内容块。
5.7 获取块 kramdown 源码
POST /api/block/getBlockKramdown,参数 {"id": "20201225220955-l154bn4"}。返回 data 包含 id 与 kramdown(该块及子块的 kramdown 标记源码):
{
"code": 0,
"msg": "",
"data": {
"id": "20201225220955-l154bn4",
"kramdown": "* {: id=\"20201225220955-2nn1mns\"}新建笔记本,在笔记本下新建文档\n {: id=\"20210131155408-3t627wc\"}\n* {: id=\"20201225220955-uwhqnug\"}在编辑器中输入 <kbd>/</kbd> 触发功能菜单\n {: id=\"20210131155408-btnfw88\"}"
}
}
kramdown 是思源内部使用的标记语法(行内属性 {: id="..."} 标注块 ID),它比标准 Markdown 保留了完整的块结构信息,是实现内容备份与迁移的底层格式。
5.8 获取子块
POST /api/block/getChildBlocks,参数 {"id": "20230506212712-vt9ajwj"},id 为父块 ID。标题下方块也算作子块。返回 data 为子块数组,每项含 id、type(如 h 标题、s 超级块、l 列表)与 subType(如 h1、u 无序列表)。遍历文档树通常从文档块出发,递归调用该接口。
5.9 转移块引用
POST /api/block/transferBlockRef,参数:
{
"fromID": "20230612160235-mv6rrh1",
"toID": "20230613093045-uwcomng",
"refIDs": ["20230613092230-cpyimmd"]
}
fromID:定义块 ID(引用原指向的块);toID:目标块 ID;refIDs:指向fromID的引用所在块 ID 列表,可选。如果不指定,所有指向fromID的块引用 ID 都会被转移。
该接口适合在块被移动或合并后批量重定向引用关系,避免引用失效。
六、属性(Attribute)操作
块属性是附加在块上的键值对,广泛用于插件、模板和数据库(属性视图)的实现中。
6.1 设置块属性
POST /api/attr/setBlockAttrs,参数:
{
"id": "20210912214605-uhi5gco",
"attrs": {
"custom-attr1": "line1\nline2"
}
}
id:块 ID;attrs:块属性对象,自定义属性必须以custom-作为前缀(这是思源对自定义属性命名空间的约定,避免与系统属性冲突)。
6.2 获取块属性
POST /api/attr/getBlockAttrs,参数 {"id": "20210912214605-uhi5gco"}。返回:
{
"code": 0,
"msg": "",
"data": {
"custom-attr1": "line1\nline2",
"id": "20210912214605-uhi5gco",
"title": "PDF 标注双链演示",
"type": "doc",
"updated": "20210916120715"
}
}
返回的 data 除自定义属性外,还包含系统内置属性:id(块 ID)、title(文档标题)、type(块类型,doc 表示文档块)、updated(更新时间)。借助这一接口可以读取块上的元数据,进而实现基于属性的自动化筛选与路由。
七、SQL 查询与事务提交
思源内核内置 SQLite 数据库索引,所有块、属性、资源等信息均可通过 SQL 查询,这是构建高级自动化(如统计、报表、批量筛选)的利器。
7.1 执行 SQL 查询
POST /api/query/sql,参数:
{
"stmt": "SELECT * FROM blocks WHERE content LIKE '%content%' LIMIT 7"
}
stmt 为 SQL 脚本。返回 data 为行对象数组({"列": "值"} 形式)。常见的可查询表包括 blocks(块)、attributes(块属性)、assets(资源)、refs(引用)、tags(标签)等。
从 kernel/api/sql.go 的实现可以看到,stmt 还支持可选的 mode 参数:
mode为空(默认):允许单条语句,通过sql.CheckSingleStatement校验;mode: "readonly":只读模式,额外通过sql.CheckReadonlyStatement校验,禁止写语句;mode: "multiple":多语句模式,不做语句校验。
注意:为保证数据安全,发布模式下禁止访问该接口(路由 kernel/api/router.go 中 /api/query/sql 挂了 model.CheckAdminRole,发布场景不满足管理员上下文即被拒绝)。这一点在编写面向发布站点的脚本时务必留意。
7.2 提交事务
POST /api/sqlite/flushTransaction,不带参。该接口强制刷新内核的写事务队列,将内存中待写入 SQLite 索引的数据落库。返回 data: null。从源码看,kernel/api/sql.go 中该接口同时调用了 model.FlushTxQueue() 与 sql.FlushQueue(),用于在外部需要及时读一致数据(如备份前)时手动触发冲刷。
八、模板渲染
8.1 渲染模板
POST /api/template/render,参数:
{
"id": "20220724223548-j6g0o87",
"path": "F:\\SiYuan\\data\\templates\\foo.md"
}
id:调用渲染所在的文档 ID(提供模板渲染的上下文);path:模板文件的绝对路径。
返回 data 包含 content(渲染后的块 DOM)与 path(模板路径)。模板内可包含思源的模板函数与 Sprig 函数(见下)。
8.2 渲染 Sprig
POST /api/template/renderSprig,参数:
{
"template": "/daily note/{{now | date \"2006/01\"}}/{{now | date \"2006-01-02\"}}"
}
template 为模板内容。返回 data 为渲染结果,例如:
{ "code": 0, "msg": "", "data": "/daily note/2023/03/2023-03-24" }
Sprig 是 Go 模板的函数库,思源内核集成了它用于生成动态路径与内容(笔记本配置中的 dailyNoteSavePath 同样使用该语法)。渲染结果可直接用于构建日记路径等动态路径。
九、文件系统访问
以下接口直接操作工作空间下的文件,路径均以工作空间为根(如 /data/...、/conf/...、/temp/...)。注意:所有文件操作都被限制在工作空间目录内,防止越权读写。
9.1 获取文件
POST /api/file/getFile,参数 {"path": "/data/20210808180117-6v0mkxr/20200923234011-ieuun1p.sy"}。
返回值不采用统一 JSON 包装:
- 响应状态码
200:文件内容; - 响应状态码
202:异常信息,body 为 JSON:
{ "code": 404, "msg": "", "data": null }
其中 code 为非零异常值,含义如下:
| code | 含义 |
|---|---|
-1 |
参数解析错误 |
403 |
无访问权限(文件不在工作空间下) |
404 |
未找到(文件不存在) |
405 |
方法不被允许(这是一个目录) |
500 |
服务器错误(文件查询失败 / 文件读取失败) |
msg 为一段描述错误的文本。
9.2 写入文件
POST /api/file/putFile,参数为 HTTP Multipart 表单:
path:工作空间路径下的文件路径;isDir:是否为创建文件夹,为true时仅创建文件夹,忽略file;modTime:最近访问和修改时间,Unix time;file:上传的文件。
返回 data: null。该接口可用于写入配置、临时文件或数据文件。
9.3 删除文件
POST /api/file/removeFile,参数 {"path": "/data/20210808180117-6v0mkxr/20200923234011-ieuun1p.sy"}。
9.4 重命名文件
POST /api/file/renameFile,参数:
{
"path": "/data/assets/image-20230523085812-k3o9t32.png",
"newPath": "/data/assets/test-20230523085812-k3o9t32.png"
}
9.5 列出文件
POST /api/file/readDir,参数 {"path": "/data/20210808180117-6v0mkxr/20200923234011-ieuun1p"}(文件夹路径)。返回 data 为条目数组:
{
"code": 0,
"msg": "",
"data": [
{ "isDir": true, "isSymlink": false, "name": "20210808180303-6yi0dv5", "updated": 1691467624 },
{ "isDir": false, "isSymlink": false, "name": "20210808180303-6yi0dv5.sy", "updated": 1663298365 }
]
}
每项含 isDir(是否目录)、isSymlink(是否符号链接)、name(名称)、updated(Unix 时间戳)。
十、导出
10.1 导出 Markdown 文本
POST /api/export/exportMdContent,参数 {"id": ""},id 为要导出的文档块 ID。返回:
{
"code": 0,
"msg": "",
"data": {
"hPath": "/0 请从这里开始",
"content": "## 🍫 内容块\n\n在思源中,唯一重要的核心概念是..."
}
}
hPath:人类可读的路径;content:Markdown 内容。
这是获取文档纯 Markdown 文本的最直接方式,适合内容备份与迁移。
10.2 导出文件与目录
POST /api/export/exportResources,参数:
{
"paths": [
"/conf/appearance/boot",
"/conf/appearance/langs",
"/conf/appearance/emojis/conf.json",
"/conf/appearance/icons/index.html"
],
"name": "zip-file-name"
}
paths:要导出的文件或文件夹路径列表,相同名称的文件/文件夹会被覆盖(即合并导出时后导出的同名项覆盖先导出的);name:(可选)导出的文件名,未设置时默认为export-YYYY-MM-DD_hh-mm-ss.zip。
返回:
{
"code": 0,
"msg": "",
"data": { "path": "temp/export/zip-file-name.zip" }
}
path 为创建的 *.zip 文件路径,ZIP 内的目录结构以 name 为根,保持 paths 中各路径的最后一级名称(如 /conf/appearance/boot 导出为 zip-file-name/boot,conf.json 导出为 zip-file-name/conf.json)。该接口常用于导出主题、语言包、图标等外观资源。
十一、格式转换:Pandoc
POST /api/convert/pandoc,用于在工作空间内调用内置 Pandoc 进行文档格式转换。工作目录约定:
- 执行调用 pandoc 命令时工作目录会被设置在
工作空间/temp/convert/pandoc/${test}下(test为请求中的dir参数); - 可先通过 API
写入文件将待转换文件写入该目录; - 再调用本接口进行转换,转换后的文件也会被写入该目录;
- 最后调用 API
获取文件获取转换后的文件内容;或者调用 API通过 Markdown 创建文档将转换结果写入文档;或者调用内部 APIimportStdMd将转换后的文件夹直接导入。
参数:
{
"dir": "test",
"args": [
"--to", "markdown_strict-raw_html",
"foo.epub",
"-o", "foo.md"
]
}
args 为 Pandoc 命令行参数数组。返回:
{
"code": 0,
"msg": "",
"data": { "path": "/temp/convert/pandoc/test" }
}
path 为工作空间下的转换目录路径。示例中的参数将 foo.epub 转换为 foo.md,且禁用原始 HTML 透传(markdown_strict-raw_html)。内核内置的 Pandoc 二进制位于 app/pandoc 目录(含 darwin / linux / windows 各平台的压缩包)。
十二、通知推送
12.1 推送消息
POST /api/notification/pushMsg,参数:
{ "msg": "test", "timeout": 7000 }
msg:消息内容;timeout:消息持续显示时间(毫秒),可以不传入,默认为 7000 毫秒。
返回 data.id 为消息 ID(如 "62jtmqi")。推送后消息会出现在思源界面的右下角通知区域。
12.2 推送报错消息
POST /api/notification/pushErrMsg,参数与 pushMsg 相同,仅展示样式为错误类型。返回 data.id 为消息 ID。
十三、网络代理
POST /api/network/forwardProxy,让内核作为正向代理转发 HTTP 请求,可用于绕过浏览器跨域限制或在插件中代理外部 API。参数:
{
"url": "https://b3log.org/siyuan/",
"method": "GET",
"timeout": 7000,
"contentType": "text/html",
"headers": [ { "Cookie": "" } ],
"payload": {},
"payloadEncoding": "text",
"responseEncoding": "text"
}
参数说明:
url:转发的 URL;method:HTTP 方法,默认为GET;timeout:超时时间(毫秒),默认为7000;contentType:HTTP Content-Type,默认为application/json;headers:HTTP 请求标头数组;payload:HTTP 请求体,可以是对象或字符串;payloadEncoding:payload所使用的编码方案,默认为text,可选值:text、base64/base64-std、base64-url、base32/base32-std、base32-hex、hex;responseEncoding:响应数据中body字段所使用的编码方案,默认为text,可选值同上。
返回值:
{
"code": 0,
"msg": "",
"data": {
"body": "",
"bodyEncoding": "text",
"contentType": "text/html",
"elapsed": 1976,
"headers": {},
"status": 200,
"url": "https://b3log.org/siyuan"
}
}
bodyEncoding:body所使用的编码方案,与请求中responseEncoding一致;elapsed:请求耗时(毫秒);status:HTTP 状态码。
当需要传输二进制内容时,可将 payload 或响应体编码为 base64 等编码方案以避免 JSON 序列化问题。
十四、系统状态查询
以下接口均无需鉴权(见 kernel/api/router.go),常用于启动检测与运维监控。
14.1 获取启动进度
POST /api/system/bootProgress(也支持 GET),不带参。返回:
{
"code": 0,
"msg": "",
"data": { "details": "Finishing boot...", "progress": 100 }
}
progress 为启动进度百分比,details 为当前启动阶段描述。内核启动完成后 progress 为 100。启动进度还支持 SSE 推送(/api/system/bootProgressSSE),便于前端实时展示。
14.2 获取系统版本
POST /api/system/version(也支持 GET),不带参。返回 data 为版本号字符串(如 "1.3.5")。注意:这是内核版本号,与桌面端/移动端版本号可能不同。
14.3 获取系统当前时间
POST /api/system/currentTime,不带参。返回 data 为毫秒精度的时间戳:
{ "code": 0, "msg": "", "data": 1631850968131 }
十五、数据库(属性视图)操作
数据库是思源笔记的结构化数据能力,内核中称为"属性视图"(Attribute View)。它以**字段(列)和条目(行)**的形式存储结构化数据:每个数据库由 avID 标识,可通过一个或多个数据库块(blockID)嵌入到文档中;一个数据库可包含多个不同布局类型的视图(viewID):table(表格)、gallery(卡片)和 kanban(看板)。内核中的相关实现可参见 kernel/av 目录(av.go、layout_table.go、layout_gallery.go、layout_kanban.go 等)与 kernel/api/av.go 的接口层。
15.1 字段类型(keyType)
| 取值 | 说明 |
|---|---|
block |
主键(绑定的块) |
text |
文本 |
number |
数字 |
date |
日期 |
select |
单选 |
mSelect |
多选 |
url |
URL |
email |
邮箱 |
phone |
电话 |
mAsset |
资源 |
template |
模板 |
created |
创建时间 |
updated |
更新时间 |
checkbox |
复选框 |
relation |
关联 |
rollup |
汇总 |
lineNumber |
行号 |
其中 block 类型是主键字段(绑定到内容块),relation / rollup 用于跨数据库关联与汇总,created / updated 为系统自动维护的时间字段。
15.2 渲染(Render)
POST /api/av/renderAttributeView,参数:
{
"id": "20240118120204-kwyzf77",
"blockID": "20240118120201-kldj15t",
"viewID": "",
"page": 1,
"pageSize": 50,
"query": "",
"groupPaging": {},
"createIfNotExist": true
}
id:数据库 ID;blockID:嵌入该数据库的数据库块,用于解析当前视图和发布权限,渲染独立数据库时可省略;viewID:要渲染的视图,省略时使用当前视图(viewID字段);page:页码,从 1 开始,默认1;pageSize:每页条目数,-1或省略表示使用视图默认值(50);query:可选的主键值全文过滤关键字;groupPaging:分组(看板)视图的可选分页配置;createIfNotExist:为true(默认)时,若数据库不存在视图则创建默认视图。
返回值结构(以表格布局为例,展示一行):
{
"code": 0,
"msg": "",
"data": {
"name": "API 测试",
"id": "20240118120204-kwyzf77",
"viewType": "table",
"viewID": "20240118120204-7rnmyc1",
"isMirror": false,
"views": [
{ "id": "20240118120204-7rnmyc1", "icon": "", "name": "表格", "desc": "", "hideAttrViewName": false, "type": "table", "pageSize": 50 }
],
"view": {
"id": "20240118120204-7rnmyc1",
"icon": "", "name": "表格", "desc": "", "hideAttrViewName": false,
"filters": [], "sorts": [], "group": null,
"pageSize": 50, "showIcon": true, "wrapField": false, "groupFolded": false, "groupHidden": 0,
"columns": [
{ "id": "20240118120204-w6cggab", "name": "主键", "type": "block", "icon": "", "wrap": false, "hidden": false, "desc": "", "calc": null, "numberFormat": "", "template": "", "pin": false, "width": "" }
],
"rows": [
{
"id": "20240118203831-fkfvvtx",
"cells": [
{
"id": "20240118203911-xrg9obl",
"value": {
"id": "20240118203911-xrg9obl", "keyID": "20240118120204-w6cggab", "blockID": "20240118203831-fkfvvtx",
"type": "block", "createdAt": 1706843791000, "updatedAt": 1706843791000,
"block": { "id": "20240118203831-fkfvvtx", "content": "3", "created": 1706843791000, "updated": 1706843791000 }
},
"valueType": "block", "color": "", "bgColor": ""
}
]
}
],
"rowCount": 5
}
}
}
关键返回字段:
data.view:渲染后的视图实例,结构随viewType而变——table返回columns/rows/rowCount,gallery返回columns/rows,kanban返回columns/groups(每个分组本身也是视图实例,含groupKey/groupValue)。view还包含filters/sorts/group/showIcon/wrapField/groupFolded/groupHidden。注意:启用的过滤/分组可能使rows为空,即使rowCount> 0;data.view.columns[]:每列含id/name/type/icon/wrap/hidden/desc/calc/numberFormat/template/pin/width;select/mSelect列还额外包含options;data.view.rows[].id:行 ID(条目 ID)。对于绑定行,它等于绑定的块 ID;对于独立行,它是生成的条目 ID,与任何块都不同;data.view.rows[].cells[].value:一个Value对象(所有 value 形态见 15.6 节)。createdAt/updatedAt为 int64 毫秒时间戳;data.views:所有视图的元数据(不含行数据);data.isMirror:当数据库块为数据库的镜像(只读副本)时为true。
15.3 获取数据库定义(Get)
POST /api/av/getAttributeView,参数 {"id": "20240118120204-kwyzf77"}。返回原始定义(不含渲染后的行或分页):
{
"code": 0,
"msg": "",
"data": {
"av": {
"spec": 4,
"id": "20240118120204-kwyzf77",
"name": "API 测试",
"keyValues": [ { "key": { "id": "...", "name": "主键", "type": "block", "icon": "", "desc": "", "numberFormat": "", "template": "" }, "values": [ ... ] } ],
"keyIDs": null,
"viewID": "20240118120204-7rnmyc1",
"views": [
{
"id": "20240118120204-7rnmyc1", "icon": "", "name": "表格", "hideAttrViewName": false, "desc": "", "pageSize": 50, "type": "table",
"table": { "spec": 0, "id": "20240118120204-grokgmm", "showIcon": true, "wrapField": false, "columns": [...], "rowIds": null },
"itemIds": ["20240118203818-ct041hj", "20240118203855-sqzbja0", "20240118203831-fkfvvtx", "20240118203842-kc31ovy", "20240531235026-uiap07y"],
"groupCreated": 0, "groupItemIds": null, "groupFolded": false, "groupHidden": 0, "groupSort": 0
}
]
}
}
}
data.av:完整的AttributeView定义——字段(keyValues)、字段顺序(keyIDs,可能为null)、当前视图(viewID)、以及所有视图的原始布局配置(table/gallery/kanban)与条目顺序(itemIds)。需要计算后的行数据请使用"渲染"接口。
15.4 获取主键值
POST /api/av/getAttributeViewPrimaryKeyValues,参数:
{ "id": "20240118120204-kwyzf77", "keyword": "", "page": 1, "pageSize": 16 }
id:数据库 ID;keyword:可选的主键文本子串过滤(不区分大小写);page:页码,从 1 开始,默认1;pageSize:每页条目数,-1或省略表示16,结果按block.updated倒序排序。
返回 data.rows 为包含主键(block)字段及其分页后值的 KeyValues 对象,data.blockIDs 为引用该数据库的所有数据库块(镜像)ID。
15.5 搜索数据库
POST /api/av/searchAttributeView,参数:
{ "keyword": "API", "excludes": [] }
keyword:搜索关键字(匹配数据库名称);excludes:可选,需从结果中排除的数据库 ID 列表。
返回 data.results[],每个顶层结果按 avID 聚合一个数据库;其 children[] 列出该数据库的各个视图(viewName/viewID/viewLayout),并附带 hPath(数据库所在文档的人类可读路径)。适合用于跨工作空间定位"哪个文档里用了哪个数据库"。
15.6 设置单元格值(核心写入接口)
这是单元格值(某一行的某个字段)的主要写入接口。请求中的 value 是一个部分 Value 对象,其结构取决于字段的 keyType。常见 value 结构如下:
keyType |
value 结构 |
|---|---|
block |
{"block": {"content": "第一行", "id": "<绑定块ID>"}, "isDetached": false} |
text |
{"text": {"content": "文本"}} |
number |
{"number": {"content": 42, "isNotEmpty": true}}(清空用 {"isNotEmpty": false}) |
date |
{"date": {"content": 1676042451000, "isNotEmpty": true}}(毫秒时间戳) |
select |
{"mSelect": [{"content": "已完成", "color": "1"}]}(至多一个选项) |
mSelect |
{"mSelect": [{"content": "A", "color": "1"}, {"content": "B", "color": "2"}]} |
url |
{"url": {"content": "https://siyuan.com"}} |
email |
{"email": {"content": "a@b.com"}} |
phone |
{"phone": {"content": "1234567890"}} |
checkbox |
{"checkbox": {"checked": true}} |
⚠️
itemID是行 ID(渲染接口返回的rows[].id)。对于绑定行,行 ID 等于绑定的块 ID;对于独立行,它是生成的条目 ID。传入错误的 ID 会把值存为孤儿数据,不会出现在渲染后的单元格中。
接口定义:POST /api/av/setAttributeViewBlockAttr,参数:
{
"avID": "20240118120204-kwyzf77",
"keyID": "20240531232156-ahsyx8l",
"itemID": "20240118203831-fkfvvtx",
"value": { "type": "number", "number": { "content": 42, "isNotEmpty": true } }
}
avID:数据库 ID;keyID:字段 ID(被更新的列);itemID:行 ID。旧参数rowID已弃用,将于 2026-12-01 后删除,请改用itemID(源码 kernel/api/av.go 中兼容读取两个字段,读到rowID时会输出弃用日志);value:部分Value对象(见上表),未知或不支持的键会被忽略。
返回值(数字值示例):
{
"code": 0,
"msg": "",
"data": {
"value": {
"id": "20240531235048-4zisj1p",
"keyID": "20240531232156-ahsyx8l",
"blockID": "20240118203831-fkfvvtx",
"type": "number",
"createdAt": 1717170648596,
"updatedAt": 1781610266432,
"number": { "content": 42, "isNotEmpty": true, "format": "", "formattedContent": "42" }
}
}
}
data.value 为更新后规范化完成的值(含 number.formattedContent 等计算字段)。请使用该返回值刷新 UI,无需重新发送请求体。
15.7 添加条目(行)
POST /api/av/addAttributeViewBlocks,可一次添加一个或多个条目。每个来源既可绑定已有块(isDetached: false),也可创建仅存在于视图内的独立行(isDetached: true)。参数:
{
"avID": "20240118120204-kwyzf77",
"blockID": "20240118120201-kldj15t",
"viewID": "",
"groupID": "",
"previousID": "",
"srcs": [
{ "id": "20240118120201-kldj15t", "isDetached": false, "content": "新行" }
],
"ignoreDefaultFill": false
}
avID:数据库 ID;blockID:拥有该数据库的数据库块(用于解析目标视图/分组);viewID:目标视图,省略时使用当前视图;groupID:看板视图的目标分组 ID,表格/卡片视图可省略;previousID:在此条目 ID 之后插入,为空表示追加到末尾;srcs[].id:绑定块时(isDetached: false)为要绑定的块 ID,需符合节点 ID 格式;srcs[].isDetached:true创建独立行,false绑定已有块;srcs[].content:主键的显示文本(isDetached: true时使用,或覆盖绑定块的内容);srcs[].itemID:可选,显式指定条目 ID,省略时自动生成;ignoreDefaultFill:为true时,跳过向过滤/分组字段自动填充默认值。
该接口返回 data: null;成功后请调用"渲染"接口获取更新后的行(含更新单元格所需的新行 ID)。
15.8 移除条目(行)
POST /api/av/removeAttributeViewBlocks,参数:
{ "avID": "20240118120204-kwyzf77", "srcIDs": ["20240118203831-fkfvvtx"] }
avID:数据库 ID;srcIDs:要移除的行 ID(渲染接口返回的rows[].id)列表。
独立行会被删除;绑定块会解绑(不会删除底层文档块)。
15.9 切换布局
POST /api/av/changeAttrViewLayout,参数:
{ "avID": "20240118120204-kwyzf77", "blockID": "20240118120201-kldj15t", "layoutType": "kanban" }
layoutType 为 table、gallery、kanban 之一。成功时服务端会重新渲染并返回视图(结构与"渲染"接口相同)。当切换到 kanban 且已配置分组时,data.view 携带 groups[] 数组;每个分组是视图实例,含 groupKey、groupValue,以及看板特有字段(coverFrom、cardAspectRatio、cardSize、fitImage、displayFieldName、fillColBackgroundColor、fields)。
15.10 设置分组
POST /api/av/setAttrViewGroup,参数:
{
"avID": "20240118120204-kwyzf77",
"blockID": "20240118120201-kldj15t",
"group": {
"field": "20240118203822-io6ofxb",
"method": 0,
"order": 0,
"hideEmpty": false
}
}
group.field:用于分组的字段(列)ID,为空字符串表示移除分组;group.method:分组方式——0按值、1按数字范围、2按相对日期、3按天、4按周、5按月、6按年;group.range:可选。method为1(数字范围)时必填:{ "numStart": 0, "numEnd": 100, "numStep": 10 };group.order:分组排序——0升序、1降序、2手动、3按选项顺序;group.hideEmpty:是否隐藏空分组。
成功时服务端会重新渲染并返回视图。
15.11 获取过滤与排序
POST /api/av/getAttributeViewFilterSort,参数:
{ "id": "20240118120204-kwyzf77", "blockID": "20240118120201-kldj15t" }
未配置时返回:
{ "code": 0, "msg": "", "data": { "filters": [], "sorts": [] } }
配置后形如:
{
"code": 0,
"msg": "",
"data": {
"filters": [
{ "column": "20240118203822-io6ofxb", "operator": "=", "value": { "type": "select", "mSelect": [ { "content": "已完成", "color": "1" } ] } }
],
"sorts": [ { "column": "20240118120204-w6cggab", "order": "DESC" } ]
}
}
结构说明:
data.filters:ViewFilter数组。顶层为单个根组节点{ "combination": "and"|"or", "filters": [...] },数组元素既可以是叶子过滤条件,也可以是嵌套的分组节点,支持递归的且/或组合;data.filters[].column:过滤规则作用的字段(列)ID(仅叶子节点);data.filters[].operator:过滤操作符(见下方操作符表,仅叶子节点);data.filters[].value:过滤值,一个Value对象(结构见 15.6 节,仅叶子节点);data.filters[].relativeDate:可选,日期过滤使用的相对时间描述({ "count": 7, "unit": 0, "direction": -1 };unit:0天、1周、2月、3年;direction:-1前、0当前、1后;仅叶子节点);data.filters[].combination:分组组合方式"and"或"or"(仅分组节点);data.filters[].filters:子过滤节点,递归的ViewFilter(仅分组节点);data.sorts:ViewSort数组;data.sorts[].column:排序规则作用的字段(列)ID;data.sorts[].order:ASC或DESC。
过滤操作符一览:
| 取值 | 说明 |
|---|---|
= |
等于 |
!= |
不等于 |
> |
大于 |
>= |
大于等于 |
< |
小于 |
<= |
小于等于 |
Contains |
包含 |
Does not contains |
不包含 |
Is empty |
为空 |
Is not empty |
不为空 |
Starts with |
以...开头 |
Ends with |
以...结尾 |
Is between |
介于之间 |
Is true |
为真(复选框) |
Is false |
为假(复选框) |
15.12 设置过滤
POST /api/av/setAttrViewFilters,参数:
{
"avID": "20240118120204-kwyzf77",
"blockID": "20240118120201-kldj15t",
"data": [
{ "column": "20240118203822-io6ofxb", "operator": "=", "value": { "type": "select", "mSelect": [ { "content": "已完成", "color": "1" } ] } }
]
}
data 为完整的 ViewFilter 新数组,会整体替换视图现有过滤规则(结构见 15.11 节),传 [] 可清空全部过滤规则。返回 data: null。
15.13 设置排序
POST /api/av/setAttrViewSorts,参数:
{
"avID": "20240118120204-kwyzf77",
"blockID": "20240118120201-kldj15t",
"data": [ { "column": "20240118120204-w6cggab", "order": "DESC" } ]
}
data 为完整的 ViewSort 新数组,会整体替换视图现有排序规则,传 [] 可清空全部排序规则。返回 data: null。
15.14 添加字段(列)
POST /api/av/addAttributeViewKey,参数:
{
"avID": "20240118120204-kwyzf77",
"keyID": "20240118120204-7k9wzbp",
"keyName": "状态",
"keyType": "select",
"keyIcon": "",
"previousKeyID": "20240118120204-w6cggab"
}
avID:数据库 ID;keyID:新字段 ID,需为合法节点 ID(14 位时间戳 +-+ 7 位随机字母数字,如20240118120204-abc1234);keyName:字段显示名;keyType:字段类型——text、number、date、select、mSelect、url、email、phone、mAsset、template、created、updated、checkbox、relation、rollup、lineNumber之一。block(主键)不能通过该接口添加;keyIcon:可选字段图标(emoji 或空字符串);previousKeyID:在此字段 ID 之后插入新列,为空字符串时使用布局默认位置(表格插入到首位,卡片/看板插入到末尾)。
15.15 移除字段(列)
POST /api/av/removeAttributeViewKey,参数:
{ "avID": "20240118120204-kwyzf77", "keyID": "20240118120204-7k9wzbp", "removeRelationDest": false }
removeRelationDest:为true且字段为关联类型时,同时移除目标数据库中对应的反向关联字段,默认为false。
移除字段会同时删除该字段的所有值。若 keyID 不存在,返回 code: -1、msg: "key not found",脚本中应捕获该错误码。
15.16 字段排序:全局与视图内
POST /api/av/sortAttributeViewKey:全局重排字段——将keyID移动到字段顺序中previousKeyID之后的位置,影响所有视图。previousKeyID为空字符串表示移动到首位;POST /api/av/sortAttributeViewViewKey:在单个视图的布局内重排列(例如表格的列顺序),不改变全局字段顺序。参数多一个viewID(目标视图,为空时使用当前视图)。
两者参数结构:
{
"avID": "20240118120204-kwyzf77",
"viewID": "20240118120204-7rnmyc1",
"keyID": "20240118203822-io6ofxb",
"previousKeyID": "20240118120204-w6cggab"
}
十六、实战:串联各接口的自动化流程
基于以上接口,可以组合出一个典型的"内容导入 + 数据库录入"自动化流水线:
- 鉴权准备:读取"设置 - 关于"中的 API Token,构造带
Authorization: Token xxx标头的 HTTP 客户端; - 定位笔记本:调用
lsNotebooks获取笔记本 ID; - 创建文档:调用
createDocWithMd,传入 GFM Markdown 内容与人类可读路径/foo/bar,获得文档 ID; - 按需写入文件:如需附带附件,调用
putFile或asset/upload(upload返回succMap,可将 Markdown 中的资源链接重写为上传后的assets/foo-id.png路径); - 操作块:用
insertBlock/appendBlock在文档中追加内容块,用getChildBlocks+getBlockKramdown递归遍历文档结构; - 录入数据库:用
renderAttributeView获取数据库视图与行 ID,用addAttributeViewBlocks添加条目,用setAttributeViewBlockAttr按keyType写入单元格值,最后用setAttrViewFilters/setAttrViewSorts调整视图展示; - 导出备份:用
exportMdContent导出 Markdown 文本,或用exportResources打包外观/配置资源,必要时调用sqlite/flushTransaction先冲刷索引队列; - 监控与通知:用
system/version、system/currentTime做版本/时间校验,用notification/pushMsg把任务结果推送到界面。
在编写上述脚本时,请始终牢记以下要点:
- 所有写接口(创建、修改、删除、移动)在路由层都带有
CheckReadonly保护,只读模式(如util.ReadOnly为真时)会被拒绝; - 所有参数 ID 必须使用合法节点 ID 格式(14 位时间戳 +
-+ 7 位随机字符); - 数据库单元格写入务必使用渲染接口返回的行 ID(
itemID),避免产生孤儿数据; /api/query/sql在发布模式下不可用,且默认只允许单条语句,需要多语句时显式传mode: "multiple"。
关于完整的接口清单,可继续阅读本文档的英文版 docs/API.md 与日文版 docs/API.ja.md;内核启动与工作空间布局可参考 docs/WORKSPACE.zh-CN.md,数据文件格式可参考 docs/SY-FORMAT.zh-CN.md。通过内核 API,思源笔记不仅是编辑器,更是一个完全可编程的知识工作空间——这正是其"人类与 AI 智能体协作"定位的技术根基。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0631
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
video-shotcraftAI宣传片skill,使用 Remotion 制作电影级产品视频:提供106 张镜头配方卡和可复用的视频魔板。适用于 Claude Code 与 Codex以及所有其他智能体Markdown00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python09
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00