@alexlikevibe/pi-jev 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/LICENSE +21 -0
- package/README.md +340 -0
- package/README.zh-CN.md +340 -0
- package/bin/pi-jev.js +13 -0
- package/dist/cli/main.js +223 -0
- package/dist/commands/completions.js +87 -0
- package/dist/commands/extension.js +58 -0
- package/dist/commands/menu.js +245 -0
- package/dist/commands/models.js +23 -0
- package/dist/compaction/convert.js +87 -0
- package/dist/compaction/decision.js +195 -0
- package/dist/compaction/extension.js +150 -0
- package/dist/compaction/jev.js +72 -0
- package/dist/compaction/summarize.js +68 -0
- package/dist/routing/decide.js +57 -0
- package/dist/routing/extension.js +81 -0
- package/dist/shared/config.js +157 -0
- package/dist/vendor/fast-jev-compaction/client.js +25 -0
- package/dist/vendor/fast-jev-compaction/compact.js +233 -0
- package/dist/vendor/fast-jev-compaction/index.js +7 -0
- package/dist/vendor/fast-jev-compaction/request.js +50 -0
- package/dist/vendor/fast-jev-compaction/state.js +255 -0
- package/dist/vendor/fast-jev-compaction/types.js +1 -0
- package/extensions/compaction.ts +1 -0
- package/extensions/jev.ts +1 -0
- package/extensions/routing.ts +1 -0
- package/media/banner.svg +198 -0
- package/package.json +55 -0
- package/src/cli/main.ts +241 -0
- package/src/commands/completions.ts +107 -0
- package/src/commands/extension.ts +61 -0
- package/src/commands/menu.ts +291 -0
- package/src/commands/models.ts +43 -0
- package/src/compaction/convert.ts +95 -0
- package/src/compaction/decision.ts +262 -0
- package/src/compaction/extension.ts +235 -0
- package/src/compaction/jev.ts +133 -0
- package/src/compaction/summarize.ts +80 -0
- package/src/routing/decide.ts +81 -0
- package/src/routing/extension.ts +92 -0
- package/src/shared/config.ts +280 -0
- package/src/vendor/fast-jev-compaction/LICENSE +21 -0
- package/src/vendor/fast-jev-compaction/client.ts +43 -0
- package/src/vendor/fast-jev-compaction/compact.ts +309 -0
- package/src/vendor/fast-jev-compaction/index.ts +7 -0
- package/src/vendor/fast-jev-compaction/request.ts +80 -0
- package/src/vendor/fast-jev-compaction/state.ts +304 -0
- package/src/vendor/fast-jev-compaction/types.ts +202 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Fan Fei
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# pi-jev
|
|
4
|
+
|
|
5
|
+
**Selective context compaction and per-turn model routing for [pi](https://github.com/earendil-works/pi-coding-agent), powered by [Jev](https://typesafe.ai).**
|
|
6
|
+
|
|
7
|
+
**English** · [简体中文](README.zh-CN.md)
|
|
8
|
+
|
|
9
|
+
<img src="media/banner.svg" alt="Pi events trigger typed Jev requests: keep scores select context, and a difficulty score selects a model" width="100%">
|
|
10
|
+
|
|
11
|
+
[](https://github.com/iefnaf/pi-jev/actions/workflows/test.yml)
|
|
12
|
+
[](https://github.com/earendil-works/pi-coding-agent)
|
|
13
|
+
[](https://typesafe.ai)
|
|
14
|
+
[](LICENSE)
|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
pi-jev uses Jev's typed judgments to decide which tool outputs still matter and how demanding a user request is. It retains useful text instead of generating a new compaction summary, and can switch models before each turn. Both features are optional; if Jev is unavailable, pi continues with its normal compaction or the current model.
|
|
19
|
+
|
|
20
|
+
| Extension | Purpose | Pi integration |
|
|
21
|
+
| --- | --- | --- |
|
|
22
|
+
| **Compaction** | Remove obsolete tool calls, shorten unneeded results, and retain remaining text verbatim | `session_before_compact` |
|
|
23
|
+
| **Routing** | Send easy requests to a cheaper model and hard requests to a stronger model | `before_agent_start` |
|
|
24
|
+
| **`/jev` settings** | Configure providers, compaction, and routing from an interactive menu | `/jev` command |
|
|
25
|
+
|
|
26
|
+
Each extension can be enabled or disabled independently through `pi config`. Configuration changes are read on the next hook, without restarting pi.
|
|
27
|
+
|
|
28
|
+
## Quick start
|
|
29
|
+
|
|
30
|
+
You need pi installed and an API key for **one** Jev transport: TypeSafe or OpenRouter. Routing targets also need to be configured and authenticated in pi.
|
|
31
|
+
|
|
32
|
+
### 1. Configure a Jev API key
|
|
33
|
+
|
|
34
|
+
Choose one option in the shell where you will launch pi:
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
# Option A: TypeSafe
|
|
38
|
+
export TYPESAFE_API_KEY="your-typesafe-api-key"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
# Option B: OpenRouter
|
|
43
|
+
export OPENROUTER_API_KEY="your-openrouter-api-key"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The provider is auto-detected when no provider is explicitly configured. If both keys are present, TypeSafe wins; set `JEVC_PROVIDER=openrouter` to select OpenRouter explicitly.
|
|
47
|
+
|
|
48
|
+
### 2. Install and launch
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
pi install npm:@alexlikevibe/pi-jev
|
|
52
|
+
pi config # Review which pi-jev extensions are enabled
|
|
53
|
+
pi
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
If you install into an already running pi session, use `/reload` to load the extensions.
|
|
57
|
+
|
|
58
|
+
### 3. Configure inside pi
|
|
59
|
+
|
|
60
|
+
```text
|
|
61
|
+
/jev
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Open **Routing**, choose a `cheap` and/or `strong` target from pi's model list, then optionally choose a thinking level. **Routing stays inactive until at least one target is set.** Compaction needs no model-target configuration; it runs with `/compact` or pi's automatic compaction.
|
|
65
|
+
|
|
66
|
+
| Task | Command or action |
|
|
67
|
+
| --- | --- |
|
|
68
|
+
| Open settings | `/jev` |
|
|
69
|
+
| Compact the current session | `/compact` |
|
|
70
|
+
| Inspect available settings | `/jev keys` |
|
|
71
|
+
| Read a routing target | `/jev get routing.cheap` |
|
|
72
|
+
| Remove a routing target | `/jev unset routing.strong` |
|
|
73
|
+
| Temporarily bypass both features | `/jev set disabled true` |
|
|
74
|
+
| Re-enable both features | `/jev set disabled false` |
|
|
75
|
+
| Write a project setting | Append `-l`, e.g. `/jev set provider openrouter -l` |
|
|
76
|
+
|
|
77
|
+
Settings writes are **global by default**, including `disabled`; use `-l` for project scope. To bypass both features for one pi process, launch it with `JEVC_DISABLED=1 pi`.
|
|
78
|
+
|
|
79
|
+
<details>
|
|
80
|
+
<summary>Install from GitHub, a checkout, or load a single extension</summary>
|
|
81
|
+
|
|
82
|
+
To install directly from GitHub:
|
|
83
|
+
|
|
84
|
+
```sh
|
|
85
|
+
pi install https://github.com/iefnaf/pi-jev
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
From a local checkout:
|
|
89
|
+
|
|
90
|
+
```sh
|
|
91
|
+
git clone https://github.com/iefnaf/pi-jev.git
|
|
92
|
+
cd pi-jev
|
|
93
|
+
npm ci
|
|
94
|
+
npm run build
|
|
95
|
+
pi install /absolute/path/to/pi-jev
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
For a development run from the repository root:
|
|
99
|
+
|
|
100
|
+
```sh
|
|
101
|
+
pi -e ./extensions/compaction.ts
|
|
102
|
+
pi -e ./extensions/routing.ts
|
|
103
|
+
pi -e ./extensions/jev.ts
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Each command loads one extension explicitly. The project's `.pi/extensions/jev-*` loaders are also auto-discovered once the repository is trusted.
|
|
107
|
+
|
|
108
|
+
</details>
|
|
109
|
+
|
|
110
|
+
## Context compaction
|
|
111
|
+
|
|
112
|
+
Instead of asking a summarization model to rewrite the conversation, pi-jev asks Jev typed questions about each eligible tool call: whether to keep the call, whether to keep its full result (`noul`), and how stale the result is (`score`). It then renders the retained content as a transcript.
|
|
113
|
+
|
|
114
|
+
- **Keep:** retain user and assistant text, pinned recent messages, and useful tool calls/results. The previous compaction summary is included as-is.
|
|
115
|
+
- **Drop:** remove obsolete tool calls together with their results. The transcript header reports the removal count.
|
|
116
|
+
- **Shorten:** retain a tool call but shorten a long result to its first `truncateHeadChars` characters, followed by an explicit truncation marker. Short results may remain unchanged.
|
|
117
|
+
- **Rescue:** preserve a borderline result if a confident staleness judgment says it is still needed.
|
|
118
|
+
- **Fall back:** let pi generate its normal summary when Jev fails, the request is aborted, the span is empty, or the estimated reduction is below `minReduction`. Missing or malformed per-call answers conservatively retain the affected call.
|
|
119
|
+
|
|
120
|
+
Requests are batched to fit the configured state and request budgets; a compaction can use multiple Jev requests. Recent-message protection applies to the converted messages within the span pi supplies for compaction.
|
|
121
|
+
|
|
122
|
+
**Verbatim applies to retained text, not every original message field:** images become `[image]` placeholders and assistant thinking blocks are omitted during conversion. Tool inputs are serialized into the transcript.
|
|
123
|
+
|
|
124
|
+
### Example result
|
|
125
|
+
|
|
126
|
+
An example run recorded in this project reduced a converted span from **32 messages / 39,379 characters** to **16 messages / 9,553 characters** in **757 ms**, using one Jev request and 652 output tokens. This is an illustrative result, not a latency or reduction guarantee.
|
|
127
|
+
|
|
128
|
+
Successful compactions store audit data in the session's `compaction` entry:
|
|
129
|
+
|
|
130
|
+
```json
|
|
131
|
+
{
|
|
132
|
+
"engine": "jev",
|
|
133
|
+
"stats": {
|
|
134
|
+
"messagesBefore": 32,
|
|
135
|
+
"messagesAfter": 16,
|
|
136
|
+
"charsBefore": 39379,
|
|
137
|
+
"charsAfter": 9553,
|
|
138
|
+
"calls": 15,
|
|
139
|
+
"pinned": 3,
|
|
140
|
+
"callsDropped": 12,
|
|
141
|
+
"ms": 757,
|
|
142
|
+
"requests": 1,
|
|
143
|
+
"jevUsage": { "input": 9784, "output": 652 }
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
This abbreviated example is the entry's `details` object. Inspect `details.engine`, `details.stats`, and `details.decisions` for the full outcome. The hook preserves `firstKeptEntryId` so pi can retain the rest of the session correctly.
|
|
149
|
+
|
|
150
|
+
## Model routing
|
|
151
|
+
|
|
152
|
+
Before a turn, Jev evaluates the **current user prompt** on a three-level difficulty rubric:
|
|
153
|
+
|
|
154
|
+
| Level | Typical request |
|
|
155
|
+
| --- | --- |
|
|
156
|
+
| `0` — trivial | Greetings, quick questions, formatting, mechanical single-file edits |
|
|
157
|
+
| `1` — moderate | Everyday coding tasks |
|
|
158
|
+
| `2` — complex | Multi-file refactors, subtle debugging, architecture decisions |
|
|
159
|
+
|
|
160
|
+
With the default thresholds:
|
|
161
|
+
|
|
162
|
+
| Condition | Action |
|
|
163
|
+
| --- | --- |
|
|
164
|
+
| Difficulty ≤ `0.5`, confidence ≥ `0.6`, and `routing.cheap` is set | Switch to the cheap model |
|
|
165
|
+
| Difficulty ≥ `1.5`, confidence ≥ `0.6`, and `routing.strong` is set | Switch to the strong model |
|
|
166
|
+
| Middle band, low confidence, missing answer, or unset target | Keep the current model |
|
|
167
|
+
|
|
168
|
+
**A middle-band request keeps the current model, including a model selected by an earlier turn.** It does not reset to an initial default. Routing uses the prompt rather than the full conversation history.
|
|
169
|
+
|
|
170
|
+
Invalid model references, unknown models, missing provider authentication, and Jev failures keep the current model. A cheap target that only accepts text is skipped when the prompt includes images. Switching to the model already in use is a no-op. Successful switches and routing errors appear as pi UI notifications.
|
|
171
|
+
|
|
172
|
+
Targets use `provider/model-id`, with an optional `:thinking` suffix, such as `:high` or `:max`. Use `/jev` to select models actually configured in your pi installation; thinking settings take effect when a model switch occurs.
|
|
173
|
+
|
|
174
|
+
## Configuration
|
|
175
|
+
|
|
176
|
+
Settings resolve in this order, highest priority first:
|
|
177
|
+
|
|
178
|
+
1. Environment variables
|
|
179
|
+
2. Project file: `.pi/jev.json`
|
|
180
|
+
3. Global file: `~/.pi/agent/jev.json`
|
|
181
|
+
4. Built-in defaults
|
|
182
|
+
|
|
183
|
+
API keys are **environment-only** and are never written to configuration files. Hooks reload configuration on every event, so changes apply to the next turn or compaction. Environment overrides continue to win over settings changed through `/jev`.
|
|
184
|
+
|
|
185
|
+
### Interactive menu and commands
|
|
186
|
+
|
|
187
|
+
Bare `/jev` opens the settings menu in interactive pi:
|
|
188
|
+
|
|
189
|
+
```text
|
|
190
|
+
pi-jev
|
|
191
|
+
├─ Toggle scope (global ⇄ project)
|
|
192
|
+
├─ General provider · model · baseUrl · disabled
|
|
193
|
+
├─ Compaction thresholds and token budgets
|
|
194
|
+
├─ Routing cheap · strong → model → thinking level
|
|
195
|
+
└─ Show resolved config
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Typed commands support completion for actions, keys, and model references:
|
|
199
|
+
|
|
200
|
+
```text
|
|
201
|
+
/jev set provider openrouter -l
|
|
202
|
+
/jev get routing.cheap
|
|
203
|
+
/jev unset routing.strong
|
|
204
|
+
/jev keys
|
|
205
|
+
/jev path -l
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Configuration file example
|
|
209
|
+
|
|
210
|
+
A project `.pi/jev.json` can set the transport and compaction policy:
|
|
211
|
+
|
|
212
|
+
```json
|
|
213
|
+
{
|
|
214
|
+
"provider": "openrouter",
|
|
215
|
+
"disabled": false,
|
|
216
|
+
"compaction": {
|
|
217
|
+
"keepThreshold": 0.5,
|
|
218
|
+
"preserveRecentMessages": 3,
|
|
219
|
+
"minReduction": 0.15
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Add routing targets through `/jev` → **Routing**, or set `routing.cheap` / `routing.strong` to your configured model references. Either target can enable routing independently.
|
|
225
|
+
|
|
226
|
+
### Shell CLI
|
|
227
|
+
|
|
228
|
+
From a built checkout, the CLI manages the same settings files:
|
|
229
|
+
|
|
230
|
+
```sh
|
|
231
|
+
node bin/pi-jev.js config
|
|
232
|
+
node bin/pi-jev.js config set provider openrouter -l
|
|
233
|
+
node bin/pi-jev.js config get routing.cheap
|
|
234
|
+
node bin/pi-jev.js config unset routing.strong
|
|
235
|
+
node bin/pi-jev.js config keys
|
|
236
|
+
node bin/pi-jev.js config path -l
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
If the package's executable is on your `PATH`, use `pi-jev config …` instead. `get` reads the resolved value; `set`, `unset`, and `path` use global scope unless `-l` / `--project` is supplied.
|
|
240
|
+
|
|
241
|
+
### Jev transports
|
|
242
|
+
|
|
243
|
+
These are the defaults implemented by this project:
|
|
244
|
+
|
|
245
|
+
| Setting | TypeSafe | OpenRouter |
|
|
246
|
+
| --- | --- | --- |
|
|
247
|
+
| Provider | `typesafe` | `openrouter` |
|
|
248
|
+
| Endpoint | `https://api.typesafe.ai/v1/systemone` | `https://openrouter.ai/api/alpha/decisions` (alpha) |
|
|
249
|
+
| API key | `TYPESAFE_API_KEY` | `OPENROUTER_API_KEY` |
|
|
250
|
+
| Jev model | `jev-latest` | `typesafe/jev-1.13` |
|
|
251
|
+
|
|
252
|
+
Both use the `{ model, state, questions }` → `{ answers }` protocol. The Jev model is separate from the pi models chosen as routing targets.
|
|
253
|
+
|
|
254
|
+
`JEVC_API_KEY` overrides the selected provider's key. It does not select the provider by itself; pair it with `JEVC_PROVIDER=openrouter` when using an OpenRouter key.
|
|
255
|
+
|
|
256
|
+
### Environment variables
|
|
257
|
+
|
|
258
|
+
General:
|
|
259
|
+
|
|
260
|
+
| Variable | Default | Purpose |
|
|
261
|
+
| --- | --- | --- |
|
|
262
|
+
| `TYPESAFE_API_KEY` | Unset | TypeSafe authentication |
|
|
263
|
+
| `OPENROUTER_API_KEY` | Unset | OpenRouter authentication |
|
|
264
|
+
| `JEVC_API_KEY` | Unset | Override the selected provider's API key |
|
|
265
|
+
| `JEVC_PROVIDER` | Auto-detected | `typesafe` or `openrouter` |
|
|
266
|
+
| `JEVC_MODEL` | Per transport | Jev model slug |
|
|
267
|
+
| `JEVC_BASE_URL` | Per transport | Jev endpoint URL |
|
|
268
|
+
| `JEVC_DISABLED` | `false` | `1`, `true`, or `yes` bypasses both hooks |
|
|
269
|
+
|
|
270
|
+
Compaction:
|
|
271
|
+
|
|
272
|
+
| Variable | Config key | Default |
|
|
273
|
+
| --- | --- | --- |
|
|
274
|
+
| `JEVC_KEEP_THRESHOLD` | `compaction.keepThreshold` | `0.5` |
|
|
275
|
+
| `JEVC_BORDERLINE` | `compaction.borderline` | `0.1` |
|
|
276
|
+
| `JEVC_PRESERVE_RECENT` | `compaction.preserveRecentMessages` | `3` |
|
|
277
|
+
| `JEVC_TRUNCATE_HEAD` | `compaction.truncateHeadChars` | `300` |
|
|
278
|
+
| `JEVC_MIN_REDUCTION` | `compaction.minReduction` | `0.15` |
|
|
279
|
+
| `JEVC_MAX_STATE_TOKENS` | `compaction.maxStateTokens` | `25000` |
|
|
280
|
+
| `JEVC_MAX_REQUEST_TOKENS` | `compaction.maxRequestTokens` | `30000` |
|
|
281
|
+
|
|
282
|
+
`keepThreshold` controls verbatim retention, while `borderline` defines the band below it where a staleness answer can rescue a result. `preserveRecentMessages` pins recent converted messages; `truncateHeadChars` limits shortened result heads. `minReduction` is the estimated reduction required to replace pi's summary. The token ceilings bound Jev state and state-plus-questions requests.
|
|
283
|
+
|
|
284
|
+
Routing:
|
|
285
|
+
|
|
286
|
+
| Variable | Default | Purpose |
|
|
287
|
+
| --- | --- | --- |
|
|
288
|
+
| `JEVC_ROUTE_CHEAP` | Unset | Easy-request model reference |
|
|
289
|
+
| `JEVC_ROUTE_STRONG` | Unset | Hard-request model reference |
|
|
290
|
+
| `JEVC_ROUTE_EASY_MAX` | `0.5` | Maximum difficulty for the cheap target |
|
|
291
|
+
| `JEVC_ROUTE_HARD_MIN` | `1.5` | Minimum difficulty for the strong target |
|
|
292
|
+
| `JEVC_ROUTE_MIN_CONFIDENCE` | `0.6` | Minimum confidence to switch models |
|
|
293
|
+
|
|
294
|
+
The routing thresholds are advanced overrides supported by the config loader; they are not exposed in the settings menu or CLI key list.
|
|
295
|
+
|
|
296
|
+
## Troubleshooting
|
|
297
|
+
|
|
298
|
+
| Symptom | What to check |
|
|
299
|
+
| --- | --- |
|
|
300
|
+
| `/jev` is unavailable | Enable `extensions/jev.ts` through `pi config`, then `/reload` if needed |
|
|
301
|
+
| Compaction uses pi's normal summary | Check the selected provider's API key, `disabled`, Jev errors, and `minReduction` |
|
|
302
|
+
| Routing never switches models | Set at least one target, verify pi model authentication, and check difficulty/confidence gates |
|
|
303
|
+
| A setting change has no effect | Check environment overrides and project settings, which take priority over global settings |
|
|
304
|
+
| The checkout CLI cannot find `dist/cli/main.js` | Run `npm run build` |
|
|
305
|
+
|
|
306
|
+
## Development
|
|
307
|
+
|
|
308
|
+
Node.js 22 is used in CI. From the repository root:
|
|
309
|
+
|
|
310
|
+
```sh
|
|
311
|
+
npm ci
|
|
312
|
+
npm run typecheck
|
|
313
|
+
npm test
|
|
314
|
+
npm run build
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
Tests use fixtures and fake `JevAsker` implementations and do not call the Jev API. They cover compaction decisions and conversion, routing, configuration precedence, the CLI, completions, model picking, and menu screens.
|
|
318
|
+
|
|
319
|
+
| Path | Responsibility |
|
|
320
|
+
| --- | --- |
|
|
321
|
+
| [src/compaction](src/compaction) | Message conversion, Jev batching, retention rules, transcript rendering, and the compaction hook |
|
|
322
|
+
| [src/routing](src/routing) | Difficulty decisions and model switching |
|
|
323
|
+
| [src/commands](src/commands) | `/jev`, settings menus, completion, and model selection |
|
|
324
|
+
| [src/cli](src/cli) | Shared configuration command engine |
|
|
325
|
+
| [src/shared/config.ts](src/shared/config.ts) | Configuration layers, defaults, and key metadata |
|
|
326
|
+
| [extensions](extensions) | Extension entry points |
|
|
327
|
+
| [src/vendor/fast-jev-compaction](src/vendor/fast-jev-compaction) | Vendored Jev client and compaction primitives |
|
|
328
|
+
| [test](test) | Offline test suite |
|
|
329
|
+
|
|
330
|
+
To add a feature, create `src/<feature>/` with a default-export extension factory and pure helper modules, add a thin entry point in `extensions/`, define configuration in `src/shared/config.ts`, and cover the behavior in `test/`. Jev request failures must allow pi to continue.
|
|
331
|
+
|
|
332
|
+
## Acknowledgments
|
|
333
|
+
|
|
334
|
+
- [tamaratran/fast-jev-compaction](https://github.com/tamaratran/fast-jev-compaction): vendored MIT Jev client and compaction primitives; its license is retained alongside the source.
|
|
335
|
+
- [@narumitw/pi-tui-kit](https://www.npmjs.com/package/@narumitw/pi-tui-kit): the interactive `/jev` settings menu.
|
|
336
|
+
- [TypeSafe](https://typesafe.ai): Jev System One; OpenRouter provides the alternative Decisions API transport.
|
|
337
|
+
|
|
338
|
+
## License
|
|
339
|
+
|
|
340
|
+
[MIT](LICENSE).
|