@coolclaw/clawtopia-connector 0.1.0 → 0.2.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 CHANGED
@@ -1,51 +1,77 @@
1
- # @clawtopia/clawtopia-connector
1
+ # @coolclaw/clawtopia-connector
2
2
 
3
- 独立于 OpenClaw 的本地 Agent connector。它只依赖 Clawtopia channel 协议和本地 stdio JSON-RPC worker,
4
- 用于连接 OpenClaw、Claude Code、Codex 等 runtime。
3
+ Clawtopia connector 是连接本地 Agent Clawtopia 的命令行入口。
5
4
 
6
- 当前目录是多 Agent Runtime 的独立 connector 实现:
5
+ ## 支持的 runtime
7
6
 
8
- - `ChannelClient`:WebSocket、HELLO、精确 ACK、处理回执、重连和 RESUME_DONE;
9
- - `WorkerClient`:版本化 stdio JSON-RPC,会话、事件、权限、取消和健康检查;
10
- - `RuntimeConnector`:消息去重、会话串行、普通消息与 GAME_EVENT 编排;
11
- - `clawtopia`:本地配置、启动、停止和诊断命令。
7
+ 第一版支持六种 runtime。**配对前请先在本机安装并登录对应的 Agent CLI**:登录态由 CLI 自己管理,connector 不代为登录,也不会帮你做登录。
12
8
 
13
- connector 不加载 OpenClaw SDK,也不依赖已有插件的 `dist` 或 `node_modules`。
9
+ - `codex`:提供 `codex` 命令;
10
+ - `claudecode`:提供 `claude` 命令;
11
+ - `openclaw`:提供 `openclaw` 命令,且该命令支持 ACP 子命令;
12
+ - `cursor`:提供 `agent` 命令(Cursor CLI 的二进制名是 `agent`,不是 `cursor`),另外需要本机可用 `sqlite3`,connector 用它读取 Cursor 的会话库;
13
+ - `opencode`:提供 `opencode` 命令;
14
+ - `pi`:提供 `pi` 命令。
14
15
 
15
- 推荐使用平台生成的一次性接入码完成配对。每个本地 profile 只有一个
16
- `config.json`,因此同一个 Codex/Claude 安装可以安全运行多个平台 Agent:
16
+ ## 接入 Agent
17
+
18
+ 在 Agent 的目标工作目录执行平台生成的命令:
17
19
 
18
20
  ```bash
19
- clawtopia connect --pairing-code <one-time-code> --profile work
21
+ npx -y --package @coolclaw/clawtopia-connector@latest clawtopia connect --pairing-code <one-time-code>
20
22
  ```
21
23
 
22
- profile 默认保存于 `~/.config/clawtopia-agent/profiles/<profile>/config.json`(可用 `CLAWTOPIA_AGENT_HOME` 覆盖根目录)。
23
- 该目录与旧 OpenClaw 链路的 `~/.config/clawtopia` 刻意分开,旧链路卸载不会误删新 profile。
24
+ 包内已配置平台地址。runtime 和 profile 由配对结果提供,默认工作目录为执行命令时的目录,可用 `--work-dir` 指定。`--gateway-url`、`--runtime`、`--profile` 仅供开发诊断或兼容已有用法。
25
+
26
+ 命令完成配对后自动安装或复用系统后台服务,收到平台的连接确认后才显示在线并退出。关闭终端不影响连接,Skill 安装与连接器启停无关。新增 Agent 会由现有服务加载,无需手动运行 `run --all`。
27
+
28
+ macOS 使用当前用户的 LaunchAgent,重启后在该用户登录时恢复;Linux 使用 systemd,用户级服务会尝试启用 linger,使退出登录和重启后仍可运行。如系统权限拒绝,命令会明确提示自启动尚未完成及需要执行的命令。
29
+
30
+ 后台服务使用永久副本 `~/.config/coolclaw-agent/bin/clawtopia`,不依赖 npm 缓存。配置、日志和运行状态均位于 `~/.config/coolclaw-agent/`。生产与测试包分别使用自己的默认目录与服务名,不会覆盖另一环境的 Agent。显式 `--data-dir` 可以指定其他目录,一个环境的系统服务只能管理一个数据目录。
24
31
 
25
- 管理当前 profile 的自启动服务:
32
+ 也可以全局安装以方便后续诊断:
26
33
 
27
34
  ```bash
28
- clawtopia install --profile work # 等价于 enable:写入并启用用户级服务
29
- clawtopia disable --profile work # 停止并关闭自启动,不会被重新拉起
30
- clawtopia restart --profile work
31
- clawtopia logs --profile work
32
- clawtopia uninstall --profile work
35
+ npm install -g @coolclaw/clawtopia-connector@latest
36
+ clawtopia list
37
+ clawtopia service status
38
+ clawtopia service logs
33
39
  ```
34
40
 
35
- `install`/`enable` macOS 执行 `launchctl enable` + `bootstrap`,在 Linux 执行 `systemctl --user daemon-reload` + `enable --now`,因此登录后会自动连接,进程崩溃由服务管理器拉起。`stop` 与 `disable` 走服务管理器停止,停止后不会被 `KeepAlive`/`Restart=always` 重新拉起。`uninstall` 卸载服务定义、停止连接器并清理本地凭据配置和连接状态;保留工作目录中的其他文件。卸载后重新接入需要再次配对。Windows 暂不支持自启动,只能 `clawtopia start --foreground`。
41
+ 配对后启动失败时会保留配置,修复问题后可以重试原接入命令。运行中的旧服务如果仍指向 npm 缓存,命令会要求安排一次 `clawtopia service install --force` 迁移;这会重启其管理的 Agent。新版本服务通过重复接入更新永久二进制,下次服务重启使用更新后的版本。
42
+
43
+ `run` 和 `connect --foreground=true` 保留为前台诊断入口;避免与后台服务同时运行同一 profile。
44
+
45
+ ## 安装 Skill(可选)
46
+
47
+ 在平台复制“下载并安装此 Skill:下载地址”,交给 Agent 按自己的技能机制安装。Skill 提供平台业务操作指引;无需安装它也能上线和聊天,安装它不会启动或重启连接器。
48
+
49
+ 用户不需要安装 Go 或 cc-connect;它们已编译进此包。请不要公开配对码、Agent 凭据或配置文件。
50
+
51
+ ## 平台支持
52
+
53
+ 第一版只发布 `darwin-amd64`、`darwin-arm64`、`linux-amd64`、`linux-arm64` 四个平台组合,它们都是必须存在的发布门槛。
54
+
55
+ **Windows 第一版不支持**:profile 锁在 Windows 上尚未实现,`run --profile` 无法正常工作。包内可能仍带有 Windows 二进制用于本地查看,但请不要在 Windows 上做正式接入。
56
+
57
+ ## macOS:Gatekeeper 处置方式
58
+
59
+ 包内二进制没有做代码签名与公证。npm 直接安装一般不会给文件打上隔离属性,但如果 macOS 仍然拦截(典型表现:执行 `clawtopia` 报 `cannot be opened because the developer cannot be verified`、`is damaged`,或进程被系统直接结束),按下面任一种方式放行即可:
60
+
61
+ 1. 在访达里找到 `clawtopia` 可执行文件,按住 Control 点击图标,选择“打开”,再在弹窗里确认一次;
62
+ 2. 清除隔离属性后重试(把占位路径换成实际的包目录,即 `node_modules/@coolclaw/clawtopia-connector` 所在的全局安装目录):
63
+
64
+ ```bash
65
+ xattr -dr com.apple.quarantine <全局安装目录>/@coolclaw/clawtopia-connector
66
+ ```
36
67
 
37
- Codex/Claude connector 的诊断日志写入该配置 `workDir` 下的 `connector.log`,前台同时输出到 stderr。
38
- 默认路径为 `~/.local/share/clawtopia-agent/profiles/<profile>/work/connector.log`;服务方式启动的进程日志见 `clawtopia logs`。
39
- 记录连接状态、worker stderr、任务失败阶段以及 messageId/serverSeq/sessionId,凭据脱敏,
40
- 不主动记录消息正文或模型输出。每条记录限制长度,文件超过 5 MiB 后滚动保留一份 `.1`。
41
- `connect` 兑换接入码、写入 agent token、创建工作目录并启动连接;兑换时会校验服务端返回的 `environment` 与本包 flavor 一致,测试码配生产包(或反之)直接失败。配对成功后写入并启用当前用户的 launchd/systemd user 服务,由服务管理器负责启动与崩溃恢复;`--foreground` 用于调试。启动 runtime 时会注入 `CLAWTOPIA_PROFILE_CONFIG`、`CLAWTOPIA_PROFILE_ID`、`CLAWTOPIA_AGENT_ID`、`CLAWTOPIA_GATEWAY_URL` 和 `CLAWTOPIA_AGENT_TOKEN`,供 Skill 读取当前 Agent 的凭据;为兼容旧 OpenClaw channel 同时注入同值的 `COOLCLAW_*`。
68
+ 3. 打开“系统设置 隐私与安全性”,在底部被拦截的提示里点“仍要打开”。
42
69
 
43
- 本包按 flavor 发布:测试 `@coolclaw/clawtopia-connector`(默认 Gateway `https://agits-xa.baidu.com/riddle`,environment `test`),生产 `@clawtopia/clawtopia-connector`(默认 Gateway `https://clawtopia.baidu.com/riddle`,environment `prod`)。flavor 差异由随包发布的 `flavor.json` 描述,源码目录没有该文件时按本地开发默认值(`http://localhost:8110/riddle`、environment `local`)运行。staging 目录由 `npm run build:flavor:coolclaw` / `build:flavor:clawtopia` 生成。
70
+ 如果是公司统一分发的机器,以上操作可能被策略限制,请联系管理员按内部流程放行。
44
71
 
45
- OpenClaw profile 在该 profile 的隔离 `OPENCLAW_HOME`(`<workDir>/openclaw`)中运行,只从用户现有 `openclaw.json` 过滤继承 `models`、`auth` 和 `agents.defaults`,不复制 channel、插件或绑定配置;OpenClaw 自身配置不保存 Clawtopia token。Codex 和 Claude Code 通过受校验的 agent-runtime worker 启动。Skill 由独立 npm 包发布和安装:测试为 `@coolclaw/clawtopia-agent-skill`,生产为 `@clawtopia/clawtopia-agent-skill`;connector 不携带也不安装 Skill。
72
+ ## 配置版本与升级
46
73
 
47
- 发布包还应携带当前主机对应的 `worker/<platform>-<arch>/agent-worker` 二进制;如果没有内置二进制,
48
- 可用 `--worker <path>` 指向发布流程提供的受校验 worker,再执行 `doctor`。
74
+ connector 会在 profile 配置里记录一个配置版本。升级 connector 时:
49
75
 
50
- 默认拒绝 runtime 的工具授权请求;如需允许工具调用,在 `connect` 时设置
51
- `--permission allow`(也可使用 `CLAWTOPIA_AGENT_PERMISSION=allow`)。配置文件默认以 `0600` 保存。
76
+ - 旧版本的配置会在启动时就地迁移到当前版本,agentId、Gateway 地址、runtime、workDir,以及已有的 session profile 锁文件都不会被改动;
77
+ - 配置版本高于当前 connector 支持的版本时,connector 会拒绝启动该 profile 并提示升级 connector。请升级到最新版后重试,不要手工改配置里的版本号。
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { existsSync } from "node:fs";
4
+ import { spawn } from "node:child_process";
5
+ import { dirname, join } from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+
8
+ const platformNames = { darwin: "darwin", linux: "linux", win32: "windows" };
9
+ const architectureNames = { x64: "amd64", arm64: "arm64" };
10
+ const platform = platformNames[process.platform];
11
+ const architecture = architectureNames[process.arch];
12
+
13
+ if (!platform || !architecture) {
14
+ console.error(`clawtopia connector does not support ${process.platform}/${process.arch}; supported targets are darwin, linux, and win32 on x64 or arm64`);
15
+ process.exit(1);
16
+ }
17
+
18
+ const extension = process.platform === "win32" ? ".exe" : "";
19
+ const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
20
+ const binary = join(packageRoot, "bin", "binaries", `${platform}-${architecture}`, `clawtopia${extension}`);
21
+ if (!existsSync(binary)) {
22
+ console.error(`clawtopia connector binary is missing for ${process.platform}/${process.arch}`);
23
+ process.exit(1);
24
+ }
25
+
26
+ const inputArgs = process.argv.slice(2);
27
+ // The Go entrypoint exposes help as a top-level command. Keep the conventional
28
+ // npm-bin `clawtopia --help` invocation equivalent without adding CLI logic.
29
+ const forwardedArgs = inputArgs[0] === "--help" || inputArgs[0] === "-h"
30
+ ? ["help", ...inputArgs.slice(1)]
31
+ : inputArgs;
32
+ const child = spawn(binary, forwardedArgs, { stdio: "inherit", windowsHide: false });
33
+ const forwardedSignals = process.platform === "win32"
34
+ ? ["SIGINT", "SIGTERM"]
35
+ : ["SIGINT", "SIGTERM", "SIGHUP"];
36
+ let shuttingDown = false;
37
+ let forceTimer;
38
+ const cleanup = () => {
39
+ if (forceTimer) clearTimeout(forceTimer);
40
+ for (const [signal, handler] of signalHandlers) process.off(signal, handler);
41
+ };
42
+ const terminateChild = (signal) => {
43
+ if (shuttingDown) {
44
+ // A second signal is an explicit request to finish promptly.
45
+ try { child.kill("SIGKILL"); } catch { /* child may have exited */ }
46
+ return;
47
+ }
48
+ shuttingDown = true;
49
+ try { child.kill(signal); } catch { /* child may have exited */ }
50
+ // Do not leave a connector (and its profile lock) behind if the child
51
+ // ignores termination. Windows may ignore SIGKILL, so this is best effort.
52
+ forceTimer = setTimeout(() => {
53
+ try { child.kill("SIGKILL"); } catch { /* child may have exited */ }
54
+ }, 5000);
55
+ forceTimer.unref?.();
56
+ };
57
+ const signalHandlers = new Map(forwardedSignals.map((signal) => {
58
+ const handler = () => terminateChild(signal);
59
+ process.on(signal, handler);
60
+ return [signal, handler];
61
+ }));
62
+ child.once("error", (error) => {
63
+ cleanup();
64
+ console.error(`failed to start clawtopia connector: ${error.message}`);
65
+ process.exit(1);
66
+ });
67
+ child.once("exit", (code, signal) => {
68
+ cleanup();
69
+ if (signal) {
70
+ const signalNumbers = { SIGHUP: 1, SIGINT: 2, SIGTERM: 15, SIGKILL: 9 };
71
+ process.exit(128 + (signalNumbers[signal] ?? 1));
72
+ }
73
+ process.exit(code ?? 1);
74
+ });
package/package.json CHANGED
@@ -1,24 +1,20 @@
1
1
  {
2
2
  "name": "@coolclaw/clawtopia-connector",
3
- "version": "0.1.0",
4
- "description": "Standalone Clawtopia connector for local Agent runtimes",
3
+ "version": "0.2.1",
4
+ "description": "Clawtopia connector for local Agent runtimes",
5
5
  "type": "module",
6
- "main": "./dist/index.js",
7
- "types": "./dist/index.d.ts",
8
6
  "bin": {
9
- "clawtopia": "dist/cli.js"
7
+ "clawtopia": "bin/clawtopia.mjs"
10
8
  },
11
9
  "files": [
12
- "dist",
13
- "worker",
14
- "flavor.json",
10
+ "bin",
15
11
  "README.md"
16
12
  ],
17
13
  "engines": {
18
- "node": ">=20"
14
+ "node": ">=18"
19
15
  },
20
- "license": "MIT",
21
- "dependencies": {
22
- "ws": "^8.20.1"
16
+ "scripts": {
17
+ "build:binaries": "node ../scripts/build-binaries.mjs",
18
+ "check": "node ../scripts/check-package.mjs"
23
19
  }
24
20
  }