jev-layer 0.1.0 → 0.2.0
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.
- package/CHANGELOG.md +45 -34
- package/CONTRIBUTING.md +146 -146
- package/LICENSE +21 -21
- package/README.md +123 -126
- package/README.ru.md +138 -117
- package/README.zh-CN.md +137 -117
- package/RELEASE.md +53 -53
- package/SECURITY.md +56 -56
- package/bin/jev.mjs +213 -213
- package/config/codex.mcp.toml +8 -8
- package/config/generic-mcp.json +13 -13
- package/config/hermes.mcp.yaml +9 -9
- package/config/jev.example.json +22 -22
- package/config/omp.mcp.json +14 -14
- package/config/providers.env.example +13 -13
- package/docs/AGENT-IMPLEMENTATION.md +250 -0
- package/docs/COMPATIBILITY.md +15 -15
- package/docs/HERMES-LOCAL-AGENT-HANDOFF.ru.md +177 -0
- package/docs/PROVIDERS.md +67 -0
- package/docs/SCHEMA-VERSIONING.md +96 -94
- package/docs/architecture.svg +77 -0
- package/docs/jev-layer-banner.svg +38 -0
- package/examples/capabilities.json +39 -39
- package/examples/route-request.json +28 -28
- package/integrations/codex/.codex-plugin/plugin.json +19 -19
- package/integrations/codex/.mcp.json +11 -11
- package/integrations/codex/AGENTS.md +1 -1
- package/integrations/codex/run-mcp.mjs +9 -9
- package/integrations/codex/skills/jev-route/SKILL.md +17 -17
- package/integrations/hermes/__init__.py +150 -51
- package/integrations/hermes/plugin.yaml +10 -5
- package/integrations/hermes/schemas.py +89 -12
- package/integrations/omp/extension.js +105 -105
- package/integrations/template/README.md +10 -10
- package/integrations/template/adapter.mjs +87 -87
- package/package.json +60 -59
- package/scripts/benchmark.mjs +35 -35
- package/scripts/browser-benchmark.mjs +92 -92
- package/scripts/browser-e2e.mjs +117 -117
- package/scripts/capability-e2e.mjs +31 -31
- package/scripts/clean-install-smoke.mjs +162 -162
- package/scripts/codex-mcp-smoke.mjs +119 -119
- package/scripts/context-filter-e2e.mjs +45 -45
- package/scripts/fail-open-smoke.mjs +120 -120
- package/scripts/feature-flags-smoke.mjs +46 -46
- package/scripts/mcp-receipt-smoke.mjs +113 -98
- package/scripts/model-route-report.mjs +15 -0
- package/scripts/openrouter-choice.mjs +59 -59
- package/scripts/replay-eval.mjs +124 -124
- package/scripts/smoke.mjs +34 -34
- package/scripts/supervision-e2e.mjs +138 -109
- package/src/browser.mjs +571 -569
- package/src/cli.mjs +33 -33
- package/src/config.mjs +85 -75
- package/src/context-filter.mjs +56 -56
- package/src/contract.mjs +72 -72
- package/src/discovery.mjs +65 -65
- package/src/hermes-adapter.mjs +123 -0
- package/src/mcp-server.mjs +267 -210
- package/src/model-route-metrics.mjs +89 -0
- package/src/model-routing.mjs +87 -0
- package/src/providers/demo.mjs +52 -52
- package/src/providers/index.mjs +12 -0
- package/src/providers/typesafe.mjs +126 -126
- package/src/receipts.mjs +227 -226
- package/src/registry.mjs +109 -109
- package/src/relevance-filter.mjs +99 -99
- package/src/route.mjs +219 -221
- package/src/shadow-compaction.mjs +170 -0
- package/src/supervision.mjs +268 -244
- package/test/browser.test.mjs +199 -199
- package/test/capability.test.mjs +54 -54
- package/test/context-filter.test.mjs +65 -65
- package/test/hermes-adapter.test.mjs +62 -0
- package/test/model-route-metrics.test.mjs +61 -0
- package/test/model-routing.test.mjs +59 -0
- package/test/openrouter-provider.test.mjs +55 -55
- package/test/provider-transports.test.mjs +205 -0
- package/test/providers.test.mjs +126 -0
- package/test/receipts.test.mjs +71 -71
- package/test/route.test.mjs +74 -74
- package/test/shadow-compaction.test.mjs +67 -0
- package/test/supervision.test.mjs +117 -99
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# Agent implementation guide
|
|
2
|
+
|
|
3
|
+
This is the implementation brief to hand to a coding agent before integrating jev-layer into a harness. It is intentionally operational: inspect the target harness first, preserve host ownership, and prove the fallback path. Do not treat a link to this repository as permission to invent an adapter or change the host's execution model.
|
|
4
|
+
|
|
5
|
+
## Contract in one paragraph
|
|
6
|
+
|
|
7
|
+
jev-layer is a **System-1 decision layer**, not an executor, permission system, security boundary, retry loop, or browser worker. The host owns capability discovery, the closed candidate set, permissions, approvals, native execution, retries, recovery, and final output. Jev receives bounded input, returns one bounded decision with a `correlation_id`, and records the host's result. If Jev is disabled, unavailable, invalid, inconclusive, or refused by policy, the host continues through its normal native path.
|
|
8
|
+
|
|
9
|
+
## Before editing
|
|
10
|
+
|
|
11
|
+
1. Identify the harness's native capability registry and native execution function.
|
|
12
|
+
2. Identify the existing permission and approval checks, especially for consequential actions.
|
|
13
|
+
3. Identify the host's normal fallback path and its error/retry boundaries.
|
|
14
|
+
4. Read [CONTRIBUTING.md](../CONTRIBUTING.md), [SECURITY.md](../SECURITY.md), and [SCHEMA-VERSIONING.md](SCHEMA-VERSIONING.md).
|
|
15
|
+
5. Confirm the harness version and transport: CLI, stdio MCP, or an existing adapter boundary.
|
|
16
|
+
6. Write a short integration plan naming the exact adapter entry point and the unchanged host-owned functions.
|
|
17
|
+
7. Only then edit the smallest possible adapter/configuration surface.
|
|
18
|
+
|
|
19
|
+
Do not begin by pasting the repository URL to an agent and asking it to "integrate Jev" without supplying the target harness, its native execution path, and its approval semantics.
|
|
20
|
+
|
|
21
|
+
## Required data flow
|
|
22
|
+
|
|
23
|
+
### 1. Build a closed capability set in the host
|
|
24
|
+
|
|
25
|
+
The host must provide only capabilities it already knows how to execute. Each candidate needs a stable id and enough metadata for bounded selection:
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"id": "repo:search",
|
|
30
|
+
"kind": "tool",
|
|
31
|
+
"name": "Search repository",
|
|
32
|
+
"description": "Find text in tracked repository files",
|
|
33
|
+
"permissions": ["read"],
|
|
34
|
+
"risk": "low",
|
|
35
|
+
"available": true
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Do not ask Jev to discover hidden host tools. Do not pass arbitrary shell commands as capability ids. Do not expose a capability that the host cannot validate and execute through its native registry.
|
|
40
|
+
|
|
41
|
+
### 2. Call `jev_route` with bounded input
|
|
42
|
+
|
|
43
|
+
Preserve schema version 1 and include the host-owned facts needed for the decision:
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"schema_version": 1,
|
|
48
|
+
"harness": "my-harness",
|
|
49
|
+
"intent": "Find the implementation of the routing contract",
|
|
50
|
+
"context": {
|
|
51
|
+
"task": "repository inspection"
|
|
52
|
+
},
|
|
53
|
+
"actor_permissions": ["read"],
|
|
54
|
+
"capabilities": [
|
|
55
|
+
{
|
|
56
|
+
"id": "repo:search",
|
|
57
|
+
"kind": "tool",
|
|
58
|
+
"name": "Search repository",
|
|
59
|
+
"description": "Find text in tracked repository files",
|
|
60
|
+
"permissions": ["read"],
|
|
61
|
+
"risk": "low",
|
|
62
|
+
"available": true
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
"policy": {
|
|
66
|
+
"deterministic": true
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Keep `intent`, `context`, and the candidate set bounded. Do not send credentials, unbounded conversation history, hidden tool descriptions, or machine-specific paths.
|
|
72
|
+
|
|
73
|
+
### 3. Treat the response as advice, never authorization
|
|
74
|
+
|
|
75
|
+
A normal decision has this shape:
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"schema_version": 1,
|
|
80
|
+
"correlation_id": "decision-id",
|
|
81
|
+
"status": "selected",
|
|
82
|
+
"selected": "repo:search",
|
|
83
|
+
"execution": {
|
|
84
|
+
"enabled": false,
|
|
85
|
+
"status": "not_started"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
The adapter must validate all of the following before execution:
|
|
91
|
+
|
|
92
|
+
- `status` permits a host action (`selected` is different from `fallback`, `no_decision`, and `needs_confirmation`);
|
|
93
|
+
- `selected` is non-null and exactly matches an id in the request's candidate set;
|
|
94
|
+
- the candidate is still available and its permissions/risk are acceptable;
|
|
95
|
+
- the host's current approval policy allows the action.
|
|
96
|
+
|
|
97
|
+
Never execute an id returned by Jev as a shell command, import path, URL, or arbitrary function name. Resolve it through the harness's native registry.
|
|
98
|
+
|
|
99
|
+
### 4. Let the host approve consequential work
|
|
100
|
+
|
|
101
|
+
Jev cannot approve, elevate, or override the host. For a consequential candidate:
|
|
102
|
+
|
|
103
|
+
1. pause after the decision;
|
|
104
|
+
2. run the host's existing approval flow;
|
|
105
|
+
3. if denied, do not execute and record `status: "not_started"`;
|
|
106
|
+
4. if approved, execute through the native host path.
|
|
107
|
+
|
|
108
|
+
The Jev decision does not replace the harness confirmation dialog, policy engine, or permission check.
|
|
109
|
+
|
|
110
|
+
### 5. Execute only through the native host path
|
|
111
|
+
|
|
112
|
+
The adapter must not become a second executor. Preserve the host's existing:
|
|
113
|
+
|
|
114
|
+
- capability lookup;
|
|
115
|
+
- permission checks;
|
|
116
|
+
- approval prompts;
|
|
117
|
+
- process/browser/tool execution;
|
|
118
|
+
- retry and recovery behavior;
|
|
119
|
+
- result shaping and user-visible output.
|
|
120
|
+
|
|
121
|
+
Jev returns a decision. The host performs the work.
|
|
122
|
+
|
|
123
|
+
### 6. Record one receipt with the same correlation id
|
|
124
|
+
|
|
125
|
+
After the host knows what happened, call `jev_record_execution`:
|
|
126
|
+
|
|
127
|
+
```json
|
|
128
|
+
{
|
|
129
|
+
"correlation_id": "decision-id",
|
|
130
|
+
"harness": "my-harness",
|
|
131
|
+
"capability_id": "repo:search",
|
|
132
|
+
"status": "completed",
|
|
133
|
+
"result": {
|
|
134
|
+
"matches": 3
|
|
135
|
+
},
|
|
136
|
+
"exit_status": 0,
|
|
137
|
+
"duration_ms": 12
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Use the same `correlation_id` from `jev_route`. Use:
|
|
142
|
+
|
|
143
|
+
- `completed` when native execution finished successfully;
|
|
144
|
+
- `failed` when native execution ran and failed;
|
|
145
|
+
- `not_started` when approval, policy, or fail-open handling prevented execution.
|
|
146
|
+
|
|
147
|
+
Bound results and errors before recording them. Never write secrets or full untrusted logs into receipts.
|
|
148
|
+
|
|
149
|
+
### 7. Preserve fail-open behavior
|
|
150
|
+
|
|
151
|
+
The following conditions must return control to the host's ordinary path without guessing a capability:
|
|
152
|
+
|
|
153
|
+
- Jev is disabled by configuration;
|
|
154
|
+
- the MCP/CLI process is unavailable or times out;
|
|
155
|
+
- the provider returns an error or malformed response;
|
|
156
|
+
- the decision is `fallback`, `no_decision`, or otherwise unusable;
|
|
157
|
+
- the selected id is not in the closed candidate set;
|
|
158
|
+
- permissions or approval reject the action.
|
|
159
|
+
|
|
160
|
+
A Jev failure is not permission to execute. Do not add an adapter retry loop that changes the host's existing retry semantics.
|
|
161
|
+
|
|
162
|
+
## Installing and wiring the package
|
|
163
|
+
|
|
164
|
+
For a published local CLI:
|
|
165
|
+
|
|
166
|
+
```sh
|
|
167
|
+
npm install --global jev-layer
|
|
168
|
+
jev init --project /path/to/workspace
|
|
169
|
+
jev add generic --project /path/to/workspace
|
|
170
|
+
jev doctor --project /path/to/workspace
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
For a stdio MCP server:
|
|
174
|
+
|
|
175
|
+
```sh
|
|
176
|
+
jev mcp
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
The generated generic adapter uses the `jev mcp` command. Keep the adapter configuration in the project/workspace where the harness owns it; do not overwrite global harness configuration. Use `JEV_LAYER_PROVIDER=demo` for offline deterministic development. Keep OpenRouter or TypeSafe credentials in the process environment or another user-owned secret store.
|
|
180
|
+
|
|
181
|
+
For an existing harness, copy the smallest relevant example from `integrations/` and adapt its transport. Do not copy an integration wholesale without checking the harness's actual registry, approval, and execution APIs.
|
|
182
|
+
|
|
183
|
+
## Copy-paste handoff for a coding agent
|
|
184
|
+
|
|
185
|
+
Use this prompt with the guide and the target harness details:
|
|
186
|
+
|
|
187
|
+
```text
|
|
188
|
+
Implement jev-layer as a thin System-1 decision layer in this harness.
|
|
189
|
+
|
|
190
|
+
Read docs/AGENT-IMPLEMENTATION.md first. Then inspect the harness's native
|
|
191
|
+
capability registry, permission checks, approval flow, execution function,
|
|
192
|
+
retry/recovery boundaries, and existing MCP/CLI integration point.
|
|
193
|
+
|
|
194
|
+
Target harness: <name and version>
|
|
195
|
+
Target integration point: <file/function/config>
|
|
196
|
+
Native execution function: <file/function>
|
|
197
|
+
Approval authority: <file/function>
|
|
198
|
+
Normal fallback path: <file/function>
|
|
199
|
+
|
|
200
|
+
Requirements:
|
|
201
|
+
- Build a closed capabilities[] set from the host registry.
|
|
202
|
+
- Call jev_route with schema_version: 1, bounded intent/context,
|
|
203
|
+
actor_permissions, capabilities, and policy.
|
|
204
|
+
- Validate status, selected id, availability, permissions, and approval in
|
|
205
|
+
the host before execution.
|
|
206
|
+
- Resolve selected ids through the native registry; never shell out to ids
|
|
207
|
+
returned by Jev and never let Jev execute host work.
|
|
208
|
+
- Preserve the existing host fallback path when Jev is disabled, unavailable,
|
|
209
|
+
invalid, inconclusive, or rejected.
|
|
210
|
+
- Call jev_record_execution with the same correlation_id after the host knows
|
|
211
|
+
the result.
|
|
212
|
+
- Add offline tests for selected execution, fail-open, unknown-id rejection,
|
|
213
|
+
approval denial, and receipt correlation.
|
|
214
|
+
- Do not add provider credentials, global config writes, hidden capability
|
|
215
|
+
discovery, arbitrary command execution, or unrelated runtime features.
|
|
216
|
+
|
|
217
|
+
Before changing code, show the files/symbols you will touch. After changing
|
|
218
|
+
code, report the exact native execution path preserved and the verification
|
|
219
|
+
commands/results.
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Replace every `<...>` placeholder with facts from the target harness. Do not leave the agent to infer them from a generic repository link.
|
|
223
|
+
|
|
224
|
+
## Minimum verification matrix
|
|
225
|
+
|
|
226
|
+
An implementation is not complete until it proves these observable behaviors:
|
|
227
|
+
|
|
228
|
+
| Scenario | Required result |
|
|
229
|
+
| --- | --- |
|
|
230
|
+
| Valid low-risk selection | Host executes the matching native capability once. |
|
|
231
|
+
| Unknown or stale selected id | Host does not execute; normal fallback remains available. |
|
|
232
|
+
| `needs_confirmation` | Host approval is requested before execution. |
|
|
233
|
+
| Approval denied | No host execution; receipt is `not_started`. |
|
|
234
|
+
| Jev disabled/unavailable/error | Normal host path continues without guessed selection. |
|
|
235
|
+
| Native execution failure | Receipt is `failed` with the same `correlation_id`. |
|
|
236
|
+
| Successful native execution | Receipt is `completed` with bounded result/timing metadata. |
|
|
237
|
+
| Replay evaluation | Routing/receipt cases replay without host execution. |
|
|
238
|
+
|
|
239
|
+
Run the existing project checks plus the matching adapter smoke fixture. At minimum, a jev-layer integration should preserve the checks in `CONTRIBUTING.md` and add a harness-specific offline fixture; provider credentials are not required for ordinary CI.
|
|
240
|
+
|
|
241
|
+
## Common incorrect implementations
|
|
242
|
+
|
|
243
|
+
- **Calling Jev after executing the tool.** Routing must happen before the host action.
|
|
244
|
+
- **Passing every hidden tool to Jev.** Send only a closed, host-owned candidate set.
|
|
245
|
+
- **Treating `selected` as authorization.** The host still validates permissions and approval.
|
|
246
|
+
- **Executing the returned id directly.** Map it through the native registry; never use it as a command.
|
|
247
|
+
- **Replacing fail-open with a retry loop.** Return to the existing host path.
|
|
248
|
+
- **Letting Jev discover or mutate global config.** Discovery and configuration remain explicit and user-owned.
|
|
249
|
+
- **Adding provider calls to ordinary CI.** Use the deterministic `demo` provider and injected fixtures.
|
|
250
|
+
- **Reporting only that an adapter was added.** Show the preserved execution path, receipt correlation, and fallback evidence.
|
package/docs/COMPATIBILITY.md
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
# Harness compatibility baseline
|
|
2
|
-
|
|
3
|
-
[English](../README.md) | [Русский](../README.ru.md) | [简体中文](../README.zh-CN.md)
|
|
4
|
-
|
|
5
|
-
This is the first-release compatibility baseline observed on 2026-09-19. It records the installed harness versions used for the release-preparation checks; it is not a claim that every provider/model combination was exercised.
|
|
6
|
-
|
|
7
|
-
| Harness | Version observed | Release-preparation coverage |
|
|
8
|
-
| --- | --- | --- |
|
|
9
|
-
| OMP | `18.2.6` | `omp --version`; OMP extension contract and host-owned execution path reviewed; Jev core smoke uses the same MCP/CLI contract. |
|
|
10
|
-
| Hermes | `0.21.3` (`upstream b675e6de`) | `hermes --version`; Python adapter syntax/contract reviewed; Jev core smoke uses the same CLI/MCP contract. |
|
|
11
|
-
| Codex CLI | `0.155.1` | `codex --version`; Codex MCP transport fixture and host-execution ownership path reviewed. The fixture does not invoke a Codex model. |
|
|
12
|
-
|
|
13
|
-
The adapters are thin and target the stable v1 contract documented in [CONTRIBUTING.md](../CONTRIBUTING.md) and [SCHEMA-VERSIONING.md](SCHEMA-VERSIONING.md). Full interactive harness/model/provider coverage is environment-specific and is not required for ordinary PR CI.
|
|
14
|
-
|
|
15
|
-
When a public release supports a different harness version, update this table, rerun the adapter/transport checks, and document any compatibility change in `CHANGELOG.md` before tagging.
|
|
1
|
+
# Harness compatibility baseline
|
|
2
|
+
|
|
3
|
+
[English](../README.md) | [Русский](../README.ru.md) | [简体中文](../README.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
This is the first-release compatibility baseline observed on 2026-09-19. It records the installed harness versions used for the release-preparation checks; it is not a claim that every provider/model combination was exercised.
|
|
6
|
+
|
|
7
|
+
| Harness | Version observed | Release-preparation coverage |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| OMP | `18.2.6` | `omp --version`; OMP extension contract and host-owned execution path reviewed; Jev core smoke uses the same MCP/CLI contract. |
|
|
10
|
+
| Hermes | `0.21.3` (`upstream b675e6de`) | `hermes --version`; Python adapter syntax/contract reviewed; Jev core smoke uses the same CLI/MCP contract. |
|
|
11
|
+
| Codex CLI | `0.155.1` | `codex --version`; Codex MCP transport fixture and host-execution ownership path reviewed. The fixture does not invoke a Codex model. |
|
|
12
|
+
|
|
13
|
+
The adapters are thin and target the stable v1 contract documented in [CONTRIBUTING.md](../CONTRIBUTING.md) and [SCHEMA-VERSIONING.md](SCHEMA-VERSIONING.md). Full interactive harness/model/provider coverage is environment-specific and is not required for ordinary PR CI.
|
|
14
|
+
|
|
15
|
+
When a public release supports a different harness version, update this table, rerun the adapter/transport checks, and document any compatibility change in `CHANGELOG.md` before tagging.
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# Hermes integration: handoff для локального агента
|
|
2
|
+
|
|
3
|
+
Этот документ описывает **текущую рабочую интеграцию** `jev-layer` в Hermes. Он нужен локальному агенту, чтобы сначала понять границы и точки входа, а не повторно «интегрировать Jev» через глобальный конфиг, произвольные shell-команды или второй executor.
|
|
4
|
+
|
|
5
|
+
## Что уже установлено
|
|
6
|
+
|
|
7
|
+
- Исходный репозиторий: `/home/hermes/jev-layer`.
|
|
8
|
+
- Активная plugin-копия Hermes: `~/.hermes/plugins/jev-layer`.
|
|
9
|
+
- Plugin регистрирует ровно шесть tools:
|
|
10
|
+
- `jev_route`;
|
|
11
|
+
- `jev_record_execution`;
|
|
12
|
+
- `jev_supervise`;
|
|
13
|
+
- `jev_browser_step`;
|
|
14
|
+
- `jev_shadow_compaction`;
|
|
15
|
+
- `jev_model_route`.
|
|
16
|
+
- Replay evidence активного профиля: `~/.hermes/jev-layer/replay/cases.jsonl`.
|
|
17
|
+
- Gateway загружает Python plugin при старте. После изменения `integrations/hermes/*`, `plugin.yaml` или списка tools нужен пользовательский `/restart` gateway.
|
|
18
|
+
|
|
19
|
+
Не путай surfaces:
|
|
20
|
+
|
|
21
|
+
```text
|
|
22
|
+
/home/hermes/jev-layer source checkout, тесты и документация
|
|
23
|
+
~/.hermes/plugins/jev-layer установленная plugin-копия текущего профиля
|
|
24
|
+
~/.hermes/jev-layer/replay/cases.jsonl profile-scoped evidence, не source artifact
|
|
25
|
+
~/.hermes/config.yaml глобальный Hermes config; не менять для этой plugin без явного задания
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Главный принцип
|
|
29
|
+
|
|
30
|
+
```text
|
|
31
|
+
Hermes registry/permissions/approval/executor/recovery
|
|
32
|
+
│ closed, bounded input
|
|
33
|
+
▼
|
|
34
|
+
jev-layer decision
|
|
35
|
+
│ correlation_id, advice only
|
|
36
|
+
▼
|
|
37
|
+
Hermes validates → native execution → jev_record_execution → JSONL evidence
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Jev **никогда** не получает право исполнять tool, shell, URL или browser action. Любое решение — advisory. Hermes остаётся владельцем discovery, policy, approval, native execution, retry, recovery и финального ответа.
|
|
41
|
+
|
|
42
|
+
Если Jev выключен, недоступен, даёт невалидный ответ или низкую уверенность, текущий normal Hermes path продолжается. Не добавляй обходной executor и не меняй retry semantics.
|
|
43
|
+
|
|
44
|
+
## Файловая карта
|
|
45
|
+
|
|
46
|
+
| Зачем | Файл |
|
|
47
|
+
| --- | --- |
|
|
48
|
+
| Hermes tool registration + profile-scoped secret bridge | `integrations/hermes/__init__.py` |
|
|
49
|
+
| JSON schemas шести tool surfaces | `integrations/hermes/schemas.py` |
|
|
50
|
+
| Plugin manifest | `integrations/hermes/plugin.yaml`, `plugin.yaml` |
|
|
51
|
+
| Один JSONL request/response adapter process | `src/hermes-adapter.mjs` |
|
|
52
|
+
| Общая bounded routing contract | `src/route.mjs`, `src/contract.mjs` |
|
|
53
|
+
| Receipt/replay JSONL format | `src/receipts.mjs` |
|
|
54
|
+
| Browser action space, progress и recovery | `src/browser.mjs` |
|
|
55
|
+
| Model recommendation | `src/model-routing.mjs` |
|
|
56
|
+
| Model-route evidence report | `src/model-route-metrics.mjs`, `scripts/model-route-report.mjs` |
|
|
57
|
+
| Context keep/drop report | `src/shadow-compaction.mjs` |
|
|
58
|
+
| Work-state judgement | `src/supervision.mjs` |
|
|
59
|
+
| Harness-neutral integration contract | `docs/AGENT-IMPLEMENTATION.md` |
|
|
60
|
+
|
|
61
|
+
## Как работают tools
|
|
62
|
+
|
|
63
|
+
### `jev_route`
|
|
64
|
+
|
|
65
|
+
Hermes сначала собирает **закрытый** `capabilities[]` из своего registry. Jev выбирает один известный id. До исполнения Hermes снова проверяет: `status`, точное совпадение id, availability, permission, risk и approval. После результата используется `jev_record_execution` с тем же `correlation_id`.
|
|
66
|
+
|
|
67
|
+
Нельзя передавать в candidates hidden tools, raw shell command, credential, неограниченную историю или capability, для которой у Hermes нет native executor.
|
|
68
|
+
|
|
69
|
+
### `jev_record_execution`
|
|
70
|
+
|
|
71
|
+
Принимает результат уже выполненного/отклонённого host action. `correlation_id` должен принадлежать decision того же gateway process. Статусы: `completed`, `failed`, `not_started`.
|
|
72
|
+
|
|
73
|
+
Receipt — evidence, не источник авторизации. В `result` нельзя писать токены, пароли, номера карт и полный неочищенный лог.
|
|
74
|
+
|
|
75
|
+
### `jev_model_route`
|
|
76
|
+
|
|
77
|
+
Возвращает рекомендацию одного из **host-declared** `models[]`. Всегда `route_mode: "shadow"`; он не меняет Hermes provider, model или reasoning effort.
|
|
78
|
+
|
|
79
|
+
Когда host закончил реальный model call, он записывает outcome через `jev_record_execution`:
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"correlation_id": "из jev_model_route",
|
|
84
|
+
"capability_id": "recommended model id",
|
|
85
|
+
"status": "completed",
|
|
86
|
+
"result": {
|
|
87
|
+
"model_route": {
|
|
88
|
+
"actual_model_id": "фактически использованный id",
|
|
89
|
+
"retry_count": 0,
|
|
90
|
+
"outcome": "verified"
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Отчёт только читает receipts:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
npm run model-route:report -- ~/.hermes/jev-layer/replay/cases.jsonl
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Пока не накоплены репрезентативные outcomes/retries/latency/cost, **не включать** auto-switching моделей.
|
|
103
|
+
|
|
104
|
+
### `jev_browser_step`
|
|
105
|
+
|
|
106
|
+
Принимает только snapshot, который сделал host: `url`, visible text, targets, tabs, scroll и progress. Возвращает один bounded action: scroll, switch tab, visible link navigation, click, native select или handoff.
|
|
107
|
+
|
|
108
|
+
- `scroll` и `switch_tab` могут быть исполнены только через native Hermes browser executor.
|
|
109
|
+
- `click`, `select`, `navigate` требуют host approval.
|
|
110
|
+
- `submit`, login, payment, delete, секретный ввод и `TYPE_TEXT` не являются быстрым Jev execution path.
|
|
111
|
+
- Progress не даёт повторять уже выполненный target и блокирует повторный scroll без измеримого состояния страницы.
|
|
112
|
+
- После каждого host шага можно записать routing case и execution receipt; это позволяет replay без повторного browser execution.
|
|
113
|
+
|
|
114
|
+
`browser-use/jev-ultrafast` был использован как архитектурный reference (динамическая индексированная action space), но его cloud/browser worker **не установлен и не запущен**. Не подменяй Hermes browser security model его executor'ом.
|
|
115
|
+
|
|
116
|
+
### `jev_shadow_compaction`
|
|
117
|
+
|
|
118
|
+
Возвращает консервативный report keep/drop для переданного context. Не меняет prompt, не удаляет сообщения и не заменяет host compaction. Pinned requirements, paths, errors и commands сохраняются без provider review; provider error удерживает всё.
|
|
119
|
+
|
|
120
|
+
### `jev_supervise`
|
|
121
|
+
|
|
122
|
+
Делает bounded judgement о work state. Hermes, не Jev, преобразует его в `continue`, `verify`, `retry`, `finish` или `escalate`. Contradictory evidence не может закончиться `finish`.
|
|
123
|
+
|
|
124
|
+
## Secrets и providers
|
|
125
|
+
|
|
126
|
+
`integrations/hermes/__init__.py` получает `OPENROUTER_API_KEY` только через Hermes profile-scoped secret store (`agent.secret_scope.get_secret`). Ключ передаётся лишь в короткоживущий локальный Node adapter; не возвращается в tool output и не логируется.
|
|
127
|
+
|
|
128
|
+
Для локальных/offline tests используй `provider: "demo"`. Provider-backed проверки — отдельные, opt-in; ключи никогда не клади в repo, plugin manifest, test fixture или обычный shell history.
|
|
129
|
+
|
|
130
|
+
## Безопасный change workflow
|
|
131
|
+
|
|
132
|
+
1. Прочитай этот документ и `docs/AGENT-IMPLEMENTATION.md`.
|
|
133
|
+
2. Проверь target surface: source checkout, installed plugin copy, active profile или global config.
|
|
134
|
+
3. Измени source в `/home/hermes/jev-layer` и сначала добавь/измени offline test.
|
|
135
|
+
4. Запусти узкий test, затем полный suite.
|
|
136
|
+
5. Синхронизируй **только нужные** source files в `~/.hermes/plugins/jev-layer`.
|
|
137
|
+
6. Запусти `hermes plugins doctor jev-layer`.
|
|
138
|
+
7. Если менялась регистрация/handler/schema/manifest, попроси пользователя о `/restart`.
|
|
139
|
+
8. После restart проверь живой gateway tool path и read back exact receipt/report.
|
|
140
|
+
9. Не делай `git push`, npm publish, GitHub release или изменение глобального Hermes config без отдельной команды пользователя.
|
|
141
|
+
|
|
142
|
+
## Проверки
|
|
143
|
+
|
|
144
|
+
Из source checkout:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
npm test
|
|
148
|
+
npm run receipt:mcp-smoke
|
|
149
|
+
npm run browser:e2e
|
|
150
|
+
npm run model-route:report -- /tmp/nonexistent-cases.jsonl
|
|
151
|
+
python3 -m py_compile integrations/hermes/__init__.py integrations/hermes/schemas.py
|
|
152
|
+
git diff --check
|
|
153
|
+
hermes plugins doctor jev-layer
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Текущее доказанное состояние: `npm test` — 35/35; MCP receipt smoke и browser fixture E2E проходят; gateway-live model route был записан и успешно связан с execution receipt/report. Это не доказательство автоматического роутинга моделей и не утверждение о real-browser speedup.
|
|
157
|
+
|
|
158
|
+
## Готовый prompt локальному агенту
|
|
159
|
+
|
|
160
|
+
```text
|
|
161
|
+
Работай только с jev-layer в указанном target surface. Сначала прочитай:
|
|
162
|
+
- docs/HERMES-LOCAL-AGENT-HANDOFF.ru.md
|
|
163
|
+
- docs/AGENT-IMPLEMENTATION.md
|
|
164
|
+
|
|
165
|
+
Сохрани host ownership: Jev даёт bounded advisory decision; Hermes владеет registry,
|
|
166
|
+
permissions, approval, execution, retry/recovery и финальным результатом. Не добавляй
|
|
167
|
+
автоматическое переключение моделей, browser executor, глобальный config write, provider
|
|
168
|
+
credential или network publication без отдельного явного требования.
|
|
169
|
+
|
|
170
|
+
Перед изменением назови source files, installed plugin files и gateway impact. Используй TDD:
|
|
171
|
+
сначала узкий offline test, затем implementation, потом npm test + релевантные smoke tests.
|
|
172
|
+
Если touch'нуты registration/handler/schema/manifest, синхронизируй plugin copy, прогоняй
|
|
173
|
+
hermes plugins doctor jev-layer и попроси /restart. После рестарта сделай live tool call,
|
|
174
|
+
запиши/прочитай exact receipt и только затем заявляй, что integration активна.
|
|
175
|
+
|
|
176
|
+
Не делай git push, npm publish, release или удаление replay/artifact без отдельной команды.
|
|
177
|
+
```
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Routing providers
|
|
2
|
+
|
|
3
|
+
CLI, stdio MCP, and the Hermes/OMP adapters use the same three providers. Routing, supervision, and browser decisions share provider resolution. The host still owns execution and approval.
|
|
4
|
+
|
|
5
|
+
| Provider | Default endpoint | Default model | Credentials |
|
|
6
|
+
| --- | --- | --- | --- |
|
|
7
|
+
| `demo` | None; deterministic word matching, no HTTP | `jev-demo` | None |
|
|
8
|
+
| `openrouter` | `https://openrouter.ai/api/alpha/decisions` | `typesafe/jev-1.13` | `OPENROUTER_API_KEY` |
|
|
9
|
+
| `typesafe` | `https://api.typesafe.ai/v1/systemone` | `jev-latest` | `TYPESAFE_API_KEY` |
|
|
10
|
+
|
|
11
|
+
Both remote providers send `{ model, state, questions }` with a Choice question and Bearer authentication. They use the [OpenRouter Decisions API](https://openrouter.ai/docs/api/api-reference/alphadecisions/submit-a-decisions-questions-and-answers-request) and the [official TypeSafe API](https://docs.typesafe.ai/api), respectively.
|
|
12
|
+
|
|
13
|
+
## Select a provider
|
|
14
|
+
|
|
15
|
+
For a stdio MCP process, export the selected provider's API key through your secret store into the harness environment, then choose one command:
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
JEV_LAYER_PROVIDER=demo jev mcp
|
|
19
|
+
JEV_LAYER_PROVIDER=openrouter jev mcp
|
|
20
|
+
JEV_LAYER_PROVIDER=typesafe jev mcp
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
For a single CLI request from the repository root:
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
jev cli --provider demo --input examples/route-request.json
|
|
27
|
+
jev cli --provider openrouter --input examples/route-request.json
|
|
28
|
+
jev cli --provider typesafe --input examples/route-request.json
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Selection precedence is: request `provider` → CLI `--provider` (CLI only) → `JEV_LAYER_PROVIDER` → `.jev/config.json` `provider` → `demo`. MCP launcher `env` entries count as process environment; update them when switching providers. Hermes and OMP delegate this choice to the CLI instead of forcing `demo`. The Hermes adapter's default process timeout is 10 seconds, allowing either provider's HTTP timeout to complete; `JEV_LAYER_TIMEOUT_S` overrides it.
|
|
32
|
+
|
|
33
|
+
`jev add <harness> --provider typesafe` generates configuration for TypeSafe in the target workspace. Use `--provider openrouter` or `--provider demo` for the other modes. Keep keys outside generated configuration.
|
|
34
|
+
|
|
35
|
+
## Endpoints, models, and custom environment names
|
|
36
|
+
|
|
37
|
+
- TypeSafe: `TYPESAFE_ENDPOINT`, `TYPESAFE_MODEL`.
|
|
38
|
+
- OpenRouter: `OPENROUTER_DECISIONS_ENDPOINT`, `OPENROUTER_DECISIONS_MODEL`; optional attribution headers use `OPENROUTER_HTTP_REFERER` and `OPENROUTER_APP_TITLE`.
|
|
39
|
+
- Endpoints are complete request URLs, including `/v1/systemone` or `/api/alpha/decisions`.
|
|
40
|
+
- Default HTTP timeouts are 2 seconds for TypeSafe and 5 seconds for OpenRouter. There are no provider retries; failures return control to the host.
|
|
41
|
+
|
|
42
|
+
The CLI and MCP read `.jev/config.json` from their working directory. `JEV_CONFIG` selects another file. To use secret-store-specific environment names, set only their names in the config:
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"provider": "typesafe",
|
|
47
|
+
"providers": {
|
|
48
|
+
"typesafe": {
|
|
49
|
+
"api_key_env": "MY_TYPESAFE_KEY",
|
|
50
|
+
"endpoint_env": "MY_TYPESAFE_ENDPOINT",
|
|
51
|
+
"model_env": "MY_TYPESAFE_MODEL"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Omitted fields retain the default environment names. A missing configured key returns `fallback` without an HTTP call, even if `TYPESAFE_API_KEY` is set. The same mapping is supported under `providers.openrouter`.
|
|
58
|
+
|
|
59
|
+
## Verification
|
|
60
|
+
|
|
61
|
+
`jev doctor` checks configuration and key presence; it does not run inference or validate a key with the provider.
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
node --test test/providers.test.mjs test/provider-transports.test.mjs
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
These offline checks cover all three provider selections, CLI/MCP precedence, custom environment names, Hermes/OMP transport, and fail-open behavior. Remote-provider requests use injected responses or a loopback HTTP server with fixture credentials. No paid inference, agent model, or real browser is invoked. Live provider/account availability requires a separately configured environment.
|