diff --git a/AGENTS.md b/AGENTS.md index 52bc6c0a571..ddefe527d6a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -181,18 +181,19 @@ A change is done when all are true: ## 11. Fork-Specific: HenkDz/paperclip -This is a fork of `paperclipai/paperclip` with QoL patches and an **external-only** Hermes adapter story on branch `feat/externalize-hermes-adapter` ([tree](https://github.com/HenkDz/paperclip/tree/feat/externalize-hermes-adapter)). +This is a fork of `paperclipai/paperclip` with QoL patches and a **built-in** Hermes adapter story on branch `feat/externalize-hermes-adapter` ([tree](https://github.com/HenkDz/paperclip/tree/feat/externalize-hermes-adapter)). ### Branch Strategy -- `feat/externalize-hermes-adapter` → core has **no** `hermes-paperclip-adapter` dependency and **no** built-in `hermes_local` registration. Install Hermes via the Adapter Plugin manager (`@henkey/hermes-paperclip-adapter` or a `file:` path). -- Older fork branches may still document built-in Hermes; treat this file as authoritative for the externalize branch. +- `feat/externalize-hermes-adapter` now ships `hermes_local` and `hermes_gateway` as built-in core adapters. +- Older fork branches may still document plugin-only Hermes; treat this file as authoritative for the current branch. -### Hermes (plugin only) +### Hermes (built-in) -- Register through **Board → Adapter manager** (same as Droid). Type remains `hermes_local` once the package is loaded. -- UI uses generic **config-schema** + **ui-parser.js** from the package — no Hermes imports in `server/` or `ui/` source. -- Optional: `file:` entry in `~/.paperclip/adapter-plugins.json` for local dev of the adapter repo. +- `hermes_local` is available without Adapter manager installation and runs the local Hermes CLI. +- `hermes_gateway` is available without Adapter manager installation and calls an already-running Hermes API server. +- Operators may still install external Hermes packages through Adapter manager to override/shadow the built-ins. +- Optional: `file:` entry in `~/.paperclip/adapter-plugins.json` remains useful for local development of override packages. ### Local Dev @@ -217,5 +218,5 @@ PR #2218 (`feat/external-adapter-phase1`) adds external adapter support. See roo - Adapters can be loaded as external plugins via `~/.paperclip/adapter-plugins.json` - The plugin-loader should have ZERO hardcoded adapter imports — pure dynamic loading - `createServerAdapter()` must include ALL optional fields (especially `detectModel`) -- Built-in UI adapters can shadow external plugin parsers — remove built-in when fully externalizing -- Reference external adapters: Hermes (`@henkey/hermes-paperclip-adapter` or `file:`) and Droid (npm) +- Built-in UI adapters can shadow external plugin parsers; external override pause/resume should restore the built-in parser. +- Reference external adapters: Droid (npm); Hermes can also be tested as an override package. diff --git a/cli/esbuild.config.mjs b/cli/esbuild.config.mjs index 7976b7c9cdf..c4506d4d629 100644 --- a/cli/esbuild.config.mjs +++ b/cli/esbuild.config.mjs @@ -21,6 +21,8 @@ const workspacePaths = [ "packages/adapter-utils", "packages/adapters/claude-local", "packages/adapters/codex-local", + "packages/adapters/hermes-gateway", + "packages/adapters/hermes-local", "packages/adapters/openclaw-gateway", ]; diff --git a/cli/package.json b/cli/package.json index ed894750eb6..8ad6c2ccad8 100644 --- a/cli/package.json +++ b/cli/package.json @@ -44,6 +44,7 @@ "@paperclipai/adapter-cursor-local": "workspace:*", "@paperclipai/adapter-gemini-local": "workspace:*", "@paperclipai/adapter-grok-local": "workspace:*", + "@paperclipai/adapter-hermes-gateway": "workspace:*", "@paperclipai/adapter-opencode-local": "workspace:*", "@paperclipai/adapter-pi-local": "workspace:*", "@paperclipai/adapter-openclaw-gateway": "workspace:*", @@ -51,6 +52,7 @@ "@paperclipai/db": "workspace:*", "@paperclipai/server": "workspace:*", "@paperclipai/shared": "workspace:*", + "@paperclipai/hermes-paperclip-adapter": "workspace:*", "drizzle-orm": "0.45.2", "dotenv": "^17.0.1", "commander": "^13.1.0", diff --git a/cli/src/adapters/registry.ts b/cli/src/adapters/registry.ts index 31dfe0d0af7..ca77e4ff5a7 100644 --- a/cli/src/adapters/registry.ts +++ b/cli/src/adapters/registry.ts @@ -6,6 +6,8 @@ import { printCursorStreamEvent } from "@paperclipai/adapter-cursor-local/cli"; import { printCursorCloudEvent } from "@paperclipai/adapter-cursor-cloud/cli"; import { printGeminiStreamEvent } from "@paperclipai/adapter-gemini-local/cli"; import { printGrokStreamEvent } from "@paperclipai/adapter-grok-local/cli"; +import { formatStdoutEvent as printHermesGatewayStreamEvent } from "@paperclipai/adapter-hermes-gateway/cli"; +import { printHermesStreamEvent } from "@paperclipai/hermes-paperclip-adapter/cli"; import { printOpenCodeStreamEvent } from "@paperclipai/adapter-opencode-local/cli"; import { printPiStreamEvent } from "@paperclipai/adapter-pi-local/cli"; import { printOpenClawGatewayStreamEvent } from "@paperclipai/adapter-openclaw-gateway/cli"; @@ -57,6 +59,16 @@ const grokLocalCLIAdapter: CLIAdapterModule = { formatStdoutEvent: printGrokStreamEvent, }; +const hermesGatewayCLIAdapter: CLIAdapterModule = { + type: "hermes_gateway", + formatStdoutEvent: printHermesGatewayStreamEvent, +}; + +const hermesLocalCLIAdapter: CLIAdapterModule = { + type: "hermes_local", + formatStdoutEvent: printHermesStreamEvent, +}; + const openclawGatewayCLIAdapter: CLIAdapterModule = { type: "openclaw_gateway", formatStdoutEvent: printOpenClawGatewayStreamEvent, @@ -73,6 +85,8 @@ const adaptersByType = new Map( cursorCloudCLIAdapter, geminiLocalCLIAdapter, grokLocalCLIAdapter, + hermesGatewayCLIAdapter, + hermesLocalCLIAdapter, openclawGatewayCLIAdapter, processCLIAdapter, httpCLIAdapter, diff --git a/doc/SPEC-implementation.md b/doc/SPEC-implementation.md index e3246ed6da9..44ff0bb0372 100644 --- a/doc/SPEC-implementation.md +++ b/doc/SPEC-implementation.md @@ -153,7 +153,7 @@ Invariant: every business record belongs to exactly one company. - `status` enum: `active | paused | idle | running | error | pending_approval | terminated` - `reports_to` uuid fk `agents.id` null - `capabilities` text null -- `adapter_type` text; built-ins include `process`, `http`, `claude_local`, `codex_local`, `gemini_local`, `opencode_local`, `pi_local`, `cursor`, and `openclaw_gateway` +- `adapter_type` text; built-ins include `process`, `http`, `claude_local`, `codex_local`, `gemini_local`, `opencode_local`, `pi_local`, `cursor`, `hermes_local`, `hermes_gateway`, and `openclaw_gateway` - `adapter_config` jsonb not null - `runtime_config` jsonb not null default `{}`; may include Paperclip runtime policy such as `modelProfiles.cheap.adapterConfig` for an optional low-cost model lane that does not change the primary adapter config - `default_environment_id` uuid fk `environments.id` null diff --git a/docs/adapters/overview.md b/docs/adapters/overview.md index dfb4b21fb3a..1682244c1fd 100644 --- a/docs/adapters/overview.md +++ b/docs/adapters/overview.md @@ -25,6 +25,7 @@ When a heartbeat fires, Paperclip: | Cursor | `cursor` | Runs Cursor in background mode | | Pi Local | `pi_local` | Runs an embedded Pi agent locally | | Hermes Local | `hermes_local` | Runs Hermes CLI locally (`hermes-paperclip-adapter`) | +| Hermes Gateway | `hermes_gateway` | Connects to a running Hermes API server | | OpenClaw Gateway | `openclaw_gateway` | Connects to an OpenClaw gateway endpoint | | [Process](/adapters/process) | `process` | Executes arbitrary shell commands | | [HTTP](/adapters/http) | `http` | Sends webhooks to external agents | diff --git a/docs/agents-runtime.md b/docs/agents-runtime.md index 81bbda7ca15..9176ed8f10a 100644 --- a/docs/agents-runtime.md +++ b/docs/agents-runtime.md @@ -40,6 +40,7 @@ Built-in adapters: - `cursor`: runs Cursor in background mode - `pi_local`: runs an embedded Pi agent locally - `hermes_local`: runs your local `hermes` CLI (`hermes-paperclip-adapter`) +- `hermes_gateway`: connects to a running Hermes API server - `openclaw_gateway`: connects to an OpenClaw gateway endpoint - `process`: generic shell command adapter - `http`: calls an external HTTP endpoint @@ -48,7 +49,7 @@ External plugin adapters (install via the adapter manager or API): - `droid_local`: runs your local Factory Droid CLI (`@henkey/droid-paperclip-adapter`) -For local CLI adapters (`claude_local`, `codex_local`, `opencode_local`, `hermes_local`, `droid_local`), Paperclip assumes the CLI is already installed and authenticated on the host machine. +For local CLI adapters (`claude_local`, `codex_local`, `opencode_local`, `hermes_local`, `droid_local`), Paperclip assumes the CLI is already installed and authenticated on the host machine. For `hermes_gateway`, Paperclip assumes the Hermes API server is already reachable and configured with an API key. ## 3.2 Runtime behavior diff --git a/docs/guides/board-operator/managing-agents.md b/docs/guides/board-operator/managing-agents.md index 4850222d0af..ff48bdbc655 100644 --- a/docs/guides/board-operator/managing-agents.md +++ b/docs/guides/board-operator/managing-agents.md @@ -28,8 +28,8 @@ Create agents from the Agents page. Each agent requires: - **Capabilities** — short description of what this agent does Common adapter choices: -- `claude_local` / `codex_local` / `opencode_local` for local coding agents -- `openclaw_gateway` / `http` for webhook-based external agents +- `claude_local` / `codex_local` / `opencode_local` / `hermes_local` for local coding agents +- `hermes_gateway` / `openclaw_gateway` / `http` for webhook-based external agents - `process` for generic local command execution For `opencode_local`, configure an explicit `adapterConfig.model` (`provider/model`). diff --git a/packages/adapters/hermes-gateway/README.md b/packages/adapters/hermes-gateway/README.md index c09b42d83af..6235656c4c4 100644 --- a/packages/adapters/hermes-gateway/README.md +++ b/packages/adapters/hermes-gateway/README.md @@ -1,10 +1,10 @@ # Hermes Gateway Adapter -External Paperclip adapter for Hermes Agent's authenticated HTTP/SSE API server. +Built-in Paperclip adapter for Hermes Agent's authenticated HTTP/SSE API server. -Install it through Paperclip's Adapter manager as a local path or npm package. The -adapter type is `hermes_gateway`; it is intentionally not registered as a built-in -core adapter. +The adapter type is `hermes_gateway` and ships with Paperclip core. Operators can +still install an external adapter package with the same type through Adapter +manager when they intentionally want to override the built-in. Required config: diff --git a/packages/adapters/hermes-gateway/tsconfig.json b/packages/adapters/hermes-gateway/tsconfig.json index e1b71318a68..8fea361a345 100644 --- a/packages/adapters/hermes-gateway/tsconfig.json +++ b/packages/adapters/hermes-gateway/tsconfig.json @@ -2,7 +2,8 @@ "extends": "../../../tsconfig.base.json", "compilerOptions": { "outDir": "dist", - "rootDir": "src" + "rootDir": "src", + "types": ["node"] }, "include": ["src"] } diff --git a/packages/adapters/hermes-local/README.md b/packages/adapters/hermes-local/README.md index a514c4ce8bc..ee16bba5d13 100644 --- a/packages/adapters/hermes-local/README.md +++ b/packages/adapters/hermes-local/README.md @@ -35,9 +35,8 @@ This adapter provides: ## Installation -```bash -npm install @paperclipai/hermes-paperclip-adapter -``` +This package ships with Paperclip core as the built-in `hermes_local` adapter. +No Adapter manager installation is required for normal Paperclip use. ### Prerequisites @@ -47,17 +46,12 @@ npm install @paperclipai/hermes-paperclip-adapter ## Quick Start -### 1. Install the adapter in Paperclip - -Install through **Board -> Adapter manager**: - -```text -@paperclipai/hermes-paperclip-adapter -``` +### 1. Optional: override the built-in for adapter development For local adapter development, install the package from a local path in Adapter manager, or add an entry to `~/.paperclip/adapter-plugins.json` and restart -Paperclip: +Paperclip. The external package can override the built-in `hermes_local` +adapter while it is enabled: ```json [ @@ -72,8 +66,8 @@ Paperclip: The adapter package exports `createServerAdapter()` for the server, a declarative config schema for the generic agent form, and `./ui-parser` for run -transcript parsing. Paperclip core does not require source edits or a built-in -`hermes_local` registration. +transcript parsing. Paperclip core imports these same package entrypoints for +the built-in adapter registration. ### 2. Create a Hermes agent in Paperclip diff --git a/packages/adapters/hermes-local/tsconfig.json b/packages/adapters/hermes-local/tsconfig.json index e1b71318a68..8fea361a345 100644 --- a/packages/adapters/hermes-local/tsconfig.json +++ b/packages/adapters/hermes-local/tsconfig.json @@ -2,7 +2,8 @@ "extends": "../../../tsconfig.base.json", "compilerOptions": { "outDir": "dist", - "rootDir": "src" + "rootDir": "src", + "types": ["node"] }, "include": ["src"] } diff --git a/packages/shared/src/constants.ts b/packages/shared/src/constants.ts index 085fb132457..ff0ea742475 100644 --- a/packages/shared/src/constants.ts +++ b/packages/shared/src/constants.ts @@ -35,6 +35,8 @@ export const AGENT_ADAPTER_TYPES = [ "codex_local", "cursor_cloud", "gemini_local", + "hermes_gateway", + "hermes_local", "opencode_local", "pi_local", "cursor", diff --git a/scripts/generate-npm-package-json.mjs b/scripts/generate-npm-package-json.mjs index f7be8cc04ba..1b285388082 100644 --- a/scripts/generate-npm-package-json.mjs +++ b/scripts/generate-npm-package-json.mjs @@ -32,6 +32,8 @@ const workspacePaths = [ "packages/adapter-utils", "packages/adapters/claude-local", "packages/adapters/codex-local", + "packages/adapters/hermes-gateway", + "packages/adapters/hermes-local", "packages/adapters/opencode-local", "packages/adapters/openclaw-gateway", ]; diff --git a/server/package.json b/server/package.json index 1e87e8144e5..50cd461e81e 100644 --- a/server/package.json +++ b/server/package.json @@ -51,6 +51,7 @@ "@paperclipai/adapter-cursor-local": "workspace:*", "@paperclipai/adapter-gemini-local": "workspace:*", "@paperclipai/adapter-grok-local": "workspace:*", + "@paperclipai/adapter-hermes-gateway": "workspace:*", "@paperclipai/adapter-openclaw-gateway": "workspace:*", "@paperclipai/adapter-opencode-local": "workspace:*", "@paperclipai/adapter-pi-local": "workspace:*", @@ -59,6 +60,7 @@ "@paperclipai/plugin-sdk": "workspace:*", "@paperclipai/shared": "workspace:*", "@paperclipai/skills-catalog": "workspace:*", + "@paperclipai/hermes-paperclip-adapter": "workspace:*", "ajv": "^8.20.0", "ajv-formats": "^3.0.1", "better-auth": "1.6.20", diff --git a/server/src/__tests__/adapter-registry.test.ts b/server/src/__tests__/adapter-registry.test.ts index fecdb883a63..a642cb9f0c3 100644 --- a/server/src/__tests__/adapter-registry.test.ts +++ b/server/src/__tests__/adapter-registry.test.ts @@ -38,6 +38,7 @@ describe("server adapter registry", () => { beforeEach(() => { unregisterServerAdapter("external_test"); unregisterServerAdapter("hermes_local"); + unregisterServerAdapter("hermes_gateway"); unregisterServerAdapter("claude_local"); setOverridePaused("claude_local", false); }); @@ -45,6 +46,7 @@ describe("server adapter registry", () => { afterEach(() => { unregisterServerAdapter("external_test"); unregisterServerAdapter("hermes_local"); + unregisterServerAdapter("hermes_gateway"); unregisterServerAdapter("claude_local"); setOverridePaused("claude_local", false); }); @@ -128,11 +130,22 @@ describe("server adapter registry", () => { ]); }); - it("does not ship hermes_local as a built-in adapter, but accepts it externally", () => { - expect(findServerAdapter("hermes_local")).toBeNull(); - expect(() => requireServerAdapter("hermes_local")).toThrow( - "Unknown adapter type: hermes_local", - ); + it("ships Hermes adapters as built-ins and still accepts external overrides", () => { + const builtInLocal = findServerAdapter("hermes_local"); + const builtInGateway = findServerAdapter("hermes_gateway"); + + expect(builtInLocal).not.toBeNull(); + expect(builtInLocal?.supportsLocalAgentJwt).toBe(true); + expect(builtInLocal?.supportsInstructionsBundle).toBe(true); + expect(builtInLocal?.requiresMaterializedRuntimeSkills).toBe(false); + expect(builtInLocal?.detectModel).toBeTypeOf("function"); + expect(builtInLocal?.getConfigSchema).toBeTypeOf("function"); + + expect(builtInGateway).not.toBeNull(); + expect(builtInGateway?.supportsLocalAgentJwt).toBe(false); + expect(builtInGateway?.supportsInstructionsBundle).toBe(false); + expect(builtInGateway?.requiresMaterializedRuntimeSkills).toBe(false); + expect(builtInGateway?.getConfigSchema).toBeTypeOf("function"); const hermesExternalAdapter: ServerAdapterModule = { type: "hermes_local", @@ -167,6 +180,10 @@ describe("server adapter registry", () => { expect(requireServerAdapter("hermes_local")).toBe(hermesExternalAdapter); expect(findActiveServerAdapter("hermes_local")?.supportsLocalAgentJwt).toBe(true); + + unregisterServerAdapter("hermes_local"); + + expect(requireServerAdapter("hermes_local")).toBe(builtInLocal); }); it("exposes capability flags from registered adapters", () => { diff --git a/server/src/__tests__/adapter-routes.test.ts b/server/src/__tests__/adapter-routes.test.ts index 4969e330e55..13e57a3539c 100644 --- a/server/src/__tests__/adapter-routes.test.ts +++ b/server/src/__tests__/adapter-routes.test.ts @@ -187,9 +187,25 @@ describe("adapter routes", () => { requiresMaterializedRuntimeSkills: true, }); - // Hermes is external-only on this branch and must not appear until the - // Adapter Manager loads @paperclipai/hermes-paperclip-adapter. - expect(res.body.find((a: any) => a.type === "hermes_local")).toBeUndefined(); + const hermesLocal = res.body.find((a: any) => a.type === "hermes_local"); + expect(hermesLocal).toBeDefined(); + expect(hermesLocal.source).toBe("builtin"); + expect(hermesLocal.capabilities).toMatchObject({ + supportsInstructionsBundle: true, + supportsSkills: true, + supportsLocalAgentJwt: true, + requiresMaterializedRuntimeSkills: false, + }); + + const hermesGateway = res.body.find((a: any) => a.type === "hermes_gateway"); + expect(hermesGateway).toBeDefined(); + expect(hermesGateway.source).toBe("builtin"); + expect(hermesGateway.capabilities).toMatchObject({ + supportsInstructionsBundle: false, + supportsSkills: false, + supportsLocalAgentJwt: false, + requiresMaterializedRuntimeSkills: false, + }); }); it("GET /api/adapters derives supportsSkills from listSkills/syncSkills presence", async () => { @@ -271,6 +287,28 @@ describe("adapter routes", () => { expect(keys).not.toContain("bootstrapPromptTemplate"); }); + it("serves built-in Hermes config schemas", async () => { + const app = createApp(); + + const local = await request(app).get("/api/adapters/hermes_local/config-schema"); + expect(local.status, JSON.stringify(local.body)).toBe(200); + expect(local.body.fields).toEqual( + expect.arrayContaining([ + expect.objectContaining({ key: "provider" }), + expect.objectContaining({ key: "timeoutSec" }), + ]), + ); + + const gateway = await request(app).get("/api/adapters/hermes_gateway/config-schema"); + expect(gateway.status, JSON.stringify(gateway.body)).toBe(200); + expect(gateway.body.fields).toEqual( + expect.arrayContaining([ + expect.objectContaining({ key: "apiBaseUrl", required: true }), + expect.objectContaining({ key: "apiKey", required: true }), + ]), + ); + }); + it("GET /api/adapters includes ACPX model availability", async () => { const app = createApp(); diff --git a/server/src/adapters/builtin-adapter-types.ts b/server/src/adapters/builtin-adapter-types.ts index 82438523df7..505162f7edd 100644 --- a/server/src/adapters/builtin-adapter-types.ts +++ b/server/src/adapters/builtin-adapter-types.ts @@ -9,6 +9,8 @@ export const BUILTIN_ADAPTER_TYPES = new Set([ "cursor", "gemini_local", "grok_local", + "hermes_gateway", + "hermes_local", "openclaw_gateway", "opencode_local", "pi_local", diff --git a/server/src/adapters/hermes-gateway-doc.ts b/server/src/adapters/hermes-gateway-doc.ts index 2db9a10de53..8fc2716806c 100644 --- a/server/src/adapters/hermes-gateway-doc.ts +++ b/server/src/adapters/hermes-gateway-doc.ts @@ -8,11 +8,11 @@ Use when: - The Hermes runtime may live on another host, a private overlay, in Docker, or behind a TLS reverse proxy. Don't use when: -- Paperclip should start the Hermes CLI directly on the same host. Use hermes_local from the external Hermes adapter plugin for that flow. +- Paperclip should start the Hermes CLI directly on the same host. Use the built-in hermes_local adapter for that flow. - Hermes is the process calling Paperclip APIs after claiming its key. That is Hermes-originated Paperclip API usage, not the gateway adapter transport. Runtime distinction: -- hermes_local: Paperclip starts Hermes on the Paperclip host through the external Hermes adapter plugin. +- hermes_local: Paperclip starts Hermes on the Paperclip host through the built-in local adapter. - hermes_gateway: Paperclip calls an already-running Hermes API server using agentDefaultsPayload.apiBaseUrl. - Hermes-originated Paperclip API usage: Hermes calls Paperclip with PAPERCLIP_API_URL and PAPERCLIP_BRIDGE_API_KEY. Create that Paperclip key with scope.kind = "task_bridge" and an approved parent/project boundary; do not expose a normal claimed agent key to Hermes-facing chat/webhook surfaces. Do not use agentDefaultsPayload.apiBaseUrl for Paperclip API calls. diff --git a/server/src/adapters/registry.ts b/server/src/adapters/registry.ts index 59570496146..03d6196f85e 100644 --- a/server/src/adapters/registry.ts +++ b/server/src/adapters/registry.ts @@ -92,6 +92,8 @@ import { agentConfigurationDoc as grokAgentConfigurationDoc, models as grokModels, } from "@paperclipai/adapter-grok-local"; +import { createServerAdapter as createHermesGatewayServerAdapter } from "@paperclipai/adapter-hermes-gateway"; +import { createServerAdapter as createHermesLocalServerAdapter } from "@paperclipai/hermes-paperclip-adapter"; import { execute as openCodeExecute, listOpenCodeSkills, @@ -342,6 +344,10 @@ const grokLocalAdapter: ServerAdapterModule = { agentConfigurationDoc: grokAgentConfigurationDoc, }; +const hermesGatewayAdapter = createHermesGatewayServerAdapter(); + +const hermesLocalAdapter = createHermesLocalServerAdapter(); + const openclawGatewayAdapter: ServerAdapterModule = { type: "openclaw_gateway", execute: openclawGatewayExecute, @@ -414,6 +420,8 @@ function registerBuiltInAdapters() { cursorLocalAdapter, geminiLocalAdapter, grokLocalAdapter, + hermesGatewayAdapter, + hermesLocalAdapter, openclawGatewayAdapter, processAdapter, httpAdapter, diff --git a/tsconfig.json b/tsconfig.json index e597c331112..31b978ab1f6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,6 +9,8 @@ { "path": "./packages/adapters/claude-local" }, { "path": "./packages/adapters/codex-local" }, { "path": "./packages/adapters/cursor-local" }, + { "path": "./packages/adapters/hermes-gateway" }, + { "path": "./packages/adapters/hermes-local" }, { "path": "./packages/adapters/droid-local" }, { "path": "./packages/adapters/openclaw-gateway" }, { "path": "./packages/adapters/opencode-local" }, diff --git a/ui/package.json b/ui/package.json index 3ba60d2bc92..75272632333 100644 --- a/ui/package.json +++ b/ui/package.json @@ -41,11 +41,13 @@ "@paperclipai/adapter-cursor-local": "workspace:*", "@paperclipai/adapter-gemini-local": "workspace:*", "@paperclipai/adapter-grok-local": "workspace:*", + "@paperclipai/adapter-hermes-gateway": "workspace:*", "@paperclipai/adapter-openclaw-gateway": "workspace:*", "@paperclipai/adapter-opencode-local": "workspace:*", "@paperclipai/adapter-pi-local": "workspace:*", "@paperclipai/adapter-utils": "workspace:*", "@paperclipai/shared": "workspace:*", + "@paperclipai/hermes-paperclip-adapter": "workspace:*", "@radix-ui/react-slot": "^1.2.4", "@tailwindcss/typography": "^0.5.19", "@tanstack/react-query": "^5.90.21", diff --git a/ui/src/adapters/adapter-display-registry.ts b/ui/src/adapters/adapter-display-registry.ts index 67e49f1e462..17a20dca8f6 100644 --- a/ui/src/adapters/adapter-display-registry.ts +++ b/ui/src/adapters/adapter-display-registry.ts @@ -82,6 +82,17 @@ const adapterDisplayMap: Record = { description: "Local Grok Build agent", icon: Bot, }, + hermes_gateway: { + label: "Hermes", + description: "Remote Hermes API server", + icon: Bot, + hideFromVisualSelection: true, + }, + hermes_local: { + label: "Hermes", + description: "Local Hermes agent", + icon: Bot, + }, opencode_local: { label: "OpenCode", description: "Local multi-provider agent", diff --git a/ui/src/adapters/hermes-gateway/index.ts b/ui/src/adapters/hermes-gateway/index.ts new file mode 100644 index 00000000000..d77f01e2fbb --- /dev/null +++ b/ui/src/adapters/hermes-gateway/index.ts @@ -0,0 +1,11 @@ +import type { UIAdapterModule } from "../types"; +import { parseStdoutLine as parseHermesGatewayStdoutLine } from "@paperclipai/adapter-hermes-gateway/ui"; +import { SchemaConfigFields, buildSchemaAdapterConfig } from "../schema-config-fields"; + +export const hermesGatewayUIAdapter: UIAdapterModule = { + type: "hermes_gateway", + label: "Hermes Gateway", + parseStdoutLine: parseHermesGatewayStdoutLine, + ConfigFields: SchemaConfigFields, + buildAdapterConfig: buildSchemaAdapterConfig, +}; diff --git a/ui/src/adapters/hermes-local/index.ts b/ui/src/adapters/hermes-local/index.ts new file mode 100644 index 00000000000..6eb325aeb7e --- /dev/null +++ b/ui/src/adapters/hermes-local/index.ts @@ -0,0 +1,11 @@ +import type { UIAdapterModule } from "../types"; +import { parseHermesStdoutLine, buildHermesConfig } from "@paperclipai/hermes-paperclip-adapter/ui"; +import { SchemaConfigFields } from "../schema-config-fields"; + +export const hermesLocalUIAdapter: UIAdapterModule = { + type: "hermes_local", + label: "Hermes", + parseStdoutLine: parseHermesStdoutLine, + ConfigFields: SchemaConfigFields, + buildAdapterConfig: buildHermesConfig, +}; diff --git a/ui/src/adapters/registry.ts b/ui/src/adapters/registry.ts index f1beb8d69eb..d698e86b312 100644 --- a/ui/src/adapters/registry.ts +++ b/ui/src/adapters/registry.ts @@ -6,6 +6,8 @@ import { cursorCloudUIAdapter } from "./cursor-cloud"; import { cursorLocalUIAdapter } from "./cursor"; import { geminiLocalUIAdapter } from "./gemini-local"; import { grokLocalUIAdapter } from "./grok-local"; +import { hermesGatewayUIAdapter } from "./hermes-gateway"; +import { hermesLocalUIAdapter } from "./hermes-local"; import { openCodeLocalUIAdapter } from "./opencode-local"; import { piLocalUIAdapter } from "./pi-local"; import { openClawGatewayUIAdapter } from "./openclaw-gateway"; @@ -57,6 +59,8 @@ function registerBuiltInUIAdapters() { cursorCloudUIAdapter, geminiLocalUIAdapter, grokLocalUIAdapter, + hermesGatewayUIAdapter, + hermesLocalUIAdapter, openCodeLocalUIAdapter, piLocalUIAdapter, cursorLocalUIAdapter,