im-hub-pro 0.2.33 → 0.2.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/README.md +117 -374
- package/README.zh-CN.md +118 -374
- package/dist/cli.js +29 -20
- package/dist/cli.js.map +1 -1
- package/dist/core/acp-server.js +6 -6
- package/dist/core/acp-server.js.map +1 -1
- package/dist/core/agent-base.d.ts.map +1 -1
- package/dist/core/agent-base.js +12 -13
- package/dist/core/agent-base.js.map +1 -1
- package/dist/core/agent-cwd.js +3 -3
- package/dist/core/agent-cwd.js.map +1 -1
- package/dist/core/agent-cwd.test.js +4 -4
- package/dist/core/agent-cwd.test.js.map +1 -1
- package/dist/core/approval-bus.d.ts.map +1 -1
- package/dist/core/approval-bus.js +12 -10
- package/dist/core/approval-bus.js.map +1 -1
- package/dist/core/approval-bus.test.js +10 -8
- package/dist/core/approval-bus.test.js.map +1 -1
- package/dist/core/approval-router.d.ts.map +1 -1
- package/dist/core/approval-router.js +1 -1
- package/dist/core/approval-router.js.map +1 -1
- package/dist/core/approval-router.test.js +16 -16
- package/dist/core/approval-router.test.js.map +1 -1
- package/dist/core/audit-log.js +2 -2
- package/dist/core/audit-log.js.map +1 -1
- package/dist/core/bgjob-reader.js +6 -6
- package/dist/core/bgjob-reader.js.map +1 -1
- package/dist/core/bgjob-reader.test.js +12 -12
- package/dist/core/bgjob-reader.test.js.map +1 -1
- package/dist/core/commands/approval.test.js +7 -7
- package/dist/core/commands/approval.test.js.map +1 -1
- package/dist/core/commands/audit.js +1 -1
- package/dist/core/commands/audit.js.map +1 -1
- package/dist/core/commands/builtin.d.ts.map +1 -1
- package/dist/core/commands/builtin.js +4 -2
- package/dist/core/commands/builtin.js.map +1 -1
- package/dist/core/commands/job.js +8 -8
- package/dist/core/commands/job.js.map +1 -1
- package/dist/core/commands/model.js +7 -7
- package/dist/core/commands/model.js.map +1 -1
- package/dist/core/commands/plan.js +2 -2
- package/dist/core/commands/plan.js.map +1 -1
- package/dist/core/commands/plan.test.js +3 -3
- package/dist/core/commands/plan.test.js.map +1 -1
- package/dist/core/commands/sessions.js +4 -4
- package/dist/core/commands/sessions.js.map +1 -1
- package/dist/core/commands/stats.js +2 -2
- package/dist/core/commands/stats.js.map +1 -1
- package/dist/core/event-bus.d.ts +1 -1
- package/dist/core/event-bus.d.ts.map +1 -1
- package/dist/core/event-bus.js +1 -1
- package/dist/core/event-bus.js.map +1 -1
- package/dist/core/intent-llm.js +1 -1
- package/dist/core/intent-llm.js.map +1 -1
- package/dist/core/job-board.d.ts +1 -3
- package/dist/core/job-board.d.ts.map +1 -1
- package/dist/core/job-board.js +2 -2
- package/dist/core/job-board.js.map +1 -1
- package/dist/core/logger.js +1 -1
- package/dist/core/logger.js.map +1 -1
- package/dist/core/metrics.js +1 -1
- package/dist/core/metrics.js.map +1 -1
- package/dist/core/onboarding.d.ts.map +1 -1
- package/dist/core/onboarding.js +4 -5
- package/dist/core/onboarding.js.map +1 -1
- package/dist/core/onboarding.test.js +1 -1
- package/dist/core/onboarding.test.js.map +1 -1
- package/dist/core/router.js +1 -1
- package/dist/core/router.js.map +1 -1
- package/dist/core/schedule.js +3 -3
- package/dist/core/schedule.js.map +1 -1
- package/dist/core/session-subtasks.test.js +6 -6
- package/dist/core/session-subtasks.test.js.map +1 -1
- package/dist/core/session.js +5 -5
- package/dist/core/session.js.map +1 -1
- package/dist/core/sqlite-helper.js +2 -2
- package/dist/core/sqlite-helper.js.map +1 -1
- package/dist/core/transcribe.js +5 -5
- package/dist/core/transcribe.js.map +1 -1
- package/dist/core/transcribe.test.js +3 -3
- package/dist/core/transcribe.test.js.map +1 -1
- package/dist/plugins/agents/acp/acp-client.d.ts.map +1 -1
- package/dist/plugins/agents/acp/acp-client.js +4 -2
- package/dist/plugins/agents/acp/acp-client.js.map +1 -1
- package/dist/plugins/agents/claude-code/adapter.test.js +10 -10
- package/dist/plugins/agents/claude-code/adapter.test.js.map +1 -1
- package/dist/plugins/agents/claude-code/index.js +5 -5
- package/dist/plugins/agents/claude-code/index.js.map +1 -1
- package/dist/plugins/agents/claude-code/mcp-approval-server.d.ts.map +1 -1
- package/dist/plugins/agents/claude-code/mcp-approval-server.js +11 -9
- package/dist/plugins/agents/claude-code/mcp-approval-server.js.map +1 -1
- package/dist/plugins/agents/claude-code/mcp-approval-server.test.js +3 -3
- package/dist/plugins/agents/claude-code/mcp-approval-server.test.js.map +1 -1
- package/dist/plugins/agents/codex/adapter.test.js +1 -1
- package/dist/plugins/agents/codex/adapter.test.js.map +1 -1
- package/dist/plugins/agents/codex/index.js +3 -3
- package/dist/plugins/agents/codex/index.js.map +1 -1
- package/dist/plugins/agents/copilot/index.js +3 -3
- package/dist/plugins/agents/copilot/index.js.map +1 -1
- package/dist/plugins/agents/opencode/http-adapter.test.js +4 -4
- package/dist/plugins/agents/opencode/http-adapter.test.js.map +1 -1
- package/dist/plugins/agents/opencode/opencode-http-adapter.d.ts +1 -1
- package/dist/plugins/agents/opencode/opencode-http-adapter.d.ts.map +1 -1
- package/dist/plugins/agents/opencode/opencode-http-adapter.js +6 -4
- package/dist/plugins/agents/opencode/opencode-http-adapter.js.map +1 -1
- package/dist/plugins/agents/opencode/serve-manager.d.ts.map +1 -1
- package/dist/plugins/agents/opencode/serve-manager.js +10 -6
- package/dist/plugins/agents/opencode/serve-manager.js.map +1 -1
- package/dist/plugins/messengers/discord/discord-adapter.d.ts +0 -1
- package/dist/plugins/messengers/discord/discord-adapter.d.ts.map +1 -1
- package/dist/plugins/messengers/discord/discord-adapter.js +3 -6
- package/dist/plugins/messengers/discord/discord-adapter.js.map +1 -1
- package/dist/plugins/messengers/discord/discord-adapter.test.js +9 -9
- package/dist/plugins/messengers/discord/discord-adapter.test.js.map +1 -1
- package/dist/plugins/messengers/feishu/feishu-adapter.d.ts +0 -1
- package/dist/plugins/messengers/feishu/feishu-adapter.d.ts.map +1 -1
- package/dist/plugins/messengers/feishu/feishu-adapter.js +4 -7
- package/dist/plugins/messengers/feishu/feishu-adapter.js.map +1 -1
- package/dist/plugins/messengers/feishu/feishu-client.d.ts +0 -1
- package/dist/plugins/messengers/feishu/feishu-client.d.ts.map +1 -1
- package/dist/plugins/messengers/feishu/feishu-client.js +0 -2
- package/dist/plugins/messengers/feishu/feishu-client.js.map +1 -1
- package/dist/plugins/messengers/telegram/markdown-to-html.js +3 -3
- package/dist/plugins/messengers/telegram/markdown-to-html.js.map +1 -1
- package/dist/plugins/messengers/telegram/media-download.js +5 -5
- package/dist/plugins/messengers/telegram/media-download.js.map +1 -1
- package/dist/plugins/messengers/telegram/media-download.test.js +3 -3
- package/dist/plugins/messengers/telegram/media-download.test.js.map +1 -1
- package/dist/plugins/messengers/telegram/telegram-adapter.d.ts +15 -0
- package/dist/plugins/messengers/telegram/telegram-adapter.d.ts.map +1 -1
- package/dist/plugins/messengers/telegram/telegram-adapter.js +165 -8
- package/dist/plugins/messengers/telegram/telegram-adapter.js.map +1 -1
- package/dist/plugins/messengers/wechat/ilink-adapter.d.ts +10 -0
- package/dist/plugins/messengers/wechat/ilink-adapter.d.ts.map +1 -1
- package/dist/plugins/messengers/wechat/ilink-adapter.js +167 -17
- package/dist/plugins/messengers/wechat/ilink-adapter.js.map +1 -1
- package/dist/plugins/messengers/wechat/ilink-client.d.ts +10 -1
- package/dist/plugins/messengers/wechat/ilink-client.d.ts.map +1 -1
- package/dist/plugins/messengers/wechat/ilink-client.js +42 -0
- package/dist/plugins/messengers/wechat/ilink-client.js.map +1 -1
- package/dist/plugins/messengers/wechat/ilink-types.d.ts +8 -0
- package/dist/plugins/messengers/wechat/ilink-types.d.ts.map +1 -1
- package/dist/plugins/messengers/wechat/ilink-types.js +10 -0
- package/dist/plugins/messengers/wechat/ilink-types.js.map +1 -1
- package/dist/plugins/messengers/wechat/media-download.d.ts +32 -0
- package/dist/plugins/messengers/wechat/media-download.d.ts.map +1 -0
- package/dist/plugins/messengers/wechat/media-download.js +78 -0
- package/dist/plugins/messengers/wechat/media-download.js.map +1 -0
- package/dist/utils/backoff.js +1 -1
- package/dist/utils/backoff.js.map +1 -1
- package/dist/utils/cross-platform.d.ts +1 -1
- package/dist/utils/cross-platform.d.ts.map +1 -1
- package/dist/utils/cross-platform.js +3 -3
- package/dist/utils/cross-platform.js.map +1 -1
- package/dist/utils/safe-equal.js +1 -1
- package/dist/utils/safe-equal.js.map +1 -1
- package/dist/web/public/_app.js +2 -2
- package/dist/web/public/index.html +13 -13
- package/dist/web/public/login.html +11 -3
- package/dist/web/public/settings.html +20 -20
- package/dist/web/public/tasks.html +76 -76
- package/dist/web/server.js +12 -12
- package/dist/web/server.js.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.2.35] - 2026-05-09
|
|
6
|
+
|
|
7
|
+
### Added — WeChat & Telegram rich media support
|
|
8
|
+
|
|
9
|
+
- **WeChat 图片 / 文件 / 语音 / 视频接收**:`handleIncomingMessage` 现在处理 iLink `item_list` 的全部 5 种类型(TEXT=1, IMAGE=2, VOICE=3, FILE=4, VIDEO=5),此前只处理 TEXT。
|
|
10
|
+
- **图片**:通过 iLink CDN 下载到 `~/.im-hub/media/wechat/<userId>/`,转为 `[图片附件:/path]` 标记传递给 Agent
|
|
11
|
+
- **语音**:优先使用微信自带转写(`voice_item.text`),无转写时下载音频后走 OpenAI Whisper 或 whisper.cpp(复用 `src/core/transcribe.ts`)
|
|
12
|
+
- **文件**:下载并保留原始文件名,显示大小,转为 `[文件附件:/path (name, size)]`
|
|
13
|
+
- **视频**:下载并显示时长和大小,转为 `[视频附件:/path (duration, size)]`
|
|
14
|
+
- **混合消息**:同一条消息中的文本 + 媒体项按顺序拼接
|
|
15
|
+
- **Telegram 图片 / 语音增强**:Telegram 适配器的图片下载和语音转写能力在本轮中同步维护和 bugfix。
|
|
16
|
+
- **新文件**:`src/plugins/messengers/wechat/media-download.ts` — 媒体下载辅助,含路径安全检查(拒绝 `../` / `/`)和 20 MB 大小上限
|
|
17
|
+
- **新类型**:`ilink-types.ts` 新增 `ITEM_TYPE` 常量和 `DownloadMediaRequest`
|
|
18
|
+
- **新方法**:`ILinkClient.downloadMedia(cdnMedia)` — 通过 iLink CDN 端点下载二进制媒体
|
|
19
|
+
|
|
20
|
+
### Tests
|
|
21
|
+
|
|
22
|
+
- 53 个新测试:
|
|
23
|
+
- 31 集成测试(`test/integration/wechat-media-integration.test.ts`)— 端到端验证 `handleIncomingMessage` 对所有媒体类型的处理,含成功 / 失败 / 边界情况
|
|
24
|
+
- 15 单元测试(`test/unit/wechat-media-download.test.ts`)— 下载辅助函数、扩展名推断、CDN 提取、安全防护
|
|
25
|
+
- 8 单元测试(`test/unit/wechat-media-handling.test.ts`)— 类型常量和消息结构验证
|
|
26
|
+
- 全量 950 pass / 0 fail
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
5
30
|
## [0.2.33] - 2026-05-09
|
|
6
31
|
|
|
7
32
|
### Fixed — audit-fixes-7950 follow-up
|
package/README.md
CHANGED
|
@@ -2,131 +2,69 @@
|
|
|
2
2
|
|
|
3
3
|
[中文文档](README.zh-CN.md)
|
|
4
4
|
|
|
5
|
-
**Universal messenger-to-agent bridge** — connect WeChat / Feishu / Telegram /
|
|
6
|
-
|
|
7
|
-
> Productized fork of the original [`im-hub`](https://www.npmjs.com/package/im-hub). On-disk config (`~/.im-hub/`), env vars (`IMHUB_*`), and HTTP headers (`X-IM-Hub-Token`) are unchanged — drop-in compatible. See [Migrating from `im-hub`](#migrating-from-im-hub) below.
|
|
8
|
-
|
|
9
|
-
## What's new in v0.2.13 → v0.2.30
|
|
10
|
-
|
|
11
|
-
- **Discord adapter** (Gateway WebSocket via `discord.js`)
|
|
12
|
-
- **Human-in-the-loop tool approval** — Claude pauses on tool calls; you reply `y`/`n` in the same IM thread, **or click an in-page card from the web chat**
|
|
13
|
-
- **Tasks dashboard** at `/tasks` with **Jobs · Background · Subtasks · Schedules · Approvals · Health · Files · Audit** tabs (per-agent filtering, multi-select batch ops, real-time SSE updates)
|
|
14
|
-
- **Multi-tenant workspaces** — per-workspace agent whitelist + rate limits, **with full CRUD UI in /settings**, plus command-level ACL on `/job` `/schedule` `/audit` (each user only sees their own)
|
|
15
|
-
- **ACP server mode** — im-hub-pro itself is an ACP-compatible agent (`POST /tasks` sync + SSE)
|
|
16
|
-
- **Persistent Job Board** + cron scheduler (SQLite, survives restarts) with 30-day retention sweep
|
|
17
|
-
- **Smart routing**: intent classifier (CJK + ASCII), circuit breaker, sticky sessions
|
|
18
|
-
- **Structured logging** (`pino`) with `traceId` end-to-end + audit log + Prometheus `/api/metrics`
|
|
19
|
-
- **Three-state theme** (light / dark / system) on every page — applied before first paint to avoid flash
|
|
20
|
-
- **v0.2.16 — Security hardening (P0 + P1)**: timing-safe token compare, Schedule `notify_url` SSRF guard, secret redaction in logs, approval-socket entropy + perms, `Session.addMessage` per-key mutex
|
|
21
|
-
- **v0.2.17 — Observability & IM polish (P2 + P3)**: static-page CSP / `X-Frame-Options` / `X-Content-Type-Options`, WebSocket connection cap + backpressure, Prometheus label-cardinality whitelist, new counters (`im_hub_audit_prune_failed_total` / `im_hub_agent_cleanup_failed_total` / `im_hub_approval_*`), UTF-16 surrogate-safe message split, auto-allow fingerprint 5→10 chars, SQLite WAL clean checkpoint on SIGINT
|
|
22
|
-
- **v0.2.18 — IM reconnect backoff (M9)**: shared `Backoff` helper (exponential + ±50% jitter) replaces fixed 2s / 5s reconnect delays in Telegram + WeChat polling; defeats thundering-herd on shared network recovery
|
|
23
|
-
- **v0.2.19 — Codex sandbox-mode plan + Dashboard filter / Audit tab**: codex now honors `session.planMode` (default sandbox switched to explicit `-s workspace-write`); jobs / subtasks / schedules tabs gain per-agent filter; new Audit tab pulls the SQLite audit log into the dashboard
|
|
24
|
-
- **v0.2.20 — Web console PR-A**: three-state theme manager + global error boundary + in-page approval cards (click Allow / Deny / Allow + Auto from the chat UI itself)
|
|
25
|
-
- **v0.2.21 — Web console PR-B**: Health tab (per-agent breaker / rate-limiter / latency p50/95/99 / sparkline) + Approvals tab (browse and resolve every pending HITL approval from the dashboard)
|
|
26
|
-
- **v0.2.22 — Web console PR-C**: SSE event stream (`/events`) replaces polling for audit / approval / job / metrics events; full Workspace CRUD UI in /settings
|
|
27
|
-
- **v0.2.23 — Web console PR-D**: Files tab — read-only browser of `~/.im-hub-workspaces/<agent>/`; Jobs tab gains multi-select + batch cancel / run; settings page header / container restyled
|
|
28
|
-
- **v0.2.30 — Production hardening**: active subtask turns now use isolated sub-sessions and native agent sessions; WebSocket chat ingress is serialized per browser connection; session metadata writes use per-key locking; Web UI defaults to loopback binding; config files are written `0600`; Telegram media downloads reject redirects; `im-hub-pro --version` reads the package version
|
|
29
|
-
|
|
30
|
-
See [CHANGELOG.md](CHANGELOG.md) and [docs/code-review-2026-05-06-main.md](docs/code-review-2026-05-06-main.md) for the full list.
|
|
31
|
-
|
|
32
|
-
## Web Chat & Tasks Dashboard
|
|
5
|
+
**Universal messenger-to-agent bridge** — connect WeChat / Feishu / Telegram / Discord to Claude Code / Codex / Copilot / OpenCode, or any custom agent via ACP. Single Node.js process, no Docker, no Redis.
|
|
33
6
|
|
|
34
|
-
|
|
35
|
-
im-hub-pro start # Web UI at http://localhost:3000
|
|
36
|
-
# / chat (with in-page approval cards)
|
|
37
|
-
# /tasks jobs · background · subtasks · schedules
|
|
38
|
-
# · approvals · health · files · audit
|
|
39
|
-
# /settings agents · messengers · ACP · workspaces
|
|
40
|
-
```
|
|
7
|
+
> Productized fork of the original [`im-hub`](https://www.npmjs.com/package/im-hub). Config dir (`~/.im-hub/`), env vars (`IMHUB_*`), and headers (`X-IM-Hub-Token`) are unchanged — drop-in upgrade. See [Migrating from `im-hub`](#migrating-from-im-hub).
|
|
41
8
|
|
|
42
|
-
|
|
43
|
-
- Agent switching and chat history
|
|
44
|
-
- **Three-state theme** (light / dark / system) with per-tab persistence + global error boundary
|
|
45
|
-
- Bilingual UI (English / 中文) — auto-detects browser language
|
|
46
|
-
- `/tasks` surfaces persistent jobs, cron schedules, **`~/.claude/bgjobs`** + **`~/.config/opencode/bgjobs`** + **`~/.codex/bgjobs`** background tasks (override via `IMHUB_BGJOB_ROOTS`), every subtask in every session, agent health (breaker · rate-limiter · p50/95/99 · sparkline), pending HITL approvals (resolve from the browser), and a read-only file browser into `~/.im-hub-workspaces/<agent>/`
|
|
47
|
-
|
|
48
|
-
## Features
|
|
9
|
+
## Highlights
|
|
49
10
|
|
|
50
|
-
- **
|
|
51
|
-
- **
|
|
52
|
-
- **
|
|
53
|
-
- **
|
|
54
|
-
- **
|
|
55
|
-
- **
|
|
56
|
-
- **
|
|
11
|
+
- **4 messengers, 4+ agents** — WeChat (image / file / voice), Feishu, Telegram, Discord; Claude Code, Codex, Copilot, OpenCode, plus any ACP endpoint
|
|
12
|
+
- **Browser dashboard** — chat UI, tasks panel (jobs / schedules / approvals / health / files / audit), settings page with workspace CRUD
|
|
13
|
+
- **Human-in-the-loop tool approval** — Claude tool calls pause for `y`/`n` in IM or in-page card; works across all platforms
|
|
14
|
+
- **Rich media in WeChat & Telegram** — receive images, files, videos; voice messages transcribed via WeChat STT, OpenAI Whisper, or whisper.cpp
|
|
15
|
+
- **Smart routing** — intent classifier (CJK + ASCII), sticky sessions, circuit breaker, rate limiter
|
|
16
|
+
- **Multi-tenant workspaces** — per-workspace agent whitelist, rate limits, command-level ACL
|
|
17
|
+
- **Persistent jobs & cron** — SQLite-backed, survives restarts, 30-day retention
|
|
18
|
+
- **Observability** — structured logging (pino + traceId), Prometheus metrics, audit log
|
|
19
|
+
- **Security** — timing-safe auth, SSRF guards, credential file permissions, approval socket entropy
|
|
57
20
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
```bash
|
|
61
|
-
npm install -g im-hub-pro
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
Requires **Node.js ≥ 18** (production deployments use ≥ 22 LTS — see [`docs/deployment.md`](docs/deployment.md)).
|
|
65
|
-
|
|
66
|
-
### Migrating from `im-hub`
|
|
67
|
-
|
|
68
|
-
Your `~/.im-hub/` config dir, `IMHUB_*` env vars, `X-IM-Hub-Token` header, and ACP wire identifiers (`im-hub-gateway`) are unchanged — this is a brand rename only.
|
|
69
|
-
|
|
70
|
-
```bash
|
|
71
|
-
npm uninstall -g im-hub
|
|
72
|
-
npm install -g im-hub-pro
|
|
73
|
-
im-hub-pro start
|
|
74
|
-
```
|
|
21
|
+
See [CHANGELOG.md](CHANGELOG.md) for the full version history.
|
|
75
22
|
|
|
76
23
|
## Quick Start
|
|
77
24
|
|
|
78
25
|
```bash
|
|
79
|
-
#
|
|
26
|
+
npm install -g im-hub-pro # Requires Node.js ≥ 18 (≥ 22 LTS recommended)
|
|
27
|
+
|
|
28
|
+
# Configure at least one messenger
|
|
80
29
|
im-hub-pro config wechat # QR-code login
|
|
81
30
|
im-hub-pro config feishu # App ID + Secret (no webhook needed)
|
|
82
31
|
im-hub-pro config telegram # @BotFather token
|
|
83
32
|
im-hub-pro config discord # Bot token; see docs/discord-setup.md
|
|
84
33
|
|
|
85
|
-
#
|
|
86
|
-
im-hub-pro config claude
|
|
87
|
-
|
|
88
|
-
# 3. (Optional) Connect a custom remote agent over ACP
|
|
34
|
+
# (Optional) Connect a custom remote agent over ACP
|
|
89
35
|
im-hub-pro config agent
|
|
90
36
|
|
|
91
|
-
#
|
|
37
|
+
# Start the bridge
|
|
92
38
|
im-hub-pro start
|
|
93
39
|
```
|
|
94
40
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
- ✅ No webhook configuration needed
|
|
98
|
-
- ✅ No public IP or domain required
|
|
99
|
-
- ✅ No ngrok or similar tools needed
|
|
100
|
-
- ✅ Works directly from localhost
|
|
101
|
-
|
|
102
|
-
### Discord
|
|
41
|
+
Web UI at `http://localhost:3000` — chat at `/`, tasks at `/tasks`, settings at `/settings`.
|
|
103
42
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
### Connect Your Own Agent
|
|
107
|
-
|
|
108
|
-
im-hub-pro speaks **ACP (Agent Communication Protocol)**, so you can plug in any agent that exposes a standard HTTP endpoint — your own business bots, internal tools, cloud services, anything.
|
|
43
|
+
### Migrating from `im-hub`
|
|
109
44
|
|
|
110
45
|
```bash
|
|
111
|
-
im-hub
|
|
112
|
-
|
|
113
|
-
#
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
After setup, chat with it the same way as built-in agents:
|
|
117
|
-
|
|
118
|
-
```
|
|
119
|
-
/myagent analyze the Q1 sales report
|
|
46
|
+
npm uninstall -g im-hub
|
|
47
|
+
npm install -g im-hub-pro
|
|
48
|
+
im-hub-pro start # config, env vars, headers all unchanged
|
|
120
49
|
```
|
|
121
50
|
|
|
122
|
-
|
|
51
|
+
## Features
|
|
123
52
|
|
|
124
|
-
|
|
53
|
+
| Category | Details |
|
|
54
|
+
|----------|---------|
|
|
55
|
+
| **Messengers** | WeChat (iLink — image / file / voice / video), Feishu (WebSocket), Telegram (grammy — photo / voice / audio), Discord (discord.js) |
|
|
56
|
+
| **Agents** | Claude Code, Codex, Copilot, OpenCode — all via shared `AgentBase`; any HTTP agent via ACP |
|
|
57
|
+
| **Web UI** | Chat with streaming, three-state theme (light / dark / system), bilingual (EN / 中文), SSE dashboard |
|
|
58
|
+
| **Tool Approval** | Human-in-the-loop over IM + in-page cards; MCP sidecar for Claude |
|
|
59
|
+
| **Jobs** | Persistent SQLite job board + cron scheduler; batch ops; background task reader |
|
|
60
|
+
| **Routing** | Intent classifier, circuit breaker, rate limiter, sticky sessions, LLM judge fallback |
|
|
61
|
+
| **Workspaces** | Multi-tenant; agent whitelist + rate limits; command-level ACL |
|
|
62
|
+
| **Observability** | pino structured logs, traceId, Prometheus `/api/metrics`, SQLite audit log |
|
|
63
|
+
| **ACP** | Client (connect to remote agents) + Server (im-hub-pro itself as an ACP agent) |
|
|
125
64
|
|
|
126
65
|
## CLI Commands
|
|
127
66
|
|
|
128
67
|
```
|
|
129
|
-
im-hub-pro # Same as 'start'
|
|
130
68
|
im-hub-pro start # Start the bridge + web UI
|
|
131
69
|
im-hub-pro config wechat # Configure WeChat
|
|
132
70
|
im-hub-pro config feishu # Configure Feishu
|
|
@@ -136,190 +74,92 @@ im-hub-pro config claude # Configure Claude Code
|
|
|
136
74
|
im-hub-pro config agent # Connect a custom ACP agent
|
|
137
75
|
im-hub-pro agents # List available agents
|
|
138
76
|
im-hub-pro messengers # List available messengers
|
|
139
|
-
im-hub-pro help
|
|
140
77
|
```
|
|
141
78
|
|
|
142
79
|
## Chat Commands
|
|
143
80
|
|
|
144
|
-
Send these as messages to the bot. Responses are streamed back in the same thread.
|
|
145
|
-
|
|
146
81
|
| Command | What it does |
|
|
147
|
-
|
|
148
|
-
|
|
|
149
|
-
| `/<agent> <prompt>` | Switch agent
|
|
150
|
-
| `/
|
|
151
|
-
| `/
|
|
152
|
-
| `/
|
|
153
|
-
| `/
|
|
154
|
-
| `/router status\|
|
|
155
|
-
|
|
|
156
|
-
| `/job ...` | Inspect / cancel persistent jobs |
|
|
157
|
-
| `/schedule ...` | List / add / remove cron schedules |
|
|
158
|
-
| `/sessions` | List recent sessions for this thread |
|
|
159
|
-
| `/model [provider/model]` | View or change the session's model |
|
|
160
|
-
| `/models` | List models the current agent supports |
|
|
161
|
-
| `/think on\|off\|...` | Toggle "think harder" / extended-thinking modes |
|
|
162
|
-
| `/stats` | Per-agent invocation / latency / error stats |
|
|
163
|
-
| `y` / `n` / `批准` / `拒绝` | Approve or deny a pending Claude tool call (HITL) |
|
|
82
|
+
|---------|-------------|
|
|
83
|
+
| any text | Route to agent (sticky session, intent-classified) |
|
|
84
|
+
| `/<agent> <prompt>` | Switch agent — `/cc`, `/oc`, `/cx`, `/co` |
|
|
85
|
+
| `/new` | New conversation (clear context) |
|
|
86
|
+
| `/model [provider/model]` | View or switch model |
|
|
87
|
+
| `/think on\|off` | Toggle extended thinking |
|
|
88
|
+
| `/job`, `/schedule`, `/audit`, `/stats` | Manage jobs, schedules, audit, stats |
|
|
89
|
+
| `/router status\|explain` | Inspect routing decisions |
|
|
90
|
+
| `y` / `n` / `批准` / `拒绝` | Approve / deny Claude tool call |
|
|
164
91
|
|
|
165
92
|
## Human-in-the-loop Tool Approval
|
|
166
93
|
|
|
167
|
-
When a Claude run
|
|
94
|
+
When a Claude run tries to use a tool, im-hub-pro pauses and sends an approval card:
|
|
168
95
|
|
|
169
96
|
```
|
|
170
97
|
🔐 Tool approval request
|
|
171
98
|
Tool: Bash
|
|
172
99
|
Input: {"command":"rm -rf node_modules"}
|
|
173
100
|
Reply y to approve / n to deny (auto-deny in 5 min)
|
|
174
|
-
req: a3f1c0d2
|
|
175
101
|
```
|
|
176
102
|
|
|
177
|
-
Reply `y
|
|
103
|
+
Reply `y` / `n` in IM, or click Allow / Deny in the web UI. Works identically across WeChat, Telegram, Feishu, and Discord. Disable with `IMHUB_APPROVAL_DISABLED=1`.
|
|
178
104
|
|
|
179
105
|
## Architecture
|
|
180
106
|
|
|
181
107
|
```
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
│
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
│
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
└────────────────┬───────────────────┘
|
|
220
|
-
┌──────┬───────┼────────┬─────────┐
|
|
221
|
-
▼ ▼ ▼ ▼ ▼
|
|
222
|
-
opencode claude codex copilot ACP remote
|
|
223
|
-
│
|
|
224
|
-
▼ (if a tool needs approval)
|
|
225
|
-
MCP sidecar ─ unix socket ─ approvalBus
|
|
226
|
-
└─ approvalRouter → IM thread
|
|
227
|
-
|
|
228
|
-
┌─ Cross-cutting ───────────────────────────────────────┐
|
|
229
|
-
│ audit-log (SQLite, 30-day retention) │
|
|
230
|
-
│ job-board (SQLite, persistent + AbortController) │
|
|
231
|
-
│ scheduler (30s tick → cron → enqueue jobs) │
|
|
232
|
-
│ workspaces (per-tenant agent whitelist + limits) │
|
|
233
|
-
│ metrics (Prometheus text via /api/metrics) │
|
|
234
|
-
│ session (~/.im-hub/sessions/, append-only JSONL) │
|
|
235
|
-
│ pino (traceId end-to-end, JSON in production) │
|
|
236
|
-
└───────────────────────────────────────────────────────┘
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
Single-process, single-instance: SQLite (`audit.db` / `jobs.db` / `schedules.db`) plus a session file tree is the entire persistence layer. No Redis, no MQ.
|
|
108
|
+
┌─ IM ingress ─────────────────────────────────────┐
|
|
109
|
+
│ WeChat iLink (long-poll + image/voice/file) │
|
|
110
|
+
│ Telegram (grammy + photo/voice/audio) │
|
|
111
|
+
│ Feishu (Lark SDK WebSocket) │
|
|
112
|
+
│ Discord (discord.js Gateway) │
|
|
113
|
+
│ Web Chat (browser WebSocket) │
|
|
114
|
+
└───────────────────────┬──────────────────────────┘
|
|
115
|
+
│ MessageContext
|
|
116
|
+
▼
|
|
117
|
+
┌── Pre-route gates ────────────────┐
|
|
118
|
+
│ workspace · rate limiter · traceId │
|
|
119
|
+
└────────────────┬──────────────────┘
|
|
120
|
+
▼
|
|
121
|
+
┌── Intent router ──────────────────┐
|
|
122
|
+
│ command → builtin │
|
|
123
|
+
│ /agent → explicit switch │
|
|
124
|
+
│ default → classify (regex/keyword/ │
|
|
125
|
+
│ sticky/LLM judge) │
|
|
126
|
+
└────────────────┬──────────────────┘
|
|
127
|
+
▼
|
|
128
|
+
┌── Agent invocation ───────────────┐
|
|
129
|
+
│ circuit breaker + spawn stream │
|
|
130
|
+
└───┬──────┬──────┬──────┬──────┬───┘
|
|
131
|
+
▼ ▼ ▼ ▼ ▼
|
|
132
|
+
claude opencode codex copilot ACP
|
|
133
|
+
│
|
|
134
|
+
▼ (tool approval)
|
|
135
|
+
MCP sidecar → approvalBus → IM thread
|
|
136
|
+
|
|
137
|
+
┌─ Cross-cutting ──────────────────────────────────┐
|
|
138
|
+
│ SQLite (audit · jobs · schedules) │
|
|
139
|
+
│ session (append-only JSONL) │
|
|
140
|
+
│ Prometheus metrics · pino structured logging │
|
|
141
|
+
└──────────────────────────────────────────────────┘
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Single process, zero external dependencies — SQLite + session files are the entire persistence layer.
|
|
240
145
|
|
|
241
146
|
For the full deep-dive see [`docs/architecture/current.md`](docs/architecture/current.md).
|
|
242
147
|
|
|
243
|
-
## Project Structure
|
|
244
|
-
|
|
245
|
-
```
|
|
246
|
-
im-hub-pro/
|
|
247
|
-
├── src/
|
|
248
|
-
│ ├── core/
|
|
249
|
-
│ │ ├── types.ts # Plugin interfaces
|
|
250
|
-
│ │ ├── registry.ts # Plugin registration
|
|
251
|
-
│ │ ├── router.ts # Message routing
|
|
252
|
-
│ │ ├── session.ts # Session manager (append-only JSONL)
|
|
253
|
-
│ │ ├── workspace.ts # Multi-tenant workspaces
|
|
254
|
-
│ │ ├── intent.ts # Intent classifier
|
|
255
|
-
│ │ ├── intent-llm.ts # LLM judge fallback (LRU cached)
|
|
256
|
-
│ │ ├── circuit-breaker.ts # Per-agent breaker
|
|
257
|
-
│ │ ├── rate-limiter.ts # Token-bucket
|
|
258
|
-
│ │ ├── job-board.ts # Persistent jobs + cancel
|
|
259
|
-
│ │ ├── schedule.ts # Cron tick → job enqueue
|
|
260
|
-
│ │ ├── audit-log.ts # SQLite audit
|
|
261
|
-
│ │ ├── metrics.ts # Prometheus quantiles
|
|
262
|
-
│ │ ├── acp-server.ts # /tasks ACP server
|
|
263
|
-
│ │ ├── approval-bus.ts # Tool-approval pub/sub
|
|
264
|
-
│ │ ├── approval-router.ts # Approval ↔ IM bridge
|
|
265
|
-
│ │ ├── bgjob-reader.ts # ~/.claude + ~/.config/opencode bgjobs
|
|
266
|
-
│ │ ├── agent-base.ts # Shared spawn-stream for CLI agents
|
|
267
|
-
│ │ ├── config-schema.ts # Zod schema
|
|
268
|
-
│ │ ├── logger.ts # pino + traceId
|
|
269
|
-
│ │ ├── sqlite-helper.ts # Shared prepare/PRAGMA cache
|
|
270
|
-
│ │ └── commands/ # /audit /router /job /schedule /model …
|
|
271
|
-
│ ├── plugins/
|
|
272
|
-
│ │ ├── messengers/
|
|
273
|
-
│ │ │ ├── wechat/ # iLink long-poll
|
|
274
|
-
│ │ │ ├── feishu/ # Lark SDK WebSocket
|
|
275
|
-
│ │ │ ├── telegram/ # grammy
|
|
276
|
-
│ │ │ └── discord/ # discord.js
|
|
277
|
-
│ │ └── agents/
|
|
278
|
-
│ │ ├── claude-code/ # + MCP approval sidecar
|
|
279
|
-
│ │ ├── codex/
|
|
280
|
-
│ │ ├── copilot/
|
|
281
|
-
│ │ ├── opencode/
|
|
282
|
-
│ │ └── acp/ # ACP client + /.well-known discovery
|
|
283
|
-
│ ├── index.ts
|
|
284
|
-
│ ├── cli.ts
|
|
285
|
-
│ └── web/
|
|
286
|
-
│ ├── server.ts # HTTP + WS + REST + ACP server
|
|
287
|
-
│ └── public/
|
|
288
|
-
│ ├── index.html # Chat UI
|
|
289
|
-
│ ├── tasks.html # Tasks dashboard
|
|
290
|
-
│ └── settings.html # Settings UI
|
|
291
|
-
├── docs/
|
|
292
|
-
│ ├── architecture/{current,target}.md
|
|
293
|
-
│ ├── adr/{0001,0002,0003}-*.md
|
|
294
|
-
│ ├── deployment.md
|
|
295
|
-
│ ├── discord-setup.md
|
|
296
|
-
│ └── upgrade-plan.md
|
|
297
|
-
├── package.json
|
|
298
|
-
├── tsconfig.json
|
|
299
|
-
└── README.md
|
|
300
|
-
```
|
|
301
|
-
|
|
302
148
|
## Configuration
|
|
303
149
|
|
|
304
|
-
Config file: `~/.im-hub/config.json`
|
|
150
|
+
Config file: `~/.im-hub/config.json` (validated by zod at startup)
|
|
305
151
|
|
|
306
152
|
```json
|
|
307
153
|
{
|
|
308
|
-
"messengers": ["wechat", "
|
|
154
|
+
"messengers": ["wechat", "telegram"],
|
|
309
155
|
"agents": ["claude-code", "opencode"],
|
|
310
156
|
"defaultAgent": "claude-code",
|
|
311
|
-
"
|
|
312
|
-
"botToken": "***",
|
|
313
|
-
"allowedGuilds": [],
|
|
314
|
-
"allowedChannels": []
|
|
315
|
-
},
|
|
157
|
+
"telegram": { "botToken": "***" },
|
|
316
158
|
"acpAgents": [
|
|
317
159
|
{
|
|
318
160
|
"name": "my-agent",
|
|
319
|
-
"aliases": ["ma"],
|
|
320
161
|
"endpoint": "https://api.example.com",
|
|
321
|
-
"auth": { "type": "bearer", "token": "***" }
|
|
322
|
-
"enabled": true
|
|
162
|
+
"auth": { "type": "bearer", "token": "***" }
|
|
323
163
|
}
|
|
324
164
|
],
|
|
325
165
|
"workspaces": [
|
|
@@ -334,12 +174,10 @@ Config file: `~/.im-hub/config.json`
|
|
|
334
174
|
}
|
|
335
175
|
```
|
|
336
176
|
|
|
337
|
-
The schema is enforced by `zod` at startup and on every PUT `/api/config` — bad configs reject loudly instead of silently breaking the bridge.
|
|
338
|
-
|
|
339
177
|
## Requirements
|
|
340
178
|
|
|
341
|
-
- **Node.js 18
|
|
342
|
-
-
|
|
179
|
+
- **Node.js ≥ 18** (≥ 22 LTS recommended)
|
|
180
|
+
- At least one agent CLI or ACP endpoint:
|
|
343
181
|
- `npm i -g @anthropic-ai/claude-code`
|
|
344
182
|
- `npm i -g @openai/codex`
|
|
345
183
|
- `npm i -g @github/copilot`
|
|
@@ -348,135 +186,45 @@ The schema is enforced by `zod` at startup and on every PUT `/api/config` — ba
|
|
|
348
186
|
## Development
|
|
349
187
|
|
|
350
188
|
```bash
|
|
351
|
-
git clone https://github.com/benking007/imhub.git
|
|
352
|
-
cd imhub
|
|
189
|
+
git clone https://github.com/benking007/imhub.git && cd imhub
|
|
353
190
|
npm install
|
|
354
191
|
npm run build # tsc + copy public/
|
|
355
192
|
npm run dev # tsc --watch
|
|
356
193
|
npm test # bun test
|
|
357
|
-
npm run
|
|
358
|
-
npm
|
|
194
|
+
npm run lint # biome lint
|
|
195
|
+
npm run typecheck # tsc --noEmit
|
|
359
196
|
```
|
|
360
197
|
|
|
198
|
+
## Deployment
|
|
199
|
+
|
|
200
|
+
See [`docs/deployment.md`](docs/deployment.md) for systemd, Docker, nginx, monitoring, and upgrade instructions.
|
|
201
|
+
|
|
361
202
|
## Roadmap
|
|
362
203
|
|
|
363
|
-
###
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
- [x] Structured logging (pino) + traceId
|
|
381
|
-
- [x] Zod config schema validation
|
|
382
|
-
- [x] AgentBase abstraction + healthCheck cache
|
|
383
|
-
- [x] Audit log (SQLite) + `/audit`
|
|
384
|
-
- [x] Intent classifier + circuit breaker + rate limiter
|
|
385
|
-
- [x] ACP server mode (`POST /tasks` sync + SSE)
|
|
386
|
-
- [x] `/.well-known/acp` discovery
|
|
387
|
-
- [x] Multi-tenant workspaces + agent whitelist
|
|
388
|
-
- [x] Persistent Job Board + cron scheduler
|
|
389
|
-
- [x] Web `/tasks` panel + REST jobs API
|
|
390
|
-
- [x] Prometheus metrics
|
|
391
|
-
|
|
392
|
-
### v0.2.14 — Tool approval
|
|
393
|
-
- [x] Human-in-the-loop tool approval over IM
|
|
394
|
-
- [x] MCP approval sidecar (claude-code adapter)
|
|
395
|
-
|
|
396
|
-
### v0.2.15 — Discord & Dashboard
|
|
397
|
-
- [x] Discord messenger adapter
|
|
398
|
-
- [x] Tasks dashboard surfaces Claude / opencode bgjobs
|
|
399
|
-
- [x] Flattened subtasks tab
|
|
400
|
-
|
|
401
|
-
### v0.2.16 — Security hardening (P0 + P1)
|
|
402
|
-
- [x] Timing-safe REST + WS token compare (shared `safe-equal`)
|
|
403
|
-
- [x] Schedule `notify_url` SSRF gate (http(s) only, RFC1918 / loopback / IPv6 ULA blocked) + 10s fetch timeout + redirect:'manual'
|
|
404
|
-
- [x] HTML token injection: `JSON.stringify` instead of single-quote splice
|
|
405
|
-
- [x] Telegram bot-token redaction in logs (pino `redact.paths` + adapter-level scrub)
|
|
406
|
-
- [x] WeChat credential file `0o600` + parent dir `0o700`
|
|
407
|
-
- [x] Approval socket path uses 128-bit random + post-listen `chmod 0o600` + stat verification
|
|
408
|
-
- [x] Job result size cap (`IMHUB_JOB_RESULT_MAX_BYTES`, default 1 MiB) + UTF-8/JSON safe truncation
|
|
409
|
-
- [x] Job-board retention + 6h sweep + `creator_id` / `workspace_id` schema migration
|
|
410
|
-
- [x] Multi-tenant ACL on `/job` `/schedule` `/audit` commands (each user sees only their own rows; legacy ownerless rows stay visible for safe upgrades)
|
|
411
|
-
- [x] Workspace whitelist enforced on direct command paths, not just routing
|
|
412
|
-
- [x] Rate-limiter opportunistic auto-cleanup (no setInterval timer)
|
|
413
|
-
- [x] `Session.addMessage` per-key mutex (defeats concurrent read-modify-write race)
|
|
414
|
-
|
|
415
|
-
### v0.2.17 — Observability & IM polish (P2 + P3)
|
|
416
|
-
- [x] Static-page security headers (`X-Frame-Options` / `X-Content-Type-Options` / `Referrer-Policy` / CSP)
|
|
417
|
-
- [x] `/api/health` declared public (k8s liveness friendly)
|
|
418
|
-
- [x] WebSocket connection cap (`IMHUB_MAX_WS_CLIENTS`, default 100) + `bufferedAmount` backpressure (4 MiB highwater)
|
|
419
|
-
- [x] Prometheus label-cardinality whitelist (`intent` / `platform` → `'other'` for unknowns)
|
|
420
|
-
- [x] New counters: `im_hub_audit_prune_failed_total`, `im_hub_agent_cleanup_failed_total`, `im_hub_approval_pending` / `im_hub_approval_requests_total` / `im_hub_approval_resolved_total{result=allow|deny|timeout}`
|
|
421
|
-
- [x] `intent-llm` cache key SHA-256 + 256-char prompt cap (defeats LRU memory bloat)
|
|
422
|
-
- [x] Auto-allow fingerprint 5 → 10 chars (`git status` ≠ `git stash` ≠ `git submo`)
|
|
423
|
-
- [x] UTF-16 surrogate-safe message split (emoji at boundary no longer renders as `□`)
|
|
424
|
-
- [x] Telegram HTML escape covers `'` / `"` (approval-card `<a href="...">` safety)
|
|
425
|
-
- [x] approval-bus over-cap deny instead of silent socket destroy
|
|
426
|
-
- [x] SQLite WAL clean checkpoint on SIGINT
|
|
427
|
-
- [x] traceId 12 hex → 16 hex (`~2^48` → `~2^64`)
|
|
428
|
-
- [x] WeChat ilink-client fetch timeouts on remaining 4 callsites
|
|
429
|
-
- [x] Discord typing interval companion `AbortController` (no race with `client.destroy()`)
|
|
430
|
-
- [x] WeChat `contextTokens` periodic cleanup on heartbeat tick
|
|
431
|
-
- [x] CI lockfile fix (Tencent mirror URLs → `https://registry.npmjs.org/`)
|
|
432
|
-
|
|
433
|
-
### v0.2.18 — IM reconnect backoff (M9)
|
|
434
|
-
- [x] Shared `Backoff` helper (exponential + ±jitter, RNG-injectable for tests)
|
|
435
|
-
- [x] Telegram `runPollingLoop`: fixed 2s / 5s setTimeouts → `Backoff(2s, 60s, 0.5)`; 30s healthy-run threshold resets backoff
|
|
436
|
-
- [x] WeChat ilink `pollLoop`: inline `Math.pow(2,n-1)` → `Backoff(2s, 30s, 0.5)`; success path resets
|
|
437
|
-
|
|
438
|
-
### v0.2.19 — Codex sandbox + Dashboard filter / Audit tab
|
|
439
|
-
- [x] Codex now honors `session.planMode`; default sandbox `--full-auto` → explicit `-s workspace-write`
|
|
440
|
-
- [x] Per-agent filter on Jobs / Subtasks / Schedules tabs (`OwnerOpts.agent` plumbed through)
|
|
441
|
-
- [x] New Audit tab in `/tasks` pulling SQLite audit log + `GET /api/audit?agent=&days=&user=&intent=`
|
|
442
|
-
|
|
443
|
-
### v0.2.20 — Web console PR-A: theme + error boundary + in-page approval
|
|
444
|
-
- [x] Three-state theme (light / dark / system) applied synchronously in `<head>` to defeat flash
|
|
445
|
-
- [x] `_app.js` shared utility: `window.imhub.{theme,i18n,api,showError}` + auto-installed error boundary
|
|
446
|
-
- [x] In-chat approval cards on `/` (Allow / Deny / Allow + Auto), routed through the same `approvalBus.resolvePending()` path as Telegram
|
|
447
|
-
- [x] `approval-router` `bindButtonHandlerForPlatform(platform)` exported so late-registered messengers (web is one) can wire their button handler
|
|
448
|
-
|
|
449
|
-
### v0.2.21 — Web console PR-B: Health + Approvals tabs
|
|
450
|
-
- [x] Health tab: per-agent breaker phase (closed/open/half-open) + rate-limiter remaining + p50/95/99 latency + invocations / success rate / cost / cooldown + 60-poll p95 sparkline
|
|
451
|
-
- [x] Approvals tab: list every pending HITL approval (reqId / threadId / tool / age / registeredAt) with browser-side Allow / Deny / Allow + Auto buttons
|
|
452
|
-
- [x] Backend: `GET /api/agent-health` / `GET /api/approvals` / `POST /api/approvals/:reqId/resolve`
|
|
453
|
-
- [x] `approval-bus.PendingApproval` now carries `input` + `registeredAt`; emits `'approval'` events for SSE
|
|
454
|
-
|
|
455
|
-
### v0.2.22 — Web console PR-C: SSE event stream + Workspace CRUD UI
|
|
456
|
-
- [x] `src/core/event-bus.ts` — typed publish/subscribe (audit / approval / job / metrics) with 200-entry replay ring buffer
|
|
457
|
-
- [x] `GET /events` SSE endpoint — token via `?token=`, 25s heartbeat, listener-error swallow
|
|
458
|
-
- [x] Dashboard `EventSource('/events?token=...')` refreshes only the visible tab; polling kept as fallback; `approval requested` flashes the tab badge
|
|
459
|
-
- [x] Settings page Workspace card — list + create / edit / delete (id locked on edit; default row uneditable + undeletable)
|
|
460
|
-
- [x] Backend `GET/POST/PATCH/DELETE /api/workspaces` + `WorkspaceRegistry.{remove(id), listFull()}`; mutations persisted back to `~/.im-hub/config.json`
|
|
461
|
-
|
|
462
|
-
### v0.2.23 — Web console PR-D: Files tab + Jobs batch ops + settings polish
|
|
463
|
-
- [x] Files tab — read-only browse of `~/.im-hub-workspaces/<agent>/`, two-pane (dir tree + content), 1 MiB cap, NUL-byte binary detect → base64
|
|
464
|
-
- [x] Path-traversal defense: agent name whitelisted against `registry.listAgents()`; resolved path must equal or live below `defaultAgentCwd(agent)`
|
|
465
|
-
- [x] Jobs tab multi-select + select-all + hidden-until-needed batch toolbar; selection state survives refresh
|
|
466
|
-
- [x] `POST /api/jobs/batch-cancel` / `batch-run` accept `{ ids: number[] }` (max 100); per-id failures don't fail the whole request
|
|
467
|
-
- [x] Settings header restyle (`.brand` + `.controls` flex groups) — fixes language `<select>` stretching across the bar; container 720→880, sticky header, theme-aware toast / `.btn-danger:hover`
|
|
468
|
-
|
|
469
|
-
### v0.3.0
|
|
204
|
+
### Done
|
|
205
|
+
|
|
206
|
+
| Version | Theme |
|
|
207
|
+
|---------|-------|
|
|
208
|
+
| v0.1.x | MVP — WeChat + 4 agents + command routing |
|
|
209
|
+
| v0.2.0 | Multi-IM — Feishu, Telegram, sessions, ACP |
|
|
210
|
+
| v0.2.13 | Foundations — logging, audit, intent, jobs, metrics, workspaces |
|
|
211
|
+
| v0.2.14 | Human-in-the-loop tool approval |
|
|
212
|
+
| v0.2.15 | Discord adapter + tasks dashboard |
|
|
213
|
+
| v0.2.16–17 | Security hardening + observability |
|
|
214
|
+
| v0.2.18–19 | IM reconnect backoff, Codex sandbox, dashboard filters |
|
|
215
|
+
| v0.2.20–23 | Web console — theme, approvals, SSE, files, batch ops |
|
|
216
|
+
| v0.2.30 | Production hardening — session isolation, serial WS, loopback bind |
|
|
217
|
+
| v0.2.35 | WeChat & Telegram rich media — image / file / voice / video |
|
|
218
|
+
|
|
219
|
+
### v0.3.0 (next)
|
|
220
|
+
|
|
470
221
|
- [ ] DingTalk adapter
|
|
471
222
|
- [ ] Slack adapter
|
|
472
|
-
- [ ]
|
|
473
|
-
- [ ]
|
|
474
|
-
- [ ]
|
|
475
|
-
- [ ] Workspace member picker UI (current CSV input is ops-friendly but error-prone)
|
|
476
|
-
|
|
477
|
-
## Community <a name="wechat-group"></a>
|
|
223
|
+
- [ ] Feishu / Discord button-style approval cards
|
|
224
|
+
- [ ] Multi-instance event bus (Redis Streams / NATS)
|
|
225
|
+
- [ ] Workspace member picker UI
|
|
478
226
|
|
|
479
|
-
|
|
227
|
+
## Community
|
|
480
228
|
|
|
481
229
|
<p align="center">
|
|
482
230
|
<a href="https://discord.gg/R83CXYz5">
|
|
@@ -488,11 +236,6 @@ Questions? Feel free to reach out on [X](https://x.com/lijieisme) or join the Di
|
|
|
488
236
|
</a>
|
|
489
237
|
</p>
|
|
490
238
|
|
|
491
|
-
<p align="center">
|
|
492
|
-
<img src="assets/wechat-group" alt="Original author WeChat" width="180"><br>
|
|
493
|
-
<sub><i>Original author's contact</i></sub>
|
|
494
|
-
</p>
|
|
495
|
-
|
|
496
239
|
## License
|
|
497
240
|
|
|
498
241
|
MIT
|