Initial gori agent gateway
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
# gori-agent-gateway
|
||||
|
||||
Hermes-gateway-style multi-IM Agent Gateway for routing instant-message webhooks to configurable CLI agents. It is intentionally standalone and not tied to Pi.
|
||||
|
||||
## Hermes reference
|
||||
|
||||
This project follows the Hermes gateway pattern: platform adapters normalize inbound messages, a central gateway applies policy/session/concurrency handling, then replies are sent through the originating adapter. The Feishu adapter ports the key Hermes behavior for tenant token caching, URL challenge handling, token verification, `im.message.receive_v1` parsing, mention cleanup, and message replies.
|
||||
|
||||
## Platform status
|
||||
|
||||
| Platform | Inbound | Outbound | Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| Feishu/Lark | Implemented | Implemented | Replies to `im.message.receive_v1` via `/im/v1/messages/{message_id}/reply`. |
|
||||
| WeCom | 501 scaffold | Implemented | Uses `gettoken` and `message/send`; inbound callback verification/encryption is not in v1. |
|
||||
| personal WeChat | External webhook scaffold | Synchronous webhook response | Native iLink/personal WeChat integration is not included in v1. |
|
||||
| QQ | 501 scaffold | Implemented | Uses QQ Bot access token and user/group text-message heuristics. |
|
||||
| Generic webhook | Implemented | Synchronous JSON | HMAC-SHA256 signed JSON endpoint for local bridges and tests. |
|
||||
|
||||
## Install and run
|
||||
|
||||
Requires Node.js 20+.
|
||||
|
||||
```bash
|
||||
npm install
|
||||
cp config.example.json config.json
|
||||
GORI_GATEWAY_CONFIG=./config.json npm run dev
|
||||
```
|
||||
|
||||
Build and run compiled output:
|
||||
|
||||
```bash
|
||||
npm run typecheck
|
||||
npm run build
|
||||
GORI_GATEWAY_CONFIG=./config.json npm start
|
||||
```
|
||||
|
||||
Endpoints:
|
||||
|
||||
- `GET /health`
|
||||
- `GET /platforms`
|
||||
- `POST /webhook/feishu`
|
||||
- `POST /webhook/wecom`
|
||||
- `POST /webhook/qq`
|
||||
- `POST /webhook/generic`
|
||||
- `POST /webhook/weixin`
|
||||
|
||||
## Configuration
|
||||
|
||||
Config is loaded from `GORI_GATEWAY_CONFIG`. If the variable is not set, the gateway loads `config.example.json` from the current working directory.
|
||||
|
||||
Important sections:
|
||||
|
||||
- `policy.allowedUsers`: allow only listed normalized user IDs when non-empty.
|
||||
- `policy.allowedChats`: allow only listed normalized chat IDs when non-empty.
|
||||
- `policy.requireMentionInGroup`: if true, group messages are ignored unless the adapter reports a bot mention.
|
||||
- `defaultAgent`: selected when a chat has not chosen an agent.
|
||||
- `agents[]`: named CLI agents using `child_process.spawn(command, args)` with `shell: false`.
|
||||
|
||||
CLI agent options:
|
||||
|
||||
- `inputMode: "stdin"`: sends the message text to stdin.
|
||||
- `inputMode: "arg"`: appends the message text as the final argv item.
|
||||
- `timeoutMs`: kills slow processes.
|
||||
- `outputMaxBytes`: caps captured stdout/stderr.
|
||||
- `cwd`: optional working directory for the agent process.
|
||||
|
||||
## Commands
|
||||
|
||||
The gateway handles these commands per chat before invoking an agent:
|
||||
|
||||
- `/help`
|
||||
- `/status`
|
||||
- `/agents`
|
||||
- `/agent <name>`
|
||||
- `/new`
|
||||
|
||||
## Feishu setup
|
||||
|
||||
1. Create a Feishu/Lark custom app and enable bot messaging.
|
||||
2. Configure event subscription for `im.message.receive_v1`.
|
||||
3. Set the request URL to `https://<host>/webhook/feishu`.
|
||||
4. Put `appId`, `appSecret`, and `verificationToken` into your config.
|
||||
5. Add bot display names to `platforms.feishu.botNames` so group mention detection can also work from flattened text.
|
||||
|
||||
The adapter accepts Feishu URL verification challenges and returns `{ "challenge": "..." }`.
|
||||
|
||||
## Generic webhook
|
||||
|
||||
Payload:
|
||||
|
||||
```json
|
||||
{
|
||||
"chat_id": "demo-chat",
|
||||
"user_id": "demo-user",
|
||||
"text": "hello",
|
||||
"message_id": "optional-message-id",
|
||||
"is_group": false,
|
||||
"mentions_bot": true
|
||||
}
|
||||
```
|
||||
|
||||
Signature header:
|
||||
|
||||
- Header name: `X-Gori-Signature`
|
||||
- Format: `sha256=<hex>` or just `<hex>`
|
||||
- Input: exact JSON request body bytes as sent by the client
|
||||
- Algorithm: HMAC-SHA256 using `platforms.webhook.secret`
|
||||
|
||||
Example:
|
||||
|
||||
```bash
|
||||
body='{"chat_id":"demo-chat","user_id":"demo-user","text":"/status"}'
|
||||
sig=$(printf '%s' "$body" | openssl dgst -sha256 -hmac 'replace-me' -hex | awk '{print $2}')
|
||||
curl -sS http://localhost:3000/webhook/generic \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H "X-Gori-Signature: sha256=$sig" \
|
||||
-d "$body"
|
||||
```
|
||||
|
||||
Response shape:
|
||||
|
||||
```json
|
||||
{ "ok": true, "output": "...agent or command output..." }
|
||||
```
|
||||
|
||||
## Security notes
|
||||
|
||||
- Do not expose the gateway publicly without HTTPS and upstream authentication/rate limits.
|
||||
- Keep platform secrets outside source control; use a copied config file or secret manager.
|
||||
- CLI agents are spawned without a shell, but they can still execute arbitrary local code. Only configure trusted commands.
|
||||
- Use `allowedUsers` and `allowedChats` in production.
|
||||
- Keep `requireMentionInGroup` enabled for group chats to avoid accidental agent invocation.
|
||||
- Set conservative `timeoutMs` and `outputMaxBytes` values for external-facing agents.
|
||||
Reference in New Issue
Block a user