{"_id":"@anwenhappy2026/x-channel","name":"@anwenhappy2026/x-channel","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@anwenhappy2026/x-channel","version":"0.1.0","private":false,"type":"module","description":"HTTP bridge channel integrated with OpenClaw server at /v1/chat/completions","main":"./dist/index.js","types":"./dist/index.d.ts","scripts":{"build":"tsc","watch":"tsc --watch","prepublishOnly":"npm run build","prepack":"npm run build"},"keywords":["openclaw","plugin","channel","http","websocket","bridge"],"author":"","license":"MIT","repository":{"type":"git","url":""},"openclaw":{"extensions":["./dist/index.js"],"setupEntry":"./dist/setup-entry.js","install":{"npmSpec":"@anwenhappy2026/x-channel","localPath":"./extensions/x-channel","defaultChoice":"npm","allowInvalidConfigRecovery":true},"startup":{"deferConfiguredChannelFullLoadUntilAfterListen":true},"channel":{"id":"x-channel","label":"x-channel","blurb":"HTTP bridge channel integrated with OpenClaw server at /v1/chat/completions"}},"peerDependencies":{"openclaw":">=2026.4.0"},"devDependencies":{"openclaw":"latest","@types/node":"^22.0.0","typescript":"^5.0.0"},"engines":{"node":">=22.0.0"},"gitHead":"64c80b441728ec1106f00e7da9356be3f9846f32","_id":"@anwenhappy2026/x-channel@0.1.0","_nodeVersion":"25.6.0","_npmVersion":"11.8.0","dist":{"integrity":"sha512-U+iMYAAahVIqNpjAKmiJqXKL0/2Xo3oVi/2SHbVerDBG2sQv4Fs43iglUq5RbGY8w2iYRnfmG9wW49tackIRFA==","shasum":"2b67900187878d00dde38e7510a0d82c36f48c71","tarball":"https://registry.npmjs.org/@anwenhappy2026/x-channel/-/x-channel-0.1.0.tgz","fileCount":27,"unpackedSize":85262,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDgMTGdvnhpOo6hfEgEzW50a4aCnpooQgVm5xxiU//8OAIhAOsajrqJVuFl3Y1xGdXoFoMSkcT1DVi+8qCyZYK1Itm0"}]},"_npmUser":{"name":"anwenhappy2026","email":"zhangchh3482@gmail.com"},"directories":{},"maintainers":[{"name":"anwenhappy2026","email":"zhangchh3482@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/x-channel_0.1.0_1776070266776_0.3286197421950918"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-13T08:51:06.674Z","0.1.0":"2026-04-13T08:51:06.914Z","modified":"2026-04-13T08:51:07.163Z"},"maintainers":[{"name":"anwenhappy2026","email":"zhangchh3482@gmail.com"}],"description":"HTTP bridge channel integrated with OpenClaw server at /v1/chat/completions","keywords":["openclaw","plugin","channel","http","websocket","bridge"],"repository":{"type":"git","url":""},"license":"MIT","readme":"# x-channel\n\n`x-channel` provides a lightweight inbound bridge into OpenClaw so you can push test messages via HTTP or allow your own WebSocket server to dispatch inbound events. It is built on the OpenClaw channel runtime and reuses the same dispatch/streaming flow as the core platform.\n\n## Auto install + first-start bootstrap\n\nIf you want OpenClaw to install and configure this plugin automatically on first startup, use the bootstrap scripts in `/scripts`:\n\n1) Build a local package tarball (optional, for offline/local install):\n\n```powershell\ncd extensions/x-channel\nnpm pack\n```\n\nThis creates a file like `xclaw-x-channel-0.1.0.tgz`.\n\n2) Start OpenClaw through the wrapper script:\n\n```powershell\ncd ../..\n./scripts/start-openclaw-with-x-channel.ps1\n```\n\nTo install from a local tarball instead of npm:\n\n```powershell\n./scripts/start-openclaw-with-x-channel.ps1 -PluginSpec \".\\extensions\\x-channel\\xclaw-x-channel-0.1.0.tgz\"\n```\n\nWhat happens on first run:\n\n- Runs `openclaw plugins install <PluginSpec>`\n- Creates/merges `~/.openclaw/openclaw.json`\n- Adds default `channels.x-channel` and `agents.defaults` values if missing\n- Writes a one-time marker file `~/.openclaw/.x-channel-bootstrap.done`\n\nSubsequent runs skip bootstrap unless you delete the marker file.\n\n## Implementation outline\n\n1. The plugin registers a channel with the identifier `x-channel` and an HTTP route on the OpenClaw server.\n2. When the gateway starts an account, it instantiates:\n   - An HTTP route registered at `/v1/chat/completions` on the OpenClaw server (no separate port needed).\n   - An optional outgoing WS client that connects to your server, handles reconnect/backoff, and forwards WS payloads into OpenClaw.\n3. Both HTTP and WS inputs run through the shared channel routing stack:\n   - `runtime.channel.routing.resolveAgentRoute(...)`\n   - `runtime.channel.reply.finalizeInboundContext(...)`\n   - `runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher(...)`\n4. WS replies use the streaming protocol defined below (accepted → zero/more delta → done). The last `delta` emitted by the dispatcher carries `done: true`. If no incremental blocks are produced, the connector falls back to the `done` frame.\n\n## Configuration\n\nAdd or merge the following into your OpenClaw config (typically `~/.openclaw/openclaw.json`):\n\n```json\n{\n  \"channels\": {\n    \"x-channel\": {\n      \"defaultAccountId\": \"default\",\n      \"defaultConversationId\": \"server-tests\",\n      \"ws\": {\n        \"enabled\": true,\n        \"url\": \"ws://127.0.0.1:9001/openclaw\",\n        \"protocols\": [],\n        \"initialRetryMs\": 1000,\n        \"maxRetryMs\": 30000,\n        \"backoffFactor\": 2,\n        \"maxRetries\": -1,\n        \"connectTimeoutMs\": 10000,\n        \"handshake\": {\n          \"client\": \"x-channel\"\n        }\n      }\n    }\n  },\n  \"agents\": {\n    \"defaults\": {\n      \"blockStreamingDefault\": \"on\",\n      \"blockStreamingBreak\": \"text_end\"\n    }\n  }\n}\n```\n\n> **Note:** The `host`, `port`, and `endpointPath` configuration options are deprecated. The HTTP route is now integrated directly into the OpenClaw server at `/v1/chat/completions`.\n\nChanging `blockStreamingDefault`/`blockStreamingBreak` affects how OpenClaw generates streaming deltas. Set `blockStreaming` in the CLI or config when you need fine-grained token-level streaming.\n\n## HTTP inbound protocol\n\n### Endpoint\n\n`POST http://<openclaw-host>:<openclaw-port>/v1/chat/completions`\n\nFor local development, this is typically: `http://127.0.0.1:18789/v1/chat/completions`\n\n### Request body\n\nOpenAI-compatible request shape:\n\n| Field | Type | Description |\n| --- | --- | --- |\n| `model` | string | Optional model label echoed in response |\n| `content` | string/array | Preferred inbound text source; when empty request is ignored |\n| `messages` | array | Required message list (OpenAI format) |\n| `stream` | boolean | `true` for SSE streaming chunks |\n| `user` | string | Optional user ID (mapped to channel sender) |\n| `metadata` | object | Optional passthrough metadata |\n\n### Sample `curl` (PowerShell):\n\n```powershell\ncurl.exe --noproxy \"*\" -i -X POST \"http://127.0.0.1:18789/v1/chat/completions\" `\n  -H \"Content-Type: application/json\" `\n  --data-raw '{\"model\":\"x-channel\",\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}],\"stream\":false,\"user\":\"u-1\"}'\n```\n\nWhen `stream=false`, response follows OpenAI `chat.completion` JSON schema.\nWhen `stream=true` (or omitted), response is SSE with `chat.completion.chunk` events and final `data: [DONE]`.\n\n## WS-driven inbound data\n\nThe outbound WS client becomes active when `channels.x-channel.ws.enabled` is `true` and `channels.x-channel.ws.url` is provided. The client:\n\n- Connects to your server using the configured `protocols` list.\n- Supports exponential backoff reconnects controlled by `initialRetryMs`, `maxRetryMs`, `backoffFactor`, and `maxRetries`.\n- Imposes a per-attempt timeout (`connectTimeoutMs`) and immediately retries if the handshake fails.\n- Sends the optional `handshake` payload after the connection opens.\n- Emits detailed logs prefixed by `[x-channel:accountId]` for lifecycle events, connection attempts, and errors.\n\n### WS request format (server → plugin client)\n\n```json\n{\n  \"requestId\": \"req-1\",\n  \"text\": \"hello from ws\",\n  \"userId\": \"u-1\",\n  \"accountId\": \"default\",\n  \"conversationId\": \"c-1\",\n  \"metadata\": { \"source\": \"ws-server\" }\n}\n```\n\n### WS reply protocol (client → server)\n\n1. **Accepted acknowledgement**\n\n```json\n{ \"ok\": true, \"requestId\": \"req-1\", \"type\": \"accepted\", \"message\": \"request accepted\" }\n```\n\n2. **Streaming delta frames**\n\nEach block produced by OpenClaw is pushed as a delta. Deltas include `index`, `kind`, and `text`. The dispatcher flags `done: true` on the final delta.\n\n```json\n{\n  \"ok\": true,\n  \"requestId\": \"req-1\",\n  \"type\": \"delta\",\n  \"index\": 0,\n  \"kind\": \"block\",\n  \"text\": \"...\",\n  \"done\": false\n}\n```\n\n3. **Completion frame**\n\nWhen OpenClaw generated no deltas, the plugin sends a standalone `done` event:\n\n```json\n{\n  \"ok\": true,\n  \"requestId\": \"req-1\",\n  \"type\": \"done\",\n  \"done\": true,\n  \"event\": { \"...\": \"...\" }\n}\n```\n\nWhen there are deltas, the final delta carries `done: true` and optional `event`/`replies` payloads derived from the final message.\n","readmeFilename":"README.md","_rev":"1-240f43e12b0a0ed496c31ee1dce5cbcd"}