Files
superpowers-zh/tests/kimi/test-plugin-manifest.sh
AI不止语 af4c03c1e0 feat(kimi): 新增 Kimi Code harness 支持(对齐上游 v6.0.0 集成模型)
issue #37:Kimi Code 已支持 Skills 能力,希望原生支持。上游 obra/superpowers
在 v6.0.0 已用插件清单模型原生集成 Kimi,本提交把同样的集成方式落到本 fork。

Kimi 走插件清单模型(与 CC plugin 同类),直接指向仓库现有 skills/,
不复制 skill、不建 symlink、不装 hook、无运行时依赖,因此无需改 npx
安装器(安装器面向需要复制 skills 的工具)。

- .kimi-plugin/plugin.json:fork 品牌清单,skills 指向 ./skills/,
  sessionStart.skill = using-superpowers(会话开始自动加载 bootstrap),
  skillInstructions 提供 Kimi 工具映射(AskUserQuestion/TodoList/Agent/
  Skill/Read/Write/Edit/Bash/Grep/Glob/FetchURL/WebSearch,保留上游权威
  英文映射以免破坏真实工具名)
- 版本同步:.version-bump.json 与 scripts/sync-plugin-version.js 双向接入
- docs/README.kimi.md:中文安装/工具映射/排错指南;README.md 工具列表加链接
- tests/kimi/:清单结构测试(适配 fork:name=superpowers-zh、校验版本同步条目)

验证:bash tests/kimi/run-tests.sh 通过;manifest 合法 JSON;版本同步双机制
均含 kimi 条目;scripts/audit.sh 静态校验 0 FAIL;README→docs/README.kimi.md
链接可解析。

注:Kimi 实际 skill 自动触发需在 Kimi Code 内验证(与本 fork 其它 harness
同样限制),清单结构已对齐上游 v6.0.0 经过验证的集成方式。
2026-06-20 02:37:31 +08:00

87 lines
2.3 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
MANIFEST="$REPO_ROOT/.kimi-plugin/plugin.json"
python3 - "$MANIFEST" <<'PY'
import json
import sys
from pathlib import Path
manifest_path = Path(sys.argv[1])
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
def assert_equal(actual, expected, label):
if actual != expected:
raise AssertionError(f"{label}: expected {expected!r}, got {actual!r}")
def assert_present(text, needle, label):
if needle not in text:
raise AssertionError(f"{label}: missing {needle!r}")
assert_equal(manifest.get("name"), "superpowers-zh", "plugin name")
assert_equal(manifest.get("skills"), "./skills/", "skills path")
assert_equal(
manifest.get("sessionStart", {}).get("skill"),
"using-superpowers",
"sessionStart.skill",
)
instructions = manifest.get("skillInstructions")
if not isinstance(instructions, str) or not instructions.strip():
raise AssertionError("skillInstructions must be a non-empty string")
for token in [
"AskUserQuestion",
"TodoList",
"Agent",
"Skill",
"Read",
"Write",
"Edit",
"Bash",
"Grep",
"Glob",
"FetchURL",
"WebSearch",
]:
assert_present(instructions, token, "skillInstructions")
version_config = json.loads(
(manifest_path.parents[1] / ".version-bump.json").read_text(encoding="utf-8")
)
version_entries = version_config.get("files")
if not isinstance(version_entries, list):
raise AssertionError(".version-bump.json must contain files list")
if not any(
entry.get("path") == ".kimi-plugin/plugin.json" and entry.get("field") == "version"
for entry in version_entries
if isinstance(entry, dict)
):
raise AssertionError(
".version-bump.json must update .kimi-plugin/plugin.json version"
)
unsupported_fields = [
"tools",
"commands",
"hooks",
"apps",
"inject",
"configFile",
"config_file",
"bootstrap",
]
present_unsupported = sorted(field for field in unsupported_fields if field in manifest)
if present_unsupported:
raise AssertionError(
"unsupported Kimi runtime fields present: "
+ ", ".join(present_unsupported)
)
print("Kimi plugin manifest looks good")
PY