| { |
| "openapi": "3.1.0", |
| "info": { |
| "title": "", |
| "version": "" |
| }, |
| "paths": { |
| "/ai/codex/auth/device-code": { |
| "post": { |
| "operationId": "start_codex_device_login", |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/CodexDeviceLogin" |
| } |
| } |
| } |
| } |
| } |
| } |
| }, |
| "/ai/codex/auth/session": { |
| "delete": { |
| "operationId": "delete_codex_session", |
| "responses": { |
| "204": { |
| "description": "" |
| } |
| } |
| } |
| }, |
| "/ai/codex/auth/status": { |
| "get": { |
| "operationId": "get_codex_auth_status", |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/CodexAuthStatus" |
| } |
| } |
| } |
| } |
| } |
| } |
| }, |
| "/ai/codex/images": { |
| "post": { |
| "operationId": "start_codex_image_generation", |
| "requestBody": { |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/CodexImageGenerationOptions" |
| } |
| } |
| }, |
| "required": true |
| }, |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/CodexImageGenerationResponse" |
| } |
| } |
| } |
| } |
| } |
| } |
| }, |
| "/blobs/{hash}": { |
| "get": { |
| "operationId": "get_blob", |
| "parameters": [ |
| { |
| "name": "hash", |
| "in": "path", |
| "description": "Blake3 hash of the blob", |
| "required": true, |
| "schema": { |
| "type": "string" |
| } |
| } |
| ], |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/octet-stream": {} |
| } |
| } |
| } |
| } |
| }, |
| "/config": { |
| "get": { |
| "operationId": "get_config", |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/AppConfig" |
| } |
| } |
| } |
| } |
| } |
| }, |
| "patch": { |
| "operationId": "patch_config", |
| "requestBody": { |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/ConfigPatch" |
| } |
| } |
| }, |
| "required": true |
| }, |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/AppConfig" |
| } |
| } |
| } |
| } |
| } |
| } |
| }, |
| "/config/providers/{id}/secret": { |
| "put": { |
| "summary": "Save (or overwrite) the keyring secret for a provider. Creates the\nprovider entry in `config.providers` if it didn't exist. `PUT` because\nsetting the secret is idempotent for the same body.", |
| "operationId": "set_provider_secret", |
| "parameters": [ |
| { |
| "name": "id", |
| "in": "path", |
| "description": "Provider id", |
| "required": true, |
| "schema": { |
| "type": "string" |
| } |
| } |
| ], |
| "requestBody": { |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/ProviderSecretRequest" |
| } |
| } |
| }, |
| "required": true |
| }, |
| "responses": { |
| "204": { |
| "description": "" |
| } |
| } |
| }, |
| "delete": { |
| "summary": "Clear a provider's keyring secret. The provider entry itself is kept.", |
| "operationId": "clear_provider_secret", |
| "parameters": [ |
| { |
| "name": "id", |
| "in": "path", |
| "description": "Provider id", |
| "required": true, |
| "schema": { |
| "type": "string" |
| } |
| } |
| ], |
| "responses": { |
| "204": { |
| "description": "" |
| } |
| } |
| } |
| }, |
| "/downloads": { |
| "get": { |
| "operationId": "list_downloads", |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/ListDownloadsResponse" |
| } |
| } |
| } |
| } |
| } |
| }, |
| "post": { |
| "operationId": "start_download", |
| "requestBody": { |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/StartDownloadRequest" |
| } |
| } |
| }, |
| "required": true |
| }, |
| "responses": { |
| "202": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/StartDownloadResponse" |
| } |
| } |
| } |
| } |
| } |
| } |
| }, |
| "/engines": { |
| "get": { |
| "operationId": "get_engine_catalog", |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/EngineCatalog" |
| } |
| } |
| } |
| } |
| } |
| } |
| }, |
| "/events": { |
| "get": { |
| "operationId": "events", |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/AppEvent" |
| } |
| } |
| } |
| } |
| } |
| } |
| }, |
| "/fonts": { |
| "get": { |
| "operationId": "list_fonts", |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/FontFaceInfo" |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| }, |
| "/google-fonts": { |
| "get": { |
| "operationId": "get_google_fonts_catalog", |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/GoogleFontCatalog" |
| } |
| } |
| } |
| } |
| } |
| } |
| }, |
| "/google-fonts/{family}/fetch": { |
| "post": { |
| "operationId": "fetch_google_font", |
| "parameters": [ |
| { |
| "name": "family", |
| "in": "path", |
| "description": "Google Fonts family name", |
| "required": true, |
| "schema": { |
| "type": "string" |
| } |
| } |
| ], |
| "responses": { |
| "204": { |
| "description": "" |
| } |
| } |
| } |
| }, |
| "/google-fonts/{family}/{file}": { |
| "get": { |
| "operationId": "get_google_font_file", |
| "parameters": [ |
| { |
| "name": "family", |
| "in": "path", |
| "description": "Google Fonts family name", |
| "required": true, |
| "schema": { |
| "type": "string" |
| } |
| }, |
| { |
| "name": "file", |
| "in": "path", |
| "description": "Font filename", |
| "required": true, |
| "schema": { |
| "type": "string" |
| } |
| } |
| ], |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "font/ttf": {} |
| } |
| } |
| } |
| } |
| }, |
| "/history/apply": { |
| "post": { |
| "operationId": "apply_command", |
| "requestBody": { |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/Op" |
| } |
| } |
| }, |
| "required": true |
| }, |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/HistoryResult" |
| } |
| } |
| } |
| } |
| } |
| } |
| }, |
| "/history/redo": { |
| "post": { |
| "operationId": "redo", |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/HistoryResult" |
| } |
| } |
| } |
| } |
| } |
| } |
| }, |
| "/history/undo": { |
| "post": { |
| "operationId": "undo", |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/HistoryResult" |
| } |
| } |
| } |
| } |
| } |
| } |
| }, |
| "/llm/catalog": { |
| "get": { |
| "operationId": "get_catalog", |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/LlmCatalog" |
| } |
| } |
| } |
| } |
| } |
| } |
| }, |
| "/llm/current": { |
| "get": { |
| "operationId": "get_current_llm", |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/LlmState" |
| } |
| } |
| } |
| } |
| } |
| }, |
| "put": { |
| "operationId": "put_current_llm", |
| "requestBody": { |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/LlmLoadRequest" |
| } |
| } |
| }, |
| "required": true |
| }, |
| "responses": { |
| "204": { |
| "description": "" |
| } |
| } |
| }, |
| "delete": { |
| "operationId": "delete_current_llm", |
| "responses": { |
| "204": { |
| "description": "" |
| } |
| } |
| } |
| }, |
| "/meta": { |
| "get": { |
| "operationId": "get_meta", |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/MetaInfo" |
| } |
| } |
| } |
| } |
| } |
| } |
| }, |
| "/operations": { |
| "get": { |
| "operationId": "list_operations", |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/ListOperationsResponse" |
| } |
| } |
| } |
| } |
| } |
| } |
| }, |
| "/operations/{id}": { |
| "delete": { |
| "operationId": "cancel_operation", |
| "parameters": [ |
| { |
| "name": "id", |
| "in": "path", |
| "description": "Operation id", |
| "required": true, |
| "schema": { |
| "type": "string" |
| } |
| } |
| ], |
| "responses": { |
| "204": { |
| "description": "" |
| } |
| } |
| } |
| }, |
| "/pages": { |
| "post": { |
| "operationId": "create_pages", |
| "requestBody": { |
| "content": { |
| "multipart/form-data": {} |
| } |
| }, |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/CreatePagesResponse" |
| } |
| } |
| } |
| } |
| } |
| } |
| }, |
| "/pages/from-paths": { |
| "post": { |
| "summary": "Create pages by reading image files from absolute paths on the server's\nfilesystem. This is the Tauri desktop import path — the webview picker\nreturns paths, and the backend reads + decodes + hashes them in parallel\nwithout a round-trip through JS memory or a multipart upload body.", |
| "description": "Web clients should keep using `POST /pages` with multipart.", |
| "operationId": "create_pages_from_paths", |
| "requestBody": { |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/CreatePagesFromPathsRequest" |
| } |
| } |
| }, |
| "required": true |
| }, |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/CreatePagesResponse" |
| } |
| } |
| } |
| } |
| } |
| } |
| }, |
| "/pages/{id}/image-layers": { |
| "post": { |
| "operationId": "add_image_layer", |
| "parameters": [ |
| { |
| "name": "id", |
| "in": "path", |
| "description": "Page id", |
| "required": true, |
| "schema": { |
| "$ref": "#/components/schemas/PageId" |
| } |
| } |
| ], |
| "requestBody": { |
| "content": { |
| "multipart/form-data": {} |
| } |
| }, |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/AddImageLayerResponse" |
| } |
| } |
| } |
| } |
| } |
| } |
| }, |
| "/pages/{id}/masks/{role}": { |
| "put": { |
| "summary": "Upsert the `Mask { role }` node on a page with the raw image bytes in\nthe body. Emits `Op::UpdateNode` if a mask of that role exists, else\n`Op::AddNode`. Used by the repair-brush / segment-edit flow; the\nfollow-up localized inpaint is a separate `POST /pipelines` call.", |
| "operationId": "put_mask", |
| "parameters": [ |
| { |
| "name": "id", |
| "in": "path", |
| "description": "Page id", |
| "required": true, |
| "schema": { |
| "$ref": "#/components/schemas/PageId" |
| } |
| }, |
| { |
| "name": "role", |
| "in": "path", |
| "description": "Mask role (segment|brushInpaint)", |
| "required": true, |
| "schema": { |
| "$ref": "#/components/schemas/MaskRole" |
| } |
| } |
| ], |
| "requestBody": { |
| "content": { |
| "image/png": {} |
| } |
| }, |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/PutMaskResponse" |
| } |
| } |
| } |
| } |
| } |
| } |
| }, |
| "/pages/{id}/thumbnail": { |
| "get": { |
| "operationId": "get_page_thumbnail", |
| "parameters": [ |
| { |
| "name": "id", |
| "in": "path", |
| "description": "Page id", |
| "required": true, |
| "schema": { |
| "$ref": "#/components/schemas/PageId" |
| } |
| } |
| ], |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "image/webp": {} |
| } |
| } |
| } |
| } |
| }, |
| "/pipelines": { |
| "post": { |
| "operationId": "start_pipeline", |
| "requestBody": { |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/StartPipelineRequest" |
| } |
| } |
| }, |
| "required": true |
| }, |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/StartPipelineResponse" |
| } |
| } |
| } |
| } |
| } |
| } |
| }, |
| "/projects": { |
| "get": { |
| "operationId": "list_projects", |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/ListProjectsResponse" |
| } |
| } |
| } |
| } |
| } |
| }, |
| "post": { |
| "operationId": "create_project", |
| "requestBody": { |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/CreateProjectRequest" |
| } |
| } |
| }, |
| "required": true |
| }, |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/ProjectSummary" |
| } |
| } |
| } |
| } |
| } |
| } |
| }, |
| "/projects/current": { |
| "put": { |
| "operationId": "put_current_project", |
| "requestBody": { |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/OpenProjectRequest" |
| } |
| } |
| }, |
| "required": true |
| }, |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/ProjectSummary" |
| } |
| } |
| } |
| } |
| } |
| }, |
| "delete": { |
| "operationId": "delete_current_project", |
| "responses": { |
| "204": { |
| "description": "" |
| } |
| } |
| } |
| }, |
| "/projects/current/export": { |
| "post": { |
| "operationId": "export_current_project", |
| "requestBody": { |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/ExportProjectRequest" |
| } |
| } |
| }, |
| "required": true |
| }, |
| "responses": { |
| "200": { |
| "description": "Export bytes. Content-Type is `application/zip` when the format produces multiple files.", |
| "content": { |
| "application/octet-stream": {} |
| } |
| } |
| } |
| } |
| }, |
| "/projects/import": { |
| "post": { |
| "operationId": "import_project", |
| "requestBody": { |
| "content": { |
| "application/zip": {} |
| } |
| }, |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/ProjectSummary" |
| } |
| } |
| } |
| } |
| } |
| } |
| }, |
| "/scene.bin": { |
| "get": { |
| "operationId": "get_scene_bin", |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/octet-stream": {} |
| } |
| } |
| } |
| } |
| }, |
| "/scene.json": { |
| "get": { |
| "operationId": "get_scene_json", |
| "responses": { |
| "200": { |
| "description": "", |
| "content": { |
| "application/json": { |
| "schema": { |
| "$ref": "#/components/schemas/SceneSnapshot" |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| }, |
| "components": { |
| "schemas": { |
| "AddImageLayerResponse": { |
| "type": "object", |
| "required": ["node"], |
| "properties": { |
| "node": { |
| "$ref": "#/components/schemas/NodeId" |
| } |
| } |
| }, |
| "AppConfig": { |
| "type": "object", |
| "properties": { |
| "data": { |
| "oneOf": [ |
| { |
| "$ref": "#/components/schemas/DataConfig" |
| } |
| ], |
| "default": { |
| "path": "C:\\Users\\Mayo\\AppData\\Local\\Koharu" |
| } |
| }, |
| "http": { |
| "oneOf": [ |
| { |
| "$ref": "#/components/schemas/HttpConfig" |
| } |
| ], |
| "default": { |
| "connect_timeout": 20, |
| "max_retries": 3, |
| "read_timeout": 300 |
| } |
| }, |
| "pipeline": { |
| "oneOf": [ |
| { |
| "$ref": "#/components/schemas/PipelineConfig" |
| } |
| ], |
| "default": { |
| "bubble_segmenter": "speech-bubble-segmentation", |
| "detector": "pp-doclayout-v3", |
| "font_detector": "yuzumarker-font-detection", |
| "inpainter": "lama-manga", |
| "ocr": "paddle-ocr-vl-1.5", |
| "renderer": "koharu-renderer", |
| "segmenter": "comic-text-detector-seg", |
| "translator": "llm" |
| } |
| }, |
| "providers": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/ProviderConfig" |
| }, |
| "default": [] |
| } |
| } |
| }, |
| "AppEvent": { |
| "oneOf": [ |
| { |
| "type": "object", |
| "required": ["id", "kind", "event"], |
| "properties": { |
| "event": { |
| "type": "string", |
| "enum": ["jobStarted"] |
| }, |
| "id": { |
| "type": "string" |
| }, |
| "kind": { |
| "type": "string" |
| } |
| } |
| }, |
| { |
| "allOf": [ |
| { |
| "$ref": "#/components/schemas/PipelineProgress" |
| }, |
| { |
| "type": "object", |
| "required": ["event"], |
| "properties": { |
| "event": { |
| "type": "string", |
| "enum": ["jobProgress"] |
| } |
| } |
| } |
| ] |
| }, |
| { |
| "allOf": [ |
| { |
| "$ref": "#/components/schemas/JobWarningEvent", |
| "description": "A single step on one page failed but the pipeline kept running.\nEmitted per failed step so clients can show a non-fatal warning while\nthe job continues with the next page." |
| }, |
| { |
| "type": "object", |
| "required": ["event"], |
| "properties": { |
| "event": { |
| "type": "string", |
| "enum": ["jobWarning"] |
| } |
| } |
| } |
| ], |
| "description": "A single step on one page failed but the pipeline kept running.\nEmitted per failed step so clients can show a non-fatal warning while\nthe job continues with the next page." |
| }, |
| { |
| "allOf": [ |
| { |
| "$ref": "#/components/schemas/JobFinishedEvent" |
| }, |
| { |
| "type": "object", |
| "required": ["event"], |
| "properties": { |
| "event": { |
| "type": "string", |
| "enum": ["jobFinished"] |
| } |
| } |
| } |
| ] |
| }, |
| { |
| "allOf": [ |
| { |
| "$ref": "#/components/schemas/DownloadProgress" |
| }, |
| { |
| "type": "object", |
| "required": ["event"], |
| "properties": { |
| "event": { |
| "type": "string", |
| "enum": ["downloadProgress"] |
| } |
| } |
| } |
| ] |
| }, |
| { |
| "type": "object", |
| "required": ["target", "event"], |
| "properties": { |
| "event": { |
| "type": "string", |
| "enum": ["llmLoading"] |
| }, |
| "target": { |
| "$ref": "#/components/schemas/LlmTarget" |
| } |
| } |
| }, |
| { |
| "type": "object", |
| "required": ["target", "event"], |
| "properties": { |
| "event": { |
| "type": "string", |
| "enum": ["llmLoaded"] |
| }, |
| "target": { |
| "$ref": "#/components/schemas/LlmTarget" |
| } |
| } |
| }, |
| { |
| "type": "object", |
| "required": ["event"], |
| "properties": { |
| "event": { |
| "type": "string", |
| "enum": ["llmFailed"] |
| }, |
| "target": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/LlmTarget" |
| } |
| ] |
| } |
| } |
| }, |
| { |
| "type": "object", |
| "required": ["event"], |
| "properties": { |
| "event": { |
| "type": "string", |
| "enum": ["llmUnloaded"] |
| } |
| } |
| }, |
| { |
| "allOf": [ |
| { |
| "$ref": "#/components/schemas/SnapshotEvent" |
| }, |
| { |
| "type": "object", |
| "required": ["event"], |
| "properties": { |
| "event": { |
| "type": "string", |
| "enum": ["snapshot"] |
| } |
| } |
| } |
| ] |
| } |
| ] |
| }, |
| "BlobRef": { |
| "type": "string", |
| "description": "Hex-encoded blake3 hash of an immutable blob." |
| }, |
| "CodexAuthAttemptStatus": { |
| "type": "string", |
| "enum": ["pending", "succeeded", "failed"] |
| }, |
| "CodexAuthStatus": { |
| "type": "object", |
| "required": ["signedIn"], |
| "properties": { |
| "accountId": { |
| "type": ["string", "null"] |
| }, |
| "login": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/CodexDeviceLoginStatus" |
| } |
| ] |
| }, |
| "signedIn": { |
| "type": "boolean" |
| } |
| } |
| }, |
| "CodexDeviceLogin": { |
| "type": "object", |
| "required": ["loginId", "verificationUrl", "userCode", "intervalSeconds", "timeoutSeconds"], |
| "properties": { |
| "intervalSeconds": { |
| "type": "integer", |
| "format": "int64", |
| "minimum": 0 |
| }, |
| "loginId": { |
| "type": "string" |
| }, |
| "timeoutSeconds": { |
| "type": "integer", |
| "format": "int64", |
| "minimum": 0 |
| }, |
| "userCode": { |
| "type": "string" |
| }, |
| "verificationUrl": { |
| "type": "string" |
| } |
| } |
| }, |
| "CodexDeviceLoginStatus": { |
| "type": "object", |
| "required": ["loginId", "status"], |
| "properties": { |
| "accountId": { |
| "type": ["string", "null"] |
| }, |
| "error": { |
| "type": ["string", "null"] |
| }, |
| "loginId": { |
| "type": "string" |
| }, |
| "status": { |
| "$ref": "#/components/schemas/CodexAuthAttemptStatus" |
| } |
| } |
| }, |
| "CodexImageGenerationOptions": { |
| "type": "object", |
| "required": ["pageId", "prompt"], |
| "properties": { |
| "instructions": { |
| "type": ["string", "null"] |
| }, |
| "model": { |
| "type": ["string", "null"] |
| }, |
| "pageId": { |
| "$ref": "#/components/schemas/PageId" |
| }, |
| "prompt": { |
| "type": "string" |
| }, |
| "quality": { |
| "type": ["string", "null"] |
| }, |
| "size": { |
| "type": ["string", "null"] |
| } |
| } |
| }, |
| "CodexImageGenerationResponse": { |
| "type": "object", |
| "required": ["operationId"], |
| "properties": { |
| "operationId": { |
| "type": "string" |
| } |
| } |
| }, |
| "ConfigPatch": { |
| "type": "object", |
| "description": "Sparse patch for `koharu_app::AppConfig`. Missing fields mean \"leave\nas-is\". The `providers` field, if present, replaces the whole provider\nlist — we do not merge by id because ordering is meaningful.", |
| "properties": { |
| "data": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/DataConfigPatch" |
| } |
| ] |
| }, |
| "http": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/HttpConfigPatch" |
| } |
| ] |
| }, |
| "pipeline": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/PipelineConfigPatch" |
| } |
| ] |
| }, |
| "providers": { |
| "type": ["array", "null"], |
| "items": { |
| "$ref": "#/components/schemas/ProviderPatch" |
| }, |
| "description": "If present, replaces the entire list. Api_key values of `\"[REDACTED]\"`\nare interpreted as \"leave the existing secret alone\"." |
| } |
| } |
| }, |
| "CreatePagesFromPathsRequest": { |
| "type": "object", |
| "required": ["paths"], |
| "properties": { |
| "paths": { |
| "type": "array", |
| "items": { |
| "type": "string" |
| } |
| }, |
| "replace": { |
| "type": "boolean" |
| } |
| } |
| }, |
| "CreatePagesResponse": { |
| "type": "object", |
| "required": ["pages"], |
| "properties": { |
| "pages": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/PageId" |
| } |
| } |
| } |
| }, |
| "CreateProjectRequest": { |
| "type": "object", |
| "required": ["name"], |
| "properties": { |
| "name": { |
| "type": "string" |
| } |
| } |
| }, |
| "DataConfig": { |
| "type": "object", |
| "required": ["path"], |
| "properties": { |
| "path": { |
| "type": "string" |
| } |
| } |
| }, |
| "DataConfigPatch": { |
| "type": "object", |
| "properties": { |
| "path": { |
| "type": ["string", "null"] |
| } |
| } |
| }, |
| "DownloadProgress": { |
| "type": "object", |
| "required": ["id", "filename", "downloaded", "status"], |
| "properties": { |
| "downloaded": { |
| "type": "integer", |
| "format": "int64", |
| "minimum": 0 |
| }, |
| "filename": { |
| "type": "string" |
| }, |
| "id": { |
| "type": "string" |
| }, |
| "status": { |
| "$ref": "#/components/schemas/DownloadStatus" |
| }, |
| "total": { |
| "type": ["integer", "null"], |
| "format": "int64", |
| "minimum": 0 |
| } |
| } |
| }, |
| "DownloadStatus": { |
| "oneOf": [ |
| { |
| "type": "object", |
| "required": ["status"], |
| "properties": { |
| "status": { |
| "type": "string", |
| "enum": ["started"] |
| } |
| } |
| }, |
| { |
| "type": "object", |
| "required": ["status"], |
| "properties": { |
| "status": { |
| "type": "string", |
| "enum": ["downloading"] |
| } |
| } |
| }, |
| { |
| "type": "object", |
| "required": ["status"], |
| "properties": { |
| "status": { |
| "type": "string", |
| "enum": ["completed"] |
| } |
| } |
| }, |
| { |
| "type": "object", |
| "required": ["reason", "status"], |
| "properties": { |
| "reason": { |
| "type": "string" |
| }, |
| "status": { |
| "type": "string", |
| "enum": ["failed"] |
| } |
| } |
| } |
| ] |
| }, |
| "EngineCatalog": { |
| "type": "object", |
| "required": [ |
| "detectors", |
| "fontDetectors", |
| "segmenters", |
| "bubbleSegmenters", |
| "ocr", |
| "translators", |
| "inpainters", |
| "renderers" |
| ], |
| "properties": { |
| "bubbleSegmenters": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/EngineCatalogEntry" |
| } |
| }, |
| "detectors": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/EngineCatalogEntry" |
| } |
| }, |
| "fontDetectors": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/EngineCatalogEntry" |
| } |
| }, |
| "inpainters": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/EngineCatalogEntry" |
| } |
| }, |
| "ocr": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/EngineCatalogEntry" |
| } |
| }, |
| "renderers": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/EngineCatalogEntry" |
| } |
| }, |
| "segmenters": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/EngineCatalogEntry" |
| } |
| }, |
| "translators": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/EngineCatalogEntry" |
| } |
| } |
| } |
| }, |
| "EngineCatalogEntry": { |
| "type": "object", |
| "required": ["id", "name", "produces"], |
| "properties": { |
| "id": { |
| "type": "string" |
| }, |
| "name": { |
| "type": "string" |
| }, |
| "produces": { |
| "type": "array", |
| "items": { |
| "type": "string" |
| } |
| } |
| } |
| }, |
| "ExportFormat": { |
| "type": "string", |
| "enum": ["khr", "psd", "rendered", "inpainted"] |
| }, |
| "ExportProjectRequest": { |
| "type": "object", |
| "required": ["format"], |
| "properties": { |
| "format": { |
| "$ref": "#/components/schemas/ExportFormat" |
| }, |
| "pages": { |
| "type": ["array", "null"], |
| "items": { |
| "$ref": "#/components/schemas/PageId" |
| }, |
| "description": "Optional subset of pages; defaults to every page." |
| } |
| } |
| }, |
| "FontFaceInfo": { |
| "type": "object", |
| "required": ["familyName", "postScriptName", "source", "cached"], |
| "properties": { |
| "cached": { |
| "type": "boolean" |
| }, |
| "category": { |
| "type": ["string", "null"] |
| }, |
| "familyName": { |
| "type": "string" |
| }, |
| "postScriptName": { |
| "type": "string" |
| }, |
| "source": { |
| "$ref": "#/components/schemas/FontSource" |
| } |
| } |
| }, |
| "FontPrediction": { |
| "type": "object", |
| "required": [ |
| "topFonts", |
| "namedFonts", |
| "direction", |
| "textColor", |
| "strokeColor", |
| "fontSizePx", |
| "strokeWidthPx", |
| "lineHeight", |
| "angleDeg" |
| ], |
| "properties": { |
| "angleDeg": { |
| "type": "number", |
| "format": "float" |
| }, |
| "direction": { |
| "$ref": "#/components/schemas/TextDirection" |
| }, |
| "fontSizePx": { |
| "type": "number", |
| "format": "float" |
| }, |
| "lineHeight": { |
| "type": "number", |
| "format": "float" |
| }, |
| "namedFonts": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/NamedFontPrediction" |
| } |
| }, |
| "strokeColor": { |
| "type": "array", |
| "items": { |
| "type": "integer", |
| "format": "int32", |
| "minimum": 0 |
| } |
| }, |
| "strokeWidthPx": { |
| "type": "number", |
| "format": "float" |
| }, |
| "textColor": { |
| "type": "array", |
| "items": { |
| "type": "integer", |
| "format": "int32", |
| "minimum": 0 |
| } |
| }, |
| "topFonts": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/TopFont" |
| } |
| } |
| } |
| }, |
| "FontSource": { |
| "type": "string", |
| "enum": ["system", "google"] |
| }, |
| "GoogleFontCatalog": { |
| "type": "object", |
| "required": ["fonts"], |
| "properties": { |
| "fonts": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/GoogleFontEntry" |
| } |
| } |
| } |
| }, |
| "GoogleFontEntry": { |
| "type": "object", |
| "required": ["family", "category", "subsets", "variants"], |
| "properties": { |
| "category": { |
| "type": "string" |
| }, |
| "family": { |
| "type": "string" |
| }, |
| "subsets": { |
| "type": "array", |
| "items": { |
| "type": "string" |
| } |
| }, |
| "variants": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/GoogleFontVariant" |
| } |
| } |
| } |
| }, |
| "GoogleFontVariant": { |
| "type": "object", |
| "required": ["style", "weight", "filename"], |
| "properties": { |
| "filename": { |
| "type": "string" |
| }, |
| "style": { |
| "type": "string" |
| }, |
| "weight": { |
| "type": "integer", |
| "format": "int32", |
| "minimum": 0 |
| } |
| } |
| }, |
| "HistoryResult": { |
| "type": "object", |
| "properties": { |
| "epoch": { |
| "type": ["integer", "null"], |
| "format": "int64", |
| "description": "New epoch. `None` only for a no-op undo/redo at the stack boundary.", |
| "minimum": 0 |
| } |
| } |
| }, |
| "HttpConfig": { |
| "type": "object", |
| "properties": { |
| "connect_timeout": { |
| "type": "integer", |
| "format": "int64", |
| "default": 20, |
| "minimum": 0 |
| }, |
| "max_retries": { |
| "type": "integer", |
| "format": "int32", |
| "default": 3, |
| "minimum": 0 |
| }, |
| "read_timeout": { |
| "type": "integer", |
| "format": "int64", |
| "default": 300, |
| "minimum": 0 |
| } |
| } |
| }, |
| "HttpConfigPatch": { |
| "type": "object", |
| "properties": { |
| "connectTimeout": { |
| "type": ["integer", "null"], |
| "format": "int64", |
| "minimum": 0 |
| }, |
| "maxRetries": { |
| "type": ["integer", "null"], |
| "format": "int32", |
| "minimum": 0 |
| }, |
| "readTimeout": { |
| "type": ["integer", "null"], |
| "format": "int64", |
| "minimum": 0 |
| } |
| } |
| }, |
| "ImageData": { |
| "type": "object", |
| "required": ["role", "blob", "naturalWidth", "naturalHeight"], |
| "properties": { |
| "blob": { |
| "$ref": "#/components/schemas/BlobRef" |
| }, |
| "name": { |
| "type": ["string", "null"] |
| }, |
| "naturalHeight": { |
| "type": "integer", |
| "format": "int32", |
| "minimum": 0 |
| }, |
| "naturalWidth": { |
| "type": "integer", |
| "format": "int32", |
| "minimum": 0 |
| }, |
| "opacity": { |
| "type": "number", |
| "format": "float" |
| }, |
| "role": { |
| "$ref": "#/components/schemas/ImageRole", |
| "description": "Role tags differentiate source / inpainted / rendered / user-imported images.\nRole is immutable on an existing node — switching roles = delete + add." |
| } |
| } |
| }, |
| "ImageDataPatch": { |
| "type": "object", |
| "properties": { |
| "blob": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/BlobRef" |
| } |
| ] |
| }, |
| "name": { |
| "type": ["string", "null"] |
| }, |
| "naturalHeight": { |
| "type": ["integer", "null"], |
| "format": "int32", |
| "minimum": 0 |
| }, |
| "naturalWidth": { |
| "type": ["integer", "null"], |
| "format": "int32", |
| "minimum": 0 |
| }, |
| "opacity": { |
| "type": ["number", "null"], |
| "format": "float" |
| } |
| } |
| }, |
| "ImageRole": { |
| "type": "string", |
| "enum": ["source", "inpainted", "rendered", "custom"] |
| }, |
| "JobFinishedEvent": { |
| "type": "object", |
| "required": ["id", "status"], |
| "properties": { |
| "error": { |
| "type": ["string", "null"] |
| }, |
| "id": { |
| "type": "string" |
| }, |
| "status": { |
| "$ref": "#/components/schemas/JobStatus" |
| } |
| } |
| }, |
| "JobStatus": { |
| "type": "string", |
| "enum": ["running", "completed", "completed_with_errors", "cancelled", "failed"] |
| }, |
| "JobSummary": { |
| "type": "object", |
| "required": ["id", "kind", "status"], |
| "properties": { |
| "error": { |
| "type": ["string", "null"] |
| }, |
| "id": { |
| "type": "string" |
| }, |
| "kind": { |
| "type": "string" |
| }, |
| "status": { |
| "$ref": "#/components/schemas/JobStatus" |
| } |
| } |
| }, |
| "JobWarningEvent": { |
| "type": "object", |
| "description": "A non-fatal step failure during a pipeline run. The pipeline recovers by\nskipping the rest of the current page's steps and moving on to the next\npage; the UI accumulates these into a list during the job.", |
| "required": ["jobId", "pageIndex", "totalPages", "stepId", "message"], |
| "properties": { |
| "jobId": { |
| "type": "string" |
| }, |
| "message": { |
| "type": "string" |
| }, |
| "pageIndex": { |
| "type": "integer", |
| "description": "0-based page index where the failure happened.", |
| "minimum": 0 |
| }, |
| "stepId": { |
| "type": "string", |
| "description": "Engine id (e.g. `\"lama-manga\"`) of the step that failed." |
| }, |
| "totalPages": { |
| "type": "integer", |
| "minimum": 0 |
| } |
| } |
| }, |
| "ListDownloadsResponse": { |
| "type": "object", |
| "required": ["downloads"], |
| "properties": { |
| "downloads": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/DownloadProgress" |
| } |
| } |
| } |
| }, |
| "ListOperationsResponse": { |
| "type": "object", |
| "required": ["operations"], |
| "properties": { |
| "operations": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/JobSummary" |
| } |
| } |
| } |
| }, |
| "ListProjectsResponse": { |
| "type": "object", |
| "required": ["projects"], |
| "properties": { |
| "projects": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/ProjectSummary" |
| } |
| } |
| } |
| }, |
| "LlmCatalog": { |
| "type": "object", |
| "required": ["localModels", "providers"], |
| "properties": { |
| "localModels": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/LlmCatalogModel" |
| } |
| }, |
| "providers": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/LlmProviderCatalog" |
| } |
| } |
| } |
| }, |
| "LlmCatalogModel": { |
| "type": "object", |
| "required": ["target", "name", "languages"], |
| "properties": { |
| "languages": { |
| "type": "array", |
| "items": { |
| "type": "string" |
| } |
| }, |
| "name": { |
| "type": "string" |
| }, |
| "target": { |
| "$ref": "#/components/schemas/LlmTarget" |
| } |
| } |
| }, |
| "LlmGenerationOptions": { |
| "type": "object", |
| "properties": { |
| "customSystemPrompt": { |
| "type": ["string", "null"] |
| }, |
| "maxTokens": { |
| "type": ["integer", "null"], |
| "format": "int32", |
| "minimum": 0 |
| }, |
| "temperature": { |
| "type": ["number", "null"], |
| "format": "double" |
| } |
| } |
| }, |
| "LlmLoadRequest": { |
| "type": "object", |
| "required": ["target"], |
| "properties": { |
| "options": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/LlmGenerationOptions" |
| } |
| ] |
| }, |
| "target": { |
| "$ref": "#/components/schemas/LlmTarget" |
| } |
| } |
| }, |
| "LlmProviderCatalog": { |
| "type": "object", |
| "required": [ |
| "id", |
| "name", |
| "requiresApiKey", |
| "requiresBaseUrl", |
| "hasApiKey", |
| "status", |
| "models" |
| ], |
| "properties": { |
| "baseUrl": { |
| "type": ["string", "null"] |
| }, |
| "error": { |
| "type": ["string", "null"] |
| }, |
| "hasApiKey": { |
| "type": "boolean" |
| }, |
| "id": { |
| "type": "string" |
| }, |
| "models": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/LlmCatalogModel" |
| } |
| }, |
| "name": { |
| "type": "string" |
| }, |
| "requiresApiKey": { |
| "type": "boolean" |
| }, |
| "requiresBaseUrl": { |
| "type": "boolean" |
| }, |
| "status": { |
| "$ref": "#/components/schemas/LlmProviderCatalogStatus" |
| } |
| } |
| }, |
| "LlmProviderCatalogStatus": { |
| "type": "string", |
| "enum": ["ready", "missing_configuration", "discovery_failed"] |
| }, |
| "LlmState": { |
| "type": "object", |
| "required": ["status"], |
| "properties": { |
| "error": { |
| "type": ["string", "null"] |
| }, |
| "status": { |
| "$ref": "#/components/schemas/LlmStateStatus" |
| }, |
| "target": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/LlmTarget" |
| } |
| ] |
| } |
| } |
| }, |
| "LlmStateStatus": { |
| "type": "string", |
| "enum": ["empty", "loading", "ready", "failed"] |
| }, |
| "LlmTarget": { |
| "type": "object", |
| "required": ["kind", "modelId"], |
| "properties": { |
| "kind": { |
| "$ref": "#/components/schemas/LlmTargetKind" |
| }, |
| "modelId": { |
| "type": "string" |
| }, |
| "providerId": { |
| "type": ["string", "null"] |
| } |
| } |
| }, |
| "LlmTargetKind": { |
| "type": "string", |
| "enum": ["local", "provider"] |
| }, |
| "MaskData": { |
| "type": "object", |
| "required": ["role", "blob"], |
| "properties": { |
| "blob": { |
| "$ref": "#/components/schemas/BlobRef" |
| }, |
| "role": { |
| "$ref": "#/components/schemas/MaskRole" |
| } |
| } |
| }, |
| "MaskDataPatch": { |
| "type": "object", |
| "properties": { |
| "blob": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/BlobRef" |
| } |
| ] |
| } |
| } |
| }, |
| "MaskRole": { |
| "type": "string", |
| "enum": ["brushInpaint", "segment", "bubble"] |
| }, |
| "MetaInfo": { |
| "type": "object", |
| "required": ["version", "mlDevice"], |
| "properties": { |
| "mlDevice": { |
| "type": "string" |
| }, |
| "version": { |
| "type": "string" |
| } |
| } |
| }, |
| "NamedFontPrediction": { |
| "type": "object", |
| "required": ["index", "name", "probability", "serif"], |
| "properties": { |
| "index": { |
| "type": "integer", |
| "minimum": 0 |
| }, |
| "language": { |
| "type": ["string", "null"] |
| }, |
| "name": { |
| "type": "string" |
| }, |
| "probability": { |
| "type": "number", |
| "format": "float" |
| }, |
| "serif": { |
| "type": "boolean" |
| } |
| } |
| }, |
| "Node": { |
| "type": "object", |
| "required": ["id", "visible", "kind"], |
| "properties": { |
| "id": { |
| "$ref": "#/components/schemas/NodeId" |
| }, |
| "kind": { |
| "$ref": "#/components/schemas/NodeKind" |
| }, |
| "transform": { |
| "$ref": "#/components/schemas/Transform" |
| }, |
| "visible": { |
| "type": "boolean" |
| } |
| } |
| }, |
| "NodeDataPatch": { |
| "oneOf": [ |
| { |
| "type": "object", |
| "required": ["text"], |
| "properties": { |
| "text": { |
| "$ref": "#/components/schemas/TextDataPatch" |
| } |
| } |
| }, |
| { |
| "type": "object", |
| "required": ["image"], |
| "properties": { |
| "image": { |
| "$ref": "#/components/schemas/ImageDataPatch" |
| } |
| } |
| }, |
| { |
| "type": "object", |
| "required": ["mask"], |
| "properties": { |
| "mask": { |
| "$ref": "#/components/schemas/MaskDataPatch" |
| } |
| } |
| } |
| ] |
| }, |
| "NodeId": { |
| "type": "string", |
| "format": "uuid" |
| }, |
| "NodeKind": { |
| "oneOf": [ |
| { |
| "type": "object", |
| "required": ["image"], |
| "properties": { |
| "image": { |
| "$ref": "#/components/schemas/ImageData" |
| } |
| } |
| }, |
| { |
| "type": "object", |
| "required": ["text"], |
| "properties": { |
| "text": { |
| "$ref": "#/components/schemas/TextData" |
| } |
| } |
| }, |
| { |
| "type": "object", |
| "required": ["mask"], |
| "properties": { |
| "mask": { |
| "$ref": "#/components/schemas/MaskData" |
| } |
| } |
| } |
| ] |
| }, |
| "NodePatch": { |
| "type": "object", |
| "properties": { |
| "data": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/NodeDataPatch" |
| } |
| ] |
| }, |
| "transform": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/Transform" |
| } |
| ] |
| }, |
| "visible": { |
| "type": ["boolean", "null"] |
| } |
| } |
| }, |
| "Op": { |
| "oneOf": [ |
| { |
| "type": "object", |
| "required": ["updateProjectMeta"], |
| "properties": { |
| "updateProjectMeta": { |
| "type": "object", |
| "required": ["patch"], |
| "properties": { |
| "patch": { |
| "$ref": "#/components/schemas/ProjectMetaPatch" |
| }, |
| "prev": { |
| "$ref": "#/components/schemas/ProjectMetaPatch" |
| } |
| } |
| } |
| } |
| }, |
| { |
| "type": "object", |
| "required": ["addPage"], |
| "properties": { |
| "addPage": { |
| "type": "object", |
| "required": ["page", "at"], |
| "properties": { |
| "at": { |
| "type": "integer", |
| "minimum": 0 |
| }, |
| "page": { |
| "$ref": "#/components/schemas/Page" |
| } |
| } |
| } |
| } |
| }, |
| { |
| "type": "object", |
| "required": ["removePage"], |
| "properties": { |
| "removePage": { |
| "type": "object", |
| "required": ["id", "prev_page", "prev_index"], |
| "properties": { |
| "id": { |
| "$ref": "#/components/schemas/PageId" |
| }, |
| "prev_index": { |
| "type": "integer", |
| "minimum": 0 |
| }, |
| "prev_page": { |
| "$ref": "#/components/schemas/Page" |
| } |
| } |
| } |
| } |
| }, |
| { |
| "type": "object", |
| "required": ["updatePage"], |
| "properties": { |
| "updatePage": { |
| "type": "object", |
| "required": ["id", "patch"], |
| "properties": { |
| "id": { |
| "$ref": "#/components/schemas/PageId" |
| }, |
| "patch": { |
| "$ref": "#/components/schemas/PagePatch" |
| }, |
| "prev": { |
| "$ref": "#/components/schemas/PagePatch" |
| } |
| } |
| } |
| } |
| }, |
| { |
| "type": "object", |
| "required": ["reorderPages"], |
| "properties": { |
| "reorderPages": { |
| "type": "object", |
| "required": ["order", "prev_order"], |
| "properties": { |
| "order": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/PageId" |
| } |
| }, |
| "prev_order": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/PageId" |
| } |
| } |
| } |
| } |
| } |
| }, |
| { |
| "type": "object", |
| "required": ["addNode"], |
| "properties": { |
| "addNode": { |
| "type": "object", |
| "required": ["page", "node", "at"], |
| "properties": { |
| "at": { |
| "type": "integer", |
| "minimum": 0 |
| }, |
| "node": { |
| "$ref": "#/components/schemas/Node" |
| }, |
| "page": { |
| "$ref": "#/components/schemas/PageId" |
| } |
| } |
| } |
| } |
| }, |
| { |
| "type": "object", |
| "required": ["removeNode"], |
| "properties": { |
| "removeNode": { |
| "type": "object", |
| "required": ["page", "id", "prev_node", "prev_index"], |
| "properties": { |
| "id": { |
| "$ref": "#/components/schemas/NodeId" |
| }, |
| "page": { |
| "$ref": "#/components/schemas/PageId" |
| }, |
| "prev_index": { |
| "type": "integer", |
| "minimum": 0 |
| }, |
| "prev_node": { |
| "$ref": "#/components/schemas/Node" |
| } |
| } |
| } |
| } |
| }, |
| { |
| "type": "object", |
| "required": ["updateNode"], |
| "properties": { |
| "updateNode": { |
| "type": "object", |
| "required": ["page", "id", "patch"], |
| "properties": { |
| "id": { |
| "$ref": "#/components/schemas/NodeId" |
| }, |
| "page": { |
| "$ref": "#/components/schemas/PageId" |
| }, |
| "patch": { |
| "$ref": "#/components/schemas/NodePatch" |
| }, |
| "prev": { |
| "$ref": "#/components/schemas/NodePatch" |
| } |
| } |
| } |
| } |
| }, |
| { |
| "type": "object", |
| "required": ["reorderNodes"], |
| "properties": { |
| "reorderNodes": { |
| "type": "object", |
| "required": ["page", "order", "prev_order"], |
| "properties": { |
| "order": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/NodeId" |
| } |
| }, |
| "page": { |
| "$ref": "#/components/schemas/PageId" |
| }, |
| "prev_order": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/NodeId" |
| } |
| } |
| } |
| } |
| } |
| }, |
| { |
| "type": "object", |
| "required": ["batch"], |
| "properties": { |
| "batch": { |
| "type": "object", |
| "required": ["ops", "label"], |
| "properties": { |
| "label": { |
| "type": "string" |
| }, |
| "ops": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/Op" |
| } |
| } |
| } |
| } |
| } |
| } |
| ] |
| }, |
| "OpenProjectRequest": { |
| "type": "object", |
| "required": ["id"], |
| "properties": { |
| "id": { |
| "type": "string", |
| "description": "`.khrproj/` directory basename (no extension). Must exist under the\nmanaged projects directory." |
| } |
| } |
| }, |
| "Page": { |
| "type": "object", |
| "required": ["id", "name", "width", "height", "nodes"], |
| "properties": { |
| "height": { |
| "type": "integer", |
| "format": "int32", |
| "minimum": 0 |
| }, |
| "id": { |
| "$ref": "#/components/schemas/PageId" |
| }, |
| "name": { |
| "type": "string" |
| }, |
| "nodes": { |
| "type": "object", |
| "description": "Stacking = insertion order. Bottom-first: `source` is typically first,\n`rendered` typically last.", |
| "additionalProperties": { |
| "$ref": "#/components/schemas/Node" |
| }, |
| "propertyNames": { |
| "type": "string", |
| "format": "uuid" |
| } |
| }, |
| "width": { |
| "type": "integer", |
| "format": "int32", |
| "minimum": 0 |
| } |
| } |
| }, |
| "PageId": { |
| "type": "string", |
| "format": "uuid" |
| }, |
| "PagePatch": { |
| "type": "object", |
| "properties": { |
| "height": { |
| "type": ["integer", "null"], |
| "format": "int32", |
| "minimum": 0 |
| }, |
| "name": { |
| "type": ["string", "null"] |
| }, |
| "width": { |
| "type": ["integer", "null"], |
| "format": "int32", |
| "minimum": 0 |
| } |
| } |
| }, |
| "PipelineConfig": { |
| "type": "object", |
| "description": "Engine selection for each pipeline stage.\nValues are engine IDs (e.g. \"pp-doclayout-v3\", \"comic-text-detector\").\nEmpty string means use default.", |
| "properties": { |
| "bubble_segmenter": { |
| "type": "string", |
| "default": "speech-bubble-segmentation" |
| }, |
| "detector": { |
| "type": "string", |
| "default": "pp-doclayout-v3" |
| }, |
| "font_detector": { |
| "type": "string", |
| "default": "yuzumarker-font-detection" |
| }, |
| "inpainter": { |
| "type": "string", |
| "default": "lama-manga" |
| }, |
| "ocr": { |
| "type": "string", |
| "default": "paddle-ocr-vl-1.5" |
| }, |
| "renderer": { |
| "type": "string", |
| "default": "koharu-renderer" |
| }, |
| "segmenter": { |
| "type": "string", |
| "default": "comic-text-detector-seg" |
| }, |
| "translator": { |
| "type": "string", |
| "default": "llm" |
| } |
| } |
| }, |
| "PipelineConfigPatch": { |
| "type": "object", |
| "properties": { |
| "bubbleSegmenter": { |
| "type": ["string", "null"] |
| }, |
| "detector": { |
| "type": ["string", "null"] |
| }, |
| "fontDetector": { |
| "type": ["string", "null"] |
| }, |
| "inpainter": { |
| "type": ["string", "null"] |
| }, |
| "ocr": { |
| "type": ["string", "null"] |
| }, |
| "renderer": { |
| "type": ["string", "null"] |
| }, |
| "segmenter": { |
| "type": ["string", "null"] |
| }, |
| "translator": { |
| "type": ["string", "null"] |
| } |
| } |
| }, |
| "PipelineProgress": { |
| "type": "object", |
| "required": [ |
| "jobId", |
| "status", |
| "currentPage", |
| "totalPages", |
| "currentStepIndex", |
| "totalSteps", |
| "overallPercent" |
| ], |
| "properties": { |
| "currentPage": { |
| "type": "integer", |
| "minimum": 0 |
| }, |
| "currentStepIndex": { |
| "type": "integer", |
| "minimum": 0 |
| }, |
| "jobId": { |
| "type": "string" |
| }, |
| "overallPercent": { |
| "type": "integer", |
| "format": "int32", |
| "minimum": 0 |
| }, |
| "status": { |
| "$ref": "#/components/schemas/PipelineStatus" |
| }, |
| "step": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/PipelineStep" |
| } |
| ] |
| }, |
| "totalPages": { |
| "type": "integer", |
| "minimum": 0 |
| }, |
| "totalSteps": { |
| "type": "integer", |
| "minimum": 0 |
| } |
| } |
| }, |
| "PipelineStatus": { |
| "oneOf": [ |
| { |
| "type": "object", |
| "required": ["status"], |
| "properties": { |
| "status": { |
| "type": "string", |
| "enum": ["running"] |
| } |
| } |
| }, |
| { |
| "type": "object", |
| "required": ["status"], |
| "properties": { |
| "status": { |
| "type": "string", |
| "enum": ["completed"] |
| } |
| } |
| }, |
| { |
| "type": "object", |
| "required": ["status"], |
| "properties": { |
| "status": { |
| "type": "string", |
| "enum": ["cancelled"] |
| } |
| } |
| }, |
| { |
| "type": "object", |
| "required": ["reason", "status"], |
| "properties": { |
| "reason": { |
| "type": "string" |
| }, |
| "status": { |
| "type": "string", |
| "enum": ["failed"] |
| } |
| } |
| } |
| ] |
| }, |
| "PipelineStep": { |
| "type": "string", |
| "enum": ["detect", "ocr", "inpaint", "llmGenerate", "render"] |
| }, |
| "ProjectMeta": { |
| "type": "object", |
| "required": ["name", "createdAt", "updatedAt"], |
| "properties": { |
| "createdAt": { |
| "type": "string", |
| "format": "date-time" |
| }, |
| "name": { |
| "type": "string" |
| }, |
| "style": { |
| "$ref": "#/components/schemas/ProjectStyle" |
| }, |
| "updatedAt": { |
| "type": "string", |
| "format": "date-time" |
| } |
| } |
| }, |
| "ProjectMetaPatch": { |
| "type": "object", |
| "properties": { |
| "name": { |
| "type": ["string", "null"] |
| }, |
| "style": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/ProjectStyle" |
| } |
| ] |
| }, |
| "updatedAt": { |
| "type": ["string", "null"], |
| "format": "date-time" |
| } |
| } |
| }, |
| "ProjectStyle": { |
| "type": "object", |
| "properties": { |
| "defaultFont": { |
| "type": ["string", "null"] |
| } |
| } |
| }, |
| "ProjectSummary": { |
| "type": "object", |
| "required": ["id", "name", "path"], |
| "properties": { |
| "id": { |
| "type": "string", |
| "description": "Stable identifier — the `.khrproj` directory basename (without the\nextension). Clients address projects by this." |
| }, |
| "name": { |
| "type": "string" |
| }, |
| "path": { |
| "type": "string", |
| "description": "Absolute filesystem path. Informational; clients never need to pass\nit back in — they use `id`." |
| }, |
| "updatedAtMs": { |
| "type": "integer", |
| "format": "int64", |
| "description": "Last modification time of the project directory on disk (ms since\nUNIX epoch). Used for \"recent projects\" ordering.", |
| "minimum": 0 |
| } |
| } |
| }, |
| "ProviderConfig": { |
| "type": "object", |
| "required": ["id"], |
| "properties": { |
| "api_key": { |
| "type": ["string", "null"], |
| "description": "Populated from credential storage on `load()`, never written to config.toml.\nSerializes as `\"[REDACTED]\"` in API responses." |
| }, |
| "base_url": { |
| "type": ["string", "null"] |
| }, |
| "id": { |
| "type": "string" |
| } |
| } |
| }, |
| "ProviderPatch": { |
| "type": "object", |
| "required": ["id"], |
| "properties": { |
| "apiKey": { |
| "type": ["string", "null"], |
| "description": "`\"[REDACTED]\"` → keep existing keyring secret; empty → clear; otherwise save." |
| }, |
| "baseUrl": { |
| "type": ["string", "null"] |
| }, |
| "id": { |
| "type": "string" |
| } |
| } |
| }, |
| "ProviderSecretRequest": { |
| "type": "object", |
| "required": ["secret"], |
| "properties": { |
| "secret": { |
| "type": "string" |
| } |
| } |
| }, |
| "PutMaskResponse": { |
| "type": "object", |
| "required": ["node", "blob"], |
| "properties": { |
| "blob": { |
| "$ref": "#/components/schemas/BlobRef" |
| }, |
| "node": { |
| "$ref": "#/components/schemas/NodeId" |
| } |
| } |
| }, |
| "Region": { |
| "type": "object", |
| "required": ["x", "y", "width", "height"], |
| "properties": { |
| "height": { |
| "type": "integer", |
| "format": "int32", |
| "minimum": 0 |
| }, |
| "width": { |
| "type": "integer", |
| "format": "int32", |
| "minimum": 0 |
| }, |
| "x": { |
| "type": "integer", |
| "format": "int32", |
| "minimum": 0 |
| }, |
| "y": { |
| "type": "integer", |
| "format": "int32", |
| "minimum": 0 |
| } |
| } |
| }, |
| "Scene": { |
| "type": "object", |
| "required": ["project", "pages"], |
| "properties": { |
| "pages": { |
| "type": "object", |
| "description": "Pages in insertion order; `IndexMap` ordering *is* the page order.", |
| "additionalProperties": { |
| "$ref": "#/components/schemas/Page" |
| }, |
| "propertyNames": { |
| "type": "string", |
| "format": "uuid" |
| } |
| }, |
| "project": { |
| "$ref": "#/components/schemas/ProjectMeta" |
| } |
| } |
| }, |
| "SceneSnapshot": { |
| "type": "object", |
| "description": "JSON-shaped scene snapshot for the UI (no postcard decoder in JS).", |
| "required": ["epoch", "scene"], |
| "properties": { |
| "epoch": { |
| "type": "integer", |
| "format": "int64", |
| "minimum": 0 |
| }, |
| "scene": { |
| "$ref": "#/components/schemas/Scene" |
| } |
| } |
| }, |
| "SnapshotEvent": { |
| "type": "object", |
| "required": ["jobs", "downloads"], |
| "properties": { |
| "downloads": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/DownloadProgress" |
| } |
| }, |
| "jobs": { |
| "type": "array", |
| "items": { |
| "$ref": "#/components/schemas/JobSummary" |
| } |
| } |
| } |
| }, |
| "StartDownloadRequest": { |
| "type": "object", |
| "required": ["modelId"], |
| "properties": { |
| "modelId": { |
| "type": "string", |
| "description": "Package id, as declared via `declare_hf_model_package!`\n(e.g. `\"model:comic-text-detector:yolo-v5\"`)." |
| } |
| } |
| }, |
| "StartDownloadResponse": { |
| "type": "object", |
| "required": ["operationId"], |
| "properties": { |
| "operationId": { |
| "type": "string", |
| "description": "Operation id. Reusing the package id keeps ids meaningful for clients\nwatching progress events." |
| } |
| } |
| }, |
| "StartPipelineRequest": { |
| "type": "object", |
| "required": ["steps"], |
| "properties": { |
| "defaultFont": { |
| "type": ["string", "null"] |
| }, |
| "pages": { |
| "type": ["array", "null"], |
| "items": { |
| "$ref": "#/components/schemas/PageId" |
| }, |
| "description": "`None` → whole project, `Some(pages)` → just those pages." |
| }, |
| "region": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/Region", |
| "description": "Optional bounding-box hint for inpainter engines (repair-brush)." |
| } |
| ] |
| }, |
| "steps": { |
| "type": "array", |
| "items": { |
| "type": "string" |
| }, |
| "description": "Engine ids (`inventory::submit!` ids) to run in order." |
| }, |
| "systemPrompt": { |
| "type": ["string", "null"] |
| }, |
| "targetLanguage": { |
| "type": ["string", "null"] |
| }, |
| "textNodeIds": { |
| "type": ["array", "null"], |
| "items": { |
| "$ref": "#/components/schemas/NodeId" |
| }, |
| "description": "Optional text-node ids for engines that can operate on individual blocks." |
| } |
| } |
| }, |
| "StartPipelineResponse": { |
| "type": "object", |
| "required": ["operationId"], |
| "properties": { |
| "operationId": { |
| "type": "string" |
| } |
| } |
| }, |
| "TextAlign": { |
| "type": "string", |
| "enum": ["left", "center", "right"] |
| }, |
| "TextData": { |
| "type": "object", |
| "properties": { |
| "confidence": { |
| "type": "number", |
| "format": "float" |
| }, |
| "detectedFontSizePx": { |
| "type": ["number", "null"], |
| "format": "float" |
| }, |
| "detector": { |
| "type": ["string", "null"] |
| }, |
| "fontPrediction": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/FontPrediction" |
| } |
| ] |
| }, |
| "linePolygons": { |
| "type": ["array", "null"], |
| "items": { |
| "type": "array", |
| "items": { |
| "type": "array", |
| "items": { |
| "type": "number", |
| "format": "float" |
| } |
| } |
| } |
| }, |
| "lockLayoutBox": { |
| "type": "boolean" |
| }, |
| "renderedDirection": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/TextDirection" |
| } |
| ] |
| }, |
| "rotationDeg": { |
| "type": ["number", "null"], |
| "format": "float" |
| }, |
| "sourceDirection": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/TextDirection" |
| } |
| ] |
| }, |
| "sourceLang": { |
| "type": ["string", "null"] |
| }, |
| "sprite": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/BlobRef", |
| "description": "Renderer-produced sprite for this block." |
| } |
| ] |
| }, |
| "spriteTransform": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/Transform", |
| "description": "Sprite placement when the renderer expands past the bubble geometry." |
| } |
| ] |
| }, |
| "style": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/TextStyle" |
| } |
| ] |
| }, |
| "text": { |
| "type": ["string", "null"] |
| }, |
| "translation": { |
| "type": ["string", "null"] |
| } |
| } |
| }, |
| "TextDataPatch": { |
| "type": "object", |
| "description": "For fields where \"set to None\" is meaningful (e.g. clearing a translation),\nthe outer `Option` is \"patch present\", the inner is \"value present\".", |
| "properties": { |
| "confidence": { |
| "type": ["number", "null"], |
| "format": "float" |
| }, |
| "detectedFontSizePx": { |
| "type": ["number", "null"], |
| "format": "float" |
| }, |
| "detector": { |
| "type": ["string", "null"] |
| }, |
| "fontPrediction": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/FontPrediction" |
| } |
| ] |
| }, |
| "linePolygons": { |
| "type": ["array", "null"], |
| "items": { |
| "type": "array", |
| "items": { |
| "type": "array", |
| "items": { |
| "type": "number", |
| "format": "float" |
| } |
| } |
| } |
| }, |
| "lockLayoutBox": { |
| "type": ["boolean", "null"] |
| }, |
| "renderedDirection": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/TextDirection" |
| } |
| ] |
| }, |
| "rotationDeg": { |
| "type": ["number", "null"], |
| "format": "float" |
| }, |
| "sourceDirection": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/TextDirection" |
| } |
| ] |
| }, |
| "sourceLang": { |
| "type": ["string", "null"] |
| }, |
| "sprite": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/BlobRef" |
| } |
| ] |
| }, |
| "spriteTransform": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/Transform" |
| } |
| ] |
| }, |
| "style": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/TextStyle" |
| } |
| ] |
| }, |
| "text": { |
| "type": ["string", "null"] |
| }, |
| "translation": { |
| "type": ["string", "null"] |
| } |
| } |
| }, |
| "TextDirection": { |
| "type": "string", |
| "description": "Reading axis of a text block.", |
| "enum": ["horizontal", "vertical"] |
| }, |
| "TextShaderEffect": { |
| "type": "object", |
| "properties": { |
| "bold": { |
| "type": "boolean" |
| }, |
| "italic": { |
| "type": "boolean" |
| } |
| } |
| }, |
| "TextStrokeStyle": { |
| "type": "object", |
| "properties": { |
| "color": { |
| "type": "array", |
| "items": { |
| "type": "integer", |
| "format": "int32", |
| "minimum": 0 |
| } |
| }, |
| "enabled": { |
| "type": "boolean" |
| }, |
| "widthPx": { |
| "type": ["number", "null"], |
| "format": "float" |
| } |
| } |
| }, |
| "TextStyle": { |
| "type": "object", |
| "required": ["fontFamilies", "color"], |
| "properties": { |
| "color": { |
| "type": "array", |
| "items": { |
| "type": "integer", |
| "format": "int32", |
| "minimum": 0 |
| } |
| }, |
| "effect": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/TextShaderEffect" |
| } |
| ] |
| }, |
| "fontFamilies": { |
| "type": "array", |
| "items": { |
| "type": "string" |
| } |
| }, |
| "fontSize": { |
| "type": ["number", "null"], |
| "format": "float" |
| }, |
| "stroke": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/TextStrokeStyle" |
| } |
| ] |
| }, |
| "textAlign": { |
| "oneOf": [ |
| { |
| "type": "null" |
| }, |
| { |
| "$ref": "#/components/schemas/TextAlign" |
| } |
| ] |
| } |
| } |
| }, |
| "TopFont": { |
| "type": "object", |
| "required": ["index", "score"], |
| "properties": { |
| "index": { |
| "type": "integer", |
| "minimum": 0 |
| }, |
| "score": { |
| "type": "number", |
| "format": "float" |
| } |
| } |
| }, |
| "Transform": { |
| "type": "object", |
| "required": ["x", "y", "width", "height"], |
| "properties": { |
| "height": { |
| "type": "number", |
| "format": "float" |
| }, |
| "rotationDeg": { |
| "type": "number", |
| "format": "float" |
| }, |
| "width": { |
| "type": "number", |
| "format": "float" |
| }, |
| "x": { |
| "type": "number", |
| "format": "float" |
| }, |
| "y": { |
| "type": "number", |
| "format": "float" |
| } |
| } |
| } |
| } |
| } |
| } |
|
|