@baize-ai/core 0.2.0 → 0.3.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.
Files changed (44) hide show
  1. package/.dockerignore +8 -18
  2. package/CHANGELOG.md +24 -1
  3. package/Dockerfile +66 -12
  4. package/README.md +85 -6
  5. package/README.zh-CN.md +63 -3
  6. package/assets/logo.png +0 -0
  7. package/cli/baize.js +6 -0
  8. package/cli/commands/a2a.js +124 -0
  9. package/cli/commands/add.js +126 -86
  10. package/cli/commands/component.js +27 -4
  11. package/cli/commands/doctor.js +2 -2
  12. package/cli/commands/init.js +28 -0
  13. package/cli/commands/self-uninstall.js +1 -1
  14. package/cli/lib/__tests__/instruction-split.test.js +1 -1
  15. package/cli/lib/a2a.js +235 -0
  16. package/cli/lib/lock.js +3 -3
  17. package/cli/lib/self-upgrade.js +1 -1
  18. package/docker-compose.yml +1 -1
  19. package/docs/docker.md +18 -4
  20. package/docs/release.md +150 -0
  21. package/package.json +1 -1
  22. package/scripts/docker-publish.sh +70 -0
  23. package/scripts/install.sh +4 -4
  24. package/scripts/pack-release.sh +361 -0
  25. package/skills/comm-bridge/package.json +7 -3
  26. package/skills/comm-bridge/scripts/c4-receive.js +23 -2
  27. package/skills/scheduler/package.json +2 -2
  28. package/skills/web-console/SKILL.md +34 -0
  29. package/skills/web-console/package.json +2 -2
  30. package/skills/web-console/public/app.js +967 -4
  31. package/skills/web-console/public/index.html +141 -0
  32. package/skills/web-console/public/styles.css +136 -0
  33. package/skills/web-console/scripts/a2a-admin.js +533 -0
  34. package/skills/web-console/scripts/channel-admin.js +99 -16
  35. package/skills/web-console/scripts/server.js +395 -1
  36. package/skills/web-console/scripts/skill-catalog.js +179 -0
  37. package/templates/claude-system.md +22 -0
  38. package/templates/pm2/ecosystem.config.cjs +4 -1
  39. package/test/a2a-cli.test.js +180 -0
  40. package/test/agent-card-api.test.js +261 -0
  41. package/test/channel-admin.test.js +87 -0
  42. package/test/component-lock.test.js +216 -0
  43. package/test/skill-catalog.test.js +118 -0
  44. package/test/web-console-routes.test.js +512 -1
package/.dockerignore CHANGED
@@ -1,18 +1,8 @@
1
- # Exclude node_modules at every depth, not just the repo root. Nested
2
- # skills/*/node_modules can carry host-compiled native binaries (e.g.
3
- # better-sqlite3) built for the host's Node ABI; leaking them into an image
4
- # running a different Node major triggers NODE_MODULE_VERSION load errors.
5
- # With these excluded, each skill's in-image `npm install` pulls the matching
6
- # prebuilt binary instead.
7
- **/node_modules
8
- .git
9
- .github
10
- *.log
11
- *.env
12
- .env.*
13
- !.env.example
14
- test
15
- docs
16
- assets
17
- README*.md
18
- CHANGELOG.md
1
+ # Publish-mode build context: source code is NOT copied into the image.
2
+ # Only entrypoint + PM2 ecosystem + pre-bundled Claude binary are needed.
3
+ *
4
+ !Dockerfile
5
+ !docker/entrypoint.sh
6
+ !templates/pm2/ecosystem.config.cjs
7
+ !.claude-local/claude
8
+ !.claude-local/claude.version
package/CHANGELOG.md CHANGED
@@ -5,6 +5,29 @@ All notable changes to baize-core will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.3.1] - 2026-08-25
9
+
10
+ ### Added
11
+ - web-console「定时任务」只读列表视图(`/api/admin/scheduler/tasks`:tasks 表列表,无管理操作;scheduler 未启动容错)
12
+
13
+ ## [0.3.0] - 2026-08-25
14
+
15
+ ### Added
16
+ - A2A 运行模式(单机/集群):`baize a2a enable/disable/status` 完整事务(daemon 启动 → 身份就绪轮询 → 注册,失败回滚);web 控制台 A2A 页模式卡 + tar.gz 上传安装(D25)
17
+ - 证书自动生成(自签 CA + CA 签发服务器证书,共享 CA 模型)
18
+ - `baize add` 孤儿残留自动清理(中断安装重试不再死循环,KI-024)
19
+ - web-console `/api/admin/a2a/install`(manifest/大小/防路径穿越校验 + `--ignore-scripts`)
20
+ - 打包脚本 `scripts/pack-release.sh`(A2A 套件私有交付)
21
+
22
+ ### Changed
23
+ - A2A CLI 集成(`baize a2a` 子命令,D21-D24:card 编辑/发现重构/能力认知/凭证轮换)
24
+ - 渠道组件 upgrade 走 npm(D18,KI-006)
25
+ - add/uninstall 持组件锁(D20,KI-007)
26
+
27
+ ### Fixed
28
+ - web-console 上传安装校验(D25 Review:身份就绪验证/凭证 issuer/CA 互信/审批抖动)
29
+ - 组件安装残留死循环(KI-024)
30
+
8
31
  ## [0.2.0] - 2026-08-23
9
32
 
10
33
  ### Added
@@ -52,7 +75,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
52
75
 
53
76
  ### Added
54
77
 
55
- - **Baize (白泽) inception**: forked from zylos-core v0.7.1 as an independent project. All identifiers renamed (`zylos` → `baize`): CLI (`baize`), npm package (`@baize-ai/core`), runtime root (`~/baize/`), config dir (`~/.baize/`), env vars (`BAIZE_*`), instruction file (`BAIZE.md`), skills (`baize-memory`), PM2 service names, Docker image (`ghcr.io/baize-ai/baize-core`), and the agent persona in system templates.
78
+ - **Baize (白泽) inception**: forked from zylos-core v0.7.1 as an independent project. All identifiers renamed (`zylos` → `baize`): CLI (`baize`), npm package (`@baize-ai/core`), runtime root (`~/baize/`), config dir (`~/.baize/`), env vars (`BAIZE_*`), instruction file (`BAIZE.md`), skills (`baize-memory`), PM2 service names, Docker image (`ghcr.io/baize01-ai/baize-core`), and the agent persona in system templates.
56
79
 
57
80
  ### Removed
58
81
 
package/Dockerfile CHANGED
@@ -12,7 +12,7 @@
12
12
 
13
13
  FROM node:22-slim
14
14
 
15
- LABEL org.opencontainers.image.source="https://github.com/baize-ai/baize-core"
15
+ LABEL org.opencontainers.image.source="https://github.com/baize01-ai/baize-core"
16
16
  LABEL org.opencontainers.image.description="Baize — autonomous AI agent infrastructure"
17
17
 
18
18
  # ── System packages ───────────────────────────────────────────────────────────
@@ -26,20 +26,31 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
26
26
  procps \
27
27
  # For `baize doctor` network checks
28
28
  dnsutils \
29
+ # Native-module build toolchain (better-sqlite3 etc.): prebuild download
30
+ # can fail at build/runtime (GitHub Releases is a flaky source); with the
31
+ # toolchain present npm falls back to source compile instead of leaving a
32
+ # broken binary in the image (D19 container crash root cause).
33
+ python3 \
34
+ make \
35
+ g++ \
29
36
  && rm -rf /var/lib/apt/lists/*
30
37
 
31
38
  # ── Global npm tools ──────────────────────────────────────────────────────────
32
39
  RUN npm install -g pm2@latest
33
40
 
34
- # ── Claude Code CLI (pre-bundled) ─────────────────────────────────────────────
41
+ # ── Claude Code CLI (pre-bundled, pinned version) ─────────────────────────────
35
42
  # The official install.sh downloads a ~340MB binary at container runtime, which
36
43
  # is unreliable inside container networks (fails ~90% through on Docker
37
- # Desktop). Bundle the verified binary in the image instead: place it at
38
- # .claude-local/claude in the build context (gitignored). Fetch with:
44
+ # Desktop). Bundle a PINNED, verified binary in the image instead:
39
45
  # curl -fsSL https://downloads.claude.ai/claude-code-releases/<ver>/linux-arm64/claude
40
- # and verify against the checksum in .../manifest.json (platforms.linux-arm64).
46
+ # (verify against .../manifest.json platforms.linux-arm64 checksum)
47
+ # echo <ver> > .claude-local/claude.version
48
+ # Upgrade = replace the binary + bump claude.version, then rebuild the image
49
+ # (explicit release decision — never auto-fetch latest at build time).
41
50
  COPY .claude-local/claude /usr/local/bin/claude
42
51
  RUN chmod +x /usr/local/bin/claude
52
+ COPY .claude-local/claude.version /usr/local/bin/claude.version
53
+ LABEL org.opencontainers.image.claude-version="$(cat .claude-local/claude.version 2>/dev/null || echo unknown)"
43
54
 
44
55
  # ── Create baize user (non-root) ──────────────────────────────────────────────
45
56
  RUN useradd -m -s /bin/bash baize \
@@ -49,15 +60,58 @@ USER baize
49
60
  ENV HOME=/home/baize
50
61
  ENV NPM_CONFIG_PREFIX=/home/baize/.npm-global
51
62
  ENV PATH="/home/baize/.npm-global/bin:/home/baize/.local/bin:/usr/local/bin:${PATH}"
63
+ # Web console must listen on all interfaces for Docker port mapping to work
64
+ # (default is 127.0.0.1, which Docker Desktop cannot reach). PM2 fork mode
65
+ # inherits process env, so this reaches the web-console service even when the
66
+ # bundled ecosystem.config.cjs predates the WEB_CONSOLE_BIND field.
67
+ ENV WEB_CONSOLE_BIND=0.0.0.0
52
68
 
53
- # ── Install baize-core from local source ─────────────────────────────────────
54
- # COPY the repo (filtered by .dockerignore) and install from it, so the image
55
- # always matches the exact commit/tag being built.
69
+ # ── Install baize-core from the npm package ─────────────────────────────────
70
+ # The image pulls the published @baize-ai/core package (no source code in the
71
+ # build context) — source stays private, the image matches the npm version
72
+ # exactly. Build with: docker build --build-arg BAZE_CORE_VERSION=0.2.0 .
73
+ ARG BAZE_CORE_VERSION=latest
56
74
  WORKDIR /home/baize
57
- COPY --chown=baize:baize . /tmp/baize-core
58
- RUN npm install -g --install-links /tmp/baize-core \
59
- && rm -rf /tmp/baize-core \
60
- && baize --version
75
+ RUN npm install -g @baize-ai/core@${BAZE_CORE_VERSION} \
76
+ && baize --version \
77
+ # ── Build-time skill dependency preinstall (reproducibility) ─────────
78
+ # `baize init` reinstalls skill deps at runtime; doing it here bakes the
79
+ # native modules (better-sqlite3 etc.) into the image with a known-good
80
+ # result and the toolchain above as fallback. Same selection logic as
81
+ # init.js installSkillDependencies (skills with a package.json that has
82
+ # dependencies).
83
+ && for skill_dir in /home/baize/.npm-global/lib/node_modules/@baize-ai/core/skills/*/; do \
84
+ if [ -f "${skill_dir}package.json" ]; then \
85
+ deps=$(node -e "const p=require('${skill_dir}package.json');console.log(p.dependencies?1:0)" 2>/dev/null || echo 0); \
86
+ if [ "$deps" = "1" ]; then \
87
+ (cd "$skill_dir" && npm install --production --no-audit --no-fund) || exit 1; \
88
+ fi; \
89
+ fi; \
90
+ done \
91
+ # ── Force local native-module compilation ──────────────────────────
92
+ # better-sqlite3 12.x prebuild download can return the WRONG platform
93
+ # binary (observed: macOS Mach-O inside linux build → ERR_DLOPEN_FAILED
94
+ # at runtime). Rebuild forces node-gyp compile with the toolchain above,
95
+ # guaranteeing a correct linux ELF regardless of prebuild availability.
96
+ && for skill_dir in /home/baize/.npm-global/lib/node_modules/@baize-ai/core/skills/*/; do \
97
+ if [ -d "${skill_dir}node_modules/better-sqlite3" ]; then \
98
+ (cd "${skill_dir}node_modules/better-sqlite3" && npm rebuild better-sqlite3) || exit 1; \
99
+ fi; \
100
+ done \
101
+ # ── Bake deps into the runtime skills dir ──────────────────────────
102
+ # init's skill sync preserves existing node_modules and (since the
103
+ # idempotent-dep check) skips reinstall when deps are loadable — so
104
+ # pre-baking here makes runtime init never touch the compiled binaries.
105
+ && mkdir -p /home/baize/baize/.claude/skills \
106
+ && for skill_dir in /home/baize/.npm-global/lib/node_modules/@baize-ai/core/skills/*/; do \
107
+ name=$(basename "$skill_dir"); \
108
+ if [ -d "$skill_dir" ] && [ -f "$skill_dir/package.json" ]; then \
109
+ mkdir -p "/home/baize/baize/.claude/skills/$name"; \
110
+ cp -r "$skill_dir"/. "/home/baize/baize/.claude/skills/$name/"; \
111
+ fi; \
112
+ done \
113
+ && node -e "const D=require('/home/baize/baize/.claude/skills/web-console/node_modules/better-sqlite3'); new D(':memory:')" \
114
+ && echo "native modules OK (locally compiled, baked into runtime skills)"
61
115
 
62
116
  # ── Workspace directories ─────────────────────────────────────────────────────
63
117
  # ~/baize is mounted as a single volume in docker-compose.yml.
package/README.md CHANGED
@@ -20,7 +20,7 @@ subscription (or an OpenAI Codex setup — Codex CLI v0.129.0+ required,
20
20
  0.146+ recommended).
21
21
 
22
22
  ```bash
23
- curl -fsSL https://raw.githubusercontent.com/baize-ai/baize-core/main/scripts/install.sh | bash
23
+ curl -fsSL https://raw.githubusercontent.com/baize01-ai/baize-core/main/scripts/install.sh | bash
24
24
  ```
25
25
 
26
26
  This installs dependencies (git, tmux, Node.js, PM2, the `baize` CLI) and runs
@@ -36,17 +36,26 @@ baize init
36
36
  **Docker deployment:**
37
37
 
38
38
  ```bash
39
+ # Global (GitHub Container Registry)
39
40
  docker run -d --name baize \
40
41
  -p 3456:3456 \
41
42
  -v baize-data:/home/baize/baize \
42
43
  -v claude-config:/home/baize/.claude \
43
- ghcr.io/baize-ai/baize-core:latest
44
+ ghcr.io/baize01-ai/baize-core:latest
45
+
46
+ # China (Aliyun ACR — fast, no mirror needed)
47
+ docker run -d --name baize \
48
+ -p 3456:3456 \
49
+ -v baize-data:/home/baize/baize \
50
+ -v claude-config:/home/baize/.claude \
51
+ crpi-8bg62qbrjs3cr3as.cn-hangzhou.personal.cr.aliyuncs.com/baize01/baize-core:latest
44
52
  ```
45
53
 
46
- Open `http://localhost:3456` for the web console (see below); configure
47
- authentication in 模型设置 (Claude API key / setup token / custom endpoint /
48
- Codex / ChatGPT login). See `docs/docker.md` for Compose setup, optional auth
49
- environment variables, and volume details.
54
+ The image is built from the published `@baize-ai/core` npm package — no source
55
+ code in the build. Open `http://localhost:3456` for the web console (see
56
+ below); configure authentication in 模型设置 (Claude API key / setup token /
57
+ custom endpoint / Codex / ChatGPT login). See `docs/docker.md` for Compose
58
+ setup, optional auth environment variables, and volume details.
50
59
 
51
60
  `baize init` is idempotent and supports interactive and non-interactive modes.
52
61
  It will:
@@ -181,6 +190,72 @@ session, audit trail, and memory.
181
190
 
182
191
  ---
183
192
 
193
+ ## A2A (Agent-to-Agent Collaboration)
194
+
195
+ A2A connects multiple Baize instances for direct, **HTTPS P2P** collaboration —
196
+ no central message server. Messages and task delegations travel straight from
197
+ one agent to another, and every instance stays fully independent.
198
+
199
+ **Components:**
200
+
201
+ | Component | Role |
202
+ |-----------|------|
203
+ | `@baize-ai/baize-a2a` | npm channel package installed on each enabled instance: HTTPS server, registration/heartbeat client, task worker, and the `baize a2a` CLI |
204
+ | `@baize-ai/baize-admin-workspace` | Standalone control plane (npm package + Docker image + Ant Design Pro console): admission approval, online status, audit, and Card-based discovery — never in the message path |
205
+
206
+ **Core concepts:**
207
+
208
+ - **Agent Card is the single source of business truth** — each agent
209
+ self-reports its `name`, `description`, and `skills` at
210
+ `GET /.well-known/baize-agent.json`. The admin does not maintain business
211
+ descriptions; it only governs admission, presence, audit, and discovery.
212
+ - **Receiver-side authorization** — every agent decides for itself who may
213
+ call it (`authz` in `config.json`: `open` by default, or an `allowlist`).
214
+ - **Card-based discovery** — peers are found through the admin directory by
215
+ text-matching the Card's name/description/skills, or by exact skill id.
216
+
217
+ **Quick start:**
218
+
219
+ ```bash
220
+ baize add @baize-ai/baize-a2a # install the channel
221
+ baize a2a enable --admin <url> --advertise <https://your-agent.example.com>
222
+ # → self-register → admin approves → JWT issued → heartbeat (30s) → discoverable
223
+ baize a2a search <query> # discover agents via the admin directory
224
+ baize a2a task <peer> <skill> "<instruction>" # delegate a task (sync wait)
225
+ ```
226
+
227
+ **CLI (`baize a2a`):**
228
+
229
+ | Command | Purpose |
230
+ |---------|---------|
231
+ | `status` | Local state: enabled / agent_id / registration / advertise_url |
232
+ | `enable --admin <url> --advertise <url>` | Enable A2A and register with the admin |
233
+ | `disable` | Disable (already-accepted tasks keep running) |
234
+ | `peer list` | Cached peers |
235
+ | `search <query>` | Discover agents via the admin directory |
236
+ | `card <id>` | Agent Card details |
237
+ | `session-summary` | Summary of the currently available peers |
238
+ | `send <peer> <text>` | Plain message (no reply wait) |
239
+ | `task <peer> <skill> "<instruction>"` | Delegate a task; sync wait by default (`--async` returns the task_id only) |
240
+ | `task status <id>` / `task cancel <id>` | Query / cancel a delegated task |
241
+
242
+ **Card editing and call authorization (web console):** the A2A page edits
243
+ your Agent Card — name, description, and Skills picked from the installed
244
+ SKILL.md list (frontmatter auto-extracted). Saving hot-refreshes the Card
245
+ within seconds and the admin probe syncs the snapshot; the Card can be
246
+ pre-filled even before A2A is enabled. The same page configures 调用授权
247
+ (call authorization): `open` with a block list (default) or `allowlist` —
248
+ rejected calls return 403 and are audited.
249
+
250
+ **Credential rotation:** each agent holds its own admin-issued JWT (RS256,
251
+ 12h validity, per-agent credentials). Agents auto-refresh before expiry and
252
+ re-fetch credentials within 60s after an admin rotation (revocation
253
+ detection + forced recovery). Rotation revokes only the target agent's
254
+ credential and re-signs it with the current key — the global signing key
255
+ stays unchanged, so rotating one agent never affects the others.
256
+
257
+ ---
258
+
184
259
  ## Configuration
185
260
 
186
261
  Persistent configuration lives in `~/baize/.baize/config.json`:
@@ -243,6 +318,10 @@ baize uninstall --self # Uninstall Baize entirely
243
318
 
244
319
  ---
245
320
 
321
+ ## Release
322
+
323
+ npm + Docker 发布的完整操作手册(认证 / 四包发布 / ghcr + 阿里云 ACR 镜像)见 [`docs/release.md`](docs/release.md)。
324
+
246
325
  ## License
247
326
 
248
327
  [MIT](./LICENSE)
package/README.zh-CN.md CHANGED
@@ -14,7 +14,7 @@ Baize(白泽)是一个本地软件研发 Agent 工作台:一个自托管
14
14
  **前置条件:** Linux 服务器(或 macOS)、[Claude](https://claude.ai) 订阅(或 OpenAI Codex 环境——Codex CLI v0.129.0+,推荐 0.146+)。
15
15
 
16
16
  ```bash
17
- curl -fsSL https://raw.githubusercontent.com/baize-ai/baize-core/main/scripts/install.sh | bash
17
+ curl -fsSL https://raw.githubusercontent.com/baize01-ai/baize-core/main/scripts/install.sh | bash
18
18
  ```
19
19
 
20
20
  安装依赖(git、tmux、Node.js、PM2、`baize` CLI)并运行 `baize init` 初始化 Agent。
@@ -29,14 +29,22 @@ baize init
29
29
  **Docker 部署:**
30
30
 
31
31
  ```bash
32
+ # 海外(GitHub Container Registry)
32
33
  docker run -d --name baize \
33
34
  -p 3456:3456 \
34
35
  -v baize-data:/home/baize/baize \
35
36
  -v claude-config:/home/baize/.claude \
36
- ghcr.io/baize-ai/baize-core:latest
37
+ ghcr.io/baize01-ai/baize-core:latest
38
+
39
+ # 国内(阿里云 ACR,免镜像加速)
40
+ docker run -d --name baize \
41
+ -p 3456:3456 \
42
+ -v baize-data:/home/baize/baize \
43
+ -v claude-config:/home/baize/.claude \
44
+ crpi-8bg62qbrjs3cr3as.cn-hangzhou.personal.cr.aliyuncs.com/baize01/baize-core:latest
37
45
  ```
38
46
 
39
- 打开 `http://localhost:3456` 进入网页控制台(见下文);认证在「模型设置」中配置(Claude API key / setup token / 自定义端点 / Codex / ChatGPT 登录)。Compose 配置、可选认证环境变量与卷说明见 `docs/docker.md`。
47
+ 镜像由已发布的 `@baize-ai/core` npm 包构建(构建上下文不含源码)。打开 `http://localhost:3456` 进入网页控制台(见下文);认证在「模型设置」中配置(Claude API key / setup token / 自定义端点 / Codex / ChatGPT 登录)。Compose 配置、可选认证环境变量与卷说明见 `docs/docker.md`。
40
48
 
41
49
  `baize init` 幂等,支持交互与非交互模式,它会:
42
50
 
@@ -147,6 +155,54 @@ baize search # 从当前源动态发现渠道目录
147
155
 
148
156
  ---
149
157
 
158
+ ## A2A(Agent-to-Agent 协作)
159
+
160
+ A2A 让多个 Baize 实例经 **HTTPS P2P** 直接协作——没有中心消息服务器,消息与任务委托直达对端 Agent,每个实例保持完全独立。
161
+
162
+ **组件:**
163
+
164
+ | 组件 | 职责 |
165
+ |------|------|
166
+ | `@baize-ai/baize-a2a` | npm 渠道包,装在每个启用实例:HTTPS server、注册/心跳客户端、任务 worker、`baize a2a` CLI |
167
+ | `@baize-ai/baize-admin-workspace` | 独立控制面(npm 包 + Docker 镜像 + Ant Design Pro 控制台):准入审批、在线状态、审计、基于 Card 的发现——不进消息路径 |
168
+
169
+ **核心概念:**
170
+
171
+ - **Agent Card 是唯一业务事实源** —— 每个 agent 在 `GET /.well-known/baize-agent.json` 自报 `name` / `description` / `skills`;admin 不维护业务描述,只管准入、在线、审计与发现。
172
+ - **接收方授权自治** —— 每个 agent 自己决定接受谁的调用(`config.json` 的 `authz`:默认 `open`,或 `allowlist`)。
173
+ - **基于 Card 的发现** —— 经 admin 目录按 Card 的 name/description/skills 文本匹配,或按 skill id 精确匹配发现 peer。
174
+
175
+ **快速上手:**
176
+
177
+ ```bash
178
+ baize add @baize-ai/baize-a2a # 安装渠道
179
+ baize a2a enable --admin <url> --advertise <https://your-agent.example.com>
180
+ # → 自注册 → 管理员审批 → 签发 JWT → 心跳(30s)→ 可发现
181
+ baize a2a search <query> # 经 admin 目录发现 agent
182
+ baize a2a task <peer> <skill> "<instruction>" # 委托任务(默认同步等待)
183
+ ```
184
+
185
+ **CLI(`baize a2a`):**
186
+
187
+ | 命令 | 用途 |
188
+ |------|------|
189
+ | `status` | 本实例状态:enabled / agent_id / 注册状态 / advertise_url |
190
+ | `enable --admin <url> --advertise <url>` | 启用 A2A 并向 admin 注册 |
191
+ | `disable` | 关闭(已接受任务继续执行) |
192
+ | `peer list` | 本地缓存 peer |
193
+ | `search <query>` | 经 admin 目录发现 agent |
194
+ | `card <id>` | Agent Card 详情 |
195
+ | `session-summary` | 当前可用 peer 摘要 |
196
+ | `send <peer> <text>` | 普通消息(不等待回复) |
197
+ | `task <peer> <skill> "<instruction>"` | 委托任务;默认同步等待终态(`--async` 只拿 task_id) |
198
+ | `task status <id>` / `task cancel <id>` | 查询 / 取消委托任务 |
199
+
200
+ **名片编辑与调用授权(网页控制台):** A2A 页可编辑本实例 Agent Card——名称、描述,以及从已安装 SKILL.md 列表勾选 Skills(frontmatter 自动提取)。保存后 Card 秒级热更新,admin 探测同步快照;A2A 未启用也可先编辑预填名片。同页配置「调用授权」:默认 `open` + 黑名单,或 `allowlist`——被拒调用返回 403 并记审计。
201
+
202
+ **凭证轮换:** 每个 agent 持有 admin 签发的独立 JWT(RS256,12h 有效,凭证独立)。agent 在过期前自动刷新;admin 轮换后 agent 60s 内自动重取凭证(吊销检测 + 强制恢复)。轮换只吊销目标 agent 的凭证并以当前 key 重签——全局签名 key 不变,单 agent 轮换不影响其他 agent。
203
+
204
+ ---
205
+
150
206
  ## 配置
151
207
 
152
208
  持久化配置在 `~/baize/.baize/config.json`:
@@ -203,6 +259,10 @@ baize uninstall --self # 完全卸载 Baize
203
259
 
204
260
  ---
205
261
 
262
+ ## Release
263
+
264
+ npm + Docker 发布的完整操作手册(认证 / 四包发布 / ghcr + 阿里云 ACR 镜像)见 [`docs/release.md`](docs/release.md)。
265
+
206
266
  ## License
207
267
 
208
268
  [MIT](./LICENSE)
package/assets/logo.png CHANGED
Binary file
package/cli/baize.js CHANGED
@@ -22,6 +22,7 @@ import { attachCommand } from './commands/attach.js';
22
22
  import { doctorCommand } from './commands/doctor.js';
23
23
  import { shellCommand } from './commands/shell.js';
24
24
  import { runtimeCommand } from './commands/runtime.js';
25
+ import { a2aCommand } from './commands/a2a.js';
25
26
 
26
27
  const commands = {
27
28
  // Environment setup
@@ -45,6 +46,8 @@ const commands = {
45
46
  remove: uninstallComponent,
46
47
  list: listComponents,
47
48
  search: searchComponents,
49
+ // A2A (Agent-to-Agent)
50
+ a2a: a2aCommand,
48
51
  // Help
49
52
  help: showHelp,
50
53
  };
@@ -120,6 +123,9 @@ Component Management:
120
123
  list List installed components
121
124
  search [keyword] Search available components
122
125
 
126
+ A2A:
127
+ a2a A2A 智能体互联管理(baize a2a --help 查看子命令)
128
+
123
129
  Other:
124
130
  help Show this help
125
131
 
@@ -0,0 +1,124 @@
1
+ /**
2
+ * baize a2a — A2A(Agent-to-Agent)互联管理。
3
+ *
4
+ * 全部子命令委托 @baize-ai/baize-a2a 的 scripts/cli.js(D19 契约 §6):
5
+ * 参数透传 + --json,成功 exit 0,失败 stderr + exit 1。
6
+ *
7
+ * Usage:
8
+ * baize a2a status
9
+ * baize a2a enable --admin <url> --advertise <url>
10
+ * baize a2a disable
11
+ * baize a2a peer list
12
+ * baize a2a search <query>
13
+ * baize a2a send <peer> <text>
14
+ * baize a2a task <peer> <skill?> <instruction> [--async]
15
+ * baize a2a task status <taskId>
16
+ * baize a2a task cancel <taskId>
17
+ */
18
+
19
+ import { a2aCliPath, runA2aCli, formatA2aOutput } from '../lib/a2a.js';
20
+ import { bold, dim, cyan, error } from '../lib/colors.js';
21
+
22
+ export const A2A_SUBCOMMANDS = ['status', 'enable', 'disable', 'peer', 'search', 'send', 'task'];
23
+
24
+ // Contract: sync task waits for a terminal state (timeout 10 min).
25
+ const TASK_TIMEOUT_MS = 660000;
26
+ const DEFAULT_TIMEOUT_MS = 120000;
27
+
28
+ export function a2aHelp() {
29
+ return `${bold('baize a2a')} — A2A(Agent-to-Agent)互联管理
30
+
31
+ 委托 @baize-ai/baize-a2a 通道 CLI(定位:BAIZE_A2A_PATH → 全局 npm 包 → ../baize-a2a 开发目录)。
32
+
33
+ Usage: ${bold('baize a2a <subcommand> [options]')}
34
+
35
+ Subcommands:
36
+ ${cyan('status')} A2A 身份与注册状态
37
+ ${cyan('enable')} --admin <url> --advertise <url>
38
+ 启用并注册:生成 agentId + 向 admin-workspace 提交注册
39
+ ${cyan('disable')} 停用(停止心跳/消息接收)
40
+ ${cyan('peer list')} peer 目录(已缓存)
41
+ ${cyan('search')} <query> 在 admin Directory 中搜索 agent
42
+ ${cyan('send')} <peer> <text> 发送一条消息给 peer
43
+ ${cyan('task')} <peer> <skill?> <instruction> [--async]
44
+ 派发任务;默认同步等待终态(超时 10 分钟),
45
+ ${dim('--async')} 立即返回 taskId
46
+ ${cyan('task status')} <taskId> 查询任务状态
47
+ ${cyan('task cancel')} <taskId> 取消任务(queued → canceled;running → cancel_requested)
48
+
49
+ Options:
50
+ --help, -h 显示帮助
51
+ --json 原始 JSON 输出(透传给 baize-a2a CLI)
52
+
53
+ Examples:
54
+ baize a2a status
55
+ baize a2a enable --admin https://admin.example.com --advertise https://a2a.example.com
56
+ baize a2a peer list
57
+ baize a2a search doccraft
58
+ baize a2a send agent_doccraft "帮我生成一份周报"
59
+ baize a2a task agent_doccraft "生成周报" --async
60
+ baize a2a task status <taskId>`;
61
+ }
62
+
63
+ function commandKind(args) {
64
+ const [sub, sub2] = args;
65
+ if (sub === 'task') {
66
+ if (sub2 === 'status') return 'task-status';
67
+ if (sub2 === 'cancel') return 'task-cancel';
68
+ return 'task';
69
+ }
70
+ if (sub === 'peer') return 'peer-list';
71
+ return sub;
72
+ }
73
+
74
+ /**
75
+ * Entry point for `baize a2a ...`.
76
+ *
77
+ * @param {string[]} args CLI args after "a2a"
78
+ * @param {object} [deps] injectable seams for tests
79
+ * @param {Function} [deps.runA2aCli] delegated runner (defaults to runA2aCli)
80
+ * @param {string|Function} [deps.cliPath] cli.js path override (defaults to a2aCliPath())
81
+ * @param {Function} [deps.exit] process.exit stand-in
82
+ * @param {Function} [deps.log] stdout writer
83
+ * @param {Function} [deps.logError] stderr writer
84
+ */
85
+ export async function a2aCommand(args = [], deps = {}) {
86
+ const run = deps.runA2aCli || runA2aCli;
87
+ const exit = deps.exit || ((code) => { process.exit(code); });
88
+ const log = deps.log || ((s) => console.log(s));
89
+ const logError = deps.logError || ((s) => console.error(s));
90
+
91
+ const first = args[0] || '';
92
+ if (!first || first === '--help' || first === '-h') {
93
+ log(a2aHelp());
94
+ return;
95
+ }
96
+ if (!A2A_SUBCOMMANDS.includes(first)) {
97
+ logError(error(`Unknown a2a subcommand: ${first}`));
98
+ logError('Usage: baize a2a <subcommand> [options] (baize a2a --help 查看全部子命令)');
99
+ return exit(1);
100
+ }
101
+
102
+ const cli = typeof deps.cliPath === 'function' ? deps.cliPath() : (deps.cliPath !== undefined ? deps.cliPath : a2aCliPath());
103
+ if (!cli) {
104
+ logError(error('未找到 baize-a2a CLI。请设置 BAIZE_A2A_PATH,安装 @baize-ai/baize-a2a(npm i -g),或确认 ../baize-a2a 开发目录存在。'));
105
+ return exit(1);
106
+ }
107
+
108
+ // Sync task dispatch waits for a terminal state (contract §6, 10 min).
109
+ const isTaskSync = first === 'task'
110
+ && args[1] !== 'status'
111
+ && args[1] !== 'cancel'
112
+ && !args.includes('--async');
113
+ const timeout = isTaskSync ? TASK_TIMEOUT_MS : DEFAULT_TIMEOUT_MS;
114
+
115
+ const result = await run(args, { cliPath: cli, timeout });
116
+ if (!result.success) {
117
+ logError(error(result.error || 'a2a 命令失败'));
118
+ if (result.output && result.output !== result.error) logError(result.output.slice(-800));
119
+ return exit(1);
120
+ }
121
+
122
+ const json = result.json || {};
123
+ log(formatA2aOutput(commandKind(args), json));
124
+ }