worldevals 0.3.0__py3-none-any.whl
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.
- worldevals/__init__.py +30 -0
- worldevals/catalog.py +90 -0
- worldevals/cli.py +83 -0
- worldevals/py.typed +0 -0
- worldevals-0.3.0.dist-info/METADATA +148 -0
- worldevals-0.3.0.dist-info/RECORD +9 -0
- worldevals-0.3.0.dist-info/WHEEL +4 -0
- worldevals-0.3.0.dist-info/entry_points.txt +2 -0
- worldevals-0.3.0.dist-info/licenses/LICENSE +21 -0
worldevals/__init__.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""WorldEvals — the Inspect Evals for robotics.
|
|
2
|
+
|
|
3
|
+
A curated catalog of physical-AI benchmarks built on
|
|
4
|
+
`Inspect Robots <https://github.com/robocurve/inspect-robots>`_. Each benchmark is its own
|
|
5
|
+
repo (e.g. `KitchenBench <https://github.com/robocurve/kitchenbench>`_); this
|
|
6
|
+
package indexes them and bridges "what exists" with "what's installed".
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from worldevals.catalog import (
|
|
12
|
+
CATALOG,
|
|
13
|
+
Benchmark,
|
|
14
|
+
benchmark_for_task,
|
|
15
|
+
by_tag,
|
|
16
|
+
catalog,
|
|
17
|
+
get,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
__version__ = "0.3.0"
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
"CATALOG",
|
|
24
|
+
"Benchmark",
|
|
25
|
+
"__version__",
|
|
26
|
+
"benchmark_for_task",
|
|
27
|
+
"by_tag",
|
|
28
|
+
"catalog",
|
|
29
|
+
"get",
|
|
30
|
+
]
|
worldevals/catalog.py
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""The WorldEvals catalog — the registry of physical-AI benchmark repos.
|
|
2
|
+
|
|
3
|
+
Each benchmark is its own repository (built on Inspect Robots) that registers its tasks
|
|
4
|
+
via entry points. WorldEvals indexes them so you can discover what exists and how
|
|
5
|
+
to install it. To add a benchmark, append a
|
|
6
|
+
[`Benchmark`][worldevals.catalog.Benchmark] entry here (PR).
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from dataclasses import dataclass
|
|
12
|
+
from typing import Literal
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass(frozen=True)
|
|
16
|
+
class Benchmark:
|
|
17
|
+
"""One benchmark repo in the WorldEvals collection."""
|
|
18
|
+
|
|
19
|
+
name: str
|
|
20
|
+
title: str
|
|
21
|
+
description: str
|
|
22
|
+
repo: str
|
|
23
|
+
install: str
|
|
24
|
+
task_keys: tuple[str, ...]
|
|
25
|
+
tags: tuple[str, ...]
|
|
26
|
+
bimanual: bool
|
|
27
|
+
contributors: tuple[str, ...]
|
|
28
|
+
status: Literal["alpha", "beta", "stable"] = "alpha"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
_KITCHENBENCH_TASKS = (
|
|
32
|
+
"kitchenbench/place_cutlery",
|
|
33
|
+
"kitchenbench/stack",
|
|
34
|
+
"kitchenbench/place_in_rack",
|
|
35
|
+
"kitchenbench/pour_pasta",
|
|
36
|
+
"kitchenbench/open_container",
|
|
37
|
+
"kitchenbench/fold_cloth",
|
|
38
|
+
"kitchenbench/seal_container",
|
|
39
|
+
"kitchenbench/handoff",
|
|
40
|
+
"kitchenbench/sort_cutlery",
|
|
41
|
+
"kitchenbench/scoop_pasta",
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
CATALOG: tuple[Benchmark, ...] = (
|
|
45
|
+
Benchmark(
|
|
46
|
+
name="kitchenbench",
|
|
47
|
+
title="KitchenBench",
|
|
48
|
+
description=(
|
|
49
|
+
"10 bimanual kitchen-manipulation tasks: pick-place, stacking, slotted "
|
|
50
|
+
"insertion, granular pour & tool-scoop, lid open/seal, cloth folding, a "
|
|
51
|
+
"two-arm handover, and a multi-instance cutlery sort."
|
|
52
|
+
),
|
|
53
|
+
repo="https://github.com/robocurve/kitchenbench",
|
|
54
|
+
install=(
|
|
55
|
+
'pip install "inspect-robots @ git+https://github.com/robocurve/inspect-robots@v0.3.0"'
|
|
56
|
+
' && pip install "kitchenbench @ git+https://github.com/robocurve/kitchenbench"'
|
|
57
|
+
),
|
|
58
|
+
task_keys=_KITCHENBENCH_TASKS,
|
|
59
|
+
tags=("kitchen", "bimanual", "manipulation"),
|
|
60
|
+
bimanual=True,
|
|
61
|
+
contributors=("robocurve",),
|
|
62
|
+
status="alpha",
|
|
63
|
+
),
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def catalog() -> tuple[Benchmark, ...]:
|
|
68
|
+
"""All benchmarks in the collection."""
|
|
69
|
+
return CATALOG
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def get(name: str) -> Benchmark:
|
|
73
|
+
"""Look up a benchmark by name; raise `KeyError` if unknown."""
|
|
74
|
+
for benchmark in CATALOG:
|
|
75
|
+
if benchmark.name == name:
|
|
76
|
+
return benchmark
|
|
77
|
+
raise KeyError(f"no benchmark named {name!r}; known: {sorted(b.name for b in CATALOG)}")
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def by_tag(tag: str) -> list[Benchmark]:
|
|
81
|
+
"""All benchmarks carrying ``tag``."""
|
|
82
|
+
return [b for b in CATALOG if tag in b.tags]
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def benchmark_for_task(task_key: str) -> Benchmark | None:
|
|
86
|
+
"""The benchmark that registers ``task_key``, or ``None`` if not in the catalog."""
|
|
87
|
+
for benchmark in CATALOG:
|
|
88
|
+
if task_key in benchmark.task_keys:
|
|
89
|
+
return benchmark
|
|
90
|
+
return None
|
worldevals/cli.py
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""The ``worldevals`` CLI: browse the benchmark catalog and see what's installed."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
from collections.abc import Sequence
|
|
7
|
+
|
|
8
|
+
from worldevals.catalog import benchmark_for_task, by_tag, catalog, get
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
12
|
+
parser = argparse.ArgumentParser(
|
|
13
|
+
prog="worldevals",
|
|
14
|
+
description="WorldEvals — the Inspect Evals for robotics (a benchmark catalog).",
|
|
15
|
+
)
|
|
16
|
+
sub = parser.add_subparsers(dest="command")
|
|
17
|
+
|
|
18
|
+
p_list = sub.add_parser("list", help="list catalogued benchmarks")
|
|
19
|
+
p_list.add_argument("--tag", help="only benchmarks carrying this tag")
|
|
20
|
+
|
|
21
|
+
p_info = sub.add_parser("info", help="show details for one benchmark")
|
|
22
|
+
p_info.add_argument("name")
|
|
23
|
+
|
|
24
|
+
sub.add_parser("tasks", help="Inspect Robots tasks installed locally, by benchmark")
|
|
25
|
+
return parser
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _cmd_list(tag: str | None) -> int:
|
|
29
|
+
benchmarks = by_tag(tag) if tag else list(catalog())
|
|
30
|
+
if not benchmarks:
|
|
31
|
+
print("(no benchmarks)" if not tag else f"(no benchmarks tagged {tag!r})")
|
|
32
|
+
return 0
|
|
33
|
+
for b in benchmarks:
|
|
34
|
+
print(f"{b.name} [{b.status}] {b.title}")
|
|
35
|
+
print(f" {len(b.task_keys)} tasks · tags: {', '.join(b.tags)}")
|
|
36
|
+
return 0
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _cmd_info(name: str) -> int:
|
|
40
|
+
try:
|
|
41
|
+
b = get(name)
|
|
42
|
+
except KeyError as exc:
|
|
43
|
+
print(str(exc))
|
|
44
|
+
return 1
|
|
45
|
+
print(f"{b.title} ({b.name}) [{b.status}]")
|
|
46
|
+
print(f" {b.description}")
|
|
47
|
+
print(f" repo: {b.repo}")
|
|
48
|
+
print(f" install: {b.install}")
|
|
49
|
+
print(f" bimanual: {b.bimanual} tags: {', '.join(b.tags)}")
|
|
50
|
+
print(" tasks:")
|
|
51
|
+
for key in b.task_keys:
|
|
52
|
+
print(f" - {key}")
|
|
53
|
+
return 0
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _cmd_tasks() -> int:
|
|
57
|
+
from inspect_robots.registry import registered
|
|
58
|
+
|
|
59
|
+
tasks = sorted(registered("task"))
|
|
60
|
+
if not tasks:
|
|
61
|
+
print("(no Inspect Robots tasks installed)")
|
|
62
|
+
return 0
|
|
63
|
+
for key in tasks:
|
|
64
|
+
b = benchmark_for_task(key)
|
|
65
|
+
print(f"{key} ← {b.name if b is not None else '—'}")
|
|
66
|
+
return 0
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def main(argv: Sequence[str] | None = None) -> int:
|
|
70
|
+
parser = build_parser()
|
|
71
|
+
args = parser.parse_args(argv)
|
|
72
|
+
if args.command == "list":
|
|
73
|
+
return _cmd_list(args.tag)
|
|
74
|
+
if args.command == "info":
|
|
75
|
+
return _cmd_info(args.name)
|
|
76
|
+
if args.command == "tasks":
|
|
77
|
+
return _cmd_tasks()
|
|
78
|
+
parser.print_help()
|
|
79
|
+
return 0
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
if __name__ == "__main__": # pragma: no cover
|
|
83
|
+
raise SystemExit(main())
|
worldevals/py.typed
ADDED
|
File without changes
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: worldevals
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: The Inspect Evals for robotics — a curated catalog of physical-AI benchmarks built on Inspect Robots.
|
|
5
|
+
Project-URL: Homepage, https://github.com/robocurve/worldevals
|
|
6
|
+
Project-URL: Documentation, https://worldevals.org/
|
|
7
|
+
Project-URL: Framework, https://github.com/robocurve/inspect-robots
|
|
8
|
+
Author: RoboCurve
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: benchmarks,catalog,evaluation,physical-ai,robotics,vla
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: inspect-robots>=0.3
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: mypy>=1.11; extra == 'dev'
|
|
25
|
+
Requires-Dist: pre-commit>=3.5; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
29
|
+
Provides-Extra: docs
|
|
30
|
+
Requires-Dist: mkdocs-gen-files<0.6.1,>=0.5; extra == 'docs'
|
|
31
|
+
Requires-Dist: mkdocs-llmstxt>=0.2; extra == 'docs'
|
|
32
|
+
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
|
|
33
|
+
Requires-Dist: mkdocs>=1.6; extra == 'docs'
|
|
34
|
+
Requires-Dist: mkdocstrings[python]>=0.26; extra == 'docs'
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
<div align="center">
|
|
38
|
+
|
|
39
|
+
# 🌍 WorldEvals
|
|
40
|
+
|
|
41
|
+
**The [Inspect Evals](https://inspect.aisi.org.uk/evals/) for robotics.**
|
|
42
|
+
|
|
43
|
+
A curated catalog of physical-AI / VLA benchmarks built on
|
|
44
|
+
[Inspect Robots](https://github.com/robocurve/inspect-robots).
|
|
45
|
+
|
|
46
|
+
[](https://github.com/robocurve/worldevals/actions/workflows/ci.yml)
|
|
47
|
+
[](LICENSE)
|
|
48
|
+
[](https://github.com/robocurve/worldevals/actions/workflows/ci.yml)
|
|
49
|
+
[](https://github.com/robocurve/inspect-robots)
|
|
50
|
+
|
|
51
|
+
**[📖 Browse the catalog → worldevals.org](https://worldevals.org/)**
|
|
52
|
+
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
[Inspect Robots](https://github.com/robocurve/inspect-robots) is the *framework* (the "Inspect
|
|
56
|
+
AI for robotics"). **WorldEvals is the collection** — but unlike Inspect Evals'
|
|
57
|
+
monorepo, each benchmark here lives in **its own repository** so it owns its
|
|
58
|
+
release cadence, dependencies, hardware notes, and leaderboard. WorldEvals is the
|
|
59
|
+
lightweight index that ties them together: what benchmarks exist, what tasks each
|
|
60
|
+
provides, and how to install them.
|
|
61
|
+
|
|
62
|
+
- `inspect-robots list` tells you what's **installed**.
|
|
63
|
+
- `worldevals list` tells you what **exists** and how to get it.
|
|
64
|
+
|
|
65
|
+
## Benchmarks
|
|
66
|
+
|
|
67
|
+
| Benchmark | Tasks | Tags | Status |
|
|
68
|
+
|---|--:|---|---|
|
|
69
|
+
| [KitchenBench](https://github.com/robocurve/kitchenbench) — 10 bimanual kitchen-manipulation tasks | 10 | kitchen, bimanual, manipulation | alpha |
|
|
70
|
+
|
|
71
|
+
## Install & use
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# Inspect Robots isn't on PyPI yet, so install it from its git tag first:
|
|
75
|
+
pip install "inspect-robots @ git+https://github.com/robocurve/inspect-robots@v0.3.0"
|
|
76
|
+
pip install "worldevals @ git+https://github.com/robocurve/worldevals"
|
|
77
|
+
|
|
78
|
+
worldevals list # all benchmarks
|
|
79
|
+
worldevals list --tag bimanual # filter by tag
|
|
80
|
+
worldevals info kitchenbench # repo, install command, task keys
|
|
81
|
+
worldevals tasks # Inspect Robots tasks installed locally, by benchmark
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Then install a benchmark and run it through Inspect Robots:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
pip install "inspect-robots @ git+https://github.com/robocurve/inspect-robots@v0.3.0"
|
|
88
|
+
pip install "kitchenbench @ git+https://github.com/robocurve/kitchenbench"
|
|
89
|
+
inspect-robots run --task kitchenbench/pour_pasta --policy kitchen_scripted --embodiment kitchen
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Backends (run on real robots)
|
|
93
|
+
|
|
94
|
+
Benchmarks are embodiment-agnostic; **backend adapters** supply a concrete
|
|
95
|
+
`Policy` + `Embodiment` so a benchmark runs on real hardware or a simulator.
|
|
96
|
+
These are their own repos too (not catalog entries):
|
|
97
|
+
|
|
98
|
+
| Adapter | Policy · Embodiment | Stack |
|
|
99
|
+
|---|---|---|
|
|
100
|
+
| [inspect-robots-yam](https://github.com/robocurve/inspect-robots-yam) | `molmoact2` · `yam_arms` | [MolmoAct2](https://github.com/allenai/molmoact2) on [I2RT YAM](https://i2rt.com/products/yam-6-dof-arm) bimanual arms |
|
|
101
|
+
| [inspect-robots-so101](https://github.com/robocurve/inspect-robots-so101) | `lerobot` · `so_arm` | [LeRobot](https://github.com/huggingface/lerobot) policies (ACT, SmolVLA, π0, …) on [SO-ARM](https://github.com/TheRobotStudio/SO-ARM100) (SO-100 / SO-101) follower arms |
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
inspect-robots run --task kitchenbench/pour_pasta --policy molmoact2 --embodiment yam_arms
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Add your benchmark
|
|
108
|
+
|
|
109
|
+
A benchmark is any repo that:
|
|
110
|
+
|
|
111
|
+
1. depends on `inspect-robots`,
|
|
112
|
+
2. defines one or more Inspect Robots `Task`s, and
|
|
113
|
+
3. registers them via `[project.entry-points."inspect_robots.tasks"]` (and, if it ships
|
|
114
|
+
a sim/embodiment or policy, `inspect_robots.embodiments` / `inspect_robots.policies`).
|
|
115
|
+
|
|
116
|
+
To list it here, add a `Benchmark(...)` entry to
|
|
117
|
+
[`src/worldevals/catalog.py`](src/worldevals/catalog.py) and open a PR. A test
|
|
118
|
+
validates every entry (unique name, well-formed repo URL, ≥1 task key). See
|
|
119
|
+
[KitchenBench](https://github.com/robocurve/kitchenbench) as the reference
|
|
120
|
+
implementation.
|
|
121
|
+
|
|
122
|
+
## Development
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
uv venv && uv pip install -e ".[dev]" # inspect_robots resolved from the v0.3.0 tag
|
|
126
|
+
uv run pre-commit install
|
|
127
|
+
uv run pytest --cov # 100% coverage required
|
|
128
|
+
uv run ruff check . && uv run mypy
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Citation
|
|
132
|
+
|
|
133
|
+
If you use WorldEvals in your research, please cite it:
|
|
134
|
+
|
|
135
|
+
```bibtex
|
|
136
|
+
@software{worldevals,
|
|
137
|
+
author = {Robocurve},
|
|
138
|
+
title = {WorldEvals: A curated catalog of physical-AI benchmarks},
|
|
139
|
+
year = {2026},
|
|
140
|
+
url = {https://github.com/robocurve/worldevals},
|
|
141
|
+
version = {0.3.0},
|
|
142
|
+
license = {MIT}
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## License
|
|
147
|
+
|
|
148
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
worldevals/__init__.py,sha256=sEvwQeYg2A3D4-ZEaW3E3lsxbwnlmmp9G-raipazfTI,662
|
|
2
|
+
worldevals/catalog.py,sha256=fQeSsC-oxPL1wy9i-OM00Hs9d5q4mSW9n32zhf91Oj0,2796
|
|
3
|
+
worldevals/cli.py,sha256=p_hoaDm7mbxVKc3dPZnMDHkBRw588FbIMYwMVB9x0fU,2472
|
|
4
|
+
worldevals/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
+
worldevals-0.3.0.dist-info/METADATA,sha256=GbsFGVC45TY2sHI_OgNGTydVtZ_VCmJrjo9AsEmR2pg,6133
|
|
6
|
+
worldevals-0.3.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
7
|
+
worldevals-0.3.0.dist-info/entry_points.txt,sha256=a0l_2SUgpvHlRMgx8BPa3WmnzvnXDfzSFLyn69dHWuA,51
|
|
8
|
+
worldevals-0.3.0.dist-info/licenses/LICENSE,sha256=NaimrZjfDyMR93d5rbHzWsYQ4UrnVsxgIXZui2UHFjU,1066
|
|
9
|
+
worldevals-0.3.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 robocurve
|
|
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.
|