DeepSeek Harness Plugin Hub

Publish and manage complete Harness Profiles. Discover Plugins for your next setup.

Explore

PluginsPresetsDocsNews

Community

Publish a pluginContactReport an issue

Resources

Plugin Hub on GitHubDeepSeek HarnessSystem statusPrivacy notice
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

Independent and unofficial. Not affiliated with, authorized by, or endorsed by DeepSeek.

DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in
← Plugins
O

dsh-openai-api

Openai Api

OpenAI-compatible HTTP surface backed by DSH agent sessions: POST /v1/chat/completions, POST /v1/responses, GET /v1/models over the harness webServer + agents services, plus a sidebar panel showing the base URL

The plugin will be installed here. Keep web if you are unsure.

npx -y @deepseek-ai/dsh plugin --profile web add github:huyang2024/dsh-openai-api#6af6c9edaf0dc5c0fa9ec130ecf44cf153464c4e
READMECompatibilityVersions

Compatibility and provenance

Openai Api is published as dsh-openai-api and currently resolves to version 0.3.0. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
web
Release source
github
Registry updated
10/28/2026

Versions

0.3.0stable
10/28/2026
0.2.0stable
10/27/2026

Related plugins

Loading related plugins…

Latest
0.3.0
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
Unavailable
Files
Unavailable
Surface
web
License
MIT
Source
github
GitHub
★ 3
Weekly downloads
0
Last push
10/28/2026
View source ↗
README badge

Click the badge to copy Markdown for your README.

Do you maintain this Plugin?Claim benefit · Priority security scan

Verify the GitHub repository declared in package.json to manage this listing. After you claim it, Hub will prioritize a security scan of the current version and publish the result when it passes.

Claim this Plugin →
Report an issue

Related plugins

More verified plugins in integrations-communication.

Acp App@deepseek-ai/dsh-acp-appThe dsh ACP profile bundle: automation-only JSON-RPC stdio and process lifecycle over dsh-baseRemote Web Ui@linxin666/dsh-remote-web-uiScan-to-pair remote access for the dsh web GUI that shares one official interface: a QR beside the settings button pairs phones and PCs into the same Web GUI (a portrait-touch adaptation layer for phones, full desktop on PCs) through one-time tokens and rRemote Bridge@linxin666/dsh-remote-bridgeDSH remote bridge: the host half serves protocol v1 over one exact /ios/v1 WebSocket route — session roster, history baseline, prompting, live turn increments with tool activity, interrupt, and in-process agent approval — to a device paired by a one-shot Im@xmanrui/dsh-im把微信、飞书、企微、钉钉、QQ、Telegram、WhatsApp、Slack、Discord、Matrix接入DSH。 Connect Telegram, WhatsApp, Slack, Discord, Matrix, WeChat, Feishu, WeCom, DingTalk, and QQ to DSH.

README

dsh-openai-api

OpenAI-compatible HTTP surface for DeepSeek Harness, backed by real DSH agent sessions.

After this plugin is installed into a dsh profile, the harness web server additionally serves:

EndpointPurpose
POST /v1/chat/completionsChat Completions API (streaming + non-streaming)
POST /v1/responsesResponses API subset (streaming + non-streaming)
GET /v1/modelsAdvertised model id

It also adds an API row at the sidebar foot (above Settings) showing the live base URL and port — see Sidebar panel.

What "agent-backed" means

Each request is served by a live DSH agent session (the harness agents registry + the agent loop), so every call gets the agent's full world: its configured tools, bash/files access, skills, prompt sections, and preset persona. This is an agent gateway, not a thin LLM proxy:

  • The agent owns tool use. Client-side tools / tool_choice / function-call messages are rejected — the agent decides what tools to call and why.
  • Streaming deltas arrive once per committed assistant message, not per token. Reasoning, tool calls, and token-level chunk streams stay off the wire; only committed assistant text reaches the client.
  • The first request for a (key, preset, session) triple seeds a session by rendering the client's full message array into a labeled transcript prompt; later requests admit only the latest user turn (the session already holds the history).

Session identity

(API key tenant, X-Agent-Preset, X-Session-Id):

  • The accepted apiKey namespaces the caller — one session per key, so different keys never share a session even for the same preset, and a client resumes its own session on reconnect.
  • The X-Agent-Preset header names the preset the session joins (absent → the profile default). Resolved only at session creation.
  • The optional X-Session-Id header (usually a URL-encoded role name) splits sessions further per role and is used as the session title. The mapping is persisted, so a profile restart resumes the previous session; a session that has been archived is recreated.

Install

# from GitHub
dsh plugin --profile web add github:huyang2024/dsh-openai-api

# or from a local checkout
dsh plugin --profile web add file:/absolute/path/to/dsh-openai-api

The package declares a DSH bundle and automatically contributes the openai-api component when newly installed into a profile, so no manual insert: is needed. Installing it from the Desktop Plugins page and choosing Enable now applies immediately; installing through the CLI requires a profile restart.

For DSH Desktop, initialize the app once, fully quit it, and use the desktop app's bundled dsh command with --profile desktop instead of --profile web (register it from the app's Manage dsh Command… menu). The npm-installed CLI cannot manage the desktop profile. You can also install this package from the desktop Plugins page using the GitHub spec or an absolute local checkout path, then choose Enable now.

Desktop uses a dynamically assigned HTTP port by default, rather than 3080. Use its actual listening address as the API base URL — the API row at the sidebar foot shows it, so the port never has to be hunted down; GET /v1/models checks that the plugin is running without calling a model.

To customize the component, update the existing row in the profile's user patch layer — $DSH_HOME/profiles/web/cordis.patch.yml (or profiles/desktop/cordis.patch.yml for Desktop):

- id: openai-api
  config:
    pathPrefix: '/v1'     # optional, default shown
    model: default        # optional; model id advertised at /v1/models
    # provider: my-provider    # optional; omit to use the host default provider
    # cwd: /absolute/workdir   # optional; omit to use the `dsh web` process cwd
    # apiKeys:                 # optional; omit for one keyless loopback-only tenant
    #   - local-key

Omit an optional key entirely rather than writing an empty value: apiKeys: [], provider: '', and cwd: '' are rejected by configuration validation (apiKeys must be a non-empty array, provider a non-empty string, and cwd an absolute path).

Restart the profile after editing its configuration.

Sidebar panel

Once the plugin is enabled, an API row appears at the sidebar foot (above Settings), styled like the harness's own To-dos row: icon, title, muted port, chevron. It starts collapsed; clicking it reveals the detail upwards (the toggle keeps its place first in the DOM, so tab and screen-reader order are unchanged), and the chevron flips down while open.

  • Collapsed it shows only the port, which is the number callers need (and on Desktop it is the runtime-assigned one, read live).
  • Expanding checks once by itself: it reads the descriptor, then requests GET <prefix>/models — that lists models and never calls one.
  • The result shares the row with the button: blue dot when the surface answers, red when it does not. The Detect button appears only when the surface is unreachable, as a retry; a 401 means the surface answered and wants a key, which counts as healthy and shows no button.
  • Base URL is generated from the live listener and copies in one click; Usage example expands to a curl line and every endpoint path.
  • Auth / Model id show whether a key is required, or that the surface is keyless and loopback-only.

The first frame after expanding already carries the full layout, so values fill in without a flash. The descriptor is read once per page session and cached: collapsing and reopening paints immediately and only re-runs the probe, and the port stays on the row while collapsed.

Hovering or opening uses the same fill as the settings and account navigation rows (a theme token, so it follows light and dark). The detail is height-capped and scrolls internally, so it never pushes out of the sidebar.

In the collapsed 56px rail the row becomes an icon button and the detail floats beside the rail, because the rail is too narrow for an inline reveal; its tooltip is the full base URL.

On Desktop the page is served over the app carrier, so the panel shows the local HTTP address to paste into other programs while the check still uses the current page. The panel never shows a key, only whether one is configured.

The panel reads an allowlisted descriptor, primarily from /api/openai-api/status: registered on the DSH Connection service, it inherits the host's loopback/origin trust checks, browser authentication, and owner-only access, and it works from the Desktop dsh-app: page through the app carrier.

Where the host supports webserver/index-inject, the same object is also injected into the authenticated index as a boot snapshot, as a fallback when a request cannot be made; Desktop currently uses the route.

The descriptor carries only pathPrefix, model, authRequired, the listener origin, and the port — never a key, provider, or cwd. A failed read shows its reason and a retry button; the OpenAI endpoints are unaffected.

Upgrading an existing installation

The package is now named dsh-openai-api. If you installed the old scoped package, uninstall it before installing this version.

Earlier versions installed as plain dependencies without a bundle declaration. After updating the package, enable it on the Plugins page; the CLI does not automatically enable a dependency that was already installed. Alternatively, add dsh-openai-api to the existing dsh.profile.bundles array in the profile's package.json, preserving the other entries.

If you previously added an insert: block for openai-api, replace just that entry with the id/config override above, keeping your configuration values and any unrelated entries. The bundle now owns the component insertion.

Configuration

All keys optional; created sessions fall back to the host defaults.

keydefaultwhat it does
modeldefaultModel id advertised at /v1/models. A request's model (absent, or this id) uses the host default selection; any other id is passed to the session as the model.
providerhost defaultProvider route for created sessions.
apiKeysunsetPer-client keys. Each distinct key is a separate tenant — one session per (key, preset, session). When set, a request must present one (Authorization: Bearer <key>); otherwise it is a 401. Unset, the surface is a single keyless tenant restricted to loopback callers.
cwdthe dsh web process's cwdAbsolute working directory for created sessions. POSIX starts with /; Windows accepts D:/dir or D:\dir.
pathPrefix/v1Route prefix for all three endpoints.
maxBodyBytes33554432Maximum accepted JSON request body in bytes.
allowedOriginsunsetExtra browser origins allowed to call cross-origin (exact origin strings).

Using the API

Use the Base URL the sidebar API row shows (Desktop assigns the port dynamically):

import OpenAI from 'openai'
const client = new OpenAI({ baseURL: 'http://127.0.0.1:3080/v1', apiKey: 'local-key' })

// Optional: choose the agent preset the session joins (absent → default preset).
const preset = { 'X-Agent-Preset': 'custom-agent-preset' }

const reply = await client.chat.completions.create(
  { model: 'default', messages: [{ role: 'user', content: 'What are you?' }] },
  { headers: preset },
)

/v1/responses follows the same session model; previous_response_id is accepted and ignored (the sticky session is the store).

Auth and trust

  • With apiKeys set, an exact Authorization: Bearer <key> is required and the matched key is the tenant.
  • Without apiKeys, only loopback callers are served (a deliberate hardening over the reference implementation, so an accidental LAN bind never exposes unauthenticated agent access).
  • Browser cross-origin calls from other origins are rejected outright — a valid key does not bypass the origin fence; list the origin in allowedOrigins when cross-origin access is genuinely needed. Preflight OPTIONS is answered on all three paths.

Local development

node --check lib/index.js     # syntax
node client/build.mjs         # build lib/client.js (browser half) from client/ sources
npm test                      # unit tests plus the protocol smoke test
node test/smoke.mjs           # the protocol smoke test alone

The browser half is built from:

FileRole
client/model.jsPure helpers: descriptor validation, address derivation, probe classification, curl example
client/ui.jsThe collapsible row and its detail (shared React plus model only)
client/entry.jsRegisters the sidebar.footer.action slot
client/styles.cssStyling, on the DSH theme tokens

lib/client.js is generated — edit the sources under client/ and rebuild. client/build.mjs --check verifies the committed artifact matches its sources. The smoke test loads the real plugin, so it attempts a session-map read and write (a failed write is only logged).