kennet 0.1.30__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.
- kennet-0.1.30.dist-info/METADATA +512 -0
- kennet-0.1.30.dist-info/RECORD +20 -0
- kennet-0.1.30.dist-info/WHEEL +4 -0
- kennet-0.1.30.dist-info/entry_points.txt +2 -0
- kennet-0.1.30.dist-info/licenses/LICENSE +202 -0
- metaphi/__init__.py +3 -0
- metaphi/__main__.py +5 -0
- metaphi/accounts.py +510 -0
- metaphi/admin.py +144 -0
- metaphi/agents.py +617 -0
- metaphi/cli.py +1821 -0
- metaphi/codebase_profile.py +493 -0
- metaphi/config.py +142 -0
- metaphi/delivery.py +465 -0
- metaphi/errors.py +108 -0
- metaphi/runs.py +567 -0
- metaphi/signature.py +151 -0
- metaphi/skill.py +440 -0
- metaphi/twin.py +366 -0
- metaphi/update.py +552 -0
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: kennet
|
|
3
|
+
Version: 0.1.30
|
|
4
|
+
Summary: The command line for Kennet, Metaphi AI's RL infrastructure.
|
|
5
|
+
License-Expression: Apache-2.0
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Requires-Dist: httpx>=0.28
|
|
9
|
+
Provides-Extra: dev
|
|
10
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
11
|
+
Requires-Dist: respx>=0.22; extra == 'dev'
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# kennet
|
|
15
|
+
|
|
16
|
+
The command line for Kennet, Metaphi AI's RL infrastructure. Sign in and twin agent traces.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
curl -fsSL https://github.com/metaphi-labs/kennet-cli/releases/latest/download/install.sh | sh
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
macOS and Linux, x86_64 and arm64, no root; it needs `ssh-keygen` (OpenSSH), which both have. It checks that the
|
|
25
|
+
latest release's `checksums.txt` is signed by Metaphi AI's release key, that the binary matches it and that it
|
|
26
|
+
starts, then puts it in `~/.local/share/kennet/versions/<version>/` with `~/.local/bin/kennet` (or
|
|
27
|
+
`$KENNET_INSTALL_DIR/kennet`) a symlink to it. It says the line to add if that directory is not on your `PATH`, and
|
|
28
|
+
at a terminal, asks before setting Kennet up in the coding agents it finds (`kennet agents install`, below; the
|
|
29
|
+
answer defaults to no). It never touches an agent's configuration in CI or without a terminal to ask at, as in a
|
|
30
|
+
container or a sandbox image; `KENNET_SETUP_AGENTS=1` answers yes ahead of time, `0` no. Run it again to upgrade; a plain-file install from an
|
|
31
|
+
earlier version is moved to this layout. The binary then keeps itself current (below).
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
brew install metaphi-labs/tap/kennet # Homebrew, macOS and Linux
|
|
35
|
+
pip install kennet # Python 3.10+, with the library
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Or download the binary for your platform from the
|
|
39
|
+
[latest release](https://github.com/metaphi-labs/kennet-cli/releases/latest), and check `checksums.txt.sig`
|
|
40
|
+
(`ssh-keygen -Y verify -n kennet-release`, the key is in `install.sh`) and `checksums.txt`. A binary put there by
|
|
41
|
+
hand does not update itself; the notice names install.sh.
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
### Staying current
|
|
45
|
+
|
|
46
|
+
`kennet --version` prints the version. Once a day `kennet` looks at the releases, on a thread that never holds a
|
|
47
|
+
command up, and when a newer one is out says so once, on stderr after the command's output, with the upgrade command
|
|
48
|
+
for how this copy was installed:
|
|
49
|
+
|
|
50
|
+
| Installed with | Upgrade |
|
|
51
|
+
| --- | --- |
|
|
52
|
+
| `install.sh` | nothing: it updates itself (below), or `kennet update` now |
|
|
53
|
+
| Homebrew | `brew upgrade metaphi-labs/tap/kennet` |
|
|
54
|
+
| `pip`, `pipx`, `uv tool` | `pip install -U kennet`, `pipx upgrade kennet`, `uv tool upgrade kennet` (`metaphi-ai` for a copy installed under that name) |
|
|
55
|
+
| a release binary put somewhere by hand | the install.sh line above |
|
|
56
|
+
|
|
57
|
+
The notice is never shown under `--json`, when stderr is not a terminal, in CI (`CI` set), or with
|
|
58
|
+
`KENNET_NO_UPDATE_NOTIFIER=1`, and at most once a day.
|
|
59
|
+
|
|
60
|
+
What install.sh installed updates itself in the background, as Claude Code does. The new version goes in a
|
|
61
|
+
directory of its own, only once its `checksums.txt` carries Metaphi AI's release signature, its archive matches,
|
|
62
|
+
and it answers `--version`; then the `kennet` symlink is flipped to it in one rename. A command already running
|
|
63
|
+
keeps running on its own version, and old versions are removed once nothing runs them (the last two are kept).
|
|
64
|
+
Downloads go to GitHub only. It never touches a Homebrew or pip install, is off in CI, and
|
|
65
|
+
`KENNET_DISABLE_AUTOUPDATE=1` turns it off for a pinned version. A failure says nothing on screen; it is a line in
|
|
66
|
+
`~/.config/metaphi/update.log`. `kennet update` looks and installs now, or prints the command for any other
|
|
67
|
+
install; when it cannot, it says why in one line with the next step (`update_unreachable` is worth a retry; a
|
|
68
|
+
signature or checksum refusal is not).
|
|
69
|
+
|
|
70
|
+
When the service no longer serves your version, every command fails with `upgrade_required` (exit 5), and
|
|
71
|
+
`next_step` is the upgrade command above.
|
|
72
|
+
|
|
73
|
+
## Quickstart (2 minutes)
|
|
74
|
+
|
|
75
|
+
```sh
|
|
76
|
+
kennet login # opens the browser; confirm the code you see in the terminal
|
|
77
|
+
kennet twin trace.json # writes trace.twin.json
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Working through a coding agent? `kennet agents install`, then ask it to twin the file: see
|
|
81
|
+
[Driving it from an agent](#driving-it-from-an-agent).
|
|
82
|
+
|
|
83
|
+
`kennet login` signs you in as yourself and hands this machine your organization's keys: a live key (`mai_sk_...`)
|
|
84
|
+
and a test key (`mai_sk_test_...`). They are kept in the config file (`~/.config/metaphi/config.json`, mode 600) and are never printed. No OS keychain is used: it prompts a person, and an agent cannot answer. Logging in again
|
|
85
|
+
replaces them; `kennet logout` revokes them. If your organization has no twinning access yet, the sign-in still
|
|
86
|
+
works and says why no key was saved.
|
|
87
|
+
|
|
88
|
+
`kennet twin trace.json --test` runs on the test key. Test runs go through the same pipeline but cost nothing; files
|
|
89
|
+
can be at most 2 MiB and an organization gets one test run in all, so use it on a representative file. Test twins and live twins never see each other.
|
|
90
|
+
|
|
91
|
+
## Driving it from an agent
|
|
92
|
+
|
|
93
|
+
```sh
|
|
94
|
+
kennet agents install # once per machine: every coding agent here now knows this CLI and Kennet's tools
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
That puts two things in each harness it finds on the machine (by its command on the `PATH` or its config
|
|
98
|
+
directory): the `kennet` skill, where that harness reads skills, and Kennet's MCP server
|
|
99
|
+
(`https://kennet.metaphi.ai/mcp/`, for authoring tasks), the way that harness takes one. A person's own config goes
|
|
100
|
+
through the harness's own `mcp add` where it has one that does not stop to sign in, else its config file; `--project` writes this repository's files instead, to commit
|
|
101
|
+
for a team, at the root of the repository you are in (never your home directory).
|
|
102
|
+
|
|
103
|
+
| Harness | Skill (you / `--project`) | MCP server (you / `--project`) | Sign in |
|
|
104
|
+
| --- | --- | --- | --- |
|
|
105
|
+
| Claude Code | `~/.claude/skills` / `.claude/skills` | `claude mcp add --scope user` / `.mcp.json` | `claude mcp login kennet` |
|
|
106
|
+
| Codex | `~/.agents/skills` / `.agents/skills` | `~/.codex/config.toml` / `.codex/config.toml` | `codex mcp login kennet` |
|
|
107
|
+
| Hum | `~/.hum/skills` / `.agents/skills` | `hum mcp add` / `.hum/config.toml` | `hum mcp login kennet` |
|
|
108
|
+
| Gemini CLI | `~/.agents/skills` / `.agents/skills` | `gemini mcp add --scope user` / `.gemini/settings.json` | `/mcp auth kennet` |
|
|
109
|
+
| GitHub Copilot CLI | `~/.agents/skills` / `.agents/skills` | `copilot mcp add` / `.mcp.json` | `/mcp auth kennet` |
|
|
110
|
+
| Cursor | `~/.agents/skills` / `.agents/skills` | `~/.cursor/mcp.json` / `.cursor/mcp.json` | Cursor's MCP settings |
|
|
111
|
+
| opencode | `~/.agents/skills` / `.agents/skills` | `$XDG_CONFIG_HOME/opencode/opencode.json[c]` (or `$OPENCODE_CONFIG`) / `opencode.json[c]` | `opencode mcp auth kennet` |
|
|
112
|
+
|
|
113
|
+
A folder several harnesses read (`~/.agents/skills`, the [Agent Skills](https://agentskills.io) standard's, and
|
|
114
|
+
`.mcp.json`) is written once. `--harness <name>` (repeatable: `claude`, `codex`, `hum`, `gemini`, `copilot`,
|
|
115
|
+
`cursor`, `opencode`) picks harnesses instead of every one found. Running it again changes nothing. Nothing of
|
|
116
|
+
anyone else's is replaced: a skill file kennet did not write stays (`--force` replaces it), and a server named
|
|
117
|
+
`kennet` that kennet did not add stays as it is, and a config file that does not parse (or would not, with the
|
|
118
|
+
server added) is not written: the row says what to add to it by hand. `kennet agents remove` takes away exactly what
|
|
119
|
+
install added: a folder or file another installed harness still reads stays until that one is removed too, and a
|
|
120
|
+
file is deleted only when kennet made it. `kennet agents list` says, per harness, what is there. With `--json` each
|
|
121
|
+
harness is a row: `skill_state` (`written`, `kept`), `mcp` (`added`, `installed`, `present`, `skipped` with
|
|
122
|
+
`mcp_detail`) and `sign_in`; `next_step` is the first `sign_in` that is a command. When no harness got either
|
|
123
|
+
piece, it fails (exit 1, `nothing_installed`) with the rows beside the error.
|
|
124
|
+
|
|
125
|
+
Then ask the agent for what you want: "twin `trace.jsonl` before I send it to the vendor". The skill is a pointer:
|
|
126
|
+
it tells the agent to run `kennet skill show`, which prints the guide for the version installed, so the guide never
|
|
127
|
+
goes stale. Any other agent can be handed the output of `kennet skill show`. `kennet skill install` is the same as
|
|
128
|
+
`kennet agents install`.
|
|
129
|
+
|
|
130
|
+
The CLI is made to be run by a coding agent (Claude Code and the like) as much as typed. Away from a terminal
|
|
131
|
+
nothing waits on a question, and every command takes `--json`: stdout is then the result, or the error object,
|
|
132
|
+
alone, and progress goes to stderr. An error that one command clears names it: `Next: <command>` on stderr,
|
|
133
|
+
`next_step` in the JSON.
|
|
134
|
+
|
|
135
|
+
```sh
|
|
136
|
+
kennet login --json # {"verification_uri", "user_code", "expires_in", "next_step": "kennet login --complete"}
|
|
137
|
+
# the person opens the page and confirms the code
|
|
138
|
+
kennet login --complete # waits for the approval (60 s away from a terminal) and saves the keys; safe to run again
|
|
139
|
+
kennet whoami --json # asks the servers: email, organization, balance, and whether each key works
|
|
140
|
+
kennet twin trace.json --no-wait --json # {"id", "status", "next_step": "kennet twins wait twin_..."}
|
|
141
|
+
kennet twins wait twin_... --json # {"output", "id"} once it ends
|
|
142
|
+
kennet twins list --json # the organization's twins, newest first
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Away from a terminal `kennet login` is `--no-wait` by itself: it prints the page and the code and returns, so the
|
|
146
|
+
agent can show them to its person. `--wait` keeps the old behaviour, one call that waits for the approval.
|
|
147
|
+
`--json` never opens a browser: it implies `--no-browser`, so a program's call never opens a tab on someone's
|
|
148
|
+
screen.
|
|
149
|
+
|
|
150
|
+
Whatever goes wrong ends in one line on stderr and a next step, never a traceback, and under `--json` in the error
|
|
151
|
+
object. A request that never got an answer is `network` (`retryable`, exit 4): `error: can't reach
|
|
152
|
+
app.metaphi.ai: the connection timed out`. Anything the CLI did not expect is `internal` (exit 1): one line,
|
|
153
|
+
and the path of the debug log (`~/.config/metaphi/debug.log`) to report it with, beside `kennet --version`.
|
|
154
|
+
|
|
155
|
+
A twin started is the service's, not the terminal's. Ctrl-C, a closed session or `--timeout` stop the waiting, never
|
|
156
|
+
the twin, and say how to come back: `kennet twins wait <id>` (add `--test` for a test twin), from any machine
|
|
157
|
+
holding the organization's key.
|
|
158
|
+
|
|
159
|
+
## Use it from your servers
|
|
160
|
+
|
|
161
|
+
A server or CI job has no browser: an owner or admin makes it a key of its own, with `kennet keys create <name>`
|
|
162
|
+
(below) or in the console, and hands it over as a secret.
|
|
163
|
+
|
|
164
|
+
```sh
|
|
165
|
+
export METAPHI_API_KEY=mai_sk_...
|
|
166
|
+
kennet twin trace.json -o out.json --json
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
`METAPHI_API_KEY` overrides whatever is saved. A key you already have can also be saved with
|
|
170
|
+
`kennet login --with-api-key`, which reads it from stdin (or prompts without echo), so it never lands in your shell
|
|
171
|
+
history or the process list.
|
|
172
|
+
|
|
173
|
+
One trace file in, one twinned file out, in the same format. `--json` prints `{"output", "id"}` on stdout, with
|
|
174
|
+
progress on stderr. Or from Python:
|
|
175
|
+
|
|
176
|
+
```python
|
|
177
|
+
from pathlib import Path
|
|
178
|
+
from metaphi.twin import twin
|
|
179
|
+
|
|
180
|
+
result = twin(Path("trace.json"), Path("out.json"), api_key="mai_sk_...")
|
|
181
|
+
result["output"] # where the twinned trace was written
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
One key per environment (`prod`, `staging`) or per customer is a good default. Revoking one stops only that key.
|
|
185
|
+
|
|
186
|
+
### Twin options
|
|
187
|
+
|
|
188
|
+
| Flag | What it does |
|
|
189
|
+
| --- | --- |
|
|
190
|
+
| `-o, --output` | Where the twinned trace goes. Default: `<name>.twin<ext>` beside the input. |
|
|
191
|
+
| `--out <dir>` | The directory the twin goes in, as `<name>.twin<ext>`; made if missing. |
|
|
192
|
+
| `--key-file <path>` | A file holding the consistency key (64 hex characters). The same key gives a person the same stand-in in every trace, so a corpus stays consistent. `KENNET_CONSISTENCY_KEY` is read when no file is named. Default: a fresh key per trace. (`--key <64 hex>` takes it as an argument, where the process list shows it.) |
|
|
193
|
+
| `--confidential <org>` | Replaces an organization even though it is public, e.g. your customer. Repeatable. |
|
|
194
|
+
| `--test` | Runs on the test key `kennet login` saved: free, small, apart from live twins. |
|
|
195
|
+
| `--no-wait` | Starts the twin and returns its id; `kennet twins wait <id>` comes back for it. |
|
|
196
|
+
| `--timeout <seconds>` | How long to wait for the twin. The twin goes on past it. |
|
|
197
|
+
|
|
198
|
+
The organization key comes from `METAPHI_API_KEY`, then the saved key. (`--api-key` still works but is deprecated: an
|
|
199
|
+
argument is visible in shell history and to other processes.)
|
|
200
|
+
|
|
201
|
+
People, private organizations, accounts and secrets are always replaced, each with one consistent synthetic value of
|
|
202
|
+
the same kind, and the trace keeps its structure. An adversarial pass then reads the output for anything still real.
|
|
203
|
+
|
|
204
|
+
### Errors
|
|
205
|
+
|
|
206
|
+
Every error from the service carries a stable `code`. Switch on the code or the exception class, never on the
|
|
207
|
+
message. On a failure the CLI prints:
|
|
208
|
+
|
|
209
|
+
```
|
|
210
|
+
error: This organization's prepaid balance is used up; add credits to continue. Nothing was started. (code: out_of_credit, request: req_5f1c...)
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
With `--json`, stdout also gets the error object:
|
|
214
|
+
`{"error": {"type", "code", "message", "retryable", "next_step", "request_id"}}`, plus `run_id` when a run failed,
|
|
215
|
+
`action_url` when a page fixes it and `retry_after_s` when the service said how long to wait. `next_step` is the
|
|
216
|
+
command that clears the error, or `null` when none does. Quote the `request_id` to support.
|
|
217
|
+
|
|
218
|
+
The exit status says what kind of end it was:
|
|
219
|
+
|
|
220
|
+
| Exit | Meaning |
|
|
221
|
+
| --- | --- |
|
|
222
|
+
| 0 | Done. |
|
|
223
|
+
| 1 | Failed. |
|
|
224
|
+
| 2 | The command line was wrong. |
|
|
225
|
+
| 3 | A sign-in or a key is needed (`auth_error`). |
|
|
226
|
+
| 4 | The same call may work later: the service is unavailable, a limit is reached, or a wait ran out. |
|
|
227
|
+
| 5 | This version is too old for the service (`upgrade_required`); `next_step` upgrades it. |
|
|
228
|
+
|
|
229
|
+
A request that fails in transit or with a retryable error is sent again at most twice, within 5 seconds in all;
|
|
230
|
+
a longer `Retry-After` is handed back as `retry_after_s`, not waited out.
|
|
231
|
+
|
|
232
|
+
From Python, each error `type` raises its own class from `metaphi.errors`. All of them subclass `MetaphiError`:
|
|
233
|
+
|
|
234
|
+
```python
|
|
235
|
+
from pathlib import Path
|
|
236
|
+
from metaphi.errors import BillingError, MetaphiError, RateLimitError
|
|
237
|
+
from metaphi.twin import twin
|
|
238
|
+
|
|
239
|
+
try:
|
|
240
|
+
twin(Path("trace.json"))
|
|
241
|
+
except BillingError: # out_of_credit
|
|
242
|
+
... # add credit: `kennet credits buy`
|
|
243
|
+
except RateLimitError as e: # rate_limited_concurrent, rate_limited_daily
|
|
244
|
+
... # e.retryable is True: try again when a run ends
|
|
245
|
+
except MetaphiError as e:
|
|
246
|
+
print(e.code, e.request_id, e.retryable)
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
| Class | `type` | Codes, for example |
|
|
250
|
+
| --- | --- | --- |
|
|
251
|
+
| `BillingError` | `billing_error` | `out_of_credit` |
|
|
252
|
+
| `AuthError` | `auth_error` | `no_organization` |
|
|
253
|
+
| `RateLimitError` | `rate_limit_error` | `rate_limited_concurrent`, `rate_limited_daily` |
|
|
254
|
+
| `InvalidRequestError` | `invalid_request_error` | `invalid_key`, `upload_already_run`, `task_not_found` |
|
|
255
|
+
| `RunError` | `run_error` | `twin_unclean`, `not_text`, `too_large`, `session_failed`, `budget_exceeded` |
|
|
256
|
+
| `IdempotencyError` | `idempotency_error` | `idempotency_key_reused`, `idempotency_key_in_use` |
|
|
257
|
+
| `APIError` | `api_error` | `unavailable`, `balance_unavailable`, `run_unavailable` |
|
|
258
|
+
|
|
259
|
+
`retryable` says whether making the same call again later may succeed. For a failed run, it means uploading the same
|
|
260
|
+
trace again.
|
|
261
|
+
|
|
262
|
+
The CLI says a few errors itself, each with the command that clears it as `next_step`. They are `auth_error`s,
|
|
263
|
+
but for the last:
|
|
264
|
+
|
|
265
|
+
| Code | When | `next_step` |
|
|
266
|
+
| --- | --- | --- |
|
|
267
|
+
| `not_signed_in` | no sign-in on this machine, or the server has ended it | `kennet login` |
|
|
268
|
+
| `authorization_pending` | `login --complete` returned before the code was approved (`retryable`) | `kennet login --complete` |
|
|
269
|
+
| `no_api_key` | signed in, but the sign-in was handed no key; the message says why, and `reason` which it is (below). Keys come with a sign-in, so `kennet login` picks them up once the organization has access | `kennet org join <org>` when an organization has invited you (`invitation_pending`); `kennet org create <name>` when you are in no organization and none has; `null` when you were taken out of yours (`removed`: an owner of it adds you back), while yours waits for approval, and from `login` itself; else `kennet login` |
|
|
270
|
+
| `not_manager` | `kennet org members` or `kennet keys` by a person in the organization who is not its owner or admin; the message says their role | `null` |
|
|
271
|
+
| `confirmation_required` | `kennet keys revoke` away from a terminal, or under `--json`, without `--yes` | the same revoke, by id, with `--yes` |
|
|
272
|
+
| `no_key`, `ambiguous_key` | `kennet keys revoke` names no live key, or a name several live keys share | `kennet keys list`; the revoke of one by id |
|
|
273
|
+
| `secret_destination_required` | `kennet keys create --json` without `--show-secret`: nothing is made | the pipe form |
|
|
274
|
+
| `name_taken`, `scope_not_held`, `too_many_keys` | `kennet keys create` with a name a live key holds, a scope the organization does not hold, or at its cap of live keys | `null`; `null`; `kennet keys list` |
|
|
275
|
+
| `test_runs_used` | `--test` once the organization's free test run is spent (exit 1) | the same `kennet twin <file>` and flags, live; `--api-key` and `--key` are left out |
|
|
276
|
+
| `no_invitation` | `kennet org join` found no open invitation from that organization: it expired or was taken back | `null` |
|
|
277
|
+
| `invitation_for_another_address` | the invitation `kennet org join` names was sent to another address than the one signed in: `kennet logout`, then `kennet login` as that address | `null` |
|
|
278
|
+
| `unreachable` (`api_error`) | the twin service did not answer (`retryable`) | `null` |
|
|
279
|
+
| `service_unavailable` (`api_error`) | a gateway or proxy answered for accounts (an HTML 502, a captive portal): `the service answered HTTP <status>; try again in a minute` (`retryable`, exit 4, `retry_after_s` when sent) | `null` |
|
|
280
|
+
| `interrupted` | Ctrl-C or a signal stopped the command (exit 130; under `--json` the error object says so) | `null` |
|
|
281
|
+
| `network` (`api_error`) | no answer from a server at all: the message names the host and why (`retryable`, exit 4) | `null` |
|
|
282
|
+
| `internal` (`api_error`) | something the CLI did not expect; `debug_log` beside the error is the file to report it with | `null` |
|
|
283
|
+
| `login_expired`, `login_refused` | the sign-in code ran out, or was declined | `kennet login` |
|
|
284
|
+
| `upgrade_required` (`upgrade_error`) | the service no longer serves this version (exit 5) | the upgrade command for this install |
|
|
285
|
+
| `step_up_required` | a change to the organization's members or keys needs a sign-in more recent than this one | `kennet login` (signs in afresh) |
|
|
286
|
+
| `timed_out` (`api_error`) | the wait ended before the twin did; it goes on | `kennet twins wait <id>` |
|
|
287
|
+
|
|
288
|
+
Any other error the CLI says itself, such as a file that is not there, is a plain `MetaphiError` with `code` `None`.
|
|
289
|
+
|
|
290
|
+
## Task deliveries
|
|
291
|
+
|
|
292
|
+
The task sets your organization holds, each a versioned set of Harbor tasks with its images pinned by digest.
|
|
293
|
+
|
|
294
|
+
```sh
|
|
295
|
+
kennet delivery list # what you hold, newest first
|
|
296
|
+
kennet delivery show eswe-mini@0.1.0 # tasks, images, download size, what a run asks
|
|
297
|
+
kennet pull eswe-mini@0.1.0 # into ./eswe-mini-0.1.0; run again and it fetches only what differs
|
|
298
|
+
kennet verify ./eswe-mini-0.1.0 # against its lock, offline; exit 1 if anything differs
|
|
299
|
+
kennet delivery diff eswe-mini@0.1.0 eswe-mini@0.1.1 # what changed, and whether a task's grading did
|
|
300
|
+
kennet delivery diff ./eswe-mini-0.1.0 eswe-mini@0.1.1 # either side can be a pulled directory
|
|
301
|
+
kennet registry login # sign docker in to your image repository, for an hour; no key is stored
|
|
302
|
+
kennet registry token # the token alone, for a pull secret or another client
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
A pulled delivery is `delivery.lock.json`, `SHA256SUMS` and `tasks/<task>/`. The lock names each task's tree hash
|
|
306
|
+
and its images by digest; `verify` needs that directory and nothing else. A version never changes: a fix is a new
|
|
307
|
+
version, shown as `newer` by `list`. You run the tasks with Harbor on your own machines.
|
|
308
|
+
|
|
309
|
+
## Follow a run
|
|
310
|
+
|
|
311
|
+
```sh
|
|
312
|
+
kennet tail acme/tasks 20261028T072322Z-db0eea # each trial's timeline, redrawn as it runs
|
|
313
|
+
kennet tail acme/tasks 20261028T072322Z-db0eea --trial <name> # one trial alone
|
|
314
|
+
kennet tail acme/tasks 20261028T072322Z-db0eea --plain # a line per event, for a log; --json: an event a line
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
```
|
|
318
|
+
20261028T072322Z-db0eea 18:03 3 trials · 1 ended · 2 running
|
|
319
|
+
|
|
320
|
+
carla-route-driver__wZRsaKP ░░░░░░░░░░░░░░░░░░░░░░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ grading 11:49
|
|
321
|
+
image cached 0:04 · sandbox 6:06
|
|
322
|
+
carla-route-driver__dvBSvmr ░░░░░░░░░░░░░░░░░░░░░█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ✓ reward 0.00
|
|
323
|
+
image cached 0:04 · sandbox 5:58
|
|
324
|
+
|
|
325
|
+
░ setting up █ agent ▓ grading
|
|
326
|
+
|
|
327
|
+
wZRsaKP │ route 7/10 HazardAtSideLane score 77.0 420 s
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
A row is a trial on the run's clock: setting its sandbox up (the image read from cache or built, the sandbox
|
|
331
|
+
made and its image loaded), the agent, then grading. Under the rows, the last lines its sandboxes wrote. It ends
|
|
332
|
+
once every trial has ended and the run is quiet; ^C ends it sooner. A run is your organization's to follow:
|
|
333
|
+
anyone else's reads as not there.
|
|
334
|
+
|
|
335
|
+
### Runs side by side
|
|
336
|
+
|
|
337
|
+
```sh
|
|
338
|
+
kennet tail acme/tasks <run-id> <run-id> # the same task on two providers, built as it runs
|
|
339
|
+
kennet tail acme/tasks <run-id> <run-id> --speed 30 # ended runs played back, each from its own start
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
Two or more runs set side by side, their first trial each. Above, a tower per run standing on one ground: a slab
|
|
343
|
+
per stage (image, placing, ready, agent, grading), as tall as its time on a scale every tower shares, the stage
|
|
344
|
+
under way growing as the clock runs. A tower is its provider's colour, Modal green and Thunder blue, any other
|
|
345
|
+
one of its own, and its stages are shades of it; red is a stage the infra failed, ⏱ an agent stopped at its time
|
|
346
|
+
limit. Below, a row per stage and a column per run: the sandbox given, the image (named, cached or built) and
|
|
347
|
+
each stage's time, the refusals a provider gave before it placed one, the agent's steps, what the sandbox used
|
|
348
|
+
(CPU and GPU as they ran, peak memory) and what the trial cost.
|
|
349
|
+
|
|
350
|
+
```
|
|
351
|
+
20261029T200817Z-f02a9c 20261029T200846Z-cfd296
|
|
352
|
+
|
|
353
|
+
sandbox modal · A100-80GB thunder · A100XL
|
|
354
|
+
8 CPU · 32 GB 8 CPU · 32 GB
|
|
355
|
+
image named 0:00 cached 0:01
|
|
356
|
+
placing 0:00 0:03
|
|
357
|
+
ready 0:06 0:02
|
|
358
|
+
agent 5:01 · 23 steps 5:06 · 18 steps
|
|
359
|
+
grading 2:20 0:03 ✗
|
|
360
|
+
cpu ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 5.6/8
|
|
361
|
+
memory peak 4.3/32 GB
|
|
362
|
+
gpu ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ 0% · 0.0 GB
|
|
363
|
+
cost $0.70 (model $0.30 · sandbox $0.40) $0.49 (model $0.23 · sandbox $0.27)
|
|
364
|
+
total 7:43 5:44
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
## Profile a codebase
|
|
368
|
+
|
|
369
|
+
```sh
|
|
370
|
+
kennet profile-codebase ./core ./billing # full git clones; computed here, then shared
|
|
371
|
+
kennet profile-codebase ./core --dry-run # write the exact document to a file and send nothing
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
Repository metadata is shared automatically with Metaphi AI, under the terms of your NDA. Please contact your Metaphi AI POC if you do not have an NDA in place.
|
|
375
|
+
|
|
376
|
+
It reads the local git history and makes no other network call. It sends counts, never code, paths, file names, commit messages, names, addresses or remote URLs. `--hide-names` sends `repo-1` for a repository's name. A send that fails keeps the document and names the command that sends it again.
|
|
377
|
+
|
|
378
|
+
## Your organization
|
|
379
|
+
|
|
380
|
+
`kennet whoami` asks the servers who you are: each organization you are in, with your role and what it may do, what you may spend now (`you:`: what is left under your monthly limit or the organization's balance, or no limit), the balance when you may see it, and which key calls run on (the saved one, or
|
|
381
|
+
`METAPHI_API_KEY`), by its last four characters. It asks the twin service whether each key works, and exits 0 only
|
|
382
|
+
when the one in use does.
|
|
383
|
+
If an organization has invited you, `kennet login` and `kennet whoami` say so (`invitation_pending`) and name the
|
|
384
|
+
command that accepts it:
|
|
385
|
+
|
|
386
|
+
```sh
|
|
387
|
+
kennet org join acme # or the invitation's id, inv_...; you join in the role it names, and its keys are saved
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
If you are in no organization and none has invited you, make yours: `kennet org create "Acme Robotics"`. You own
|
|
391
|
+
it. During the private beta Metaphi AI approves each new organization; you are mailed when yours is, and
|
|
392
|
+
`kennet login` then saves its keys, with no second sign-in. `kennet whoami` says so while it waits.
|
|
393
|
+
|
|
394
|
+
A sign-in handed no key clears the keys and organization saved before it and keeps why, so `kennet whoami`
|
|
395
|
+
says that reason again rather than a refused key. If an owner or admin takes you out of your organization, its keys stop working and the CLI says so (`removed`):
|
|
396
|
+
only an owner of it can add you back. When a saved key is refused, `kennet whoami` says why from what it may read, and
|
|
397
|
+
changes no key: an invitation to accept, a key replaced by a sign-in elsewhere, or no organization at all; `kennet
|
|
398
|
+
login` then says the rest.
|
|
399
|
+
|
|
400
|
+
A sign-in the server has ended is an error, not a name read back from a file.
|
|
401
|
+
|
|
402
|
+
Owners and admins manage the organization's members from here:
|
|
403
|
+
|
|
404
|
+
```sh
|
|
405
|
+
kennet org request kennet:runs --reason "evals" # ask for more; with no scope, what you asked for so far
|
|
406
|
+
kennet org domain add acme.com # prints a TXT record; then `kennet org domain verify acme.com`
|
|
407
|
+
kennet org members # members and open invitations, with each one's role
|
|
408
|
+
kennet org members add bob@acme.com # in as a member; --role owner|admin|billing|member
|
|
409
|
+
kennet org members role bob@acme.com admin # change a member's role
|
|
410
|
+
kennet org members remove bob@acme.com # take them out, or take back their invitation
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
An address on a domain your organization claims joins at once. Any other address is mailed an invitation, which
|
|
414
|
+
the person accepts signed in as that address, within a week. Only an owner makes, changes or removes an owner,
|
|
415
|
+
and the organization always keeps one. A change needs a recent sign-in: when yours is too old, `kennet` offers a
|
|
416
|
+
fresh one at a terminal and tries again; elsewhere it fails with `step_up_required` and `kennet login` signs in
|
|
417
|
+
afresh. `--org <id>` picks the organization when you manage several.
|
|
418
|
+
|
|
419
|
+
And its service keys, the ones CI and servers call with (also on the console's keys page,
|
|
420
|
+
<https://app.metaphi.ai/console>):
|
|
421
|
+
|
|
422
|
+
```sh
|
|
423
|
+
kennet keys list # live keys: name, id, last four, scopes, last use; --all adds revoked
|
|
424
|
+
kennet keys create github-ci | gh secret set METAPHI_API_KEY # all the org holds; --scope less, --test
|
|
425
|
+
kennet keys revoke github-ci # by name or id; asks first at a terminal, --yes elsewhere
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
`create` shows the key once: at a terminal with a warning, and down a pipe alone on stdout, so it goes straight
|
|
429
|
+
into a secret store (what it made and the warning are on stderr). `--json` carries it only with `--show-secret`;
|
|
430
|
+
without the flag it makes nothing (`secret_destination_required`).
|
|
431
|
+
Accounts keeps only its hash. Like a change to members, it needs a recent sign-in.
|
|
432
|
+
|
|
433
|
+
## Credits
|
|
434
|
+
|
|
435
|
+
Each completed trace draws your organization's credit; a run that fails costs nothing. When the balance
|
|
436
|
+
reaches zero, new runs are refused until credit is added.
|
|
437
|
+
|
|
438
|
+
```sh
|
|
439
|
+
kennet credits # the balance (owners, admins and billing members)
|
|
440
|
+
kennet credits buy --amount 200 # pay through Stripe Checkout in the browser; waits until it lands
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
Only owners and billing members can buy; a billing member sees the balance and buys credit, nothing else.
|
|
444
|
+
|
|
445
|
+
### Running out of credit
|
|
446
|
+
|
|
447
|
+
When `kennet twin` is refused with `out_of_credit` at a terminal, and you may buy for your organization, it offers to
|
|
448
|
+
add credit there and then, opens Stripe Checkout, and carries on with the same run once the payment lands:
|
|
449
|
+
|
|
450
|
+
```
|
|
451
|
+
$ kennet twin trace.json
|
|
452
|
+
acme is out of credit.
|
|
453
|
+
Add credit now? Amount in $ [100]:
|
|
454
|
+
Pay in the browser:
|
|
455
|
+
https://checkout.stripe.com/c/pay/...
|
|
456
|
+
Paid. acme: balance $100.00
|
|
457
|
+
uploaded trace.json (48,112 bytes)
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
Enter takes $100; `n` or Ctrl-C declines. The run is retried once, under the Idempotency-Key of the first attempt, so
|
|
461
|
+
it can never start twice. If you may not buy, it names who can and where.
|
|
462
|
+
|
|
463
|
+
In CI, a pipe or with `--json` nothing is asked. The command exits 1 with the error and one more line on stderr:
|
|
464
|
+
|
|
465
|
+
```
|
|
466
|
+
Add credit: https://app.metaphi.ai/console?add=credit or run: kennet credits buy --amount <amount>
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
With `--json` the error object carries the same two things: `action_url`, the page, and `next_step`,
|
|
470
|
+
`kennet credits buy`, which prints a Stripe Checkout link and waits until it is paid.
|
|
471
|
+
|
|
472
|
+
The library never prompts: `twin()` raises `BillingError`, whose `action_url` is the add-credit page when the service
|
|
473
|
+
sent one.
|
|
474
|
+
|
|
475
|
+
## Metaphi AI's admins
|
|
476
|
+
|
|
477
|
+
An account holding `metaphi:admin` runs accounts' admin from here, on its own `kennet login`: `metaphi:admin:read`
|
|
478
|
+
reads, `metaphi:admin` also changes, and accounts writes every change to its audit under your name.
|
|
479
|
+
|
|
480
|
+
```sh
|
|
481
|
+
kennet admin orgs # every organization: access, members, keys, credit, grants
|
|
482
|
+
kennet admin requests # what organizations asked for; --status all is every decision
|
|
483
|
+
kennet admin create-org acme --name "Acme" # holds nothing until you approve scopes
|
|
484
|
+
kennet admin org acme approve --scope kennet:twin # pre-approve, or --preset standard
|
|
485
|
+
kennet admin org acme approve --request req_x # settle a request; --scope for part of it
|
|
486
|
+
kennet admin org acme deny --request req_x --reason "..." # it may ask again; block: it may not
|
|
487
|
+
kennet admin org acme # what it holds, who is in it; then a verb:
|
|
488
|
+
kennet admin org acme add bob@acme.com --role owner # in, or moved from another organization
|
|
489
|
+
kennet admin org acme grant kennet:twin # ungrant takes it back, from its keys too; revoke-all
|
|
490
|
+
kennet admin org acme billing invoiced --credit-limit 500 # prepaid | invoiced | internal; funds-members on|off
|
|
491
|
+
kennet admin org acme transactions # its ledger, newest first, and its balance
|
|
492
|
+
kennet admin grants sme@gmail.com # a person's scopes; grant and revoke <email> <scope>
|
|
493
|
+
kennet admin credit org:acme 500 --days 90 # or a person's address; --note; end <subject> <grant id>
|
|
494
|
+
kennet admin limits bob@acme.com --usd 200 # a monthly cap; --product, --clear
|
|
495
|
+
kennet admin models org:acme 'anthropic/*' # the models it may call; --none, --clear
|
|
496
|
+
kennet admin audit --actor ac@metaphi.ai # the changes admins made
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
## Configuration
|
|
500
|
+
|
|
501
|
+
| Variable | Default |
|
|
502
|
+
| --- | --- |
|
|
503
|
+
| `METAPHI_API_KEY` | the key saved by `kennet login` (or `kennet login --with-api-key`) |
|
|
504
|
+
| `METAPHI_API` | `https://api.metaphi.ai/v1/kennet`, the Kennet API |
|
|
505
|
+
| `METAPHI_HOME` | `~/.config/metaphi` (directory mode 700, config file mode 600) |
|
|
506
|
+
| `METAPHI_TWIN_TIMEOUT` | `7200`: seconds `kennet twin` waits for its twin to end (`--timeout` per call) |
|
|
507
|
+
| `METAPHI_ALLOW_CUSTOM_HOST` | unset: the CLI talks only to `https://*.metaphi.ai`; `1` allows another https host |
|
|
508
|
+
| `KENNET_NO_UPDATE_NOTIFIER` | unset: `1` turns the daily new-release notice off |
|
|
509
|
+
| `KENNET_DISABLE_AUTOUPDATE` | unset: `1` stops the release binary from updating itself |
|
|
510
|
+
|
|
511
|
+
Sign out with `kennet logout`. It ends this sign-in everywhere it is used, revokes the keys `kennet login`
|
|
512
|
+
handed out, and clears the saved keys from this machine.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
metaphi/__init__.py,sha256=P7W0fgz-tri_VAY6mdhyBbW61Xp_16DH5QhvYOvMaV4,59
|
|
2
|
+
metaphi/__main__.py,sha256=frrN2tWqdwWgbXo8mtmTBh-GZAUjG5Fkhb9K0ajb40A,59
|
|
3
|
+
metaphi/accounts.py,sha256=ENV_qjX6UOmYQBv8Z83Cj-ZnPP3diy5BH4FHC6Gce_8,23919
|
|
4
|
+
metaphi/admin.py,sha256=NH2Jqu8h-rZQsNzlGzx1-LNJu6ronD8yCCB51EiM-LQ,6700
|
|
5
|
+
metaphi/agents.py,sha256=F4_9QjaHZ9FEkZDYwheViHCR9AzzG42d0Ur8Qn7pt4s,29246
|
|
6
|
+
metaphi/cli.py,sha256=kqxoR7R8_ZPtrPnnB07HrraLihD7MGswVsT_iETwkos,96067
|
|
7
|
+
metaphi/codebase_profile.py,sha256=68irvAU9EqxaMpSCP-tWNHxNOrBvCViv2Zh-FgZrkho,26788
|
|
8
|
+
metaphi/config.py,sha256=onQ3BUGuA9gbftcWgWqHOkjuRoSMLpi48t72CqsEOjw,5210
|
|
9
|
+
metaphi/delivery.py,sha256=lvFB8LR307SAX5scu3mMvXcFD2Dt4FKN5koaO94gJLQ,23915
|
|
10
|
+
metaphi/errors.py,sha256=aHdXolR0uGl3P0eWDPoOJjfsA_b-nZggFvtReo1aW9s,5131
|
|
11
|
+
metaphi/runs.py,sha256=DYh46IHTPc-ipcLF5W6MuGzBpyKD-4vUELTxIAivszg,29447
|
|
12
|
+
metaphi/signature.py,sha256=NRtkqTRYN5jtO19OM4QPdvHwDkoKmByPMXEPPjDlVKs,5745
|
|
13
|
+
metaphi/skill.py,sha256=quV-pQOwDbVnnogUf_p6_Wd5e4RrkgE8aY9uWjVTp2U,35534
|
|
14
|
+
metaphi/twin.py,sha256=xM9gq7S1JYRj0f-_pKClhq5BMy57vztQfRlg0IIioYw,18852
|
|
15
|
+
metaphi/update.py,sha256=Xgu1-gcWIpui8S8ObT-2qCjaDjwL_Eg6Q6ZyicFKfAk,23651
|
|
16
|
+
kennet-0.1.30.dist-info/METADATA,sha256=cTD3xVTie7SZriSx6YVOxYQG8Ehi2UZOTYRYpM6ccs8,32243
|
|
17
|
+
kennet-0.1.30.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
18
|
+
kennet-0.1.30.dist-info/entry_points.txt,sha256=38zxSo91jpmT0IQZd4tP6BDfALkG9IKljqMv0Qp3WOg,44
|
|
19
|
+
kennet-0.1.30.dist-info/licenses/LICENSE,sha256=yVuuHRzgI17MzTVgt3LsHvuX80innw--CmNPDCzO_iw,11358
|
|
20
|
+
kennet-0.1.30.dist-info/RECORD,,
|