omp-wechat 1.3.0 → 1.4.1
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/README.md +10 -10
- package/dist/index.js +29 -27
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,9 +12,9 @@ WeChat user → iLink Bot API → [OMP/Pi process] → SDK → AI provider
|
|
|
12
12
|
└──── reply ← message_end ─┘
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
The extension runs **inside** the OMP/Pi process.
|
|
15
|
+
The extension runs **inside** the OMP/Pi process. The iLink long-poll loop starts at extension load time (not `session_start`) as a background promise. A singleton port lock ensures only one process runs the poll loop at a time — other OMP/Pi processes standby with a 30s failover timer to take over if the lock holder crashes.
|
|
16
16
|
|
|
17
|
-
For boot-time persistence, install a launchd/systemd service via `/wechat install`. The service runs `omp --mode rpc` (or `pi --mode rpc`) with `
|
|
17
|
+
For boot-time persistence, install a launchd/systemd service via `/wechat install`. The service runs `omp --mode rpc` (or `pi --mode rpc`) with a `get_state` JSON-RPC heartbeat piped to stdin every 5s — without an active RPC client, `omp --mode rpc` exits on idle stdin, so the heartbeat keeps the process alive. `KeepAlive`/`Restart=always` handles crashes and reboots.
|
|
18
18
|
|
|
19
19
|
- **No external `bun` required** — OMP/Pi is a standalone binary with an embedded runtime
|
|
20
20
|
- **Singleton** — port lock guarantees one poll loop across all concurrent OMP/Pi processes
|
|
@@ -26,7 +26,7 @@ For boot-time persistence, install a launchd/systemd service via `/wechat instal
|
|
|
26
26
|
|
|
27
27
|
## Features
|
|
28
28
|
|
|
29
|
-
- **OMP/Pi extension**: installs via `omp plugin link .` or `pi plugin link .`, auto-starts poll loop
|
|
29
|
+
- **OMP/Pi extension**: installs via `omp plugin link .` or `pi plugin link .`, auto-starts poll loop at extension load time
|
|
30
30
|
- **Slash commands**: `/wechat login`, `/wechat status`, `/wechat pair`, `/wechat allow`, `/wechat revoke`, `/wechat list`, `/wechat stop`, `/wechat install`, `/wechat uninstall`
|
|
31
31
|
- **Singleton**: port lock guarantees one poll loop across all concurrent OMP/Pi processes — no duplicate replies
|
|
32
32
|
- **Failover**: 30s timer takes over automatically if the lock holder crashes
|
|
@@ -56,7 +56,7 @@ bun run build
|
|
|
56
56
|
omp plugin link . # or: pi plugin link .
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
This links the extension into OMP/Pi. The poll loop starts
|
|
59
|
+
This links the extension into OMP/Pi. The poll loop starts at extension load time — no `session_start` required.
|
|
60
60
|
|
|
61
61
|
### Login (scan QR code)
|
|
62
62
|
|
|
@@ -68,7 +68,7 @@ A QR code appears in the terminal. Scan it with WeChat and confirm on your phone
|
|
|
68
68
|
|
|
69
69
|
### Run
|
|
70
70
|
|
|
71
|
-
No explicit run command needed — the poll loop
|
|
71
|
+
No explicit run command needed — the poll loop starts at extension load time. Once running, send a message to the bot on WeChat — it will be processed and the reply sent back.
|
|
72
72
|
|
|
73
73
|
To check status: `/wechat status`. To stop: `/wechat stop`.
|
|
74
74
|
|
|
@@ -78,9 +78,9 @@ To check status: `/wechat status`. To stop: `/wechat stop`.
|
|
|
78
78
|
/wechat install
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
Installs a launchd (macOS) or systemd (Linux) service that runs the host (`omp --mode rpc` or `pi --mode rpc`) at boot.
|
|
81
|
+
Installs a launchd (macOS) or systemd (Linux) service that runs the host (`omp --mode rpc` or `pi --mode rpc`) at boot. A `get_state` JSON-RPC heartbeat is piped to stdin every 5s to keep the process alive (without an active RPC client, `omp --mode rpc` exits on idle stdin). `KeepAlive`/`Restart=always` handles crashes and reboots.
|
|
82
82
|
|
|
83
|
-
Logs: `~/.omp
|
|
83
|
+
Logs: `~/.omp/logs/rpc.log` (stderr only; stdout discarded) and `~/.omp/logs/wechat.log` (poll loop)
|
|
84
84
|
Manage: `launchctl start|stop com.omp-wechat` (macOS) or `sudo systemctl start|stop omp-wechat` (Linux)
|
|
85
85
|
|
|
86
86
|
To remove: `/wechat uninstall`
|
|
@@ -149,14 +149,14 @@ The logged-in user (who scanned the QR code) is automatically added to the allow
|
|
|
149
149
|
|
|
150
150
|
| Scenario | Behavior |
|
|
151
151
|
|---|---|
|
|
152
|
-
| Host process starts | Poll loop starts
|
|
152
|
+
| Host process starts | Poll loop starts at extension load time (acquires singleton lock) |
|
|
153
153
|
| Other host processes | Standby with 30s failover timer, take over if lock holder dies |
|
|
154
154
|
| Host process exits | Poll loop stops, lock released, all sessions disposed |
|
|
155
155
|
| Host crashes | Failover timer in another process detects dead lock and takes over; or launchd/systemd restarts the host (if `/wechat install` was run) |
|
|
156
156
|
| Machine reboots | Service auto-starts the host (if installed), poll loop resumes |
|
|
157
157
|
| No boot service | Poll loop only runs while a host process is active |
|
|
158
158
|
|
|
159
|
-
Logs: `~/.omp
|
|
159
|
+
Logs: `~/.omp/logs/wechat.log` (poll loop) and `~/.omp/logs/rpc.log` (boot service stderr)
|
|
160
160
|
|
|
161
161
|
## Project Structure
|
|
162
162
|
|
|
@@ -164,7 +164,7 @@ Logs: `~/.omp-wechat/logs/daemon.log` (poll loop) and `~/.omp-wechat/logs/rpc.lo
|
|
|
164
164
|
OMP-Wechat/
|
|
165
165
|
├── package.json # omp.extensions / pi.extensions manifest
|
|
166
166
|
├── src/
|
|
167
|
-
│ ├── index.ts # OMP/Pi extension entry (
|
|
167
|
+
│ ├── index.ts # OMP/Pi extension entry (extension load + /wechat commands)
|
|
168
168
|
│ ├── bridge.ts # In-process poll loop + message handling + singleton port lock
|
|
169
169
|
│ ├── service.ts # Boot-time launchd/systemd install
|
|
170
170
|
│ ├── config.ts # Config loading (config.yml + defaults)
|
package/dist/index.js
CHANGED
|
@@ -1914,6 +1914,7 @@ class ChatSession {
|
|
|
1914
1914
|
systemPrompt: config.systemPrompt,
|
|
1915
1915
|
modelPattern: config.model
|
|
1916
1916
|
});
|
|
1917
|
+
session.setAdvisorEnabled(false);
|
|
1917
1918
|
if (modelFallbackMessage) {
|
|
1918
1919
|
logger.warn(`Model fallback: ${modelFallbackMessage}`);
|
|
1919
1920
|
}
|
|
@@ -2471,7 +2472,9 @@ function getLogDir() {
|
|
|
2471
2472
|
return join8(homedir7(), ".omp", "logs");
|
|
2472
2473
|
}
|
|
2473
2474
|
function resolveHostBinary() {
|
|
2474
|
-
|
|
2475
|
+
const exe = process.execPath || "omp";
|
|
2476
|
+
const basename2 = exe.split("/").pop() || "omp";
|
|
2477
|
+
return basename2;
|
|
2475
2478
|
}
|
|
2476
2479
|
function plistPath() {
|
|
2477
2480
|
return join8(homedir7(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
|
|
@@ -2488,10 +2491,9 @@ function generatePlist() {
|
|
|
2488
2491
|
|
|
2489
2492
|
<key>ProgramArguments</key>
|
|
2490
2493
|
<array>
|
|
2491
|
-
<string
|
|
2492
|
-
<string
|
|
2493
|
-
<string>rpc</string>
|
|
2494
|
-
<string>--no-title</string>
|
|
2494
|
+
<string>/bin/sh</string>
|
|
2495
|
+
<string>-c</string>
|
|
2496
|
+
<string>while true; do echo '{"id":"ka","type":"get_state"}'; sleep 5; done | exec ${omp} --mode rpc --no-title >/dev/null</string>
|
|
2495
2497
|
</array>
|
|
2496
2498
|
|
|
2497
2499
|
<key>RunAtLoad</key>
|
|
@@ -2503,11 +2505,6 @@ function generatePlist() {
|
|
|
2503
2505
|
<key>ThrottleInterval</key>
|
|
2504
2506
|
<integer>10</integer>
|
|
2505
2507
|
|
|
2506
|
-
<key>StandardInputPath</key>
|
|
2507
|
-
<string>/dev/null</string>
|
|
2508
|
-
|
|
2509
|
-
<key>StandardOutPath</key>
|
|
2510
|
-
<string>${logDir}/rpc.log</string>
|
|
2511
2508
|
<key>StandardErrorPath</key>
|
|
2512
2509
|
<string>${logDir}/rpc.log</string>
|
|
2513
2510
|
|
|
@@ -2561,15 +2558,14 @@ Wants=network-online.target
|
|
|
2561
2558
|
Type=simple
|
|
2562
2559
|
User=${user}
|
|
2563
2560
|
Group=${user}
|
|
2564
|
-
ExecStart
|
|
2565
|
-
StandardInput=null
|
|
2561
|
+
ExecStart=/bin/sh -c 'while true; do echo "{\\"id\\":\\"ka\\",\\"type\\":\\"get_state\\"}"; sleep 5; done | exec ${omp} --mode rpc --no-title >/dev/null'
|
|
2566
2562
|
Restart=always
|
|
2567
2563
|
RestartSec=10
|
|
2568
2564
|
|
|
2569
2565
|
Environment=HOME=${homedir7()}
|
|
2570
2566
|
Environment=PATH=/usr/local/bin:/usr/bin:/bin
|
|
2571
2567
|
|
|
2572
|
-
StandardOutput=
|
|
2568
|
+
StandardOutput=null
|
|
2573
2569
|
StandardError=append:${logDir}/rpc.log
|
|
2574
2570
|
|
|
2575
2571
|
NoNewPrivileges=true
|
|
@@ -2659,21 +2655,27 @@ function wechatExtension(pi) {
|
|
|
2659
2655
|
if (pi.pi && typeof pi.setLabel === "function") {
|
|
2660
2656
|
pi.setLabel("OMP-Wechat Bridge");
|
|
2661
2657
|
}
|
|
2658
|
+
bridge = new WeChatBridge;
|
|
2659
|
+
daemonState = bridge.start();
|
|
2660
|
+
if (daemonState.running) {
|
|
2661
|
+
logger.info("WeChat bridge started at extension load");
|
|
2662
|
+
} else {
|
|
2663
|
+
logger.debug("WeChat bridge: another instance holds the lock, starting failover watch");
|
|
2664
|
+
setInterval(() => {
|
|
2665
|
+
if (daemonState?.running)
|
|
2666
|
+
return;
|
|
2667
|
+
daemonState = bridge.start();
|
|
2668
|
+
if (daemonState.running) {
|
|
2669
|
+
logger.info("WeChat bridge: took over from failed instance");
|
|
2670
|
+
}
|
|
2671
|
+
}, 30000);
|
|
2672
|
+
}
|
|
2662
2673
|
pi.on("session_start", async (_event, ctx) => {
|
|
2663
|
-
bridge
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
logger.debug("WeChat bridge: another instance holds the lock, starting failover watch");
|
|
2669
|
-
ctx.setInterval(() => {
|
|
2670
|
-
if (daemonState?.running)
|
|
2671
|
-
return;
|
|
2672
|
-
daemonState = bridge.start();
|
|
2673
|
-
if (daemonState.running) {
|
|
2674
|
-
ctx.ui.notify("WeChat bridge: took over from failed instance", "info");
|
|
2675
|
-
}
|
|
2676
|
-
}, 30000);
|
|
2674
|
+
if (bridge && !daemonState?.running) {
|
|
2675
|
+
daemonState = bridge.start();
|
|
2676
|
+
if (daemonState.running) {
|
|
2677
|
+
ctx.ui.notify("WeChat bridge started", "info");
|
|
2678
|
+
}
|
|
2677
2679
|
}
|
|
2678
2680
|
});
|
|
2679
2681
|
pi.registerCommand("wechat", {
|