feat(kimi): add Kimi Code CLI integration support
Add complete support for Kimi Code CLI agent format. - Add convert_kimi() function to generate YAML agent specs - Add install_kimi() function to install agents to ~/.config/kimi/agents/ - Add Kimi to tool detection and installer UI - Add integrations/kimi/ directory (generated files gitignored) - Update integrations/README.md with Kimi documentation - Add generated agent directories to .gitignore Users can generate agents with: ./scripts/convert.sh --tool kimi
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -75,4 +75,6 @@ integrations/aider/CONVENTIONS.md
|
|||||||
integrations/windsurf/.windsurfrules
|
integrations/windsurf/.windsurfrules
|
||||||
integrations/openclaw/*
|
integrations/openclaw/*
|
||||||
integrations/qwen/agents/
|
integrations/qwen/agents/
|
||||||
|
integrations/kimi/*/
|
||||||
!integrations/openclaw/README.md
|
!integrations/openclaw/README.md
|
||||||
|
!integrations/kimi/README.md
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ supported agentic coding tools.
|
|||||||
- **[Cursor](#cursor)** — `.mdc` rule files in `cursor/`
|
- **[Cursor](#cursor)** — `.mdc` rule files in `cursor/`
|
||||||
- **[Aider](#aider)** — `CONVENTIONS.md` in `aider/`
|
- **[Aider](#aider)** — `CONVENTIONS.md` in `aider/`
|
||||||
- **[Windsurf](#windsurf)** — `.windsurfrules` in `windsurf/`
|
- **[Windsurf](#windsurf)** — `.windsurfrules` in `windsurf/`
|
||||||
|
- **[Kimi Code](#kimi-code)** — YAML agent specs in `kimi/`
|
||||||
|
|
||||||
## Quick Install
|
## Quick Install
|
||||||
|
|
||||||
@@ -172,3 +173,36 @@ cd /your/project && /path/to/agency-agents/scripts/install.sh --tool windsurf
|
|||||||
```
|
```
|
||||||
|
|
||||||
See [windsurf/README.md](windsurf/README.md) for details.
|
See [windsurf/README.md](windsurf/README.md) for details.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Kimi Code
|
||||||
|
|
||||||
|
Each agent is converted to a Kimi Code CLI agent specification (YAML format with
|
||||||
|
separate system prompt files). Agents are installed to `~/.config/kimi/agents/`.
|
||||||
|
|
||||||
|
Because the Kimi agent files are generated from the source Markdown, run
|
||||||
|
`./scripts/convert.sh --tool kimi` before installing from a fresh clone.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/convert.sh --tool kimi
|
||||||
|
./scripts/install.sh --tool kimi
|
||||||
|
```
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
After installation, use an agent with the `--agent-file` flag:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kimi --agent-file ~/.config/kimi/agents/frontend-developer/agent.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Or in a specific project:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /your/project
|
||||||
|
kimi --agent-file ~/.config/kimi/agents/frontend-developer/agent.yaml \
|
||||||
|
--work-dir /your/project
|
||||||
|
```
|
||||||
|
|
||||||
|
See [kimi/README.md](kimi/README.md) for details.
|
||||||
|
|||||||
108
integrations/kimi/README.md
Normal file
108
integrations/kimi/README.md
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
# Kimi Code CLI Integration
|
||||||
|
|
||||||
|
Converts all Agency agents into Kimi Code CLI agent specifications. Each agent
|
||||||
|
becomes a directory containing `agent.yaml` (agent spec) and `system.md` (system
|
||||||
|
prompt).
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- [Kimi Code CLI](https://github.com/MoonshotAI/kimi-cli) installed
|
||||||
|
|
||||||
|
### Install
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Generate integration files (required on fresh clone)
|
||||||
|
./scripts/convert.sh --tool kimi
|
||||||
|
|
||||||
|
# Install agents
|
||||||
|
./scripts/install.sh --tool kimi
|
||||||
|
```
|
||||||
|
|
||||||
|
This copies agents to `~/.config/kimi/agents/`.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Activate an Agent
|
||||||
|
|
||||||
|
Use the `--agent-file` flag to load a specific agent:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kimi --agent-file ~/.config/kimi/agents/frontend-developer/agent.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
### In a Project
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /your/project
|
||||||
|
kimi --agent-file ~/.config/kimi/agents/frontend-developer/agent.yaml \
|
||||||
|
--work-dir /your/project \
|
||||||
|
"Review this React component for performance issues"
|
||||||
|
```
|
||||||
|
|
||||||
|
### List Installed Agents
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ls ~/.config/kimi/agents/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Agent Structure
|
||||||
|
|
||||||
|
Each agent directory contains:
|
||||||
|
|
||||||
|
```
|
||||||
|
~/.config/kimi/agents/frontend-developer/
|
||||||
|
├── agent.yaml # Agent specification (tools, subagents)
|
||||||
|
└── system.md # System prompt with personality and instructions
|
||||||
|
```
|
||||||
|
|
||||||
|
### agent.yaml format
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: 1
|
||||||
|
agent:
|
||||||
|
name: frontend-developer
|
||||||
|
extend: default # Inherits from Kimi's built-in default agent
|
||||||
|
system_prompt_path: ./system.md
|
||||||
|
tools:
|
||||||
|
- "kimi_cli.tools.shell:Shell"
|
||||||
|
- "kimi_cli.tools.file:ReadFile"
|
||||||
|
# ... all default tools
|
||||||
|
```
|
||||||
|
|
||||||
|
## Regenerate
|
||||||
|
|
||||||
|
After modifying source agents:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/convert.sh --tool kimi
|
||||||
|
./scripts/install.sh --tool kimi
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Agent file not found
|
||||||
|
|
||||||
|
Ensure you've run `convert.sh` before `install.sh`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/convert.sh --tool kimi
|
||||||
|
```
|
||||||
|
|
||||||
|
### Kimi CLI not detected
|
||||||
|
|
||||||
|
Make sure `kimi` is in your PATH:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
which kimi
|
||||||
|
kimi --version
|
||||||
|
```
|
||||||
|
|
||||||
|
### Invalid YAML
|
||||||
|
|
||||||
|
Validate the generated files:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -c "import yaml; yaml.safe_load(open('integrations/kimi/frontend-developer/agent.yaml'))"
|
||||||
|
```
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
# windsurf — Single .windsurfrules for Windsurf
|
# windsurf — Single .windsurfrules for Windsurf
|
||||||
# openclaw — OpenClaw SOUL.md files (openclaw_workspace/<agent>/SOUL.md)
|
# openclaw — OpenClaw SOUL.md files (openclaw_workspace/<agent>/SOUL.md)
|
||||||
# qwen — Qwen Code SubAgent files (~/.qwen/agents/*.md)
|
# qwen — Qwen Code SubAgent files (~/.qwen/agents/*.md)
|
||||||
|
# kimi — Kimi Code CLI agent files (~/.config/kimi/agents/)
|
||||||
# all — All tools (default)
|
# all — All tools (default)
|
||||||
#
|
#
|
||||||
# Output is written to integrations/<tool>/ relative to the repo root.
|
# Output is written to integrations/<tool>/ relative to the repo root.
|
||||||
@@ -348,6 +349,53 @@ HEREDOC
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
convert_kimi() {
|
||||||
|
local file="$1"
|
||||||
|
local name description slug outdir agent_file body
|
||||||
|
|
||||||
|
name="$(get_field "name" "$file")"
|
||||||
|
description="$(get_field "description" "$file")"
|
||||||
|
slug="$(slugify "$name")"
|
||||||
|
body="$(get_body "$file")"
|
||||||
|
|
||||||
|
outdir="$OUT_DIR/kimi/$slug"
|
||||||
|
agent_file="$outdir/agent.yaml"
|
||||||
|
mkdir -p "$outdir"
|
||||||
|
|
||||||
|
# Kimi Code CLI agent format: YAML with separate system prompt file
|
||||||
|
cat > "$agent_file" <<HEREDOC
|
||||||
|
version: 1
|
||||||
|
agent:
|
||||||
|
name: ${slug}
|
||||||
|
extend: default
|
||||||
|
system_prompt_path: ./system.md
|
||||||
|
tools:
|
||||||
|
- "kimi_cli.tools.multiagent:Task"
|
||||||
|
- "kimi_cli.tools.ask_user:AskUserQuestion"
|
||||||
|
- "kimi_cli.tools.todo:SetTodoList"
|
||||||
|
- "kimi_cli.tools.shell:Shell"
|
||||||
|
- "kimi_cli.tools.file:ReadFile"
|
||||||
|
- "kimi_cli.tools.file:ReadMediaFile"
|
||||||
|
- "kimi_cli.tools.file:Glob"
|
||||||
|
- "kimi_cli.tools.file:Grep"
|
||||||
|
- "kimi_cli.tools.file:WriteFile"
|
||||||
|
- "kimi_cli.tools.file:StrReplaceFile"
|
||||||
|
- "kimi_cli.tools.web:SearchWeb"
|
||||||
|
- "kimi_cli.tools.web:FetchURL"
|
||||||
|
- "kimi_cli.tools.plan:ExitPlanMode"
|
||||||
|
- "kimi_cli.tools.plan.enter:EnterPlanMode"
|
||||||
|
HEREDOC
|
||||||
|
|
||||||
|
# Write system prompt to separate file
|
||||||
|
cat > "$outdir/system.md" <<HEREDOC
|
||||||
|
# ${name}
|
||||||
|
|
||||||
|
${description}
|
||||||
|
|
||||||
|
${body}
|
||||||
|
HEREDOC
|
||||||
|
}
|
||||||
|
|
||||||
# Aider and Windsurf are single-file formats — accumulate into temp files
|
# Aider and Windsurf are single-file formats — accumulate into temp files
|
||||||
# then write at the end.
|
# then write at the end.
|
||||||
AIDER_TMP="$(mktemp)"
|
AIDER_TMP="$(mktemp)"
|
||||||
@@ -445,6 +493,7 @@ run_conversions() {
|
|||||||
cursor) convert_cursor "$file" ;;
|
cursor) convert_cursor "$file" ;;
|
||||||
openclaw) convert_openclaw "$file" ;;
|
openclaw) convert_openclaw "$file" ;;
|
||||||
qwen) convert_qwen "$file" ;;
|
qwen) convert_qwen "$file" ;;
|
||||||
|
kimi) convert_kimi "$file" ;;
|
||||||
aider) accumulate_aider "$file" ;;
|
aider) accumulate_aider "$file" ;;
|
||||||
windsurf) accumulate_windsurf "$file" ;;
|
windsurf) accumulate_windsurf "$file" ;;
|
||||||
esac
|
esac
|
||||||
@@ -470,7 +519,7 @@ main() {
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
local valid_tools=("antigravity" "gemini-cli" "opencode" "cursor" "aider" "windsurf" "openclaw" "qwen" "all")
|
local valid_tools=("antigravity" "gemini-cli" "opencode" "cursor" "aider" "windsurf" "openclaw" "qwen" "kimi" "all")
|
||||||
local valid=false
|
local valid=false
|
||||||
for t in "${valid_tools[@]}"; do [[ "$t" == "$tool" ]] && valid=true && break; done
|
for t in "${valid_tools[@]}"; do [[ "$t" == "$tool" ]] && valid=true && break; done
|
||||||
if ! $valid; then
|
if ! $valid; then
|
||||||
@@ -486,7 +535,7 @@ main() {
|
|||||||
|
|
||||||
local tools_to_run=()
|
local tools_to_run=()
|
||||||
if [[ "$tool" == "all" ]]; then
|
if [[ "$tool" == "all" ]]; then
|
||||||
tools_to_run=("antigravity" "gemini-cli" "opencode" "cursor" "aider" "windsurf" "openclaw" "qwen")
|
tools_to_run=("antigravity" "gemini-cli" "opencode" "cursor" "aider" "windsurf" "openclaw" "qwen" "kimi")
|
||||||
else
|
else
|
||||||
tools_to_run=("$tool")
|
tools_to_run=("$tool")
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|||||||
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||||
INTEGRATIONS="$REPO_ROOT/integrations"
|
INTEGRATIONS="$REPO_ROOT/integrations"
|
||||||
|
|
||||||
ALL_TOOLS=(claude-code copilot antigravity gemini-cli opencode openclaw cursor aider windsurf qwen)
|
ALL_TOOLS=(claude-code copilot antigravity gemini-cli opencode openclaw cursor aider windsurf qwen kimi)
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Usage
|
# Usage
|
||||||
@@ -118,6 +118,7 @@ detect_aider() { command -v aider >/dev/null 2>&1; }
|
|||||||
detect_openclaw() { command -v openclaw >/dev/null 2>&1 || [[ -d "${HOME}/.openclaw" ]]; }
|
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_windsurf() { command -v windsurf >/dev/null 2>&1 || [[ -d "${HOME}/.codeium" ]]; }
|
||||||
detect_qwen() { command -v qwen >/dev/null 2>&1 || [[ -d "${HOME}/.qwen" ]]; }
|
detect_qwen() { command -v qwen >/dev/null 2>&1 || [[ -d "${HOME}/.qwen" ]]; }
|
||||||
|
detect_kimi() { command -v kimi >/dev/null 2>&1; }
|
||||||
|
|
||||||
is_detected() {
|
is_detected() {
|
||||||
case "$1" in
|
case "$1" in
|
||||||
@@ -131,6 +132,7 @@ is_detected() {
|
|||||||
aider) detect_aider ;;
|
aider) detect_aider ;;
|
||||||
windsurf) detect_windsurf ;;
|
windsurf) detect_windsurf ;;
|
||||||
qwen) detect_qwen ;;
|
qwen) detect_qwen ;;
|
||||||
|
kimi) detect_kimi ;;
|
||||||
*) return 1 ;;
|
*) return 1 ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
@@ -148,6 +150,7 @@ tool_label() {
|
|||||||
aider) printf "%-14s %s" "Aider" "(CONVENTIONS.md)" ;;
|
aider) printf "%-14s %s" "Aider" "(CONVENTIONS.md)" ;;
|
||||||
windsurf) printf "%-14s %s" "Windsurf" "(.windsurfrules)" ;;
|
windsurf) printf "%-14s %s" "Windsurf" "(.windsurfrules)" ;;
|
||||||
qwen) printf "%-14s %s" "Qwen Code" "(~/.qwen/agents)" ;;
|
qwen) printf "%-14s %s" "Qwen Code" "(~/.qwen/agents)" ;;
|
||||||
|
kimi) printf "%-14s %s" "Kimi Code" "(~/.config/kimi/agents)" ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,6 +447,28 @@ install_qwen() {
|
|||||||
warn "Tip: Run '/agents manage' in Qwen Code to refresh, or restart session"
|
warn "Tip: Run '/agents manage' in Qwen Code to refresh, or restart session"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
install_kimi() {
|
||||||
|
local src="$INTEGRATIONS/kimi"
|
||||||
|
local dest="${HOME}/.config/kimi/agents"
|
||||||
|
local count=0
|
||||||
|
|
||||||
|
[[ -d "$src" ]] || { err "integrations/kimi missing. Run convert.sh first."; return 1; }
|
||||||
|
|
||||||
|
mkdir -p "$dest"
|
||||||
|
|
||||||
|
local d
|
||||||
|
while IFS= read -r -d '' d; do
|
||||||
|
local name; name="$(basename "$d")"
|
||||||
|
mkdir -p "$dest/$name"
|
||||||
|
cp "$d/agent.yaml" "$dest/$name/agent.yaml"
|
||||||
|
cp "$d/system.md" "$dest/$name/system.md"
|
||||||
|
(( count++ )) || true
|
||||||
|
done < <(find "$src" -mindepth 1 -maxdepth 1 -type d -print0)
|
||||||
|
|
||||||
|
ok "Kimi Code: installed $count agents to $dest"
|
||||||
|
ok "Usage: kimi --agent-file ~/.config/kimi/agents/<agent-name>/agent.yaml"
|
||||||
|
}
|
||||||
|
|
||||||
install_tool() {
|
install_tool() {
|
||||||
case "$1" in
|
case "$1" in
|
||||||
claude-code) install_claude_code ;;
|
claude-code) install_claude_code ;;
|
||||||
@@ -456,6 +481,7 @@ install_tool() {
|
|||||||
aider) install_aider ;;
|
aider) install_aider ;;
|
||||||
windsurf) install_windsurf ;;
|
windsurf) install_windsurf ;;
|
||||||
qwen) install_qwen ;;
|
qwen) install_qwen ;;
|
||||||
|
kimi) install_kimi ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
204
scripts/test-kimi-integration.sh
Executable file
204
scripts/test-kimi-integration.sh
Executable file
@@ -0,0 +1,204 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# test-kimi-integration.sh — Test Kimi Code CLI integration locally
|
||||||
|
#
|
||||||
|
# Finds appropriate Python with PyYAML installed
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./scripts/test-kimi-integration.sh [--verbose]
|
||||||
|
#
|
||||||
|
# This script validates that the Kimi Code integration works correctly by:
|
||||||
|
# 1. Running convert.sh to generate integration files
|
||||||
|
# 2. Validating YAML syntax of all generated agent files
|
||||||
|
# 3. Checking required fields exist in agent specs
|
||||||
|
# 4. Verifying system prompt files exist
|
||||||
|
# 5. Testing with Kimi CLI if available
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||||
|
TEST_DIR="/tmp/kimi-agency-test-$$"
|
||||||
|
VERBOSE=false
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
if [[ -t 1 && -z "${NO_COLOR:-}" ]]; then
|
||||||
|
C_GREEN=$'\033[0;32m'
|
||||||
|
C_RED=$'\033[0;31m'
|
||||||
|
C_YELLOW=$'\033[1;33m'
|
||||||
|
C_CYAN=$'\033[0;36m'
|
||||||
|
C_BOLD=$'\033[1m'
|
||||||
|
C_DIM=$'\033[2m'
|
||||||
|
C_RESET=$'\033[0m'
|
||||||
|
else
|
||||||
|
C_GREEN=''; C_RED=''; C_YELLOW=''; C_CYAN=''; C_BOLD=''; C_DIM=''; C_RESET=''
|
||||||
|
fi
|
||||||
|
|
||||||
|
ok() { printf "${C_GREEN}[✓]${C_RESET} %s\n" "$*"; }
|
||||||
|
err() { printf "${C_RED}[✗]${C_RESET} %s\n" "$*" >&2; }
|
||||||
|
warn() { printf "${C_YELLOW}[!]${C_RESET} %s\n" "$*"; }
|
||||||
|
info() { printf "${C_CYAN}[i]${C_RESET} %s\n" "$*"; }
|
||||||
|
dim() { printf "${C_DIM}%s${C_RESET}\n" "$*"; }
|
||||||
|
header() { printf "\n${C_BOLD}%s${C_RESET}\n" "$*"; }
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
if [[ -d "$TEST_DIR" ]]; then
|
||||||
|
rm -rf "$TEST_DIR"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
# Find Python with PyYAML
|
||||||
|
find_python() {
|
||||||
|
for py in python3 python /usr/bin/python3 /usr/bin/python; do
|
||||||
|
if command -v "$py" >/dev/null 2>&1; then
|
||||||
|
if $py -c "import yaml" 2>/dev/null; then
|
||||||
|
echo "$py"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
err "No Python with PyYAML found. Install with: pip install pyyaml"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
PYTHON=$(find_python)
|
||||||
|
|
||||||
|
# Parse args
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--verbose|-v) VERBOSE=true; shift ;;
|
||||||
|
--help|-h)
|
||||||
|
echo "Usage: $0 [--verbose] [--help]"
|
||||||
|
echo ""
|
||||||
|
echo "Test Kimi Code CLI integration locally."
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*) echo "Unknown option: $1"; exit 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
FAILED=0
|
||||||
|
|
||||||
|
header "=== Kimi Code Integration Tests ==="
|
||||||
|
|
||||||
|
# Step 1: Generate integration files
|
||||||
|
header "Step 1: Converting agents..."
|
||||||
|
if "$REPO_ROOT/scripts/convert.sh" --tool kimi >/dev/null 2>&1; then
|
||||||
|
ok "Convert script completed"
|
||||||
|
else
|
||||||
|
err "Convert script failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Count generated agents
|
||||||
|
AGENT_COUNT=$(find "$REPO_ROOT/integrations/kimi" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | wc -l)
|
||||||
|
if [[ $AGENT_COUNT -eq 0 ]]; then
|
||||||
|
err "No agents generated!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
ok "Generated $AGENT_COUNT agent directories"
|
||||||
|
|
||||||
|
# Step 2: Validate YAML syntax
|
||||||
|
header "Step 2: Validating YAML syntax..."
|
||||||
|
for agent_file in "$REPO_ROOT"/integrations/kimi/*/agent.yaml; do
|
||||||
|
[[ -f "$agent_file" ]] || continue
|
||||||
|
agent_name=$(basename "$(dirname "$agent_file")")
|
||||||
|
|
||||||
|
if $PYTHON -c "import yaml; yaml.safe_load(open('$agent_file'))" 2>/dev/null; then
|
||||||
|
ok "$agent_name/agent.yaml"
|
||||||
|
else
|
||||||
|
err "$agent_name/agent.yaml - Invalid YAML"
|
||||||
|
(( FAILED++ )) || true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Step 3: Validate schema
|
||||||
|
header "Step 3: Validating agent schema..."
|
||||||
|
for agent_file in "$REPO_ROOT"/integrations/kimi/*/agent.yaml; do
|
||||||
|
[[ -f "$agent_file" ]] || continue
|
||||||
|
agent_name=$(basename "$(dirname "$agent_file")")
|
||||||
|
|
||||||
|
errors=()
|
||||||
|
|
||||||
|
# Check version
|
||||||
|
version=$($PYTHON -c "import yaml; print(yaml.safe_load(open('$agent_file')).get('version', 'MISSING'))" 2>/dev/null)
|
||||||
|
if [[ "$version" != "1" ]]; then
|
||||||
|
errors+=("version must be 1, got: $version")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check agent.name
|
||||||
|
name=$($PYTHON -c "import yaml; print(yaml.safe_load(open('$agent_file')).get('agent', {}).get('name', 'MISSING'))" 2>/dev/null)
|
||||||
|
if [[ "$name" == "MISSING" || -z "$name" ]]; then
|
||||||
|
errors+=("missing agent.name")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check agent.system_prompt_path
|
||||||
|
spp=$($PYTHON -c "import yaml; print(yaml.safe_load(open('$agent_file')).get('agent', {}).get('system_prompt_path', 'MISSING'))" 2>/dev/null)
|
||||||
|
if [[ "$spp" == "MISSING" || -z "$spp" ]]; then
|
||||||
|
errors+=("missing agent.system_prompt_path")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check agent.tools
|
||||||
|
tools=$($PYTHON -c "import yaml; print('HAS_TOOLS' if yaml.safe_load(open('$agent_file')).get('agent', {}).get('tools') else 'MISSING')" 2>/dev/null)
|
||||||
|
if [[ "$tools" != "HAS_TOOLS" ]]; then
|
||||||
|
errors+=("missing agent.tools")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${#errors[@]} -eq 0 ]]; then
|
||||||
|
ok "$agent_name - schema valid"
|
||||||
|
else
|
||||||
|
err "$agent_name - schema errors:"
|
||||||
|
for e in "${errors[@]}"; do
|
||||||
|
echo " $e"
|
||||||
|
done
|
||||||
|
(( FAILED++ )) || true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Step 4: Check system prompt files exist
|
||||||
|
header "Step 4: Checking system prompt files..."
|
||||||
|
for agent_dir in "$REPO_ROOT"/integrations/kimi/*/; do
|
||||||
|
[[ -d "$agent_dir" ]] || continue
|
||||||
|
agent_name=$(basename "$agent_dir")
|
||||||
|
|
||||||
|
if [[ -f "$agent_dir/system.md" ]]; then
|
||||||
|
ok "$agent_name/system.md exists"
|
||||||
|
else
|
||||||
|
err "$agent_name/system.md missing"
|
||||||
|
(( FAILED++ )) || true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Step 5: Test with Kimi CLI if available
|
||||||
|
header "Step 5: Testing with Kimi CLI..."
|
||||||
|
if command -v kimi >/dev/null 2>&1; then
|
||||||
|
info "Kimi CLI found: $(kimi --version 2>&1 | head -1)"
|
||||||
|
|
||||||
|
# Find first agent
|
||||||
|
FIRST_AGENT=$(find "$REPO_ROOT/integrations/kimi" -name "agent.yaml" -print -quit 2>/dev/null)
|
||||||
|
|
||||||
|
if [[ -n "$FIRST_AGENT" ]]; then
|
||||||
|
# Test that Kimi accepts the agent file (just validate, don't run)
|
||||||
|
if kimi --agent-file "$FIRST_AGENT" --help >/dev/null 2>&1; then
|
||||||
|
ok "Kimi CLI accepts agent file: $(basename "$(dirname "$FIRST_AGENT")")"
|
||||||
|
else
|
||||||
|
err "Kimi CLI rejected agent file"
|
||||||
|
(( FAILED++ )) || true
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "No agent files found to test"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "Kimi CLI not found, skipping runtime tests"
|
||||||
|
dim " Install from: https://github.com/MoonshotAI/kimi-cli"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
header "=== Test Summary ==="
|
||||||
|
if [[ $FAILED -eq 0 ]]; then
|
||||||
|
ok "All tests passed!"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
err "$FAILED test(s) failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
Reference in New Issue
Block a user