infini-cli 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.
- infini_cli-0.1.0/PKG-INFO +159 -0
- infini_cli-0.1.0/README.md +127 -0
- infini_cli-0.1.0/pyproject.toml +49 -0
- infini_cli-0.1.0/setup.cfg +4 -0
- infini_cli-0.1.0/src/infini/__init__.py +6 -0
- infini_cli-0.1.0/src/infini/__main__.py +4 -0
- infini_cli-0.1.0/src/infini/adapters.py +68 -0
- infini_cli-0.1.0/src/infini/cli.py +287 -0
- infini_cli-0.1.0/src/infini/diff.py +167 -0
- infini_cli-0.1.0/src/infini/engine.py +191 -0
- infini_cli-0.1.0/src/infini/inspect.py +102 -0
- infini_cli-0.1.0/src/infini/mock.py +108 -0
- infini_cli-0.1.0/src/infini/parse.py +207 -0
- infini_cli-0.1.0/src/infini/replay.py +137 -0
- infini_cli-0.1.0/src/infini/schema.json +181 -0
- infini_cli-0.1.0/src/infini/trace.py +178 -0
- infini_cli-0.1.0/src/infini/ui.py +70 -0
- infini_cli-0.1.0/src/infini_cli.egg-info/PKG-INFO +159 -0
- infini_cli-0.1.0/src/infini_cli.egg-info/SOURCES.txt +21 -0
- infini_cli-0.1.0/src/infini_cli.egg-info/dependency_links.txt +1 -0
- infini_cli-0.1.0/src/infini_cli.egg-info/entry_points.txt +2 -0
- infini_cli-0.1.0/src/infini_cli.egg-info/requires.txt +11 -0
- infini_cli-0.1.0/src/infini_cli.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: infini-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: INFINI — the open standard for agent loops. Write a Loopfile, run it on any engine.
|
|
5
|
+
Author: NickAiNYC and INFINI contributors
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/NickAiNYC/infini
|
|
8
|
+
Project-URL: Documentation, https://github.com/NickAiNYC/infini#readme
|
|
9
|
+
Project-URL: Repository, https://github.com/NickAiNYC/infini
|
|
10
|
+
Project-URL: Issues, https://github.com/NickAiNYC/infini/issues
|
|
11
|
+
Keywords: agents,loops,ai,standard,loopfile,infini
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
Requires-Dist: pyyaml>=6.0
|
|
24
|
+
Requires-Dist: jsonschema>=4.20
|
|
25
|
+
Requires-Dist: rich>=13.0
|
|
26
|
+
Requires-Dist: click>=8.1
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
29
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
30
|
+
Provides-Extra: ui
|
|
31
|
+
Requires-Dist: flask>=3.0; extra == "ui"
|
|
32
|
+
|
|
33
|
+
# INFINI CLI
|
|
34
|
+
|
|
35
|
+
The reference implementation of the `infini` command-line tool.
|
|
36
|
+
|
|
37
|
+
> The CLI is the **INFINI Reference Engine**. It conforms to the same Loopfile spec as every other engine. The only asymmetry: it ships first with new spec features, since the spec is developed against it.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Install
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pip install infini-cli
|
|
45
|
+
|
|
46
|
+
# With adapter extras
|
|
47
|
+
pip install infini-cli[hermes,openclaw]
|
|
48
|
+
|
|
49
|
+
# From source
|
|
50
|
+
git clone https://github.com/NickAiNYC/infini
|
|
51
|
+
cd infini/cli && pip install -e .
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Requires Python 3.10+.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Commands
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
infini validate [Loopfile] # check spec compliance
|
|
62
|
+
infini run [Loopfile] # execute a loop (--mock for no API key)
|
|
63
|
+
infini inspect [run_dir] # inspect a trace (--web opens Observatory, coming soon)
|
|
64
|
+
infini replay [run_dir] # time-travel debug from any step
|
|
65
|
+
infini diff [v1] [v2] # semantic diff between loops or traces
|
|
66
|
+
infini ui [trace] # launch the Observatory web app
|
|
67
|
+
infini engines # list detected adapters (reads adapter.yaml)
|
|
68
|
+
infini init [--target] # scaffold a minimal project (Loopfile, loops/, state/, runs/)
|
|
69
|
+
infini new <name> # create a new project scaffold
|
|
70
|
+
infini graph [Loopfile] # render a simple ASCII graph of steps
|
|
71
|
+
infini benchmark [Loopfile] # preview benchmark estimate (real profiling needs a run)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Commands not yet implemented (planned)
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
infini install [loop_ref] # pull from registry (planned — registry not yet live)
|
|
78
|
+
infini publish [Loopfile] # push to registry (planned)
|
|
79
|
+
infini ci [Loopfile] # run loop against fixtures (GitHub Action)
|
|
80
|
+
infini search [query] # search the registry (planned)
|
|
81
|
+
infini migrate [Loopfile] # migrate a Loopfile between spec versions
|
|
82
|
+
infini keys generate # generate a publisher signing keypair
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Mock mode
|
|
86
|
+
|
|
87
|
+
`infini run --mock` simulates LLM calls so you can run any Loopfile
|
|
88
|
+
without an API key. Useful for evaluation, CI, demos, and the conformance
|
|
89
|
+
suite. Mock mode is deterministic: same Loopfile + same seed = same output.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Conformance
|
|
94
|
+
|
|
95
|
+
The CLI implements:
|
|
96
|
+
|
|
97
|
+
| Capability | Status |
|
|
98
|
+
| ---------------- | :----: |
|
|
99
|
+
| Parse Loopfile | ✅ |
|
|
100
|
+
| Run Loop | ✅ |
|
|
101
|
+
| Verify | ✅ |
|
|
102
|
+
| Inspect Trace | ✅ |
|
|
103
|
+
| Replay | ✅ |
|
|
104
|
+
| Diff | ✅ |
|
|
105
|
+
|
|
106
|
+
This makes the CLI the **canonical conformance reference**. If your adapter disagrees with the CLI on a spec edge case, the CLI is right until an RFC says otherwise.
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Architecture
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
cli/
|
|
114
|
+
├── README.md # you are here
|
|
115
|
+
├── pyproject.toml # package metadata
|
|
116
|
+
├── src/infini/
|
|
117
|
+
│ ├── __init__.py
|
|
118
|
+
│ ├── main.py # entrypoint
|
|
119
|
+
│ ├── parse.py # Loopfile parser
|
|
120
|
+
│ ├── validate.py # JSON Schema validator
|
|
121
|
+
│ ├── run.py # reference engine
|
|
122
|
+
│ ├── inspect.py # trace inspector (Loop Observatory)
|
|
123
|
+
│ ├── replay.py # time-travel debugger
|
|
124
|
+
│ ├── diff.py # semantic diff
|
|
125
|
+
│ ├── registry.py # publish/install/search
|
|
126
|
+
│ ├── ci.py # CI mode
|
|
127
|
+
│ ├── migrate.py # spec migration
|
|
128
|
+
│ └── keys.py # signing key management
|
|
129
|
+
└── tests/
|
|
130
|
+
├── conformance/ # spec conformance suite
|
|
131
|
+
├── fixtures/ # example Loopfiles
|
|
132
|
+
└── expected/ # expected trace shapes
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
The full source ships with the next CLI release. This README documents the contract.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## The Loop Observatory
|
|
140
|
+
|
|
141
|
+
`infini inspect <run_dir>` opens the Loop Observatory — the signature feature.
|
|
142
|
+
|
|
143
|
+
The Observatory shows, for any run:
|
|
144
|
+
|
|
145
|
+
- the graph of decisions taken,
|
|
146
|
+
- every verification checkpoint and its verdict,
|
|
147
|
+
- total runtime, token count, and dollar cost,
|
|
148
|
+
- artifacts produced at each step,
|
|
149
|
+
- where the loop failed (if it did), and what was retried,
|
|
150
|
+
- what changed between iterations,
|
|
151
|
+
- governance events (Hermes) and tool calls (OpenClaw) in a swimlane view.
|
|
152
|
+
|
|
153
|
+
The Inspector ships today. The full UI (annotated timeline, cost waterfall, artifact gallery, replay studio) is in preview.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## License
|
|
158
|
+
|
|
159
|
+
MIT. See [repository LICENSE](../LICENSE).
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# INFINI CLI
|
|
2
|
+
|
|
3
|
+
The reference implementation of the `infini` command-line tool.
|
|
4
|
+
|
|
5
|
+
> The CLI is the **INFINI Reference Engine**. It conforms to the same Loopfile spec as every other engine. The only asymmetry: it ships first with new spec features, since the spec is developed against it.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install infini-cli
|
|
13
|
+
|
|
14
|
+
# With adapter extras
|
|
15
|
+
pip install infini-cli[hermes,openclaw]
|
|
16
|
+
|
|
17
|
+
# From source
|
|
18
|
+
git clone https://github.com/NickAiNYC/infini
|
|
19
|
+
cd infini/cli && pip install -e .
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Requires Python 3.10+.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Commands
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
infini validate [Loopfile] # check spec compliance
|
|
30
|
+
infini run [Loopfile] # execute a loop (--mock for no API key)
|
|
31
|
+
infini inspect [run_dir] # inspect a trace (--web opens Observatory, coming soon)
|
|
32
|
+
infini replay [run_dir] # time-travel debug from any step
|
|
33
|
+
infini diff [v1] [v2] # semantic diff between loops or traces
|
|
34
|
+
infini ui [trace] # launch the Observatory web app
|
|
35
|
+
infini engines # list detected adapters (reads adapter.yaml)
|
|
36
|
+
infini init [--target] # scaffold a minimal project (Loopfile, loops/, state/, runs/)
|
|
37
|
+
infini new <name> # create a new project scaffold
|
|
38
|
+
infini graph [Loopfile] # render a simple ASCII graph of steps
|
|
39
|
+
infini benchmark [Loopfile] # preview benchmark estimate (real profiling needs a run)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Commands not yet implemented (planned)
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
infini install [loop_ref] # pull from registry (planned — registry not yet live)
|
|
46
|
+
infini publish [Loopfile] # push to registry (planned)
|
|
47
|
+
infini ci [Loopfile] # run loop against fixtures (GitHub Action)
|
|
48
|
+
infini search [query] # search the registry (planned)
|
|
49
|
+
infini migrate [Loopfile] # migrate a Loopfile between spec versions
|
|
50
|
+
infini keys generate # generate a publisher signing keypair
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Mock mode
|
|
54
|
+
|
|
55
|
+
`infini run --mock` simulates LLM calls so you can run any Loopfile
|
|
56
|
+
without an API key. Useful for evaluation, CI, demos, and the conformance
|
|
57
|
+
suite. Mock mode is deterministic: same Loopfile + same seed = same output.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Conformance
|
|
62
|
+
|
|
63
|
+
The CLI implements:
|
|
64
|
+
|
|
65
|
+
| Capability | Status |
|
|
66
|
+
| ---------------- | :----: |
|
|
67
|
+
| Parse Loopfile | ✅ |
|
|
68
|
+
| Run Loop | ✅ |
|
|
69
|
+
| Verify | ✅ |
|
|
70
|
+
| Inspect Trace | ✅ |
|
|
71
|
+
| Replay | ✅ |
|
|
72
|
+
| Diff | ✅ |
|
|
73
|
+
|
|
74
|
+
This makes the CLI the **canonical conformance reference**. If your adapter disagrees with the CLI on a spec edge case, the CLI is right until an RFC says otherwise.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Architecture
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
cli/
|
|
82
|
+
├── README.md # you are here
|
|
83
|
+
├── pyproject.toml # package metadata
|
|
84
|
+
├── src/infini/
|
|
85
|
+
│ ├── __init__.py
|
|
86
|
+
│ ├── main.py # entrypoint
|
|
87
|
+
│ ├── parse.py # Loopfile parser
|
|
88
|
+
│ ├── validate.py # JSON Schema validator
|
|
89
|
+
│ ├── run.py # reference engine
|
|
90
|
+
│ ├── inspect.py # trace inspector (Loop Observatory)
|
|
91
|
+
│ ├── replay.py # time-travel debugger
|
|
92
|
+
│ ├── diff.py # semantic diff
|
|
93
|
+
│ ├── registry.py # publish/install/search
|
|
94
|
+
│ ├── ci.py # CI mode
|
|
95
|
+
│ ├── migrate.py # spec migration
|
|
96
|
+
│ └── keys.py # signing key management
|
|
97
|
+
└── tests/
|
|
98
|
+
├── conformance/ # spec conformance suite
|
|
99
|
+
├── fixtures/ # example Loopfiles
|
|
100
|
+
└── expected/ # expected trace shapes
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
The full source ships with the next CLI release. This README documents the contract.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## The Loop Observatory
|
|
108
|
+
|
|
109
|
+
`infini inspect <run_dir>` opens the Loop Observatory — the signature feature.
|
|
110
|
+
|
|
111
|
+
The Observatory shows, for any run:
|
|
112
|
+
|
|
113
|
+
- the graph of decisions taken,
|
|
114
|
+
- every verification checkpoint and its verdict,
|
|
115
|
+
- total runtime, token count, and dollar cost,
|
|
116
|
+
- artifacts produced at each step,
|
|
117
|
+
- where the loop failed (if it did), and what was retried,
|
|
118
|
+
- what changed between iterations,
|
|
119
|
+
- governance events (Hermes) and tool calls (OpenClaw) in a swimlane view.
|
|
120
|
+
|
|
121
|
+
The Inspector ships today. The full UI (annotated timeline, cost waterfall, artifact gallery, replay studio) is in preview.
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## License
|
|
126
|
+
|
|
127
|
+
MIT. See [repository LICENSE](../LICENSE).
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "infini-cli"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "INFINI — the open standard for agent loops. Write a Loopfile, run it on any engine."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [{ name = "NickAiNYC and INFINI contributors" }]
|
|
13
|
+
keywords = ["agents", "loops", "ai", "standard", "loopfile", "infini"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.10",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Topic :: Software Development :: Libraries",
|
|
24
|
+
]
|
|
25
|
+
dependencies = [
|
|
26
|
+
"pyyaml>=6.0",
|
|
27
|
+
"jsonschema>=4.20",
|
|
28
|
+
"rich>=13.0",
|
|
29
|
+
"click>=8.1",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.optional-dependencies]
|
|
33
|
+
dev = ["pytest>=7.0", "pytest-cov"]
|
|
34
|
+
ui = ["flask>=3.0"]
|
|
35
|
+
|
|
36
|
+
[project.scripts]
|
|
37
|
+
infini = "infini.cli:main"
|
|
38
|
+
|
|
39
|
+
[project.urls]
|
|
40
|
+
Homepage = "https://github.com/NickAiNYC/infini"
|
|
41
|
+
Documentation = "https://github.com/NickAiNYC/infini#readme"
|
|
42
|
+
Repository = "https://github.com/NickAiNYC/infini"
|
|
43
|
+
Issues = "https://github.com/NickAiNYC/infini/issues"
|
|
44
|
+
|
|
45
|
+
[tool.setuptools.packages.find]
|
|
46
|
+
where = ["src"]
|
|
47
|
+
|
|
48
|
+
[tool.setuptools.package-data]
|
|
49
|
+
infini = ["schema.json"]
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""Adapter discovery and capability metadata.
|
|
2
|
+
|
|
3
|
+
Scans the adapters/ directory for adapter.yaml manifests and reports
|
|
4
|
+
actual capabilities (parse, run, verify, inspect, replay, diff) instead
|
|
5
|
+
of just directory names.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Optional
|
|
11
|
+
|
|
12
|
+
import yaml
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def find_adapters_dir(start: Optional[Path] = None) -> Optional[Path]:
|
|
16
|
+
"""Search upwards from start (or cwd) for an adapters/ directory."""
|
|
17
|
+
p = Path(start or Path.cwd()).resolve()
|
|
18
|
+
root = p.anchor
|
|
19
|
+
while True:
|
|
20
|
+
candidate = p / "adapters"
|
|
21
|
+
if candidate.is_dir():
|
|
22
|
+
return candidate
|
|
23
|
+
if str(p) == root:
|
|
24
|
+
return None
|
|
25
|
+
p = p.parent
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def load_adapter_manifest(adapter_dir: Path) -> dict | None:
|
|
29
|
+
"""Load an adapter's adapter.yaml manifest. Returns None if not found."""
|
|
30
|
+
manifest_path = adapter_dir / "adapter.yaml"
|
|
31
|
+
if not manifest_path.exists():
|
|
32
|
+
return None
|
|
33
|
+
try:
|
|
34
|
+
with manifest_path.open("r", encoding="utf-8") as fh:
|
|
35
|
+
data = yaml.safe_load(fh)
|
|
36
|
+
return data if isinstance(data, dict) else None
|
|
37
|
+
except Exception:
|
|
38
|
+
return None
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def detect_adapters(base: Optional[Path] = None) -> list[dict]:
|
|
42
|
+
"""Scan for adapters and return their manifests.
|
|
43
|
+
|
|
44
|
+
Returns a list of dicts, each with at minimum:
|
|
45
|
+
- name: adapter directory name
|
|
46
|
+
- path: absolute path to the adapter directory
|
|
47
|
+
- manifest: the parsed adapter.yaml (or None if no manifest)
|
|
48
|
+
- capabilities: list of supported capability strings (from manifest, or [])
|
|
49
|
+
"""
|
|
50
|
+
adapters_dir = find_adapters_dir(base)
|
|
51
|
+
if not adapters_dir:
|
|
52
|
+
return []
|
|
53
|
+
|
|
54
|
+
results = []
|
|
55
|
+
for p in sorted(adapters_dir.iterdir()):
|
|
56
|
+
if not p.is_dir():
|
|
57
|
+
continue
|
|
58
|
+
manifest = load_adapter_manifest(p)
|
|
59
|
+
caps = []
|
|
60
|
+
if manifest and isinstance(manifest.get("capabilities"), dict):
|
|
61
|
+
caps = [k for k, v in manifest["capabilities"].items() if v is True]
|
|
62
|
+
results.append({
|
|
63
|
+
"name": p.name,
|
|
64
|
+
"path": str(p),
|
|
65
|
+
"manifest": manifest,
|
|
66
|
+
"capabilities": caps,
|
|
67
|
+
})
|
|
68
|
+
return results
|