mirror of
https://github.com/msitarzewski/agency-agents.git
synced 2026-07-11 10:43:41 +03:00
feat(tools): add ZCode (Z.ai GLM agent harness)
ZCode reads per-agent markdown from `.zcode/agents/{slug}.md` (project) and
`~/.config/zcode/agents/{slug}.md` (global), with `name` + `description` YAML
frontmatter and an optional `tools` list — the same plain-agent-markdown shape
as Qwen.
- tools.json: add the `zcode` entry (dual-scope, per-agent, format `zcode-md`).
- convert.sh: add `convert_zcode` (byte-identical to the qwen converter,
output to integrations/zcode/agents/) + register in the dispatch, valid_tools,
tools_to_run, and parallel_tools.
- install.sh: add `zcode` to ALL_TOOLS, `install_zcode`, `detect_zcode`, and the
resolve_dest / bin / is_detected / display / label dispatches.
Directories + file format verified against ZCode's published docs. Renderer
contract: `zcode-md` output is byte-identical to `qwen-md`, verified by
diffing `convert.sh --tool zcode` against `--tool qwen` (243/243 files match).
check-tools.sh passes (16 tools consistent across tools.json, install.sh, and
convert.sh); bash -n clean on both scripts.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WdX6PvnCfRgYD11yVpXVor
This commit is contained in:
+42
-3
@@ -18,6 +18,7 @@
|
||||
# windsurf — Single .windsurfrules for Windsurf
|
||||
# openclaw — OpenClaw workspaces (integrations/openclaw/<agent>/SOUL.md)
|
||||
# qwen — Qwen Code SubAgent files (~/.qwen/agents/*.md)
|
||||
# zcode — ZCode agent files (.zcode/agents/*.md · ~/.config/zcode/agents/*.md)
|
||||
# kimi — Kimi Code CLI agent files (~/.config/kimi/agents/)
|
||||
# codex — Codex custom agent TOML files (~/.codex/agents/*.toml)
|
||||
# osaurus — Osaurus skill files (~/.osaurus/skills/<name>/SKILL.md)
|
||||
@@ -425,6 +426,43 @@ HEREDOC
|
||||
fi
|
||||
}
|
||||
|
||||
convert_zcode() {
|
||||
local file="$1"
|
||||
local name description tools slug outfile body
|
||||
|
||||
name="$(get_field "name" "$file")"
|
||||
description="$(get_field "description" "$file")"
|
||||
tools="$(get_field "tools" "$file")"
|
||||
slug="$(slugify "$name")"
|
||||
body="$(get_body "$file")"
|
||||
|
||||
outfile="$OUT_DIR/zcode/agents/${slug}.md"
|
||||
mkdir -p "$(dirname "$outfile")"
|
||||
|
||||
# ZCode agent format (Z.ai GLM harness): .md with YAML frontmatter in
|
||||
# .zcode/agents/ (project) or ~/.config/zcode/agents/ (global). name and
|
||||
# description required; tools optional (only if present in source). Byte-
|
||||
# identical to the qwen-md shape, which the Agency Agents app renders natively.
|
||||
if [[ -n "$tools" ]]; then
|
||||
cat > "$outfile" <<HEREDOC
|
||||
---
|
||||
name: ${slug}
|
||||
description: ${description}
|
||||
tools: ${tools}
|
||||
---
|
||||
${body}
|
||||
HEREDOC
|
||||
else
|
||||
cat > "$outfile" <<HEREDOC
|
||||
---
|
||||
name: ${slug}
|
||||
description: ${description}
|
||||
---
|
||||
${body}
|
||||
HEREDOC
|
||||
fi
|
||||
}
|
||||
|
||||
convert_kimi() {
|
||||
local file="$1"
|
||||
local name description slug outdir agent_file body
|
||||
@@ -608,6 +646,7 @@ run_conversions() {
|
||||
cursor) convert_cursor "$file" ;;
|
||||
openclaw) convert_openclaw "$file" ;;
|
||||
qwen) convert_qwen "$file" ;;
|
||||
zcode) convert_zcode "$file" ;;
|
||||
kimi) convert_kimi "$file" ;;
|
||||
osaurus) convert_osaurus "$file" ;;
|
||||
vibe) convert_vibe "$file" ;;
|
||||
@@ -641,7 +680,7 @@ main() {
|
||||
esac
|
||||
done
|
||||
|
||||
local valid_tools=("antigravity" "gemini-cli" "opencode" "cursor" "aider" "windsurf" "openclaw" "qwen" "kimi" "codex" "osaurus" "hermes" "vibe" "all")
|
||||
local valid_tools=("antigravity" "gemini-cli" "opencode" "cursor" "aider" "windsurf" "openclaw" "qwen" "zcode" "kimi" "codex" "osaurus" "hermes" "vibe" "all")
|
||||
local valid=false
|
||||
for t in "${valid_tools[@]}"; do [[ "$t" == "$tool" ]] && valid=true && break; done
|
||||
if ! $valid; then
|
||||
@@ -660,7 +699,7 @@ main() {
|
||||
|
||||
local tools_to_run=()
|
||||
if [[ "$tool" == "all" ]]; then
|
||||
tools_to_run=("antigravity" "gemini-cli" "opencode" "cursor" "aider" "windsurf" "openclaw" "qwen" "kimi" "codex" "osaurus" "hermes" "vibe")
|
||||
tools_to_run=("antigravity" "gemini-cli" "opencode" "cursor" "aider" "windsurf" "openclaw" "qwen" "zcode" "kimi" "codex" "osaurus" "hermes" "vibe")
|
||||
else
|
||||
tools_to_run=("$tool")
|
||||
fi
|
||||
@@ -671,7 +710,7 @@ main() {
|
||||
|
||||
if $use_parallel && [[ "$tool" == "all" ]]; then
|
||||
# Tools that write to separate dirs can run in parallel; buffer output so each tool's output stays together
|
||||
local parallel_tools=(antigravity gemini-cli opencode cursor openclaw qwen codex osaurus hermes vibe)
|
||||
local parallel_tools=(antigravity gemini-cli opencode cursor openclaw qwen zcode codex osaurus hermes vibe)
|
||||
local parallel_out_dir
|
||||
parallel_out_dir="$(mktemp -d)"
|
||||
info "Converting: ${#parallel_tools[@]}/${n_tools} tools in parallel (output buffered per tool)..."
|
||||
|
||||
+29
-2
@@ -22,6 +22,7 @@
|
||||
# windsurf -- Copy .windsurfrules to current directory
|
||||
# openclaw -- Copy workspaces to ~/.openclaw/agency-agents/
|
||||
# qwen -- Copy SubAgents to ~/.qwen/agents/ (user-wide) or .qwen/agents/ (project)
|
||||
# zcode -- Copy agents to ~/.config/zcode/agents/ (global) or .zcode/agents/ (project)
|
||||
# codex -- Copy custom agent TOML files to ~/.codex/agents/
|
||||
# osaurus -- Copy skills to ~/.osaurus/skills/
|
||||
# hermes -- Copy lazy-router plugin to ~/.hermes/plugins/ and enable it
|
||||
@@ -129,7 +130,7 @@ INTEGRATIONS="$REPO_ROOT/integrations"
|
||||
# shellcheck source=lib.sh
|
||||
. "$SCRIPT_DIR/lib.sh"
|
||||
|
||||
ALL_TOOLS=(claude-code copilot antigravity gemini-cli opencode openclaw cursor aider windsurf qwen kimi codex osaurus hermes vibe)
|
||||
ALL_TOOLS=(claude-code copilot antigravity gemini-cli opencode openclaw cursor aider windsurf qwen zcode kimi codex osaurus hermes vibe)
|
||||
|
||||
# The division set is derived from divisions.json (the single source of truth)
|
||||
# so the installer can never drift from the catalog — a hardcoded copy silently
|
||||
@@ -268,6 +269,7 @@ resolve_dest() {
|
||||
opencode) var="OPENCODE_AGENTS_DIR" ;;
|
||||
openclaw) var="OPENCLAW_DIR" ;;
|
||||
qwen) var="QWEN_AGENTS_DIR" ;;
|
||||
zcode) var="ZCODE_AGENTS_DIR" ;;
|
||||
codex) var="CODEX_AGENTS_DIR" ;;
|
||||
osaurus) var="OSAURUS_SKILLS_DIR" ;;
|
||||
hermes) var="HERMES_PLUGIN_DIR" ;;
|
||||
@@ -283,6 +285,7 @@ resolve_tool_path() {
|
||||
claude-code) bin="claude" ;; copilot) bin="code" ;; gemini-cli) bin="gemini" ;;
|
||||
opencode) bin="opencode" ;; openclaw) bin="openclaw" ;; cursor) bin="cursor" ;;
|
||||
aider) bin="aider" ;; windsurf) bin="windsurf" ;; qwen) bin="qwen" ;;
|
||||
zcode) bin="zcode" ;;
|
||||
kimi) bin="kimi" ;; codex) bin="codex" ;; antigravity) bin="" ;;
|
||||
osaurus) bin="osaurus" ;; hermes) bin="hermes" ;; vibe) bin="vibe" ;;
|
||||
esac
|
||||
@@ -379,6 +382,7 @@ detect_aider() { command -v aider >/dev/null 2>&1; }
|
||||
detect_openclaw() { command -v openclaw >/dev/null 2>&1 || [[ -d "${HOME}/.openclaw" ]]; }
|
||||
detect_windsurf() { command -v windsurf >/dev/null 2>&1 || [[ -d "${HOME}/.codeium" ]]; }
|
||||
detect_qwen() { command -v qwen >/dev/null 2>&1 || [[ -d "${HOME}/.qwen" ]]; }
|
||||
detect_zcode() { command -v zcode >/dev/null 2>&1 || [[ -d "${HOME}/.zcode" ]] || [[ -d "${HOME}/.config/zcode" ]]; }
|
||||
detect_kimi() { command -v kimi >/dev/null 2>&1; }
|
||||
detect_codex() { command -v codex >/dev/null 2>&1 || [[ -d "${HOME}/.codex" ]]; }
|
||||
detect_osaurus() { command -v osaurus >/dev/null 2>&1 || [[ -d "${HOME}/.osaurus" ]]; }
|
||||
@@ -397,6 +401,7 @@ is_detected() {
|
||||
aider) detect_aider ;;
|
||||
windsurf) detect_windsurf ;;
|
||||
qwen) detect_qwen ;;
|
||||
zcode) detect_zcode ;;
|
||||
kimi) detect_kimi ;;
|
||||
codex) detect_codex ;;
|
||||
osaurus) detect_osaurus ;;
|
||||
@@ -419,6 +424,7 @@ tool_label() {
|
||||
aider) printf "%-14s %s" "Aider" "(CONVENTIONS.md)" ;;
|
||||
windsurf) printf "%-14s %s" "Windsurf" "(.windsurfrules)" ;;
|
||||
qwen) printf "%-14s %s" "Qwen Code" "(~/.qwen/agents)" ;;
|
||||
zcode) printf "%-14s %s" "ZCode" "(~/.config/zcode/agents)" ;;
|
||||
kimi) printf "%-14s %s" "Kimi Code" "(~/.config/kimi/agents)" ;;
|
||||
codex) printf "%-14s %s" "Codex" "(~/.codex/agents)" ;;
|
||||
osaurus) printf "%-14s %s" "Osaurus" "(~/.osaurus/skills)" ;;
|
||||
@@ -547,7 +553,7 @@ tool_simple_name() {
|
||||
claude-code) echo "Claude Code";; copilot) echo "Copilot";; antigravity) echo "Antigravity";;
|
||||
gemini-cli) echo "Gemini CLI";; opencode) echo "OpenCode";; openclaw) echo "OpenClaw";;
|
||||
cursor) echo "Cursor";; aider) echo "Aider";; windsurf) echo "Windsurf";;
|
||||
qwen) echo "Qwen Code";; kimi) echo "Kimi Code";; codex) echo "Codex";; osaurus) echo "Osaurus";; *) echo "$1";;
|
||||
qwen) echo "Qwen Code";; zcode) echo "ZCode";; kimi) echo "Kimi Code";; codex) echo "Codex";; osaurus) echo "Osaurus";; *) echo "$1";;
|
||||
esac
|
||||
}
|
||||
|
||||
@@ -903,6 +909,26 @@ install_qwen() {
|
||||
warn "Tip: Run '/agents manage' in Qwen Code to refresh, or restart session"
|
||||
}
|
||||
|
||||
install_zcode() {
|
||||
local src="$INTEGRATIONS/zcode/agents"
|
||||
local dest; dest="$(resolve_dest zcode "${HOME}/.config/zcode/agents")"
|
||||
local count=0
|
||||
|
||||
[[ -d "$src" ]] || { err "integrations/zcode missing. Run convert.sh first."; return 1; }
|
||||
|
||||
mkdir -p "$dest"
|
||||
|
||||
local f
|
||||
while IFS= read -r -d '' f; do
|
||||
slug_allowed "$(basename "$f" .md)" || continue
|
||||
install_file "$f" "$dest/"
|
||||
incr count
|
||||
done < <(find "$src" -maxdepth 1 -name "*.md" -print0)
|
||||
|
||||
ok "ZCode: installed $count agents to $dest"
|
||||
warn "ZCode: set ZCODE_AGENTS_DIR=.zcode/agents (in a project) to install there instead."
|
||||
}
|
||||
|
||||
install_kimi() {
|
||||
local src="$INTEGRATIONS/kimi"
|
||||
local dest; dest="$(resolve_dest kimi "${HOME}/.config/kimi/agents")"
|
||||
@@ -1126,6 +1152,7 @@ install_tool() {
|
||||
aider) install_aider ;;
|
||||
windsurf) install_windsurf ;;
|
||||
qwen) install_qwen ;;
|
||||
zcode) install_zcode ;;
|
||||
kimi) install_kimi ;;
|
||||
codex) install_codex ;;
|
||||
osaurus) install_osaurus ;;
|
||||
|
||||
+2
-1
@@ -15,6 +15,7 @@
|
||||
"openclaw": {"id":"openclaw","label":"OpenClaw","short":"openclaw","kebab":"openclaw","accent":"#E11D48","icon":null,"order":12,"scope":{"user":true,"project":false},"detect":{"dirs":[".openclaw"],"agentsDir":".openclaw/agency-agents"},"version":{"bin":"openclaw","args":["--version"]},"format":"openclaw-workspace","installKind":"per-agent","slugFrom":"name","dest":{"user":[".openclaw/agency-agents/{slug}/SOUL.md",".openclaw/agency-agents/{slug}/AGENTS.md",".openclaw/agency-agents/{slug}/IDENTITY.md"],"project":[]}},
|
||||
"windsurf": {"id":"windsurf","label":"Windsurf","short":"Windsurf","kebab":"windsurf","accent":"#09B6A2","icon":"windsurf","order":13,"scope":{"user":false,"project":true},"detect":{"dirs":[".codeium"],"agentsDir":null},"version":{"bin":"windsurf","args":["--version"]},"format":"windsurf-rules","installKind":"roster","slugFrom":null,"dest":{"user":[],"project":[".windsurfrules"]}},
|
||||
"hermes": {"id":"hermes","label":"Hermes","short":"Hermes","kebab":"hermes","accent":"#7C3AED","icon":null,"order":14,"scope":{"user":true,"project":false},"detect":{"dirs":[".hermes"],"agentsDir":".hermes/plugins"},"version":{"bin":"hermes","args":["--version"]},"format":"hermes-router-plugin","installKind":"plugin","slugFrom":null,"dest":{"user":[".hermes/plugins/agency-agents-router"],"project":[]}},
|
||||
"vibe": {"id":"vibe","label":"Mistral Vibe","short":"Vibe","kebab":"vibe","accent":"#FA520F","icon":null,"order":15,"scope":{"user":true,"project":true},"detect":{"dirs":[".vibe"],"agentsDir":".vibe/agents"},"version":{"bin":"vibe","args":["--version"]},"format":"vibe-toml","installKind":"per-agent","slugFrom":"name","dest":{"user":[".vibe/agents/{slug}.toml",".vibe/prompts/{slug}.md"],"project":[".vibe/agents/{slug}.toml",".vibe/prompts/{slug}.md"]}}
|
||||
"vibe": {"id":"vibe","label":"Mistral Vibe","short":"Vibe","kebab":"vibe","accent":"#FA520F","icon":null,"order":15,"scope":{"user":true,"project":true},"detect":{"dirs":[".vibe"],"agentsDir":".vibe/agents"},"version":{"bin":"vibe","args":["--version"]},"format":"vibe-toml","installKind":"per-agent","slugFrom":"name","dest":{"user":[".vibe/agents/{slug}.toml",".vibe/prompts/{slug}.md"],"project":[".vibe/agents/{slug}.toml",".vibe/prompts/{slug}.md"]}},
|
||||
"zcode": {"id":"zcode","label":"ZCode","short":"ZCode","kebab":"zcode","accent":"#4263EB","icon":"zcode","order":16,"scope":{"user":true,"project":true},"detect":{"dirs":[".zcode"],"agentsDir":".zcode/agents"},"version":{"bin":"zcode","args":["--version"]},"format":"zcode-md","installKind":"per-agent","slugFrom":"name","dest":{"user":[".config/zcode/agents/{slug}.md"],"project":[".zcode/agents/{slug}.md"]}}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user