Metadata-Version: 2.4
Name: python-yama
Version: 0.1.0
Summary: A reproducible evaluation runner for tool-using Agent skills
Project-URL: Repository, https://github.com/world-sim-dev/yama
Project-URL: Issues, https://github.com/world-sim-dev/yama/issues
Author-email: Farmer Sun <podpodiumapp@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: agent,evaluation,llm,skill,testing
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Testing
Requires-Python: >=3.12
Requires-Dist: fastapi>=0.139.0
Requires-Dist: jinja2>=3.1
Requires-Dist: litellm<2.0,>=1.80
Requires-Dist: orjson>=3.11.9
Requires-Dist: pyyaml>=6.0
Requires-Dist: rich<15.0,>=14.1
Description-Content-Type: text/markdown

# yama

`yama` 是一个可复现的 Agent Skill 评测框架：用声明式 YAML Case 描述模型看到的 System Prompt、Skill metadata、Tool Schema 与多轮 User Message，通过 LiteLLM 统一调用 LLM 并驱动 Tool Loop，再对 Transcript 做确定性 Hard Check 或 LLM Judge 评分。完整 Case Schema 与执行契约见[设计文档](docs/agent-skill-test-framework-design.md)。

## 快速开始

```bash
# 在 Plugin 根目录下直接运行，默认收集 __evals__/cases/**/*.yaml
cd dingding-simple
OPENAI_API_KEY=... uv run --project yama yama

# 在 Workspace 根目录（存在 yama.toml）按名字指定 Plugin
OPENAI_API_KEY=... uv run --project yama yama --plugin dingding-simple
```

## 编写一个 Case

一个 Case 是一份 YAML 文件，按 `context`（模型看到什么）→ `mocks`（Tool 怎么被执行）→ `steps`（依次发送的用户回合与断言）→ `outcome`（整个 Case 的通过门槛）的结构组织：

```yaml
context:
  system_prompt: { default: true }     # 使用 Plugin 根目录下的 SYSTEM.md

  tools:
    - file: tools/read-dsl.yaml         # Tool Schema，相对 __evals__ 目录解析

mocks:
  tools:
    read_dsl:
      respond:
        result:
          visualStyle: { name: 复古胶片 }

steps:
  - id: request-directions
    user: 给我几个创意方向
    assert:
      hard:
        - tool_called: { name: read_dsl }
        - assistant_contains: 创意方向

outcome:
  require:
    hard_checks: all_pass
```

- `context.tools` 是发给模型的 Tool Schema，`mocks.tools` 是 Runner 收到 Tool Call 后如何返回结果；两者的 Tool 名字集合必须完全一致。
- 需要 Skill 时在 `context.skills` 中按名字声明，并在 `context.tools` 中同时声明 `{builtin: skill}`；模型通过 `skill(name, file?)` 读取正文。
- 需要模拟命令行工具时声明 `{builtin: bash}`，在 `mocks.cli` 中按命令配置输出。
- `steps[].assert.hard` 是确定性检查（`tool_called`、`tool_arguments`、`assistant_contains` 等九种类型）；还可以加 `assert.judge` 做 LLM 打分。

完整 Schema（Skill/Tool/Mock 的全部写法、`bash` 沙箱、Message Injection、Judge 配置等）见[设计文档](docs/agent-skill-test-framework-design.md)。

## 命令行使用

```bash
uv run --project yama yama --plugin dingding-simple --report
```

| 参数 | 含义 |
| --- | --- |
| `paths`（位置参数，可多个） | 显式指定要跑的 Case YAML 路径 |
| `--plugin-root PATH` | 以指定路径作为单一 Plugin Root |
| `--plugin NAME`（可重复） | 按 `yama.toml` 中的 Plugin 名字选择 |
| `--all-plugins` | 运行 `yama.toml` 中配置的全部 Plugin |
| `--response-script PATH` | 用脚本化 LLM 响应回放，不调用真实模型 |
| `--result-dir PATH` | 覆盖产物根目录（默认 `<plugin_root>/.yama/runs`） |
| `--report [PATH]` | 额外生成单文件 HTML 报告（默认 `.yama/reports/latest.html`） |
| `--list` | 只打印匹配到的 Case，不运行 |
| `--no-artifacts` | 不写任何产物文件 |
| `--json` | 输出机器可读 JSON 而不是 Rich 表格 |

`--plugin`/`--all-plugins`/`--plugin-root` 三者互斥；都不提供时默认用当前目录向上搜索到的 `yama.toml` 所在目录作为 Workspace Root（找不到则用 cwd），把该目录当作单一 Plugin Root 运行。
