File size: 13,089 Bytes
33ae6b5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
725264a
 
33ae6b5
725264a
 
 
 
 
 
 
 
 
 
 
 
 
33ae6b5
 
 
 
 
725264a
 
 
 
 
 
 
 
33ae6b5
 
 
725264a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33ae6b5
725264a
33ae6b5
725264a
 
 
 
 
 
 
33ae6b5
725264a
33ae6b5
725264a
33ae6b5
725264a
 
 
 
 
33ae6b5
725264a
33ae6b5
725264a
33ae6b5
725264a
33ae6b5
725264a
 
 
 
 
33ae6b5
725264a
33ae6b5
725264a
33ae6b5
725264a
 
 
33ae6b5
725264a
33ae6b5
725264a
 
 
 
33ae6b5
725264a
33ae6b5
725264a
33ae6b5
725264a
33ae6b5
725264a
 
 
 
33ae6b5
725264a
33ae6b5
725264a
 
 
 
33ae6b5
725264a
33ae6b5
725264a
33ae6b5
725264a
33ae6b5
725264a
 
 
 
 
 
33ae6b5
725264a
33ae6b5
725264a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33ae6b5
 
 
 
 
725264a
 
 
33ae6b5
 
725264a
33ae6b5
 
 
725264a
33ae6b5
 
 
 
 
725264a
33ae6b5
725264a
 
 
 
33ae6b5
725264a
 
 
 
 
 
 
 
33ae6b5
 
 
725264a
 
 
 
 
 
 
 
33ae6b5
725264a
33ae6b5
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
---
title: Referência da API HTTP
---

# Referência da API HTTP

O Koharu expõe uma API HTTP local em:

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

Esta é a mesma API usada pela UI desktop e pela Web UI em modo headless.

## Modelo de runtime

Comportamento atual importante:

- a API é servida pelo mesmo processo da GUI ou do runtime headless
- o servidor faz bind em `127.0.0.1` por padrão; use `--host` para fazer bind em outro lugar
- a API e o servidor MCP compartilham o mesmo projeto carregado, modelos e estado do pipeline
- quando nenhum `--port` é fornecido, o Koharu escolhe uma porta local aleatória
- tudo, exceto `/api/v1/downloads`, `/api/v1/operations` e `/api/v1/events`, retorna `503 Service Unavailable` até o app terminar a inicialização

## Modelo de recursos

A API é centrada em projetos. Apenas um projeto fica aberto por vez e contém:

- uma lista de `Pages` indexada por `PageId`
- `Nodes` por página (camadas de imagem, máscaras, blocos de texto) referenciados por `NodeId`
- um armazenamento `Blob` endereçado por conteúdo, que guarda os bytes brutos das imagens por hash Blake3
- um snapshot de `Scene` montado a partir dessas peças, avançado por um contador `epoch`
- um histórico de mutações `Op` que podem ser desfeitas ou refeitas

As mutações sempre passam pela camada de histórico (`POST /history/apply`), de modo que a cena, o autosave e os assinantes de eventos permaneçam sincronizados.

## Formatos comuns de response

Tipos de response frequentemente usados incluem:

- `MetaInfo` — versão do app e label do dispositivo de ML
- `EngineCatalog` — ids das engines instaláveis por etapa do pipeline
- `ProjectSummary` — id, nome, caminho, contagem de páginas, último acesso
- `SceneSnapshot``{ epoch, scene }`
- `LlmState` — estado atual de carga do LLM (status, target, error)
- `LlmCatalog` — modelos locais + de provedor agrupados por família
- `JobSummary``{ id, kind, status, error }`
- `DownloadProgress` — id do pacote, contagens de bytes, status

## Endpoints

### Meta

| Método | Path        | Finalidade                                          |
| ------ | ----------- | --------------------------------------------------- |
| `GET`  | `/meta`     | obtém a versão do app e o backend de ML ativo       |
| `GET`  | `/engines`  | lista as engines de pipeline registradas por etapa  |

### Fontes

| Método | Path                                  | Finalidade                                                       |
| ------ | ------------------------------------- | ---------------------------------------------------------------- |
| `GET`  | `/fonts`                              | catálogo combinado de fontes do sistema + Google Fonts para render |
| `GET`  | `/google-fonts`                       | catálogo do Google Fonts como uma lista isolada                  |
| `POST` | `/google-fonts/{family}/fetch`        | baixa e faz cache de uma família do Google Fonts                 |
| `GET`  | `/google-fonts/{family}/{file}`       | serve o arquivo TTF/WOFF em cache                                |

### Projetos

Todo projeto vive sob o diretório gerenciado `{data.path}/projects/`; clientes nunca fornecem caminhos do filesystem.

| Método   | Path                              | Finalidade                                                          |
| -------- | --------------------------------- | ------------------------------------------------------------------- |
| `GET`    | `/projects`                       | lista os projetos gerenciados                                       |
| `POST`   | `/projects`                       | cria um novo projeto (body `{ name }`)                              |
| `POST`   | `/projects/import`                | extrai um arquivo `.khr` em um diretório novo e o abre              |
| `PUT`    | `/projects/current`               | abre um projeto gerenciado por `id`                                 |
| `DELETE` | `/projects/current`               | fecha a sessão atual                                                |
| `POST`   | `/projects/current/export`        | exporta o projeto atual; retorna bytes binários                     |

`POST /projects/current/export` aceita `{ format, pages? }` onde `format` é um de `khr`, `psd`, `rendered`, `inpainted`. Quando o formato produz múltiplos arquivos, a response é `application/zip`.

### Páginas

| Método | Path                                    | Finalidade                                                  |
| ------ | --------------------------------------- | ----------------------------------------------------------- |
| `POST` | `/pages`                                | cria páginas a partir de N arquivos de imagem enviados (multipart) |
| `POST` | `/pages/from-paths`                     | caminho rápido só para Tauri que importa por caminho absoluto |
| `POST` | `/pages/{id}/image-layers`              | adiciona um node de imagem Custom a partir de um arquivo enviado |
| `PUT`  | `/pages/{id}/masks/{role}`              | faz upsert de um node de máscara a partir de bytes PNG brutos |
| `GET`  | `/pages/{id}/thumbnail`                 | obtém a thumbnail da página (cache em WebP)                 |

`role` é `segment` ou `brushInpaint`. `POST /pages` aceita um campo opcional `replace=true`; a importação é ordenada pelo nome de arquivo em ordem natural.

### Cena e blobs

| Método | Path                | Finalidade                                                              |
| ------ | ------------------- | ----------------------------------------------------------------------- |
| `GET`  | `/scene.json`       | snapshot completo da cena para clientes web/UI                          |
| `GET`  | `/scene.bin`        | `Snapshot { epoch, scene }` codificado em postcard para o cliente Tauri |
| `GET`  | `/blobs/{hash}`     | bytes brutos do blob por hash Blake3                                    |

`/scene.bin` inclui o epoch atual no header de response `x-koharu-epoch`.

### Histórico (mutações)

Todas as mutações da cena passam por aqui. Cada response retorna `{ epoch }`.

| Método | Path                | Finalidade                                  |
| ------ | ------------------- | ------------------------------------------- |
| `POST` | `/history/apply`    | aplica um `Op` (incluindo `Op::Batch`)      |
| `POST` | `/history/undo`     | reverte a última op aplicada                |
| `POST` | `/history/redo`     | reaplica a última op desfeita               |

`Op` é a união discriminada que cobre add/remove/update node, add/remove page, batch e outras transições da cena. O body é a variante com tag JSON.

### Pipelines

| Método | Path          | Finalidade                                       |
| ------ | ------------- | ------------------------------------------------ |
| `POST` | `/pipelines`  | inicia uma execução de pipeline como uma operação |

Campos do body:

- `steps` — ids das engines a executar em ordem (validados contra o registry)
- `pages` — subconjunto opcional de `PageId`s; omita para processar o projeto inteiro
- `region` — bounding box opcional para o inpainter (fluxo de pincel de reparo)
- `targetLanguage`, `systemPrompt`, `defaultFont` — overrides opcionais por execução

A response carrega um `operationId`. O progresso e a conclusão chegam em `/events` como `JobStarted`, `JobProgress`, `JobWarning` e `JobFinished`.

### Operações

`/operations` é o registry unificado para jobs em andamento e recém-concluídos (pipelines + downloads).

| Método   | Path                  | Finalidade                                                         |
| -------- | --------------------- | ------------------------------------------------------------------ |
| `GET`    | `/operations`         | snapshot de toda operação em andamento ou recente                  |
| `DELETE` | `/operations/{id}`    | cancela uma execução de pipeline; remoção best-effort para downloads |

### Downloads

| Método | Path                | Finalidade                                       |
| ------ | ------------------- | ------------------------------------------------ |
| `GET`  | `/downloads`        | snapshot de todo download ativo ou recente       |
| `POST` | `/downloads`        | inicia o download de um pacote de modelo (`{ modelId }`) |

`modelId` é um id de pacote declarado via `declare_hf_model_package!` (ex.: `"model:comic-text-detector:yolo-v5"`). A response é `{ operationId }`, reutilizando o id do pacote.

### Controle do LLM

O modelo carregado é um recurso singleton em `/llm/current`.

| Método   | Path             | Finalidade                                       |
| -------- | ---------------- | ------------------------------------------------ |
| `GET`    | `/llm/current`   | estado atual (status, target, error)             |
| `PUT`    | `/llm/current`   | carrega o target informado (local ou de provedor) |
| `DELETE` | `/llm/current`   | descarrega / libera o modelo                     |
| `GET`    | `/llm/catalog`   | lista os modelos locais + de provedor disponíveis |

`PUT /llm/current` aceita um `LlmLoadRequest`:

- targets de provedor — `{ kind: "provider", providerId, modelId }`
- targets locais — `{ kind: "local", modelId }`
- `options { temperature, maxTokens, customSystemPrompt }` opcional

`PUT /llm/current` retorna `204` assim que a tarefa de carga é enfileirada. O estado pronto efetivo é publicado como `LlmLoaded` em `/events`.

### Configuração

| Método   | Path                                    | Finalidade                                          |
| -------- | --------------------------------------- | --------------------------------------------------- |
| `GET`    | `/config`                               | lê o `AppConfig` atual                              |
| `PATCH`  | `/config`                               | aplica um `ConfigPatch`; persiste e faz broadcast   |
| `PUT`    | `/config/providers/{id}/secret`         | salva (ou sobrescreve) a chave de API de um provedor |
| `DELETE` | `/config/providers/{id}/secret`         | limpa a chave de API armazenada de um provedor      |

`AppConfig` expõe os top-level `data`, `http`, `pipeline` e `providers`:

- `data.path` — diretório de dados local usado para runtime, cache de modelos e projetos
- `http { connectTimeout, readTimeout, maxRetries }` — client HTTP compartilhado usado por downloads e requests baseados em provedor
- `pipeline { detector, fontDetector, segmenter, bubbleSegmenter, ocr, translator, inpainter, renderer }` — id da engine selecionada para cada etapa
- `providers[] { id, baseUrl?, apiKey? }` — chaves de API salvas vão e voltam como o placeholder redatado `"[REDACTED]"`; nunca o segredo bruto

Ids de provedores embutidos:

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

As chaves de API ficam armazenadas no credential store da plataforma, não em `config.toml`. Fazer PATCH de `apiKey: ""` limpa a chave salva; fazer PATCH de `"[REDACTED]"` mantém o valor inalterado. As rotas dedicadas `/config/providers/{id}/secret` são a forma explícita, fora do PATCH, de gerenciar o segredo de um provedor.

## Stream de eventos

O Koharu expõe um stream de Server-Sent Events em:

```text
GET /events
```

Comportamento:

- uma conexão nova (sem header `Last-Event-ID`) começa com um evento `Snapshot` contendo os registries atuais de jobs e downloads
- na reconexão, o servidor reenvia, em ordem, os eventos com `seq > Last-Event-ID` que ainda estão no buffer; se o id solicitado já saiu do ring, o servidor reenvia um `Snapshot`
- cada evento ao vivo é emitido com seu `seq` no campo `id:` do SSE
- um keepalive de 15 segundos é mantido

As variantes de evento atualmente incluem:

- `Snapshot` — estado completo inicial para clientes novos e em recuperação de atraso
- `JobStarted`, `JobProgress`, `JobWarning`, `JobFinished` — ciclo de vida do job de pipeline
- `DownloadProgress` — ticks de progresso de download de pacote
- `ConfigChanged` — config foi aplicada via `PATCH /config` ou via uma rota de segredo
- `LlmLoaded`, `LlmUnloaded` — transições do ciclo de vida do LLM
- `SceneAdvanced` — emitido quando uma mutação de cena avança o epoch

## Workflow típico

A ordem normal da API para um projeto novo é:

1. `POST /projects` — cria o projeto
2. `POST /pages` (ou `/pages/from-paths` no Tauri) — importa as imagens
3. `PUT /llm/current` — carrega um modelo de tradução (local ou de provedor)
4. `POST /pipelines` — dispara `detect → ocr → translate → inpaint → render`
5. acompanha `GET /events` até `JobFinished`
6. `POST /projects/current/export` com `format = "rendered"` ou `"psd"`

Para controle mais fino, faça `POST /history/apply` com payloads `Op` explícitos em vez de rodar um pipeline completo.

Se você prefere acesso orientado a agentes em vez de orquestrar endpoints HTTP, veja a [Referência das ferramentas MCP](mcp-tools.md).