python-yama 0.1.0__tar.gz

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. python_yama-0.1.0/.github/workflows/publish.yml +28 -0
  2. python_yama-0.1.0/.gitignore +51 -0
  3. python_yama-0.1.0/CLAUDE.md +71 -0
  4. python_yama-0.1.0/LICENSE +21 -0
  5. python_yama-0.1.0/PKG-INFO +98 -0
  6. python_yama-0.1.0/README.md +73 -0
  7. python_yama-0.1.0/docs/agent-skill-test-framework-design.md +2516 -0
  8. python_yama-0.1.0/pyproject.toml +49 -0
  9. python_yama-0.1.0/skills/eval-plugin-with-yama/SKILL.md +163 -0
  10. python_yama-0.1.0/skills/eval-plugin-with-yama/references/case-schema.md +365 -0
  11. python_yama-0.1.0/skills/eval-plugin-with-yama/references/debugging.md +153 -0
  12. python_yama-0.1.0/tests/test_assertions.py +631 -0
  13. python_yama-0.1.0/tests/test_cli.py +300 -0
  14. python_yama-0.1.0/tests/test_cli_shim.py +198 -0
  15. python_yama-0.1.0/tests/test_framework.py +2819 -0
  16. python_yama-0.1.0/tests/test_main_entrypoint.py +39 -0
  17. python_yama-0.1.0/tests/test_mocks.py +521 -0
  18. python_yama-0.1.0/tests/test_public_api.py +71 -0
  19. python_yama-0.1.0/tests/test_report.py +101 -0
  20. python_yama-0.1.0/tests/test_skill_tool.py +122 -0
  21. python_yama-0.1.0/tests/test_workspace.py +200 -0
  22. python_yama-0.1.0/uv.lock +1790 -0
  23. python_yama-0.1.0/yama/__init__.py +31 -0
  24. python_yama-0.1.0/yama/__main__.py +3 -0
  25. python_yama-0.1.0/yama/assertions.py +577 -0
  26. python_yama-0.1.0/yama/cli.py +318 -0
  27. python_yama-0.1.0/yama/llm.py +365 -0
  28. python_yama-0.1.0/yama/loaders/__init__.py +6 -0
  29. python_yama-0.1.0/yama/loaders/case.py +378 -0
  30. python_yama-0.1.0/yama/loaders/common.py +29 -0
  31. python_yama-0.1.0/yama/loaders/tool_loader.py +173 -0
  32. python_yama-0.1.0/yama/mocks.py +383 -0
  33. python_yama-0.1.0/yama/models.py +159 -0
  34. python_yama-0.1.0/yama/report.py +854 -0
  35. python_yama-0.1.0/yama/runner.py +531 -0
  36. python_yama-0.1.0/yama/tools/__init__.py +0 -0
  37. python_yama-0.1.0/yama/tools/base.py +19 -0
  38. python_yama-0.1.0/yama/tools/bash/__init__.py +0 -0
  39. python_yama-0.1.0/yama/tools/bash/_cli_shim.py +71 -0
  40. python_yama-0.1.0/yama/tools/bash/bash.py +285 -0
  41. python_yama-0.1.0/yama/tools/bash/fs.py +530 -0
  42. python_yama-0.1.0/yama/tools/skill/__init__.py +0 -0
  43. python_yama-0.1.0/yama/tools/skill/skill.py +57 -0
  44. python_yama-0.1.0/yama/workspace.py +115 -0
@@ -0,0 +1,28 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ publish:
10
+ runs-on: ubuntu-latest
11
+ environment: pypi
12
+ permissions:
13
+ # Listing any permission resets the rest to none, so contents: read
14
+ # must be granted back for checkout to fetch the (private) repo.
15
+ contents: read
16
+ # Required for PyPI Trusted Publishing (OIDC).
17
+ id-token: write
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+ with:
21
+ # hatch-vcs derives the version from git tags; a shallow clone
22
+ # without tags would produce a wrong dev version.
23
+ fetch-depth: 0
24
+ - uses: astral-sh/setup-uv@v5
25
+ - name: Build sdist and wheel
26
+ run: uv build
27
+ - name: Publish to PyPI
28
+ run: uv publish
@@ -0,0 +1,51 @@
1
+ # Python bytecode and caches
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # Virtual environments
7
+ .venv/
8
+ venv/
9
+ env/
10
+ ENV/
11
+
12
+ # Build and packaging artifacts
13
+ build/
14
+ dist/
15
+ *.egg-info/
16
+ .eggs/
17
+ *.egg
18
+
19
+ # Test, coverage, lint, and type-check caches
20
+ .pytest_cache/
21
+ .coverage
22
+ .coverage.*
23
+ htmlcov/
24
+ coverage.xml
25
+ .tox/
26
+ .nox/
27
+ .mypy_cache/
28
+ .pyright/
29
+ .ruff_cache/
30
+ .hypothesis/
31
+
32
+ # Local environment and secrets
33
+ .env
34
+ .env.*
35
+ !.env.example
36
+
37
+ # Logs and temporary files
38
+ *.log
39
+ *.tmp
40
+ *.swp
41
+ *~
42
+
43
+ # Editors and operating systems
44
+ .idea/
45
+ .vscode/
46
+ .DS_Store
47
+ Thumbs.db
48
+
49
+ # Claude Code local state (settings.json itself is shared/committed)
50
+ .claude/settings.local.json
51
+ .claude/worktrees/
@@ -0,0 +1,71 @@
1
+ # yama
2
+
3
+ Reproducible evaluation runner for tool-using Agent skills (see `README.md` and
4
+ `docs/agent-skill-test-framework-design.md` for the case schema and execution contract).
5
+
6
+ ## Testing
7
+
8
+ - Overall unit test coverage must stay **at or above 80%**. Run:
9
+
10
+ ```bash
11
+ uv run pytest tests/ --cov=yama --cov-report=term-missing
12
+ ```
13
+
14
+ Check the `TOTAL` line at the end of the report. When adding or changing code in
15
+ `yama/`, add or update tests in `tests/` so the total does not drop below 80%.
16
+ - Prefer direct unit tests of pure functions/classes (`yama/assertions.py`,
17
+ `yama/mocks.py`, `yama/workspace.py`, etc.) over building full end-to-end cases;
18
+ reserve end-to-end `ResolvedCase`/`YamaRunner` tests for behavior that only
19
+ emerges from the full pipeline.
20
+ - `tests/test_framework.py` resolves its external `vidmuse-plugins` fixture repo by
21
+ walking up from the test file to find a `vidmuse-plugins` sibling directory
22
+ (not a fixed `parents[N]` depth), so it keeps working from nested git worktrees.
23
+
24
+ ## Documentation
25
+
26
+ - When changing the implementation in `yama/` (case schema, execution contract,
27
+ assertions, mocks, workspace semantics, etc.), update
28
+ `docs/agent-skill-test-framework-design.md` in the same change so the design
29
+ doc never drifts from the code.
30
+ - `README.md` only documents the minimal subset needed to write a basic Case
31
+ and run the CLI (the `context`/`mocks`/`steps`/`outcome` skeleton, and
32
+ `cli.py`'s argument parser). Update `README.md` in the same change whenever
33
+ any of that basic subset changes: CLI flags are added/removed/renamed
34
+ (`cli.py:_parser`), the minimal Case fields shown in the README example
35
+ change meaning or name, or a default path/convention referenced in the
36
+ README (default `SYSTEM.md`, `__evals__/cases/**/*.yaml` collection glob,
37
+ default `.yama/runs` / `.yama/reports/latest.html` locations) changes.
38
+ Everything beyond that basic subset only needs to stay in
39
+ `docs/agent-skill-test-framework-design.md`.
40
+ - When changing the Case syntax (schema fields, mock/assertion/judge
41
+ configuration, path conventions) or the Case execution logic (tool loop,
42
+ step advancement, failure semantics, artifact layout, CLI behavior), update
43
+ `skills/eval-plugin-with-yama/` (`SKILL.md` and its `references/*.md`) in
44
+ the same change so the skill's authoring guidance and failure-debugging
45
+ guidance never drift from the actual behavior.
46
+
47
+ ## Communication
48
+
49
+ - Speak to the user in Chinese (中文).
50
+
51
+ ## Workflow
52
+
53
+ - Do not commit code unless the user explicitly asks you to.
54
+ - Do not push to remote unless the user explicitly asks you to.
55
+ - Do not proactively open a pull request. Only open a PR when the user
56
+ explicitly asks for one.
57
+ - Do not create a git worktree unless the user explicitly allows it. By
58
+ default, develop directly on the current branch.
59
+
60
+ ## Releasing
61
+
62
+ - The package version is derived from git tags by `hatch-vcs`; there is no
63
+ `version` field in `pyproject.toml` to edit. Untagged commits build as
64
+ `+g<hash>` dev versions, which PyPI rejects, so only tagged commits can be
65
+ published.
66
+ - To release: `git tag v<X.Y.Z> && git push origin v<X.Y.Z>` (only when the
67
+ user explicitly asks to release). `.github/workflows/publish.yml` then
68
+ builds the tagged commit and publishes it to PyPI via OIDC trusted
69
+ publishing — no API tokens are involved.
70
+ - Pre-1.0 versioning: bump minor (`0.2.0`) for new features or breaking
71
+ changes (e.g. Case schema changes), patch (`0.1.1`) for bug fixes.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Farmer Sun
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,98 @@
1
+ Metadata-Version: 2.4
2
+ Name: python-yama
3
+ Version: 0.1.0
4
+ Summary: A reproducible evaluation runner for tool-using Agent skills
5
+ Project-URL: Repository, https://github.com/world-sim-dev/yama
6
+ Project-URL: Issues, https://github.com/world-sim-dev/yama/issues
7
+ Author-email: Farmer Sun <podpodiumapp@gmail.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: agent,evaluation,llm,skill,testing
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Topic :: Software Development :: Testing
17
+ Requires-Python: >=3.12
18
+ Requires-Dist: fastapi>=0.139.0
19
+ Requires-Dist: jinja2>=3.1
20
+ Requires-Dist: litellm<2.0,>=1.80
21
+ Requires-Dist: orjson>=3.11.9
22
+ Requires-Dist: pyyaml>=6.0
23
+ Requires-Dist: rich<15.0,>=14.1
24
+ Description-Content-Type: text/markdown
25
+
26
+ # yama
27
+
28
+ `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)。
29
+
30
+ ## 快速开始
31
+
32
+ ```bash
33
+ # 在 Plugin 根目录下直接运行,默认收集 __evals__/cases/**/*.yaml
34
+ cd dingding-simple
35
+ OPENAI_API_KEY=... uv run --project yama yama
36
+
37
+ # 在 Workspace 根目录(存在 yama.toml)按名字指定 Plugin
38
+ OPENAI_API_KEY=... uv run --project yama yama --plugin dingding-simple
39
+ ```
40
+
41
+ ## 编写一个 Case
42
+
43
+ 一个 Case 是一份 YAML 文件,按 `context`(模型看到什么)→ `mocks`(Tool 怎么被执行)→ `steps`(依次发送的用户回合与断言)→ `outcome`(整个 Case 的通过门槛)的结构组织:
44
+
45
+ ```yaml
46
+ context:
47
+ system_prompt: { default: true } # 使用 Plugin 根目录下的 SYSTEM.md
48
+
49
+ tools:
50
+ - file: tools/read-dsl.yaml # Tool Schema,相对 __evals__ 目录解析
51
+
52
+ mocks:
53
+ tools:
54
+ read_dsl:
55
+ respond:
56
+ result:
57
+ visualStyle: { name: 复古胶片 }
58
+
59
+ steps:
60
+ - id: request-directions
61
+ user: 给我几个创意方向
62
+ assert:
63
+ hard:
64
+ - tool_called: { name: read_dsl }
65
+ - assistant_contains: 创意方向
66
+
67
+ outcome:
68
+ require:
69
+ hard_checks: all_pass
70
+ ```
71
+
72
+ - `context.tools` 是发给模型的 Tool Schema,`mocks.tools` 是 Runner 收到 Tool Call 后如何返回结果;两者的 Tool 名字集合必须完全一致。
73
+ - 需要 Skill 时在 `context.skills` 中按名字声明,并在 `context.tools` 中同时声明 `{builtin: skill}`;模型通过 `skill(name, file?)` 读取正文。
74
+ - 需要模拟命令行工具时声明 `{builtin: bash}`,在 `mocks.cli` 中按命令配置输出。
75
+ - `steps[].assert.hard` 是确定性检查(`tool_called`、`tool_arguments`、`assistant_contains` 等九种类型);还可以加 `assert.judge` 做 LLM 打分。
76
+
77
+ 完整 Schema(Skill/Tool/Mock 的全部写法、`bash` 沙箱、Message Injection、Judge 配置等)见[设计文档](docs/agent-skill-test-framework-design.md)。
78
+
79
+ ## 命令行使用
80
+
81
+ ```bash
82
+ uv run --project yama yama --plugin dingding-simple --report
83
+ ```
84
+
85
+ | 参数 | 含义 |
86
+ | --- | --- |
87
+ | `paths`(位置参数,可多个) | 显式指定要跑的 Case YAML 路径 |
88
+ | `--plugin-root PATH` | 以指定路径作为单一 Plugin Root |
89
+ | `--plugin NAME`(可重复) | 按 `yama.toml` 中的 Plugin 名字选择 |
90
+ | `--all-plugins` | 运行 `yama.toml` 中配置的全部 Plugin |
91
+ | `--response-script PATH` | 用脚本化 LLM 响应回放,不调用真实模型 |
92
+ | `--result-dir PATH` | 覆盖产物根目录(默认 `<plugin_root>/.yama/runs`) |
93
+ | `--report [PATH]` | 额外生成单文件 HTML 报告(默认 `.yama/reports/latest.html`) |
94
+ | `--list` | 只打印匹配到的 Case,不运行 |
95
+ | `--no-artifacts` | 不写任何产物文件 |
96
+ | `--json` | 输出机器可读 JSON 而不是 Rich 表格 |
97
+
98
+ `--plugin`/`--all-plugins`/`--plugin-root` 三者互斥;都不提供时默认用当前目录向上搜索到的 `yama.toml` 所在目录作为 Workspace Root(找不到则用 cwd),把该目录当作单一 Plugin Root 运行。
@@ -0,0 +1,73 @@
1
+ # yama
2
+
3
+ `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)。
4
+
5
+ ## 快速开始
6
+
7
+ ```bash
8
+ # 在 Plugin 根目录下直接运行,默认收集 __evals__/cases/**/*.yaml
9
+ cd dingding-simple
10
+ OPENAI_API_KEY=... uv run --project yama yama
11
+
12
+ # 在 Workspace 根目录(存在 yama.toml)按名字指定 Plugin
13
+ OPENAI_API_KEY=... uv run --project yama yama --plugin dingding-simple
14
+ ```
15
+
16
+ ## 编写一个 Case
17
+
18
+ 一个 Case 是一份 YAML 文件,按 `context`(模型看到什么)→ `mocks`(Tool 怎么被执行)→ `steps`(依次发送的用户回合与断言)→ `outcome`(整个 Case 的通过门槛)的结构组织:
19
+
20
+ ```yaml
21
+ context:
22
+ system_prompt: { default: true } # 使用 Plugin 根目录下的 SYSTEM.md
23
+
24
+ tools:
25
+ - file: tools/read-dsl.yaml # Tool Schema,相对 __evals__ 目录解析
26
+
27
+ mocks:
28
+ tools:
29
+ read_dsl:
30
+ respond:
31
+ result:
32
+ visualStyle: { name: 复古胶片 }
33
+
34
+ steps:
35
+ - id: request-directions
36
+ user: 给我几个创意方向
37
+ assert:
38
+ hard:
39
+ - tool_called: { name: read_dsl }
40
+ - assistant_contains: 创意方向
41
+
42
+ outcome:
43
+ require:
44
+ hard_checks: all_pass
45
+ ```
46
+
47
+ - `context.tools` 是发给模型的 Tool Schema,`mocks.tools` 是 Runner 收到 Tool Call 后如何返回结果;两者的 Tool 名字集合必须完全一致。
48
+ - 需要 Skill 时在 `context.skills` 中按名字声明,并在 `context.tools` 中同时声明 `{builtin: skill}`;模型通过 `skill(name, file?)` 读取正文。
49
+ - 需要模拟命令行工具时声明 `{builtin: bash}`,在 `mocks.cli` 中按命令配置输出。
50
+ - `steps[].assert.hard` 是确定性检查(`tool_called`、`tool_arguments`、`assistant_contains` 等九种类型);还可以加 `assert.judge` 做 LLM 打分。
51
+
52
+ 完整 Schema(Skill/Tool/Mock 的全部写法、`bash` 沙箱、Message Injection、Judge 配置等)见[设计文档](docs/agent-skill-test-framework-design.md)。
53
+
54
+ ## 命令行使用
55
+
56
+ ```bash
57
+ uv run --project yama yama --plugin dingding-simple --report
58
+ ```
59
+
60
+ | 参数 | 含义 |
61
+ | --- | --- |
62
+ | `paths`(位置参数,可多个) | 显式指定要跑的 Case YAML 路径 |
63
+ | `--plugin-root PATH` | 以指定路径作为单一 Plugin Root |
64
+ | `--plugin NAME`(可重复) | 按 `yama.toml` 中的 Plugin 名字选择 |
65
+ | `--all-plugins` | 运行 `yama.toml` 中配置的全部 Plugin |
66
+ | `--response-script PATH` | 用脚本化 LLM 响应回放,不调用真实模型 |
67
+ | `--result-dir PATH` | 覆盖产物根目录(默认 `<plugin_root>/.yama/runs`) |
68
+ | `--report [PATH]` | 额外生成单文件 HTML 报告(默认 `.yama/reports/latest.html`) |
69
+ | `--list` | 只打印匹配到的 Case,不运行 |
70
+ | `--no-artifacts` | 不写任何产物文件 |
71
+ | `--json` | 输出机器可读 JSON 而不是 Rich 表格 |
72
+
73
+ `--plugin`/`--all-plugins`/`--plugin-root` 三者互斥;都不提供时默认用当前目录向上搜索到的 `yama.toml` 所在目录作为 Workspace Root(找不到则用 cwd),把该目录当作单一 Plugin Root 运行。