harness-ai-desktop
开发工具 活跃维护

harness-ai-desktop

harness-home/harness-ai-desktop

Electron开发的桌面客户端,可在本地回环地址进程内启动AI代理运行时,支持托管会话、远程审批与受控插件扩展,开箱即用无需复杂部署。

0
Stars 标星
0
Forks 分支
0
Watchers 关注
0
Open Issues
TypeScript
主要语言
MIT
开源协议
1.2 MB
仓库大小
26 天前
最后推送
一键安装扩展 / 插件指令
dsh plugin --profile web add github:harness-home/harness-ai-desktop
git clone https://github.com/harness-home/harness-ai-desktop.git
git clone git@github.com:harness-home/harness-ai-desktop.git
README.md main

harness-ai-desktop — Electron client that boots the DeepSeek Harness runtime in-process, on loopback

CI License: MIT Status: developer preview Platform: Windows x64 Electron 43 Node 22.19 or 24 and up Built on DeepSeek Harness

English · 简体中文

How it works · Features · Security · Build · Releases · Layout · Roadmap

--- **harness-ai-desktop** is the desktop client of [Harness AI](https://github.com/harness-home): a Codex / Claude Code–style agent workbench built on [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (`dsh`). The agent runtime runs **inside this app, on your machine** — in the Electron main process itself, bound to loopback, with no inbound port. The client adds what an agent runtime does not ship: an account, hosted session history that follows you to your phone, remote approvals, and a plugin market with a supply-chain gate in front of it. > [!IMPORTANT] > **Developer preview.** The upstream runtime is a developer preview and states that breaking changes are expected; this client tracks it at a pinned version. Installers are on the [Releases](https://github.com/harness-home/harness-ai-desktop/releases) page — unsigned, each carrying a SHA-256 to verify against — or [build from source](#building-from-source). ## How it works ```mermaid flowchart LR subgraph machine["Your machine"] direction TB ui["Embedded dsh Web UI
+ Harness AI plugins"] main["Electron main process"] dsh["dsh runtime, in-process
127.0.0.1:43110"] files["Workspace files · credentials · session log"] main --> dsh ui <--> dsh dsh --> files end main -.->|"outbound only"| server["harness-ai-server
account · hosted sessions · market catalog"] server -.-> phone["harness-ai-app
follow · answer · approve"] dsh -.->|"API key from the local credential store"| model["Model provider"] ``` Three properties hold that diagram together: 1. **The runtime never listens outside loopback.** Everything the mobile client sees is there because *this* client pushed it out over an outbound connection. Nothing dials in. 2. **The shell talks to the runtime through one narrow adapter** (`HarnessAdapter`), and to the hosted service through the local `/api` surface — it never reaches into `dsh` internals, which keeps an upstream upgrade a version bump rather than a rewrite. 3. **Our own features are plugins.** Branding, the account panel, the market panel, the native directory picker and the Windows sandbox runner are Cordis plugins layered onto the upstream profile — the same extension mechanism third-party plugins use. ## What it does ### Runtime hosting | | | | --- | --- | | **In-process boot** | Composes a desktop profile from the official bundle layers and boots the `dsh` Host inside the Electron main process — no child runtime, no second Node installation. | | **Loopback binding** | Binds `127.0.0.1:43110`; an occupied port moves to the next free one, up to 20 probes. | | **Version pinning** | Every `@deepseek-ai/*` package is referenced through a pnpm catalog, so an upstream upgrade is a one-line change (`pnpm dsh:version`) instead of an edit across thirty dependency entries. | | **Electron host fixes** | Two upstream code paths spawn Node through `process.execPath`, which under Electron means *a second copy of the app*. Both are corrected at the seam: a `child_process` shim for the native directory-picker worker, and a trampoline for the Windows ACL PowerShell sandbox runner. | ### Account, hosted sessions and remote control | | | | --- | --- | | **Sign-in** | Account sign-in from inside the app; each device carries its own identity and can be revoked server-side. | | **Session hosting** | Local session events are mirrored to `harness-ai-server`, so the same conversation can be read and continued from the mobile client. | | **Client-side redaction** | Credential-shaped strings are masked *before* upload, sessions whose working directory hits the denylist are never synced, and large blobs never ride the event channel. | | **Attachments** | Images the agent produced are content-addressed (`sha256:…`), uploaded on a channel of their own behind the events, deduplicated per account and capped by a server-side quota. | | **Remote approvals and prompts** | A tool that steps outside the workspace raises an approval instead of executing. Settle it at the desk, or from your phone. Prompts sent while the desktop is offline are queued server-side and drained on reconnect. | ### Plugin market, with a supply-chain gate The runtime's permission system governs tool calls, not the code a plugin ships. So every defence sits **before** installation: - **Risk flags** on each catalog entry — install scripts, native build, no provenance, no license, low adoption, new package. - **A disclosure gate** in front of every install, including installs handed over from the website via `harness-ai://install?listing=`, stating plainly that a plugin runs with the same access as the client itself. - **An integrity re-check** against the registry before anything is written: the integrity hash the catalog recorded must still match. This closes the hole a pinned version number leaves open — the same version can be republished with different bytes. - **`--ignore-scripts`, written explicitly**, never inherited from a config file that might drift. - **Capability inspection** after install, reporting what the package actually reaches for: network, file writes, native modules. - **An install journal** that records the profile manifest before every change and restores it after a failure or a crash — restoring the manifest text only, never deleting `node_modules`. ### Reliability Single-instance lock · crash audit of the previous run · secret-masked file logs · system tray · a recovery page (retry / open logs / quit) when boot fails · and a boot watchdog that measures **progress** rather than wall-clock time (20 s without progress, 180 s absolute), so a slow machine is not mistaken for a hung one. ### Updates The client checks for a new version shortly after starting and every six hours, and downloads one in the background — the tray reports it. **Nothing is ever installed behind your back.** When a version is downloaded, you are asked once: | Answer | What happens | | --- | --- | | **Restart and install** | The app restarts into the new version now. | | **Later** | The download is kept and installs the next time you quit. | | **Cancel** | The download is kept, but nothing installs by itself. The tray still offers to install it whenever you want. | Closing the dialog is the same as cancelling. A check you start yourself always answers, including "you are up to date". ## Security model | Line | Guarantee | | --- | --- | | Loopback only | The runtime binds `127.0.0.1`. No inbound connection reaches your machine — not from the server, not from the phone. | | Model keys stay local | API keys live in the `dsh` credential store on your machine and are never uploaded. | | Redaction before upload | Masking and the working-directory denylist run client-side, so the hosted service never receives what was filtered out. | | Approvals are explicit | Work outside the workspace needs a human answer, and every decision is auditable. | | Installs are disclosed | Nothing is installed without a gate that names the risk, and the website can only hand over a catalog id — never a package name and version. | Found a vulnerability? See [SECURITY.md](https://github.com/harness-home/.github/blob/main/SECURITY.md). ## Configuring an installed client Some settings belong to a network rather than to a person, and being wrong about them should not require a new build. Those live in **`harness-ai.config.json`**, next to `Harness AI.exe` in the installation directory. Edit it, restart the client, and the log line `config: plugin registry …` states what took effect. | Key | Default | What it is for | | --- | --- | --- | | `pluginRegistry` | `https://registry.npmjs.org/` | The npm registry the plugin market resolves and downloads from. Where the public registry is slow or unreachable, point it at a mirror — `https://registry.npmmirror.com/`, for instance. | | `serverUrl` | `https://api.harnessai.io` | The Harness AI service this client signs in to and syncs hosted sessions with. Self-hosted deployments point it at their own server; running your own service does not require your own build of the client. | Pointing at a mirror does not lower the bar the market enforces: the integrity re-check reads from the same registry the tarball will come from, so a mirror that serves different bytes than the catalog recorded is refused rather than trusted. It must be a mirror of the public registry, though — a registry that serves its own packages under the same names cannot satisfy that check. A malformed file never stops the client: the value is dropped, the reason is logged, and the default applies. `HARNESS_PLUGIN_REGISTRY` overrides the file for a single run. Installing an update rewrites the file with the shipped defaults, so re-apply local changes afterwards. ## Building from source **Prerequisites** — Node `^22.19.0 || >=24`, pnpm 11, Windows x64 (the only packaged target today), and a DeepSeek API key for anything that talks to a model. The wire contracts this client shares with the mobile client and the hosted service come from npm as [`@harness-ai/contracts`](https://www.npmjs.com/package/@harness-ai/contracts), so a plain clone installs and builds — nothing else from the workspace is required. ```bash pnpm install # postinstall fetches the Electron binary pnpm typecheck pnpm test # 146 unit tests, offline pnpm dev # build the in-repo plugins, then run the shell ``` | Command | What it does | | --- | --- | | `pnpm dev` | Generate icons → build in-repo plugins → `electron-vite dev`. | | `pnpm build` | Production build of main / preload / renderer plus the plugins. | | `pnpm typecheck` | `tsc --noEmit`; must be clean. | | `pnpm test` | The Vitest unit suite — offline and fast by design. | | `pnpm test:e2e` | The suite that needs the network or a real registry: plugin installs, hosted-attachment round trip. | | `pnpm dist:win` | NSIS installer into `dist/`, behind a third-party-notice gate and an `afterPack` check. | | `pnpm smoke:packaged` | Boot the packaged app and assert the loopback endpoint, the runtime page and the brand plugin. | | `pnpm dsh:version` | Move every pinned `dsh` package to a new upstream version in one step. | The release checklist, including the manual passes, is in [docs/acceptance.md](https://github.com/harness-home/harness-ai-desktop/blob/main/docs/acceptance.md). ## Releases Every push and pull request runs typecheck, the unit suite and a production build on Windows — the platform the client ships on. A release is a tag. Pushing `v` runs the same gate, packages the NSIS installer and publishes it, together with `latest.yml` and the blockmap the in-app updater reads: ```bash git tag v0.1.5 && git push origin v0.1.5 ``` The tag must match `version` in `package.json`, and [CHANGELOG.md](https://github.com/harness-home/harness-ai-desktop/blob/main/CHANGELOG.md) must carry a section for it — both are checked before anything is built, and that section becomes the release notes. Installers are **not code-signed** — SmartScreen will warn, and the release notes carry the SHA-256 to check against. ## Project layout ``` src/main/ Electron main: boot, tray, updater, crash audit, logging, deep links harness/ The dsh seam — adapter, boot, hosting bridge, market and install guard account/ Account service and device identity src/preload/ Context-isolated bridge to the renderer src/renderer/ Shell chrome around the embedded runtime UI src/shared/ i18n (en-US / zh-CN) and the shell API types plugins/ brand/ Product identity inside the runtime UI (tray, theme, sidebar) account-ui/ Sign-in and device panel market-ui/ Plugin market panel, risk chips and the install gate electron-directory-picker/ Native workspace picker windows-pwsh-sandbox/ Windows ACL sandbox runner, corrected for the Electron host scripts/ Icon generation, packaging checks, smoke and acceptance drivers ``` ## Roadmap | | | | --- | --- | | ✅ Shipped | In-process runtime hosting · account and device identity · hosted session sync · attachment sync · remote approvals and queued prompts · plugin market with the install gate · Windows packaging | | 🚧 In progress | A stable update feed — releases ship `latest.yml`, but the feed host stays a sentinel until the distribution location is settled | | 📋 Planned | macOS packaging and code signing · a second harness behind the same adapter, if and when one earns its place | ## Contributing Issues and pull requests are welcome — start with [CONTRIBUTING.md](https://github.com/harness-home/.github/blob/main/CONTRIBUTING.md). It covers the commit conventions, the English-only source rule, and how a change to upstream behaviour is expected to be staged: plugin first, upstream patch last. ## Acknowledgements Built on [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (MIT) and [Cordis](https://github.com/deepseek-ai/cordis). Third-party notices for a packaged build are generated at release time into `THIRD_PARTY_NOTICES.md`. ## License [MIT](https://github.com/harness-home/harness-ai-desktop/blob/main/LICENSE) © harness-home