@ band- app/ 工作人员
band-worker 是一个在机器上运行的过程, 它服务于一个乐队中枢。 它拨打枢纽 @band-app/link完成握手 并回答中枢的呼叫 @band-app/host-local:文件,git,进程,终端,语言服务器,代理流程和代理环境. 中枢通过它 RemoteHost (单位:千美元)packages/host-remote) 及其定义 /api/workers/connect 终点 这里的测试使用自己的链接服务器.
安装
软件包是 @band-app/worker 它的二进制是 band-worker它需要22.5号或更新的,和 git 在机器上工作树. node-pty 安装期间在 Linux 上编译, 因此一个 C++ 工具链、 Python 和 make 必须在场(macOS和容器图像不需要).
npm install -g @band-app/worker
band-worker --hub https://hub.example.com --token "$BAND_WORKER_TOKEN" --root ~/code
pnpm --filter @band-app/worker build 将软件包捆入 dist/band-worker.mjs编辑 @band-app/* 软件包是内置的,每个第三方软件包都保持依赖性,所以本地模块(node-pty, (中文(简体) ), @vscode/ripgrep为工人运行的机器安装. scripts/pack-smoke.sh 将工人打包, 安装到空目录中, 运行 band-worker --help 然后从安装开始一个 PTY 。 中情局负责.
退职 src/ 结束 tsx设置 BAND_WORKER_USE_DIST=1 运行捆绑 从一次离职.
发布工作流程发布此软件包的版本与桌面应用程序相同,下面的容器图像为 ghcr.io/band-app/band-worker。 。 。 .
作为服务运行
band-worker install-service --hub <url> --token <bootstrap token> [--root <dir> --name <name> --labels k=v --worker-id <id> --state-dir <dir>] 登记工人,使其在登录时开始,在失败时重新开始(src/service.ts:
- Linux: 系统化用户单元
~/.config/systemd/user/band-worker.service读取~/.band/worker-service/worker.env,则systemctl --user enable --now财务报告和审定财务报表loginctl enable-linger。当拒绝继续运行时,命令会打印运行内容. - macOS: 发射代理
~/Library/LaunchAgents/app.band.worker.plist携带环境和日志到~/.band/worker-service/worker.log。 。 。 .
~/.band/worker-service 是模式 0700,而持有该符号的文件是 0600。 命令和单位文件都不打印或包含文件外的符号. band-worker uninstall-service 移除服务文件并保持工人状态. band-worker status 服务运行时出站为0个出站,安装但停站时出站为3个出站,未安装时出站为4个出站.
容器图像
docker/worker.Dockerfile 构建一个 node:22-bookworm-slim 与包装的工人形象, git, (中文(简体) ), ssh, (中文(简体) ), curl, (中文(简体) ), jq 财务报告和审定财务报表 bash它以 uid 1001 运行 (worker并且使工作树木 /work 音量、工人代号和会话符 /home/worker/.band/worker。 。 。 .
docker run -d -v band-work:/work -v band-worker-state:/home/worker/.band/worker \
-e BAND_HUB_URL=https://hub.example.com \
-e BAND_WORKER_TOKEN=bwb_... ghcr.io/band-app/band-worker:latest
# or from a checkout:
docker build -f docker/worker.Dockerfile -t band-worker .
工人们都明白 http 只为回回回回路枢纽. 对于同一多克主机上的中枢,添加 --network host 和使用情况 http://127.0.0.1:<port>;否则将枢纽置于HTTPS后.
运行它
pnpm --filter @band-app/worker start -- \
--hub https://hub.example.com \
--token "$BAND_WORKER_TOKEN" \
--root ~/code --root ~/work \
--labels gpu=1,zone=home --name laptop
| 旗帜 | 环境 | 含义 |
|---|---|---|
--hub <url> | BAND_HUB_URL | 中枢URL. http 财务报告和审定财务报表 ws 仅用于回回转, 因为问候带有符号. |
--token <token> | BAND_WORKER_TOKEN, (中文(简体) ), BAND_BOOTSTRAP_TOKEN | 会话符号,或靴子符号(前缀) bwb_) (中文(简体) ). |
--worker-id <id> | BAND_WORKER_ID | 中间的ID 发行的靴子标志。 没有它 中心就给工人取名 当它交易的标志. |
--root <dir> | BAND_WORKER_ROOTS | 工人可以使用的名录。 复说多相. 没有, <state dir>/worktrees。 。 。 . |
--name <name> | BAND_WORKER_NAME | 报告为 name 标签. |
--labels k=v,... | BAND_WORKER_LABELS | 放置标签. |
--state-dir <dir> | BAND_WORKER_STATE_DIR | 默认 $BAND_HOME/worker,或 ~/.band/worker。 。 。 . |
--ephemeral | BAND_WORKER_EPHEMERAL=1 | 闲时退出 . |
--idle-exit <dur> | BAND_WORKER_IDLE_EXIT | 临时工人离开前的休息时间(90s, (中文(简体) ), 10m默认值 10m) (中文(简体) ). |
出站代码:在信号或闲置出站后0个出站,1个出站中心拒绝工人或靴子夹出站失败后,2个出站命令行差.
路径政策
中枢呼叫只有在解决时才能指定路径,其中 .. 折叠和并联,然后是其中之一:
- 一个根 (
--root,通过 repo 拾取器添加根,或默认值<state dir>/worktrees) (中文(简体) ). - 工人自行管理的文件夹: 克隆目录( E)
--repos-dir默认值~/band/repos) (中文(简体) ). 无论根由何方,它都是从启动开始服务的,因为工人创造了它。 管理目录本身不能被删除或移动 . - 根子里面的活树.
任何其它的都以"是在工人的根外"拒绝. 留言中补充道:"这是个活生生的树,它不在根内",只针对一个连接了活生生的活生生的活生生树,而活活生生的主回波是在根外. 一个普通的退票 永远不会得到提示。 在管理好的文件夹内连接到其他地方的链接会像其他任何文件一样被拒绝.
状态和标志
状态目录( 模式 0700) 持有 worker-id,创建一次并重新使用,这样枢纽在重启后看到同一个工人 session-token (第0600节). 会话符号随 --token 以给定方式使用。 拖曳符一次交换到会话符 POST /api/workers/exchange 与 { token, workerId?, name? },回答者为 { sessionToken, workerId }中心将标志绑在它发给的工人身份证上,工人采用该标志并保存为 worker-id。一个会话符号存在直至取消。 重新使用相同的靴子 重新使用保存的。 托肯斯从来没有被记录.
乐队CLI
工人自己带 band 同一版的CLI,从未从中枢取来. 它按此顺序寻找二进制 :
BAND_CLI_PATH。 。 。 .- 包裹
@band-app/worker-cli-<platform>-<arch>(单位:千美元)darwin-arm64, (中文(简体) ),linux-x64, (中文(简体) ),linux-arm64),可选依附@band-app/workernpm只安装一个匹配机器的. Resources/binaries/band除了桌面应用程序的捆绑工人.apps/cli/target/{release,debug}/band在一次离职中.
一开始,工人跑 band skills install 将它的目录放在它开始的每一个代理和终端的 PATH 上。 这些过程通过中继器使用自己的代号称为中枢. 由于没有二进制, 工人会记录一条线, 命名包, 运行时没有 band。多克图像构建 CLI 和设置 BAND_CLI_PATH。 。 。 .
一个比这个变化年长的工人 仍然需要一个新的中心 与CLI cli.fetch中枢解答方法未发现,老工人登录一个警告,并不停地运行着它先前缓存的任何副本. 这名工人在开始时删除了已缓存的旧副本,并且从未将其目录放入PATH上.
路径政策
呼唤中的每一条道路都必须是绝对的,一次 .. 和符号链接解决,在宣布的根内。 检查仅当调用时才会在路径末端跟随一个符号链接(readFile, (中文(简体) ), writeFile, (中文(简体) ), list),这样 rm 财务报告和审定财务报表 rename 链接行为。 通过连接的文字 会被检查到它会降落的地方。 根本身不能被去除或更名. 拒绝的呼叫以代码失败 -32010 财务报告和审定财务报表 data.path。 。 。 .
每一个根之外的道路,如果一旦解决了,它就是或躺在一棵工作树内,这个工人名单上的回放就是允许的 git worktree list,而雷波本身 在一个根。 Repo是一个在工人身上有 URL 映射的, 或者一个 git 文件夹是一个根或直接坐在一个. 覆盖 Repo 文件夹外的另一个工具 。 只有已解析的路径算数,所以拒绝在根上连接到非工作树文件夹指向,允许在已注册的工作树上指向. 工人最多每5秒读一张Repo的工作树单 worktree.create 财务报告和审定财务报表 worktree.remove 立刻清理干净 一条平地取出的工作树 git 工人在5秒内再次被拒绝。 当拒绝的路径是根内不包含的 repo 的工作树时, 错误名称会重新发送, 并说要将其文件夹添加为根 .
该政策涵盖了枢纽名称的道路。 它不限制一个 shell,命令或代理一旦运行会做什么,并且一个本地进程将一个目录互换到检查与使用之间的同义链接仍然可以逃脱.
电话
方法以 Host 接口 : host.info, (中文(简体) ), exec, (中文(简体) ), git.exec, (中文(简体) ), git.gh, (中文(简体) ), worktree.*, (中文(简体) ), fs.*, (中文(简体) ), search.*, (中文(简体) ), lsp.*, (中文(简体) ), acp.*, (中文(简体) ), scripts.*, (中文(简体) ), pty.*, (中文(简体) ), agentEnv.*。params是带有界面参数名的对象. src/methods-basic.ts 财务报告和审定财务报表 src/methods-streams.ts 列出它们.
结果就是 { json }, (中文(简体) ), { bytes } (基数64)或 { chan, as }超过256个KiB进入了工人在答复前打开的频道。 中枢读取到最后,再结束自己的一面来放出频道. 给工人的电文限制数据同样有用: fs.writeFile 带 data: { chan } 用于打开中枢的频道.
呼唤溪流打开一个频道 并用它的ID回复, 所以枢纽看到 link.open 在答复前:
fs.readStream, (中文(简体) ),fs.watch, (中文(简体) ),search.stream:字节或新线限定的JSON,工人到中枢. 中枢结束或重置频道以停止.lsp.connect:语言服务器 stdio,双向.acp.spawn:一个频道的代理 stdout和 stdin,另一个频道的stderr,加acp.exit作为通知。 结束其侧面的中枢关闭了stdin,而重置频道会杀死代理.pty.attach:终端输出向下,按键向上. 关闭频道解开收视器,并与killOnClose它杀死终端。 答复载有屏幕快照。 出入口的终端结束其频道并发送pty.exit通知.
终端以终端守护进程运行,这是工人在第一个产卵上发射的分离过程(src/terminal-daemon.ts,捆绑到 dist/terminal-daemon.mjs,与枢纽守护进程相同的代码). 它拥有PTY和回转镜,所以一个外壳能活下来一个工人重启,升级或崩溃. 守护进程的文件在 <state dir>/run/ (mode 0700): pid 记录, 符和日志, 和 socket(mode 0600, 移动到私人 dir in /tmp 当路径会超过 Unix 套接字限制时 。 后退检查站已经进入 <state dir>/terminal-history/。 。 。 .
在重启之后,当中心连接时,工人会重新连接到守护进程. pty.listAll 列出相同的终端标识,以及 pty.attach 重放屏幕。 在工人倒下时离开的一发炮弹 留下了记录 <state dir>/run/exits/,工人发送其 pty.exit (出境代码, killed: false在下一个连接,一次。 守护进程在没有外壳和工人连接时退出. 关闭一个终端会杀死它的外壳. band-worker uninstall-service 结束守护进程和每个外壳。 系统化单位 KillMode=process 和已发射列表 AbandonProcessGroup,所以停止或重新启动服务使得贝壳运行.
BAND_TERMINAL_DAEMON=0 将终端保留在工人的流程中,在其中结束。 一名工人开始测试过程(Worker.start 无 persistentTerminals)同样这样做.
双向模式
一个麻风工人问枢纽一旦无所事事 能否退出 --idle-exit (枢纽可以替换为 lifecycle.policy) (中文(简体) ). 它以代码0退出,只有当枢机回答它上面的每一个工作树都被存储时. 拒绝,如运行的终端或上传失败,会让工人保持起来,在另一个闲暇时间之后再次问起. 对一个没有的中枢 lifecycle.idle 处理器会像以前一样立即离开.
正在呼叫中,每个开放频道都算作活动,包括中心打开的频道。 该读取器按自己的时间表制作(host.info, (中文(简体) ), worktree.list, (中文(简体) ), git.exec, (中文(简体) ), git.gh,则只读 fs.* 财务报告和审定财务报表 search.listFiles 电话)在工人运行时将其扣住,但不会重启闲置的时钟,因此状态传票人不会让机器保持清醒. 失去枢纽一小时(或闲置时间,如果更长)的工人也会出站,因为没有枢纽就不能储存任何东西.
两种方法为枢纽的睡眠服务,并唤醒握手: lifecycle.exportSessions 读取给定会话 id 的代理会话文件 ~/.claude/projects, (中文(简体) ), ~/.codex/sessions 和目录 BAND_AGENT_SESSION_DIRS,以及 lifecycle.importSessions 移动在后面的文件。 见 电子工人。 。 。 .
测试
pnpm --filter @band-app/worker test 运行 node:test 套接字套件对接随机端口上的真实链接服务器。 发光和装饰套房开始真正的 bin/band-worker.mjs。每次测试都使用临时 BAND_HOME 和州目录.