Skip to content

Latest commit

 

History

History
139 lines (109 loc) · 5.13 KB

File metadata and controls

139 lines (109 loc) · 5.13 KB

Generic Server

opagent-server is a minimal, local HTTP host for runtime.Runtime. It is intended for CLIs, local apps, integration tests, and small developer tools—not as a public multi-user service.

Defaults and authentication

  • Address: 127.0.0.1:19531
  • Data: ~/.opagent
  • Token: <baseDir>/run/local-connection-token
  • Header: X-OpAgent-Connection-Token

v0.1 accepts only explicit loopback IP addresses. /health and /version are public probes; every /v1 endpoint requires the token. The token is a 32-byte random base64url capability stored in a 0600 regular file below a 0700 run directory.

The Server also embeds /web/, a static single-Workspace console. Static assets load without a Token so the connection screen can render; all data APIs remain authenticated.

API

Method and path Purpose
GET /health Liveness response
GET /version Server name and version
GET /v1/config/models List safe model summaries without API Tokens
PUT /v1/config/model Add or update one standalone provider model
GET /v1/workspace/list List Server-authorized Workspace roots
POST /v1/workspace/open Register a directory when the host opted in
GET /v1/files?workspaceID=...&path=... List one Workspace directory
GET /v1/file?workspaceID=...&path=... Read one bounded UTF-8 text file
POST /v1/thread/create Create a Runtime-owned thread
POST /v1/chat/stream Submit or reconnect to a turn over SSE
POST /v1/chat/control Interrupt a thread turn
GET /v1/thread/snapshot?threadID=... Read the persisted Runtime snapshot

Create request:

{"agentID":"agent-web","workspaceID":"workspace-...","title":"First chat"}

Existing embedders may continue to pass an explicit cwd; callers must not send both workspaceID and cwd. A workspaceID request first sets that Workspace to trusted and selects Runtime's full profile with host-file and internet access confirmed; the explicit cwd form retains the host's existing permission workflow.

Model save request:

{
  "providerKey": "openai",
  "providerLabel": "OpenAI",
  "api": "openai-responses",
  "baseURL": "https://api.openai.com/v1",
  "apiToken": "secret",
  "modelID": "gpt-5.4",
  "modelLabel": "GPT 5.4"
}

apiToken may be omitted when updating an existing model. The Server preserves the saved value, writes models.json atomically with mode 0600, reloads Runtime configuration, and returns only hasAPIToken: true.

Workspace and file boundary

Options.Workspaces registers explicit filesystem roots. If none are supplied to the Go API or CLI, <baseDir>/workspace is created and used. With standalone defaults, that path is ~/.opagent/workspace. AllowWorkspaceOpen is false by default; the command enables dynamic opening, but never infers the process working directory as a Workspace.

File paths are always relative to a registered root. The Server resolves symlinks and uses a traversal-resistant directory capability for the actual open. Preview is limited to regular UTF-8 text files no larger than 2 MiB. Runtime state and Workspace roots containing <baseDir> are rejected. v0.1 does not write, rename, upload, or delete Workspace files.

Chat request:

{
  "threadID": "thread-...",
  "modelKey": "provider:model",
  "message": "Explain this repository",
  "turnRequestID": "turnreq-client-generated"
}

turnRequestID is generated when omitted. Retrying an existing ID must use the same thread, model, and message or the Server returns 409.

Interrupt request:

{"threadID":"thread-...","action":"interrupt"}

SSE and reconnect

Each SSE data value is a Protocol GeneralContent. Event IDs have the form <turnRequestID>:<sequence>. Reconnect by resending the identical chat request with Last-Event-ID. The Server retains at most 256 events per turn and 128 active/recent turns for five minutes; an expired replay returns 409.

Slow clients are detached from the live stream instead of blocking Runtime. Disconnecting a client does not cancel the turn. Use the interrupt endpoint for explicit cancellation. Runtime shutdown cancels all in-flight handlers.

Embedding

srv, err := server.New(server.Options{
    BaseDir: "/absolute/data",
    Workspaces: []string{"/absolute/workspace"},
})
if err != nil { /* handle */ }

handler := srv.Handler() // httptest or another loopback host
err = srv.Run(ctx)       // owns Runtime + HTTP lifecycle

Pass Runtime in Options to reuse a ready-compatible implementation. Its BaseDir must match the Server base directory.

Ready() synchronizes browser launch and WebURL(true) returns a local bootstrap URL with the connection Token in the fragment. The Web client immediately moves that Token to per-origin sessionStorage and removes the fragment.

The Server has no second message store, websocket surface, file mutation, terminal, SSH manager, user accounts, tenant auth, public-network listener, or OpenAI-compatible endpoint. For remote use, forward the remote loopback port and connect the browser to that local forwarded URL; ongoing file and chat requests then execute on the target Server machine.