Agent preset
deskpet-bridge
DeskPet Bridge - a local JS agent preset for DSH (DeepSeek Harness)
- Source
- dfzjb
- stars
- 3 stars
- Updated
- Updated 6 hours ago
Readme
# DeskPet Bridge
English | [中文](README.zh.md)
A local JavaScript **agent preset** for [DSH (DeepSeek Harness)](https://github.com/deepseek-ai/deepseek-harness) that exposes the agent's runtime status over HTTP + SSE and adds a **programmable approval channel**.
## Overview
`deskpet-bridge` is a standalone agent preset (three files) that you drop into DSH's `.agent-presets/` directory. It requires **no modification to the DSH codebase**.
## What it does for DSH
### 1. Extends DSH's web server
Registers three new routes on DSH's built-in `webServer`, giving DSH a few externally-callable endpoints:
| Endpoint | Purpose |
|---|---|
| `GET /api/deskpet/v2/get-status` | Query the current agent status snapshot |
| `GET /api/deskpet/v2/events` | Server-Sent Events realtime stream |
| `POST /api/deskpet/v2/approve` | Submit an approval decision |
### 2. Status observability
Listens to DSH's internal `agent/status` event, maintains a status cache (`idle` / `running` …), and counts state changes (`changes`) plus agent count (`agentCount`) — making DSH's runtime state queryable and subscribable by external programs.
### 3. Programmable approval channel (core)
Acts as an **answerer** in DSH's approval mechanism:
- Registers on `approval/request` with `{ prepend: true }`, claiming the approval ahead of DSH's default approval panel (`api-proxy`).
- Holds the approval (returns a pending Promise) and pushes the request to external clients over SSE.
- Resolves the approval when an external client submits a decision via `/approve` — **allowed-once** or **rejected**.
- Times out after 120 s (or on abort signal) as **cancelled**, so approvals never hang forever.
### 4. Realtime event stream
Broadcasts DSH internal events over SSE: `hello` / `agent-status` / `approval-request` / `approval-decided` / `approval-expired`, with a 5-second heartbeat.
### 5. Graceful fallback
When no external client is connected, the approval answerer calls `next()`, falling back to DSH's default approval panel — so DSH's original approval flow stays intact.
## Files
| File | Purpose |
|---|---|
| `agent.cordis.yml` | Composition entry: `id: deskpet-bridge` + `name: ./bridge.js` |
| `bridge.js` | Core plugin (ESM: `export name / inject / apply`) |
| `preset.yml` | Preset metadata (name + description) |
## Installation
Copy the three files into `%DSH_HOME%/.agent-presets/deskpet-bridge/`, then select (or set as default) the `deskpet-bridge` preset for your agent session.
## API Contract
Base: `http://127.0.0.1:3080` · Prefix: `/api/deskpet/v2/`
**GET /get-status**
```json
{"ok":true,"status":"idle","agentCount":4,"changes":0,"connectedClients":0,"pendingApprovals":0}
```
**GET /events** (SSE, `text/event-stream`)
Events: `hello` / `agent-status` / `approval-request` / `approval-decided` / `approval-expired`
**POST /approve**
```json
{"approvalId":"appr_N","decision":"approve-once"} → 200 {"ok":true,"outcome":"allowed-once"}
{"approvalId":"appr_N","decision":"reject"} → 200 {"ok":true,"outcome":"rejected"}
Unknown approvalId → 404 {"ok":false,"error":"unknown approvalId"}
```
## How approval works
```text
approval/request (waterfall)
└─ prepend answerer claims it
├─ external client connected → hold + push SSE approval-request
│ └─ POST /approve → resolve allowed-once / rejected
└─ no client → next() → DSH default approval panel
120s timeout / abort → cancelled
```
## License
MIT — aligned with DSH's license.
Install
# Copy the composition to $DSH_HOME/.agent-presets/deskpet-bridge/agent.cordis.yml
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dfzjb-deskpet-bridge from the hub