hailin
20e96f31cd
fix(openclaw-bridge): use regex replace for base64url (ES2020 compat)
...
replaceAll() requires ES2021+, tsconfig targets ES2020.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 07:40:56 -07:00
hailin
a7c5b264fa
fix(openclaw-bridge): implement correct v3 device auth protocol
...
- device.id = SHA256(rawPubKey, hex) — not a random UUID
- device.publicKey = raw 32-byte key encoded as base64url (not SPKI DER)
- sign the full v3 payload string (not just raw nonce bytes):
"v3|{deviceId}|{clientId}|{mode}|{role}|{scopes}|{ts}|{token}|{nonce}|{platform}|"
- device.signature encoded as base64url
Matches buildDeviceAuthPayloadV3/verifyDeviceSignature from openclaw dist.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 07:40:15 -07:00
hailin
bb4b73f847
fix(openclaw-bridge): include nonce in device handshake params
...
The gateway expects device.nonce (the challenge nonce) to be echoed
back in the connect request. Without it the connection is rejected with
'device: must have required property nonce'.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 07:32:29 -07:00
hailin
00a944c9a9
fix(openclaw-bridge): use 'gateway-client'/'backend' as WS client id/mode
...
openclaw gateway validates client.id against a fixed set of known IDs.
Using a random UUID caused the connection to be rejected immediately with
'client/id must be equal to constant'. Use 'gateway-client' + 'backend'.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 07:30:06 -07:00
hailin
b0801e0983
feat(bridge): DingTalk channel plugin + OpenClaw Protocol v3 rewrite
...
Core changes:
- src/channels/dingtalk.ts: DingTalk Stream SDK channel (no public IP needed)
- TokenManager: auto-refresh with refreshPromise mutex (prevents race condition)
- UserQueue: per-user serial queue, max depth 5
- MsgDedup: O(1) Map<string,timestamp> with 10min TTL + 10k cap
- RateLimiter: sliding window 10 msg/min per user
- ResilientOcClient: 10s heartbeat poll + atomic reconnect guard
- DingTalkStream: exponential backoff reconnect (2s→60s), immediate ACK
- replyToUser: sessionWebhook expiry check + 4800-char chunking
- src/openclaw-client.ts: rewritten for correct Protocol v3 wire format
- Request frame: { type:"req", id, method, params }
- Challenge-response Ed25519 handshake (connect.challenge → connect req)
- Correct rpc() with configurable timeoutMs
- src/index.ts: fixed RPC method names
- agent.run → chat.send with { sessionKey, message, timeoutSeconds }
- metrics.get → gateway.status
- Dockerfile: adds start-dingtalk.sh COPY + chmod
- supervisord.conf: dingtalk-channel program block (autorestart=unexpected)
- start-dingtalk.sh: exits 0 if DINGTALK_CLIENT_ID unset (no restart loop)
- CHANNEL_DEV_GUIDE.md: full dev guide for future channel integrations
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 05:10:01 -07:00
hailin
7d5840c245
feat(openclaw): Phase 1 — server pool + agent instance deployment infrastructure
...
## inventory-service
- New: pool_servers table (public schema, platform-admin managed)
- New: PoolServer entity, PoolServerRepository, PoolServerController
- CRUD endpoints at /api/v1/inventory/pool-servers
- Internal /deploy-creds endpoint (x-internal-api-key protected) for SSH key retrieval
- increment/decrement endpoints for capacity tracking
## agent-service
- New: agent_instances table (tenant schema)
- New: AgentInstance entity, AgentInstanceRepository, AgentInstanceController
- New: AgentInstanceDeployService — SSH-based docker deployment
- Queries pool server availability from inventory-service
- AES-256 encrypts OpenClaw gateway token at rest
- Allocates host ports in range 20000-29999
- Fires docker run for it0hub/openclaw-bridge:latest
- Async deploy with error capture
- Added ssh2 dependency for SSH execution
- Added INVENTORY_SERVICE_URL, INTERNAL_API_KEY, VAULT_MASTER_KEY to docker-compose
## openclaw-bridge (new package)
- packages/openclaw-bridge/ — custom Docker image
- Two processes via supervisord: OpenClaw gateway + IT0 Bridge (Node.js)
- IT0 Bridge exposes REST API on port 3000:
GET /health, GET /status, POST /task, GET /sessions, GET /metrics
- Connects to OpenClaw gateway at ws://127.0.0.1:18789 via WebSocket RPC
- Sends heartbeat to IT0 agent-service every 60s
- Dockerfile: multi-stage build (openclaw source + bridge TS compilation)
## Web Admin
- New: /server-pool page — list/add/edit/delete pool servers with capacity bars
- New: /openclaw-instances page — cross-tenant instance monitoring with status filter
- Sidebar: added 服务器池 (Database icon) + OpenClaw 实例 (Boxes icon) to platform_admin nav
## Flutter App
- my_agents_page: rewritten to show real AgentInstance data from /api/v1/agent/instances
- Added AgentInstance model with status-driven UI (running/deploying/stopped/error)
- Status badges with color coding + spinner for deploying state
- Summary chips showing running vs stopped counts
- api_endpoints.dart: added agentInstances endpoint
## Design docs
- OPENCLAW_INTEGRATION_PLAN.md: complete architecture document with all confirmed decisions
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 11:11:21 -08:00