botmux 3.29.0 → 3.30.0
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.en.md +3 -3
- package/README.md +4 -3
- package/package.json +12 -8
- package/scripts/botmux-launcher.sh +120 -0
- package/scripts/install-path-entry.mjs +6 -4
- package/scripts/postinstall-bin.mjs +3 -2
package/README.en.md
CHANGED
|
@@ -50,7 +50,7 @@ botmux start # start the daemon (botmux autostart enable for aut
|
|
|
50
50
|
>
|
|
51
51
|
> Stable macOS CLI releases use a consistent Apple Developer ID signature. Replacing the binary during an upgrade therefore preserves the code identity used by macOS file and App Data permissions instead of appearing as a new program for every version. Canary, beta, and RC builds remain ad-hoc signed.
|
|
52
52
|
>
|
|
53
|
-
> To upgrade: `botmux upgrade` (
|
|
53
|
+
> To upgrade: **always re-run the curl command above** (this also upgrades npm/pnpm global installs — in-place replacement, no second PATH line), then open a new terminal and run `botmux restart`; on ≥3.18 binary installs `botmux upgrade` is equivalent. To install a pinned version (rollbacks included): `curl -fsSL https://raw.githubusercontent.com/deepcoldy/botmux/master/install.sh | BOTMUX_VERSION=v3.18.8 sh` (the variable must precede the `sh` on the right side of the pipe). ⚠️ **Do not npm-upgrade from releases older than v3.18.0** — crossing the Node-sources → binary form boundary leaves the daemon unable to restart.
|
|
54
54
|
|
|
55
55
|
<details>
|
|
56
56
|
<summary>Already living in the Node ecosystem? npm works too (same binary)</summary>
|
|
@@ -59,9 +59,9 @@ botmux start # start the daemon (botmux autostart enable for aut
|
|
|
59
59
|
npm install -g botmux # requires Node >= 22 to run the install itself
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
-
The npm package carries **the same self-contained binary** (only the one matching your os/arch is installed)
|
|
62
|
+
The npm package carries **the same self-contained binary** (only the one matching your os/arch is installed). The package's `bin` points at a shipped sh launcher that the package manager links onto PATH itself, so **npm, pnpm and bun all work without any lifecycle script** (pnpm 10/11 and bun skip dependency postinstalls by default, which used to leave those installs with no `botmux` command at all). The postinstall still points `~/.botmux/bin/botmux` at the same binary and writes PATH. So you still end up with exactly **one** botmux **version** — both entry points exec the same binary — and no more "two Node versions each carrying their own global botmux, fighting each other / no idea which one I just updated".
|
|
63
63
|
|
|
64
|
-
The only difference is **who installs it
|
|
64
|
+
The only difference is **who installs it**: the npm path needs Node ≥ 22 to run the install itself, the curl path never touches Node; **upgrades always re-run the curl command, no matter how you installed** (npm-upgrading from a pre-v3.18.0 install across that form boundary can leave the daemon unable to come back). Once running, the two are identical — same binary, same commands.
|
|
65
65
|
|
|
66
66
|
</details>
|
|
67
67
|
|
package/README.md
CHANGED
|
@@ -50,7 +50,7 @@ botmux start # 启动 daemon(botmux autostart enable 设开机
|
|
|
50
50
|
>
|
|
51
51
|
> 正式版 macOS CLI 使用稳定的 Apple Developer ID 签名。升级替换二进制后,macOS 的文件与 App 数据访问授权仍绑定同一代码身份,不会因为版本哈希变化而把 botmux 当成一个新程序;canary / beta / rc 等预览版仍使用 ad-hoc 签名。
|
|
52
52
|
>
|
|
53
|
-
>
|
|
53
|
+
> 升级:**一律重跑上面那条 curl 命令**(npm / pnpm 全局安装也用它,原地替换、不会重复往启动文件里追加 PATH),装完开个新终端跑 `botmux restart`;≥3.18 的二进制安装上 `botmux upgrade` 与其等价。装指定版本(含回滚):`curl -fsSL https://raw.githubusercontent.com/deepcoldy/botmux/master/install.sh | BOTMUX_VERSION=v3.18.8 sh`(变量必须在管道右侧的 `sh` 前面)。⚠️ **v3.18.0 之前的老版本不要用 npm 升级**——跨「Node 源码 → 二进制」形态边界会让 daemon 重启失败。
|
|
54
54
|
|
|
55
55
|
<details>
|
|
56
56
|
<summary>已经在用 Node 生态?也可以走 npm(同一个二进制)</summary>
|
|
@@ -59,9 +59,9 @@ botmux start # 启动 daemon(botmux autostart enable 设开机
|
|
|
59
59
|
npm install -g botmux # 需要 Node >= 22 装包本身
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
-
npm 包内带的是**同一个自包含二进制**(按 os/arch
|
|
62
|
+
npm 包内带的是**同一个自包含二进制**(按 os/arch 只装匹配的那一个)。包的 `bin` 指向随包发布的 sh 启动器,由包管理器自己链到 PATH——**npm / pnpm / bun 三种装法都不依赖生命周期脚本**(pnpm 10/11 与 bun 默认不跑依赖的 postinstall,早期版本因此装完没有任何 `botmux` 命令)。postinstall 仍会把 `~/.botmux/bin/botmux` 指向同一个二进制并写 PATH。所以装完始终只有**一个** botmux **版本**(两个入口都 exec 同一个二进制),不再出现「装了两个 Node 版本、各自带一份全局 botmux 互相打架 / 不知道更新了哪个」。
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
区别只在**谁来装**:npm 路径需要 Node ≥ 22 才能执行安装本身,curl 路径全程不碰 Node;**无论哪种装法,升级都重跑 curl**(v3.18.0 之前的老版本用 npm 跨形态升级会让 daemon 起不回来)。跑起来之后两者完全一致——同样的二进制、同样的命令。
|
|
65
65
|
|
|
66
66
|
</details>
|
|
67
67
|
|
|
@@ -71,6 +71,7 @@ npm 包内带的是**同一个自包含二进制**(按 os/arch 只装匹配的
|
|
|
71
71
|
|
|
72
72
|
- **[实时流式卡片](https://deepcoldy.github.io/botmux/cards)** — 每轮对话一张实时刷新的卡片,终端画面原样截图回传;一键显示/隐藏输出、翻屏、重启/关闭/接管会话。
|
|
73
73
|
- **[多机器人协作](https://deepcoldy.github.io/botmux/multi-bot)** — 同群多 bot @mention 路由,不同 CLI 背后不同模型,天然多样性;方案评审 / 代码 review / 技术选型让它们互相挑刺。
|
|
74
|
+
- **[群内真人独立 lane](docs/principal-lanes.md)** — 可复用 Dashboard 的「跨身份打断隔离(XPI)」开关,让同一群里的真人各用独立 CLI 上下文和 git worktree;消息仍公开可见,引用别人的任务仍可走建议/确认协作。
|
|
74
75
|
- **[多话题并行编排](https://deepcoldy.github.io/botmux/multi-topic)** — 给编排者一个大任务,它自动在群里种话题、拉各 bot 起独立会话跑流水线,飞书任务面板一眼看完所有子任务进度。
|
|
75
76
|
- **[可交互 Web 终端](https://deepcoldy.github.io/botmux/web-terminal)** — 不只是看输出,浏览器 / 手机直接操作 CLI,移动端带悬浮快捷键栏(Esc、Ctrl+C、方向键)。
|
|
76
77
|
- **[会话接入 & 接力](https://deepcoldy.github.io/botmux/adopt)** — 本地 tmux 里跑到一半,手机 `/adopt` 接管;`/relay` 把整个会话(原进程、原记忆)搬进团队群继续。
|
package/package.json
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "botmux",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.30.0",
|
|
4
4
|
"description": "Bridge between IM platforms and AI coding CLIs — one topic, one CLI session with live streaming",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"botmux": "scripts/botmux-launcher.sh"
|
|
8
|
+
},
|
|
6
9
|
"files": [
|
|
10
|
+
"scripts/botmux-launcher.sh",
|
|
7
11
|
"scripts/postinstall-bin.mjs",
|
|
8
12
|
"scripts/install-path-entry.mjs",
|
|
9
13
|
"README.md",
|
|
@@ -15,7 +19,7 @@
|
|
|
15
19
|
"access": "public"
|
|
16
20
|
},
|
|
17
21
|
"scripts": {
|
|
18
|
-
"build": "bun run audit:domains && node scripts/generate-app-icon-data.mjs && node scripts/generate-pi-initial-prompt-extension.mjs && node scripts/clean-dist.mjs && tsc && bun run typecheck:scripts && bun run typecheck:test-mocks && node scripts/generate-runtime-build-id.mjs && cp src/setup/lark-scopes.json dist/setup/ && bun run dashboard:bundle && chmod +x dist/cli.js && node scripts/audit-dist.mjs && node scripts/audit-embedded-assets.mjs --require-dist",
|
|
22
|
+
"build": "bun run audit:domains && node scripts/generate-app-icon-data.mjs && node scripts/generate-pi-initial-prompt-extension.mjs && node scripts/generate-pi-turn-boundary-extension.mjs && node scripts/clean-dist.mjs && tsc && bun run typecheck:scripts && bun run typecheck:test-mocks && node scripts/generate-runtime-build-id.mjs && cp src/setup/lark-scopes.json dist/setup/ && bun run dashboard:bundle && chmod +x dist/cli.js && node scripts/audit-dist.mjs && node scripts/audit-embedded-assets.mjs --require-dist",
|
|
19
23
|
"verify:binary": "bun scripts/verify-binary.mjs",
|
|
20
24
|
"typecheck:scripts": "tsc -p tsconfig.scripts.json",
|
|
21
25
|
"typecheck:test-mocks": "tsc -p tsconfig.test-mocks.json",
|
|
@@ -82,12 +86,12 @@
|
|
|
82
86
|
},
|
|
83
87
|
"optionalDependencies": {
|
|
84
88
|
"@napi-rs/canvas": "^0.1.65",
|
|
85
|
-
"botmux-darwin-arm64": "3.
|
|
86
|
-
"botmux-darwin-x64": "3.
|
|
87
|
-
"botmux-linux-arm64": "3.
|
|
88
|
-
"botmux-linux-arm64-musl": "3.
|
|
89
|
-
"botmux-linux-x64": "3.
|
|
90
|
-
"botmux-linux-x64-musl": "3.
|
|
89
|
+
"botmux-darwin-arm64": "3.30.0",
|
|
90
|
+
"botmux-darwin-x64": "3.30.0",
|
|
91
|
+
"botmux-linux-arm64": "3.30.0",
|
|
92
|
+
"botmux-linux-arm64-musl": "3.30.0",
|
|
93
|
+
"botmux-linux-x64": "3.30.0",
|
|
94
|
+
"botmux-linux-x64-musl": "3.30.0"
|
|
91
95
|
},
|
|
92
96
|
"devDependencies": {
|
|
93
97
|
"@midscene/web": "^1.7.6",
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# botmux launcher — the `bin` entry npm/pnpm/bun link onto PATH.
|
|
3
|
+
#
|
|
4
|
+
# ── WHY THIS FILE EXISTS ───────────────────────────────────────────────────────
|
|
5
|
+
# The main package ships NO binary (0.1MB, 6 files): the compiled single-file
|
|
6
|
+
# executable lives in a platform subpackage (`botmux-linux-x64`, …) pulled in as
|
|
7
|
+
# an optional dependency. `bin` can only point INSIDE the main package, so it
|
|
8
|
+
# cannot name that binary directly — hence this dispatcher, which resolves the
|
|
9
|
+
# subpackage at RUN time and `exec`s it.
|
|
10
|
+
#
|
|
11
|
+
# Until now the only thing that produced a runnable `botmux` was
|
|
12
|
+
# `scripts/postinstall-bin.mjs`, which writes ~/.botmux/bin/botmux. That still
|
|
13
|
+
# runs and is still what gives multi-Node-version boxes ONE unambiguous global
|
|
14
|
+
# botmux. But postinstall is not guaranteed to run:
|
|
15
|
+
#
|
|
16
|
+
# MEASURED on v3.18.13, isolated HOME, each manager's own global install:
|
|
17
|
+
# npm i -g botmux → postinstall runs → launcher written → `botmux` works
|
|
18
|
+
# bun add -g botmux → "Blocked 2 postinstalls" → NO launcher → no command
|
|
19
|
+
# pnpm add -g botmux → script not run at all → NO launcher → no command
|
|
20
|
+
#
|
|
21
|
+
# Both failures exit 0 and print "installed botmux@3.18.13" / "+ botmux 3.18.13",
|
|
22
|
+
# so the user believes it worked and only finds out at `botmux: command not found`.
|
|
23
|
+
# bun can be rescued with `bun pm -g trust botmux`; pnpm could NOT be rescued —
|
|
24
|
+
# `onlyBuiltDependencies: [botmux]` still produced no launcher (measured).
|
|
25
|
+
#
|
|
26
|
+
# With a `bin` entry the package manager links this script itself, so all three
|
|
27
|
+
# get a working command with no lifecycle script at all. postinstall then becomes
|
|
28
|
+
# an OPTIMISATION (the single canonical launcher) rather than a prerequisite.
|
|
29
|
+
#
|
|
30
|
+
# ── WHY sh AND NOT node ────────────────────────────────────────────────────────
|
|
31
|
+
# A Node dispatcher would reintroduce a Node dependency for a package whose whole
|
|
32
|
+
# point is a self-contained binary, and would add interpreter startup to every
|
|
33
|
+
# invocation. `bin` pointing at a shell script works on npm, pnpm and bun alike
|
|
34
|
+
# (measured, all three link it and run it). `exec` replaces this process, so the
|
|
35
|
+
# binary receives the original argv and signals with no shell left in between.
|
|
36
|
+
#
|
|
37
|
+
# Windows is not handled here: there are no win32 platform subpackages at all
|
|
38
|
+
# (only darwin/linux × x64/arm64 ± musl), so there is nothing for a .cmd shim to
|
|
39
|
+
# dispatch to. WSL2 reports as linux and is the supported route.
|
|
40
|
+
|
|
41
|
+
set -e
|
|
42
|
+
|
|
43
|
+
# Resolve this script through symlinks, then take the PACKAGE root.
|
|
44
|
+
#
|
|
45
|
+
# Two things make this fiddly, both MEASURED:
|
|
46
|
+
# · `bin` entries are linked into the manager's bin dir, so $0 is often a
|
|
47
|
+
# symlink — but pnpm instead generates a wrapper that runs `/bin/sh <path>`,
|
|
48
|
+
# where <path> goes through a symlinked package dir. Either way the honest
|
|
49
|
+
# answer comes from resolving the path and then `cd -P`.
|
|
50
|
+
# · This file lives in `<pkg>/scripts/`, so the package root is the PARENT of
|
|
51
|
+
# this script's directory. Using the script's own dir made every sibling
|
|
52
|
+
# lookup miss by one level.
|
|
53
|
+
target=$0
|
|
54
|
+
# Bounded: a symlink cycle would otherwise spin here forever.
|
|
55
|
+
i=0
|
|
56
|
+
while [ -L "$target" ] && [ "$i" -lt 40 ]; do
|
|
57
|
+
link=$(readlink "$target")
|
|
58
|
+
case $link in
|
|
59
|
+
/*) target=$link ;;
|
|
60
|
+
*) target=$(dirname "$target")/$link ;;
|
|
61
|
+
esac
|
|
62
|
+
i=$((i + 1))
|
|
63
|
+
done
|
|
64
|
+
# `cd -P` resolves any symlinked parent directory (pnpm's store links).
|
|
65
|
+
pkg=$(cd "$(dirname "$target")/.." && pwd -P)
|
|
66
|
+
|
|
67
|
+
# musl (Alpine and most slim images): npm/pnpm/bun select the -musl subpackage via
|
|
68
|
+
# each subpackage's `libc` field, so we must look for that same name. Positive
|
|
69
|
+
# evidence only — never claim musl on a glibc box.
|
|
70
|
+
libc=''
|
|
71
|
+
if [ "$(uname -s)" = Linux ]; then
|
|
72
|
+
# ⚠️ ONE `ls` PER DIRECTORY. `ls a/glob b/glob` exits non-zero when EITHER
|
|
73
|
+
# glob misses, i.e. it is an AND — and on real Alpine the loader lives only in
|
|
74
|
+
# /lib, so the combined form NEVER fired and only /etc/alpine-release saved it
|
|
75
|
+
# (MEASURED on alpine:3.20: combined → exit 1, per-dir OR → exit 0). That left
|
|
76
|
+
# a musl box without that file resolving to the glibc subpackage name. Same
|
|
77
|
+
# per-directory shape as install.sh, postinstall-bin.mjs and binary-self-update.ts.
|
|
78
|
+
if ls /lib/ld-musl-* >/dev/null 2>&1 \
|
|
79
|
+
|| ls /usr/lib/ld-musl-* >/dev/null 2>&1 \
|
|
80
|
+
|| [ -f /etc/alpine-release ]; then
|
|
81
|
+
libc='-musl'
|
|
82
|
+
fi
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
case $(uname -s) in
|
|
86
|
+
Linux) os=linux ;;
|
|
87
|
+
Darwin) os=darwin ;;
|
|
88
|
+
*) os='' ;;
|
|
89
|
+
esac
|
|
90
|
+
case $(uname -m) in
|
|
91
|
+
x86_64|amd64) arch=x64 ;;
|
|
92
|
+
aarch64|arm64) arch=arm64 ;;
|
|
93
|
+
*) arch='' ;;
|
|
94
|
+
esac
|
|
95
|
+
|
|
96
|
+
if [ -z "$os" ] || [ -z "$arch" ]; then
|
|
97
|
+
echo "botmux: unsupported platform $(uname -s)/$(uname -m)." >&2
|
|
98
|
+
echo "Supported: linux-x64, linux-arm64, darwin-x64, darwin-arm64. On Windows use WSL2." >&2
|
|
99
|
+
exit 1
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
sub="botmux-$os-$arch$libc"
|
|
103
|
+
|
|
104
|
+
# Two layouts, both MEASURED against real global installs of v3.18.13:
|
|
105
|
+
# npm → <main>/node_modules/botmux-linux-x64/botmux (nested)
|
|
106
|
+
# pnpm, bun → <main>/../botmux-linux-x64/botmux (sibling / hoisted)
|
|
107
|
+
# Try the exact-libc name first, then the other libc as a fallback: a mirrored or
|
|
108
|
+
# repacked registry can drop the `libc` field, leaving the "wrong" one installed.
|
|
109
|
+
for name in "$sub" "botmux-$os-$arch"; do
|
|
110
|
+
for candidate in "$pkg/node_modules/$name/botmux" "$pkg/../$name/botmux"; do
|
|
111
|
+
if [ -x "$candidate" ]; then
|
|
112
|
+
exec "$candidate" "$@"
|
|
113
|
+
fi
|
|
114
|
+
done
|
|
115
|
+
done
|
|
116
|
+
|
|
117
|
+
echo "botmux: no platform binary found for $sub." >&2
|
|
118
|
+
echo "The optional platform package did not install. Reinstall with:" >&2
|
|
119
|
+
echo " npm i -g botmux --force (or: pnpm add -g botmux / bun add -g botmux)" >&2
|
|
120
|
+
exit 1
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
* Put `~/.botmux/bin` on the user's PATH by writing their shell's startup file.
|
|
3
3
|
*
|
|
4
4
|
* WHY THIS EXISTS
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* The package's `bin` is a sh launcher the package manager links onto PATH, but
|
|
6
|
+
* that only covers installs done BY a package manager: `install.sh` (the curl
|
|
7
|
+
* route) has no manager involved, and the postinstall launcher at
|
|
8
|
+
* `~/.botmux/bin/botmux` is what gives a multi-Node-version box ONE unambiguous
|
|
9
|
+
* global botmux. If that directory is not on PATH, those routes still leave the
|
|
10
|
+
* user with `botmux: command not found` — which is what this file prevents.
|
|
9
11
|
*
|
|
10
12
|
* Both installers used to just PRINT a hint, and the hint was:
|
|
11
13
|
*
|
|
@@ -330,8 +330,9 @@ try {
|
|
|
330
330
|
// This used to only PRINT `echo 'export PATH=…' >> ~/.profile`. Two problems:
|
|
331
331
|
// the user had to act on it, and for zsh users the suggested file is WRONG —
|
|
332
332
|
// zsh never reads ~/.profile (measured), so following the hint verbatim left
|
|
333
|
-
// `botmux` still not found.
|
|
334
|
-
//
|
|
333
|
+
// `botmux` still not found. PATH is the only way THIS launcher becomes a
|
|
334
|
+
// command (the package's own `bin` is linked by the package manager and is a
|
|
335
|
+
// separate entry point); we now write the right startup file
|
|
335
336
|
// for the user's actual shell (bash/zsh/fish/other) and tell them what we did.
|
|
336
337
|
//
|
|
337
338
|
// ⚠️ DO NOT GATE THIS ON `process.env.PATH`. It used to be wrapped in
|