feat(server): expose browser transport
This commit is contained in:
parent
aaadc40fbc
commit
57c939f188
15 changed files with 2236 additions and 208 deletions
|
|
@ -160,6 +160,134 @@
|
|||
"summary": "Get server information"
|
||||
}
|
||||
},
|
||||
"/api/browser/control": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"browser"
|
||||
],
|
||||
"operationId": "v2.browser.control.connect",
|
||||
"parameters": [],
|
||||
"security": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "InvalidRequestError",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/InvalidRequestError"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "UnauthorizedError",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/UnauthorizedError"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "WebSocket Origin is not allowed."
|
||||
},
|
||||
"409": {
|
||||
"description": "ConflictError",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ConflictError"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"426": {
|
||||
"description": "WebSocket subprotocol opencode.browser.control.v1 is required."
|
||||
}
|
||||
},
|
||||
"description": "Establish an authenticated WebSocket carrying Session-scoped browser attachments and semantic browser commands.",
|
||||
"summary": "Connect desktop browser host",
|
||||
"x-websocket": true,
|
||||
"x-websocket-subprotocol": "opencode.browser.control.v1",
|
||||
"x-websocket-incoming": "BrowserControl.FromDesktop",
|
||||
"x-websocket-outgoing": "BrowserControl.FromServer"
|
||||
}
|
||||
},
|
||||
"/api/browser/tunnel": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"browser"
|
||||
],
|
||||
"operationId": "v2.browser.tunnel.connect",
|
||||
"parameters": [],
|
||||
"security": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "InvalidRequestError",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/InvalidRequestError"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "UnauthorizedError",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/UnauthorizedError"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "WebSocket Origin is not allowed."
|
||||
},
|
||||
"426": {
|
||||
"description": "WebSocket subprotocol opencode.browser.tunnel.v1 is required."
|
||||
},
|
||||
"503": {
|
||||
"description": "ServiceUnavailableError",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ServiceUnavailableError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Establish an authenticated WebSocket carrying one TCP stream dialed from the OpenCode server.",
|
||||
"summary": "Open browser network tunnel",
|
||||
"x-websocket": true,
|
||||
"x-websocket-subprotocol": "opencode.browser.tunnel.v1",
|
||||
"x-websocket-incoming": "BrowserTunnel.FromDesktop and binary DATA frames",
|
||||
"x-websocket-outgoing": "BrowserTunnel.FromServer and binary DATA frames"
|
||||
}
|
||||
},
|
||||
"/api/location": {
|
||||
"get": {
|
||||
"tags": [
|
||||
|
|
@ -12012,6 +12140,64 @@
|
|||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"ConflictError": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"_tag": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"ConflictError"
|
||||
]
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"resource": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"_tag",
|
||||
"message"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"ServiceUnavailableError": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"_tag": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"ServiceUnavailableError"
|
||||
]
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"service": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"_tag",
|
||||
"message"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"Location.Info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
@ -12838,35 +13024,6 @@
|
|||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"ConflictError": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"_tag": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"ConflictError"
|
||||
]
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"resource": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"_tag",
|
||||
"message"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"CommandNotFoundError": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
@ -13058,35 +13215,6 @@
|
|||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"ServiceUnavailableError": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"_tag": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"ServiceUnavailableError"
|
||||
]
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"service": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"_tag",
|
||||
"message"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"SessionBusyError": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
@ -13705,7 +13833,14 @@
|
|||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
|
@ -13715,7 +13850,7 @@
|
|||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"LLM.ToolContent": {
|
||||
"Tool.Content": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/Tool.TextContent"
|
||||
|
|
@ -13741,12 +13876,12 @@
|
|||
"type": "array",
|
||||
"prefixItems": [
|
||||
{
|
||||
"$ref": "#/components/schemas/LLM.ToolContent"
|
||||
"$ref": "#/components/schemas/Tool.Content"
|
||||
}
|
||||
],
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/LLM.ToolContent"
|
||||
"$ref": "#/components/schemas/Tool.Content"
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
|
|
@ -13795,12 +13930,12 @@
|
|||
"type": "array",
|
||||
"prefixItems": [
|
||||
{
|
||||
"$ref": "#/components/schemas/LLM.ToolContent"
|
||||
"$ref": "#/components/schemas/Tool.Content"
|
||||
}
|
||||
],
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/LLM.ToolContent"
|
||||
"$ref": "#/components/schemas/Tool.Content"
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
|
|
@ -17114,6 +17249,49 @@
|
|||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"Tool.FileContent1": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"file"
|
||||
]
|
||||
},
|
||||
"uri": {
|
||||
"type": "string"
|
||||
},
|
||||
"mime": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"uri",
|
||||
"mime"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"Tool.Content1": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/Tool.TextContent"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/Tool.FileContent1"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Session.Message.ProviderState8": {
|
||||
"type": "object"
|
||||
},
|
||||
|
|
@ -17197,12 +17375,12 @@
|
|||
"type": "array",
|
||||
"prefixItems": [
|
||||
{
|
||||
"$ref": "#/components/schemas/LLM.ToolContent"
|
||||
"$ref": "#/components/schemas/Tool.Content1"
|
||||
}
|
||||
],
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/LLM.ToolContent"
|
||||
"$ref": "#/components/schemas/Tool.Content1"
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
|
|
@ -17320,12 +17498,12 @@
|
|||
"type": "array",
|
||||
"prefixItems": [
|
||||
{
|
||||
"$ref": "#/components/schemas/LLM.ToolContent"
|
||||
"$ref": "#/components/schemas/Tool.Content1"
|
||||
}
|
||||
],
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/LLM.ToolContent"
|
||||
"$ref": "#/components/schemas/Tool.Content1"
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
|
|
@ -29135,6 +29313,10 @@
|
|||
{
|
||||
"name": "server"
|
||||
},
|
||||
{
|
||||
"name": "browser",
|
||||
"description": "Desktop browser host control and server-network tunnel routes."
|
||||
},
|
||||
{
|
||||
"name": "location"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import { SkillGroup } from "./groups/skill.js"
|
|||
import { EventGroup, makeEventGroup } from "./groups/event.js"
|
||||
import type { Definition } from "@opencode-ai/schema/event"
|
||||
import { AgentGroup } from "./groups/agent.js"
|
||||
import { BrowserGroup } from "./groups/browser.js"
|
||||
import { PluginGroup } from "./groups/plugin.js"
|
||||
import { HealthGroup } from "./groups/health.js"
|
||||
import { ServerGroup } from "./groups/server.js"
|
||||
|
|
@ -85,6 +86,7 @@ type ApiGroups<
|
|||
| typeof HealthGroup
|
||||
| typeof ServerGroup
|
||||
| typeof DebugGroup
|
||||
| typeof BrowserGroup
|
||||
| LocationGroups<LocationId>
|
||||
| FormGroups<LocationId, LocationService, FormLocationId, FormLocationService>
|
||||
| SessionGroups<SessionLocationId, SessionLocationService>
|
||||
|
|
@ -146,6 +148,7 @@ const makeApiFromGroup = <
|
|||
HttpApi.make("server")
|
||||
.add(HealthGroup)
|
||||
.add(ServerGroup)
|
||||
.add(BrowserGroup)
|
||||
.add(LocationGroup.middleware(locationMiddleware))
|
||||
.add(AgentGroup.middleware(locationMiddleware))
|
||||
.add(PluginGroup.middleware(locationMiddleware))
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ export const groupNames = {
|
|||
"server.debug": "debug",
|
||||
"server.location": "location",
|
||||
"server.agent": "agent",
|
||||
"server.browser": "browser",
|
||||
"server.plugin": "plugin",
|
||||
"server.session": "session",
|
||||
"server.message": "message",
|
||||
|
|
@ -63,5 +64,16 @@ export const groupNames = {
|
|||
"server.vcs": "vcs",
|
||||
} as const
|
||||
|
||||
export const promiseOmitEndpoints = new Set(["pty.connect", "pty.connectToken"])
|
||||
export const effectOmitEndpoints = new Set(["fs.read", "pty.connect", "pty.connectToken"])
|
||||
export const promiseOmitEndpoints = new Set([
|
||||
"browser.control.connect",
|
||||
"browser.tunnel.connect",
|
||||
"pty.connect",
|
||||
"pty.connectToken",
|
||||
])
|
||||
export const effectOmitEndpoints = new Set([
|
||||
"browser.control.connect",
|
||||
"browser.tunnel.connect",
|
||||
"fs.read",
|
||||
"pty.connect",
|
||||
"pty.connectToken",
|
||||
])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue