跳转至

HTTP API 参考

Koharu 在本地暴露 HTTP API:

http://127.0.0.1:<PORT>/api/v1

桌面 UI 与 headless Web UI 使用的就是这套 API。

运行时模型

当前实现中的重要行为:

  • API 与 GUI 或 headless 运行时由同一个进程提供
  • 服务器默认绑定到 127.0.0.1;使用 --host 可绑定到其他地址
  • API 与 MCP 服务器共享同一个已加载的项目、模型和管线状态
  • 没有提供 --port 时,Koharu 会选择一个随机本地端口
  • 在应用完成启动之前,除 /api/v1/downloads/api/v1/operations/api/v1/events 之外的所有路由都会返回 503 Service Unavailable

资源模型

API 是以项目为中心的。同一时间只会打开一个项目,它包含:

  • 一组 Pages,按 PageId 索引
  • 每个页面下的 Nodes(图像图层、掩码、文本块),通过 NodeId 引用
  • 一个内容寻址的 Blob 存储,按 Blake3 哈希保存原始图像字节
  • 由这些组件构建出的 Scene 快照,并通过 epoch 计数器递进
  • 一段 Op 修改历史,可以撤销与重做

所有修改都必须经过历史层(POST /history/apply),以保证场景、自动保存和事件订阅者都保持同步。

常见响应类型

高频返回结构包括:

  • MetaInfo:应用版本与 ML 设备
  • EngineCatalog:每个管线阶段可安装的引擎 id
  • ProjectSummary:id、名称、路径、页数、最近一次打开时间
  • SceneSnapshot{ epoch, scene }
  • LlmState:当前 LLM 加载状态(status、target、error)
  • LlmCatalog:按系列分组的本地 + 提供商模型
  • JobSummary{ id, kind, status, error }
  • DownloadProgress:包 id、字节数、状态

端点

元信息

方法 路径 用途
GET /meta 获取应用版本与当前 ML 后端
GET /engines 列出每个管线阶段已注册的引擎

字体

方法 路径 用途
GET /fonts 系统字体 + Google Fonts 的合并目录,用于渲染
GET /google-fonts 单独列出 Google Fonts 目录
POST /google-fonts/{family}/fetch 下载并缓存某个 Google Fonts 字体族
GET /google-fonts/{family}/{file} 提供已缓存的 TTF/WOFF 文件

项目

每个项目都位于受管理的 {data.path}/projects/ 目录下;客户端永远不需要传入文件系统路径。

方法 路径 用途
GET /projects 列出受管理的项目
POST /projects 创建新项目(请求体 { name }
POST /projects/import 把一个 .khr 归档解压到新目录并打开
PUT /projects/current 通过 id 打开一个受管理项目
DELETE /projects/current 关闭当前会话
POST /projects/current/export 导出当前项目;返回二进制字节

POST /projects/current/export 接受 { format, pages? },其中 formatkhrpsdrenderedinpainted 之一。当某种格式会产生多个文件时,响应类型是 application/zip

页面

方法 路径 用途
POST /pages 通过 multipart 上传 N 张图片创建页面
POST /pages/from-paths Tauri 专用的快速通道,按绝对路径导入
POST /pages/{id}/image-layers 从上传文件添加一个 Custom 图像节点
PUT /pages/{id}/masks/{role} 用原始 PNG 字节 upsert 一个掩码节点
GET /pages/{id}/thumbnail 获取页面缩略图(以 WebP 缓存)

rolesegmentbrushInpaintPOST /pages 接受可选字段 replace=true;导入时会按文件名自然顺序排序。

Scene 与 blobs

方法 路径 用途
GET /scene.json 完整的场景快照,供 web/UI 客户端使用
GET /scene.bin postcard 编码的 Snapshot { epoch, scene },供 Tauri 客户端使用
GET /blobs/{hash} 按 Blake3 哈希返回 blob 的原始字节

/scene.bin 会在 x-koharu-epoch 响应头里附带当前 epoch。

历史(修改)

所有场景修改都从这里走。每个响应都返回 { epoch }

方法 路径 用途
POST /history/apply 应用一个 Op(包括 Op::Batch
POST /history/undo 撤销上一次应用的 op
POST /history/redo 重新应用上一次撤销的 op

Op 是一个带判别字段的联合类型,覆盖添加/删除/更新节点、添加/删除页面、批量操作以及其他场景过渡。请求体是带 JSON tag 的变体。

管线

方法 路径 用途
POST /pipelines 以 operation 形式启动一次管线运行

请求体字段:

  • steps:按顺序执行的引擎 id(会与注册表校验)
  • pages:可选的 PageId 子集;省略时处理整个项目
  • region:可选的 inpainter 边界框(修复笔刷流程使用)
  • targetLanguagesystemPromptdefaultFont:每次运行可覆盖的可选参数

响应携带 operationId。进度与完成事件会通过 /eventsJobStartedJobProgressJobWarningJobFinished 推送。

Operations

/operations 是正在运行和最近完成的任务(管线 + 下载)的统一登记表。

方法 路径 用途
GET /operations 所有正在运行或最近的 operation 的快照
DELETE /operations/{id} 取消一次管线运行;对下载尽力而为地清理

Downloads

方法 路径 用途
GET /downloads 所有正在进行或最近的下载快照
POST /downloads 启动一次模型包下载({ modelId }

modelId 是通过 declare_hf_model_package! 声明的包 id(例如 "model:comic-text-detector:yolo-v5")。响应是 { operationId },其值复用包 id。

LLM 控制

已加载模型是位于 /llm/current 的单例资源。

方法 路径 用途
GET /llm/current 当前状态(status、target、error)
PUT /llm/current 加载指定的 target(local 或 provider)
DELETE /llm/current 卸载 / 释放当前模型
GET /llm/catalog 列出可用的本地模型 + 提供商支持的模型

PUT /llm/current 接受 LlmLoadRequest

  • provider target:{ kind: "provider", providerId, modelId }
  • local target:{ kind: "local", modelId }
  • 可选的 options { temperature, maxTokens, customSystemPrompt }

PUT /llm/current 在加载任务入队后立即返回 204。实际就绪状态会作为 LlmLoaded 事件发布到 /events

配置

方法 路径 用途
GET /config 读取当前 AppConfig
PATCH /config 应用 ConfigPatch;持久化并广播变更
PUT /config/providers/{id}/secret 保存(或覆盖)某个 provider 的 API key
DELETE /config/providers/{id}/secret 清除某个 provider 已保存的 API key

AppConfig 暴露顶层的 datahttppipelineproviders

  • data.path:本地数据目录,用于运行时、模型缓存与项目
  • http { connectTimeout, readTimeout, maxRetries }:下载与 provider 请求共用的 HTTP 客户端
  • pipeline { detector, fontDetector, segmenter, bubbleSegmenter, ocr, translator, inpainter, renderer }:每个阶段选用的引擎 id
  • providers[] { id, baseUrl?, apiKey? }:保存的 API key 在往返中始终以遮蔽占位符 "[REDACTED]" 出现,绝不返回原始密钥

内置 provider id:

  • openai
  • gemini
  • claude
  • deepseek
  • deepl
  • google-translate
  • caiyun
  • openai-compatible

API key 保存在平台凭据存储中,而不是 config.toml 里。PATCH apiKey: "" 会清除已保存的 key;PATCH "[REDACTED]" 表示保持原值不变。专门的 /config/providers/{id}/secret 路由是显式管理某个 provider 密钥的非 PATCH 方式。

事件流

Koharu 通过以下地址暴露 Server-Sent Events:

GET /events

行为:

  • 全新连接(不带 Last-Event-ID 请求头)会先收到一个 Snapshot 事件,包含当前的任务和下载登记表
  • 重连时,服务器会按顺序回放缓冲区中 seq > Last-Event-ID 的事件;如果请求的 id 已经从环形缓冲区中滚出,则会重新发送一个 Snapshot
  • 每个实时事件都会用其 seq 作为 SSE id: 字段
  • 维持 15 秒的 keep-alive

当前事件变体包括:

  • Snapshot:用于全新客户端与延迟恢复客户端的完整状态种子
  • JobStartedJobProgressJobWarningJobFinished:管线任务生命周期
  • DownloadProgress:包下载进度
  • ConfigChanged:通过 PATCH /config 或 secret 路由应用了配置变更
  • LlmLoadedLlmUnloaded:LLM 生命周期切换
  • SceneAdvanced:场景修改使 epoch 推进时触发

典型工作流

新建一个项目时常见的 API 调用顺序:

  1. POST /projects:创建项目
  2. POST /pages(或 Tauri 下的 /pages/from-paths):导入图片
  3. PUT /llm/current:加载翻译模型(本地或 provider)
  4. POST /pipelines:启动 detect → ocr → translate → inpaint → render
  5. 监听 GET /events 直到 JobFinished
  6. POST /projects/current/exportformat = "rendered""psd"

如果你需要更精细的控制,可以直接 POST /history/apply 携带显式 Op 负载,而不是运行整条管线。

如果你更想用面向 Agent 的接口,而不是手动编排 HTTP 端点,请参见 MCP 工具参考