From 3abd045205f11c3fcee37f729e9625ee31222fd2 Mon Sep 17 00:00:00 2001 From: "omnigent-ci[bot]" <294685417+omnigent-ci[bot]@users.noreply.github.com> Date: Wed, 19 Aug 2026 21:46:08 +0000 Subject: [PATCH] chore(api): sync openapi.json from omnigent@752d3eb --- public/openapi.json | 426 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 390 insertions(+), 36 deletions(-) diff --git a/public/openapi.json b/public/openapi.json index 7d50412..daa53ef 100644 --- a/public/openapi.json +++ b/public/openapi.json @@ -123,7 +123,7 @@ "type": "array" }, "skills": { - "description": "Skills bundled in the agent spec (`skills//SKILL.md`). Lets the Web UI's new-session composer offer a slash-command menu before a session (and its runner) exists. Host-discovered skills are runner-owned, so they are NOT listed here \u2014 the session snapshot's `skills` field carries the merged set once a runner is bound. Empty list when the spec bundles no skills or when the bundle cannot be loaded.", + "description": "Skills bundled in the agent spec (`skills//SKILL.md`). Lets the Web UI's new-session composer offer a slash-command menu before a session (and its runner) exists. Host-discovered skills are runner-owned, so they are NOT listed here \u2014 the session snapshot's `skills` field carries the merged set once a runner is bound. Empty list when the spec bundles no skills or when the bundle cannot be loaded.", "items": { "$ref": "#/components/schemas/SkillSummary" }, @@ -251,6 +251,91 @@ "title": "Body_upload_session_file_v1_sessions__session_id__resources_files_post", "type": "object" }, + "BrandingInfo": { + "properties": { + "app_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "App Name" + }, + "heading": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Heading" + }, + "logos": { + "$ref": "#/components/schemas/BrandingLogosInfo" + }, + "powered_by": { + "title": "Powered By", + "type": "boolean" + } + }, + "required": [ + "app_name", + "heading", + "logos", + "powered_by" + ], + "title": "BrandingInfo", + "type": "object" + }, + "BrandingLogosInfo": { + "properties": { + "favicon": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Favicon" + }, + "loading": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Loading" + }, + "main": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Main" + } + }, + "required": [ + "main", + "loading", + "favicon" + ], + "title": "BrandingLogosInfo", + "type": "object" + }, "BrowserActionRequestEvent": { "description": "Request that the desktop renderer perform one browser action.\n\nEmitted by the server `POST /v1/sessions/{id}/browser/action_request`\nroute when a runner-side `browser_*` tool dispatch needs the\nOmnigent desktop app's embedded browser to act. The event fans out\non the session stream to every subscribed renderer; each renderer\nfirst POSTs `/browser/action_claim/{action_id}` and only the\nwinning claimant executes the action and POSTs the result back to\n`/browser/action_result/{action_id}`. The claim lease prevents\ndouble execution when more than one renderer is subscribed.", "properties": { @@ -539,6 +624,17 @@ "description": "Sub-agent instance name, the suffix of `title` after the first `\":\"`, e.g. `\"auth\"`. `None` if `title` is `None` or missing a colon.", "title": "Session Name" }, + "task_summary": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Task Summary" + }, "title": { "anyOf": [ { @@ -1286,6 +1382,25 @@ "title": "CreatedEvent", "type": "object" }, + "DailyCost": { + "description": "One day's LLM spend for the daily timeline chart.", + "properties": { + "cost_usd": { + "default": 0.0, + "title": "Cost Usd", + "type": "number" + }, + "day": { + "title": "Day", + "type": "string" + } + }, + "required": [ + "day" + ], + "title": "DailyCost", + "type": "object" + }, "ElicitationRequestEvent": { "description": "Synchronous request for a decision from upstream.\n\nEmitted by Omnigent (or, under the new contract, by a harness)\nwhen the LLM / a tool / a policy needs a verdict before\nproceeding. The consumer replies via\n`POST /v1/sessions/{session_id}/events` with\n`type == \"approval\"` and\n`omnigent.server.schemas.ElicitationResult` fields in\n`data`. This preserves MCP request/reply correlation by id\nwithout threading elicitations through PATCH.\n\nWire shape matches the existing emit at\n`omnigent/runtime/policies/approval.py:175`.", "properties": { @@ -2476,7 +2591,7 @@ } ], "default": null, - "description": "`True` on the last chunk of a terminal-observed message; `None` otherwise. Signals the web UI that no further chunks for `message_id` will arrive.", + "description": "Optional provider completion marker for the message.", "title": "Final" }, "index": { @@ -2489,7 +2604,7 @@ } ], "default": null, - "description": "0-based chunk order within the message, e.g. `3`. `None` when not terminal-observed streaming.", + "description": "0-based chunk order within the message, e.g. `3`. Used to suppress repeated chunks; `None` for in-process streaming.", "title": "Index" }, "message_id": { @@ -2502,7 +2617,7 @@ } ], "default": null, - "description": "For terminal-observed streaming (claude-native), the vendor's stable per-message id, e.g. `\"2ca51d97-2f0f-493a-aed7-85a5b56c5747\"`. Lets the web UI scope an in-flight buffer to one assistant message and reconcile it against the final item. `None` for ordinary in-process task streaming, where deltas already group by the active response.", + "description": "For native terminal streaming, the provider's stable per-message id, e.g. `\"2ca51d97-2f0f-493a-aed7-85a5b56c5747\"`. `None` for ordinary in-process task streaming, where deltas group by the active response.", "title": "Message Id" }, "sequence_number": { @@ -3416,6 +3531,131 @@ "title": "SendCommentsRequest", "type": "object" }, + "ServerInfoResponse": { + "properties": { + "accounts_enabled": { + "title": "Accounts Enabled", + "type": "boolean" + }, + "branding": { + "$ref": "#/components/schemas/BrandingInfo" + }, + "databricks_features": { + "title": "Databricks Features", + "type": "boolean" + }, + "dictation_available": { + "title": "Dictation Available", + "type": "boolean" + }, + "features": { + "additionalProperties": { + "type": "boolean" + }, + "title": "Features", + "type": "object" + }, + "harness_install_enabled": { + "title": "Harness Install Enabled", + "type": "boolean" + }, + "installable_harnesses": { + "items": { + "type": "string" + }, + "title": "Installable Harnesses", + "type": "array" + }, + "login_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Login Url" + }, + "managed_sandboxes_enabled": { + "title": "Managed Sandboxes Enabled", + "type": "boolean" + }, + "needs_setup": { + "title": "Needs Setup", + "type": "boolean" + }, + "public_sharing_enabled": { + "title": "Public Sharing Enabled", + "type": "boolean" + }, + "sandbox_provider": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Sandbox Provider" + }, + "sandbox_providers": { + "items": { + "type": "string" + }, + "title": "Sandbox Providers", + "type": "array" + }, + "server_version": { + "title": "Server Version", + "type": "string" + }, + "sharing_mode": { + "enum": [ + "on", + "read_only", + "restricted_read_only", + "off" + ], + "title": "Sharing Mode", + "type": "string" + }, + "single_user": { + "title": "Single User", + "type": "boolean" + }, + "smart_routing_enabled": { + "title": "Smart Routing Enabled", + "type": "boolean" + }, + "smart_routing_sources": { + "$ref": "#/components/schemas/SmartRoutingSourcesInfo" + } + }, + "required": [ + "accounts_enabled", + "single_user", + "login_url", + "needs_setup", + "databricks_features", + "managed_sandboxes_enabled", + "sandbox_provider", + "sandbox_providers", + "sharing_mode", + "public_sharing_enabled", + "server_version", + "smart_routing_enabled", + "smart_routing_sources", + "features", + "harness_install_enabled", + "installable_harnesses", + "dictation_available", + "branding" + ], + "title": "ServerInfoResponse", + "type": "object" + }, "ServerStreamEvent": { "discriminator": { "mapping": { @@ -5797,6 +6037,17 @@ "SessionUsage": { "description": "One session's rolled-up LLM spend for the `GET /v1/usage` report.\n\n`cost_usd` is the subtree total \u2014 the session plus every sub-agent it\nspawned \u2014 read from `session_usage` via\n`omnigent.runtime.policies.builder.load_session_usage`. It is the\nauthoritative session figure (the same value the web session sidebar\nshows as \"Session cost\" and the daily rollup records).\n\n`models` is the per-model cost breakdown, mirroring the web session\nsidebar's per-model list. Deliberately **not guaranteed to sum to\n`cost_usd`**: native harnesses report a single cumulative session\ntotal and the server attributes it to the currently-active model, so on\na session that switched models mid-run each model's bucket is a snapshot\nof the running total rather than that model's own spend. The header\n`cost_usd` stays authoritative; the per-model values are shown\nfaithfully as recorded (same convention as the web UI).", "properties": { + "agent_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Agent Name" + }, "cost_usd": { "default": 0.0, "description": "Authoritative cumulative USD spend for this session's subtree.", @@ -5808,11 +6059,33 @@ "title": "Created At", "type": "integer" }, + "harness": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Harness" + }, "id": { "description": "Session/conversation identifier, e.g. `\"conv_abc123\"`.", "title": "Id", "type": "string" }, + "llm_model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Llm Model" + }, "models": { "additionalProperties": { "type": "number" @@ -5821,6 +6094,20 @@ "title": "Models", "type": "object" }, + "other_harnesses": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Other Harnesses" + }, "title": { "anyOf": [ { @@ -6081,6 +6368,24 @@ "title": "SlashCommandData", "type": "object" }, + "SmartRoutingSourcesInfo": { + "properties": { + "external": { + "title": "External", + "type": "boolean" + }, + "oss": { + "title": "Oss", + "type": "boolean" + } + }, + "required": [ + "external", + "oss" + ], + "title": "SmartRoutingSourcesInfo", + "type": "object" + }, "StoreHarnessCredentialRequest": { "description": "Request body for `POST /v1/hosts/{id}/harnesses/{harness}/credential`.\n\nCarries the credential in the body (never the URL). The secret field is\noptional so the `adopt` kind \u2014 which references an existing host env var\nby name rather than sending a value \u2014 can omit it.", "properties": { @@ -6925,6 +7230,13 @@ "title": "Cost Today", "type": "number" }, + "daily_costs": { + "items": { + "$ref": "#/components/schemas/DailyCost" + }, + "title": "Daily Costs", + "type": "array" + }, "object": { "const": "usage_report", "default": "usage_report", @@ -7222,6 +7534,74 @@ ] } }, + "/v1/branding/logo/{variant}": { + "get": { + "description": "Serve a validated public branding asset, or 404 when unset.", + "operationId": "branding_logo_v1_branding_logo__variant__get", + "parameters": [ + { + "in": "path", + "name": "variant", + "required": true, + "schema": { + "title": "Variant", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "image/gif": { + "schema": { + "format": "binary", + "type": "string" + } + }, + "image/jpeg": { + "schema": { + "format": "binary", + "type": "string" + } + }, + "image/png": { + "schema": { + "format": "binary", + "type": "string" + } + }, + "image/webp": { + "schema": { + "format": "binary", + "type": "string" + } + }, + "image/x-icon": { + "schema": { + "format": "binary", + "type": "string" + } + } + }, + "description": "Validated raster branding image" + }, + "404": { + "description": "Branding image not configured or invalid" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Branding Logo" + } + }, "/v1/harnesses": { "get": { "operationId": "list_harnesses_v1_harnesses_get", @@ -7621,7 +8001,7 @@ }, "/v1/hosts/{host_id}/harnesses/{harness}/credential": { "post": { - "description": "Write a harness provider credential onto a connected host.\n\nBacks the Web UI setup dialog's \"Add a credential\" action so a user can\nconfigure a Claude / Codex / Pi credential on a connected host without a\nterminal. Owner-scoped, allowlisted, and gated behind\n`OMNIGENT_HARNESS_INSTALL_ENABLED` exactly like the install route\n(404 when disabled). The host daemon does the write with the same\nnon-interactive core the `omnigent setup` wizard uses.\n\nSecurity: the server is an authz'd pass-through \u2014 it validates\nownership + the allowlist and forwards the secret over the (TLS) tunnel;\nit never persists the secret or logs it. The secret rides in the request\nbody (not the URL), and the frame field is redaction-named so it never\nlands on a telemetry span.\n\n**Parameters**\n\n- `body` \u2014 The credential payload (kind + secret / gateway / adopt).\n\n**Returns:** `{\"object\": \"harness_credential\", \"harness\": ..., \"configured_harnesses\": {...}, \"gateway_inference\": {...} | None}` \u2014 refreshed readiness so the UI can flip the badge without a reconnect, plus the refreshed gateway-inference map (`None` when the host didn't report one).\n\n**Raises**\n\n- `HTTPException` \u2014 404 when disabled or host unknown, 400 when the harness isn't UI-configurable or the body is invalid, 403 when not the owner, 409 when offline, 502 on host-side failure, 504 on timeout.", + "description": "Write a harness provider credential onto a connected host.\n\nBacks the Web UI setup dialog's \"Add a credential\" action so a user can\nconfigure a Claude / Codex / Pi credential on a connected host without a\nterminal. Owner-scoped, allowlisted, and gated behind\n`harness_install` release feature exactly like the install route\n(404 when disabled). The host daemon does the write with the same\nnon-interactive core the `omnigent setup` wizard uses.\n\nSecurity: the server is an authz'd pass-through \u2014 it validates\nownership + the allowlist and forwards the secret over the (TLS) tunnel;\nit never persists the secret or logs it. The secret rides in the request\nbody (not the URL), and the frame field is redaction-named so it never\nlands on a telemetry span.\n\n**Parameters**\n\n- `body` \u2014 The credential payload (kind + secret / gateway / adopt).\n\n**Returns:** `{\"object\": \"harness_credential\", \"harness\": ..., \"configured_harnesses\": {...}, \"gateway_inference\": {...} | None}` \u2014 refreshed readiness so the UI can flip the badge without a reconnect, plus the refreshed gateway-inference map (`None` when the host didn't report one).\n\n**Raises**\n\n- `HTTPException` \u2014 404 when disabled or host unknown, 400 when the harness isn't UI-configurable or the body is invalid, 403 when not the owner, 409 when offline, 502 on host-side failure, 504 on timeout.", "operationId": "store_host_harness_credential_v1_hosts__host_id__harnesses__harness__credential_post", "parameters": [ { @@ -7687,7 +8067,7 @@ }, "/v1/hosts/{host_id}/harnesses/{harness}/install": { "post": { - "description": "Install a missing, npm-installable harness CLI onto a host.\n\nBacks the Web UI's New Chat dialog \"Install\" action so a user can\ninstall a harness the connected host is missing without dropping to a\nterminal. Owner-scoped like the other host actions: only the host owner\nmay install onto it. Scoped to the UI-installable allowlist (claude,\ncodex, pi, opencode, qwen) \u2014 curl/brew and interactive-auth harnesses\nare refused. The whole route is gated behind\n`OMNIGENT_HARNESS_INSTALL_ENABLED` (default off): when disabled it\nreturns 404 so the feature is invisible until opted in.\n\nConcurrent requests for the same (host, harness) coalesce onto one\nin-flight install so a double-click can't fire two global npm installs.\n\n**Returns:** `{\"object\": \"harness_install\", \"harness\": ..., \"configured_harnesses\": {...}, \"gateway_inference\": {...} | None}` \u2014 the host's refreshed readiness map so the UI can flip the badge without a reconnect, plus its refreshed gateway-inference map (`None` when the host didn't report one).\n\n**Raises**\n\n- `HTTPException` \u2014 404 when the feature is disabled or the host is unknown, 400 when the harness is not UI-installable, 403 when the caller is not the host owner, 409 when the host is offline, 502 on a host-side install failure, 504 on host timeout.", + "description": "Install a missing, npm-installable harness CLI onto a host.\n\nBacks the Web UI's New Chat dialog \"Install\" action so a user can\ninstall a harness the connected host is missing without dropping to a\nterminal. Owner-scoped like the other host actions: only the host owner\nmay install onto it. Scoped to the UI-installable allowlist (claude,\ncodex, pi, opencode, qwen) \u2014 curl/brew and interactive-auth harnesses\nare refused. The whole route is gated behind\n`harness_install` in `OMNIGENT_FEATURES` (default off): when\ndisabled it returns 404 so the feature is invisible until opted in.\n\nConcurrent requests for the same (host, harness) coalesce onto one\nin-flight install so a double-click can't fire two global npm installs.\n\n**Returns:** `{\"object\": \"harness_install\", \"harness\": ..., \"configured_harnesses\": {...}, \"gateway_inference\": {...} | None}` \u2014 the host's refreshed readiness map so the UI can flip the badge without a reconnect, plus its refreshed gateway-inference map (`None` when the host didn't report one).\n\n**Raises**\n\n- `HTTPException` \u2014 404 when the feature is disabled or the host is unknown, 400 when the harness is not UI-installable, 403 when the caller is not the host owner, 409 when the host is offline, 502 on a host-side install failure, 504 on host timeout.", "operationId": "install_host_harness_v1_hosts__host_id__harnesses__harness__install_post", "parameters": [ { @@ -7964,33 +8344,7 @@ "content": { "application/json": { "schema": { - "additionalProperties": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "string" - }, - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "additionalProperties": { - "type": "boolean" - }, - "type": "object" - }, - { - "type": "null" - } - ] - }, - "title": "Response Info V1 Info Get", - "type": "object" + "$ref": "#/components/schemas/ServerInfoResponse" } } }, @@ -10373,7 +10727,7 @@ }, "/v1/sessions/{session_id}/permissions/{target_user_id}": { "delete": { - "description": "Revoke a user's permission on a session.\n\nRequires manage-level access. Cannot revoke your own\nmanage grant (prevents orphaned sessions). Returns 204\nwhether or not the grant existed (idempotent).\n\n**Returns:** 204 No Content.\n\n**Raises**\n\n- `OmnigentError` \u2014 404 if no session or no access, 403 if attempting to revoke own manage grant.", + "description": "Revoke a permission on a session \u2014 someone else's, or your own.\n\nTwo shapes, one endpoint:\n\n* *Revoke* \u2014 removing **another** user's grant is a management\n action and needs manage access.\n* *Leave* \u2014 removing **your own** grant (\"unshare myself\", so a\n shared session stops cluttering your sidebar) needs only read\n access, since giving up access requires no privilege.\n\nEither way the owner grant is protected: it is what keeps the\nsession reachable, so revoking it would orphan the session. That\nguard covers the self case too \u2014 an owner cannot leave, and\narchives or deletes instead. A manage-level *grantee* is still a\nguest and may leave. Leaving records no lasting refusal, so the\nowner re-granting brings the session back.\n\nIdempotent: 204 whether or not a grant existed.\n\n**Returns:** 204 No Content.\n\n**Raises**\n\n- `OmnigentError` \u2014 404 if no session or no access, 403 when the target holds the owner grant, 400 when leaving a sub-agent session, 401 if unauthenticated.", "operationId": "revoke_permission_v1_sessions__session_id__permissions__target_user_id__delete", "parameters": [ { @@ -10387,7 +10741,7 @@ } }, { - "description": "User whose grant to revoke, e.g. `\"alice@example.com\"`.", + "description": "User whose grant to revoke, or the caller's own id to leave, e.g. `\"alice@example.com\"`.", "in": "path", "name": "target_user_id", "required": true, @@ -12391,7 +12745,7 @@ }, "/v1/sessions/{source_id}/fork": { "post": { - "description": "Fork an existing session into a new session.\n\nDeep-copies the source session's conversation items and\nclones the agent into a new session. When `body.agent_id`\nis set, the fork binds that built-in agent instead of the\nsource's \u2014 switching harness (e.g. Claude-SDK \u2192 Claude Code,\nor Claude \u2192 Codex). The source's model settings carry over\nonly within the same provider family; a same-family native\ntarget also carries conversation history (the runner rebuilds\nits transcript). The REPL/CLI binds the fork to its runner via\n`PATCH /v1/sessions/{id}` after creation.\n\nWhen `body.up_to_response_id` is set, only history up to and\nincluding that response is copied into the fork (a \"fork from\nthis response\"); a native target then rebuilds its transcript\nfrom the truncated items instead of resuming the source's full\nnative transcript.\n\n**Parameters**\n\n- `body` \u2014 The validated `SessionForkRequest`.\n\n**Returns:** A `SessionResponse` describing the newly created fork (status `\"idle\"`).\n\n**Raises**\n\n- `OmnigentError` \u2014 404 if *source_id* does not exist or `body.agent_id` is not a bindable built-in agent; 403 if the caller lacks read access; 400 if the source is a sub-agent session, has no agent binding, or `body.up_to_response_id` names no response in the source session.", + "description": "Fork an existing session into a new session.\n\nDeep-copies the source session's conversation items and\nclones the agent into a new session. When `body.agent_id`\nis set, the fork binds that built-in agent instead of the\nsource's \u2014 switching harness (e.g. Claude-SDK \u2192 Claude Code,\nor Claude \u2192 Codex). The source's model settings carry over\nonly within the same provider family; a same-family native\ntarget also carries conversation history (the runner rebuilds\nits transcript). The REPL/CLI binds the fork to its runner via\n`PATCH /v1/sessions/{id}` after creation.\n\nWhen `body.up_to_response_id` is set, only history up to and\nincluding that response is copied into the fork (a \"fork from\nthis response\"); a native target then rebuilds its transcript\nfrom the truncated items instead of resuming the source's full\nnative transcript.\n\nA sub-agent source is allowed, which is how a sub-agent is\npromoted to a session of its own: the fork is always a fresh\ntop-level conversation (no parent, its own spawn-tree root, its\nown owner grant), so it appears in the sidebar and outlives the\nparent. The source keeps running under its parent untouched,\nand the fork does not adopt the source's own children.\n\n**Parameters**\n\n- `body` \u2014 The validated `SessionForkRequest`.\n\n**Returns:** A `SessionResponse` describing the newly created fork (status `\"idle\"`).\n\n**Raises**\n\n- `OmnigentError` \u2014 404 if *source_id* does not exist or `body.agent_id` is not a bindable built-in agent; 403 if the caller lacks read access; 400 if the source has no agent binding, or `body.up_to_response_id` names no response in the source session.", "operationId": "fork_session_v1_sessions__source_id__fork_post", "parameters": [ {