pi-jev-lens 0.2.0 → 0.2.1
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/README.md +154 -133
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
# pi-jev-lens
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
function
|
|
3
|
+
Your coding agent reads a 600-line file to change one function. jev-lens sends the model the outline of the file and
|
|
4
|
+
that one function. The agent can ask for the rest with the `recall` tool, and the footer of the result tells it so.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
session. jev-lens
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
agent can ask for exactly the part
|
|
6
|
+
jev-lens is an extension for [pi](https://github.com/earendil-works/pi-mono), the coding agent. Tool output is most
|
|
7
|
+
of what a coding agent pays for. Every `cat`, every test run and every `grep` goes into the prompt in full and stays
|
|
8
|
+
there for the rest of the session. jev-lens acts before that first send. Code builds a small set of candidate views
|
|
9
|
+
of the output. A view is a subset of the lines of the output, with line numbers. Then [jev](https://docs.typesafe.ai),
|
|
10
|
+
the judgment model from TypeSafe, picks the smallest view that still lets the agent do its next step. Nothing is
|
|
11
|
+
generated or summarized. Every view is made of lines from the original, so the agent can ask for exactly the part
|
|
12
|
+
that it does not have.
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
This is what the model sees instead of a file of 1.5k tokens:
|
|
14
15
|
|
|
15
16
|
```
|
|
16
17
|
1│ import { parse } from "./parse.js";
|
|
@@ -29,51 +30,57 @@ full output, or recall(id, lines: "a-b") / recall(id, pattern: "...") for a slic
|
|
|
29
30
|
|
|
30
31
|
## What the numbers say
|
|
31
32
|
|
|
32
|
-
We
|
|
33
|
-
|
|
33
|
+
We measured the defaults on 500 real agent trajectories (OpenHands on SWE-rebench: 3300 large tool results, 11.6
|
|
34
|
+
million tokens) and on our own daily pi sessions. A token is the unit that a model provider bills. The research log
|
|
35
|
+
is STATUS.md. These are the main results:
|
|
34
36
|
|
|
35
|
-
| | |
|
|
37
|
+
| result | source |
|
|
36
38
|
|---|---|
|
|
37
|
-
|
|
|
38
|
-
|
|
|
39
|
-
|
|
|
40
|
-
|
|
|
41
|
-
|
|
|
42
|
-
|
|
43
|
-
Read the two savings numbers together. The benchmark agent spends its output budget on pytest runs and grep,
|
|
44
|
-
compress to almost nothing
|
|
45
|
-
the one thing
|
|
46
|
-
whole session,
|
|
47
|
-
percentage. What you save depends on what your agent reads.
|
|
48
|
-
|
|
49
|
-
Three
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
39
|
+
| 79 % fewer tokens sent for large tool results (11.6M became 2.4M) | the 500 benchmark trajectories |
|
|
40
|
+
| 88 % fewer on command output (test runs, grep, build logs), 58 % on docs, 47 % on listings, 31 % on code | the same, per kind of output |
|
|
41
|
+
| 31 % fewer tokens for large tool results | our own sessions with gpt-6-astra, which reads code with `cat` and runs few tests |
|
|
42
|
+
| 2 of 26 later edits missed their block, 0.3 % of results had a dropped line quoted, 2.2 % had a dropped identifier used | the harm side, same 500 trajectories |
|
|
43
|
+
| 8 % lower cost, 17 % smaller final prompt, the same pass rate, zero recalls | live end-to-end runs in pi where the agent reads big files, 3 runs each |
|
|
44
|
+
|
|
45
|
+
Read the two savings numbers together. The benchmark agent spends its output budget on pytest runs and grep, and
|
|
46
|
+
those compress to almost nothing. An agent that mostly reads source code sits closer to the code number, because
|
|
47
|
+
code is the one thing that jev-lens does not compress unless jev is confident. Both numbers are shares of large tool
|
|
48
|
+
results only. Over a whole session, the footer counts the system prompt, the conversation and every small result too,
|
|
49
|
+
so it will show a lower percentage. What you save depends on what your agent reads.
|
|
50
|
+
|
|
51
|
+
Three results shaped the design:
|
|
52
|
+
|
|
53
|
+
1. Compress before the first send, not after. Pruning old results later removes 19 % of the tokens and costs 17 %
|
|
54
|
+
more money, because every rewrite of an old message breaks the prompt cache. The prompt cache is the provider's
|
|
55
|
+
discount for a prompt prefix that did not change since the last call. Post-send pruning is still in the code, but
|
|
56
|
+
it is off by default.
|
|
57
|
+
2. Code is different. Test logs and grep output can lose 90 % of their lines and the agent does not miss them. The
|
|
58
|
+
agent edits from code, and an edit fails when its old text is a line that the model never saw. So views of code
|
|
59
|
+
keep every retained line byte for byte, and code is sent in full unless jev is confident. The policy that always
|
|
60
|
+
sends an outline saved more and missed 17 % of later edits. It is available, but you must turn it on.
|
|
61
|
+
3. Views built in code beat prompt tuning. In four rounds, a researcher model rewrote the questions to jev and the
|
|
62
|
+
thresholds. None of its changes held up on data that it had not seen. Every gain that held was a new kind of view:
|
|
63
|
+
only the failing tests, grep match groups, JSON keys, the file that the agent read with `cat`.
|
|
59
64
|
|
|
60
65
|
## Install
|
|
61
66
|
|
|
62
67
|
```sh
|
|
63
68
|
pi install npm:pi-jev-lens # from npm
|
|
64
|
-
pi install git:github.com/dizk/pi-jev-lens # or
|
|
69
|
+
pi install git:github.com/dizk/pi-jev-lens # or from GitHub
|
|
65
70
|
```
|
|
66
71
|
|
|
67
|
-
jev needs a TypeSafe API key
|
|
68
|
-
|
|
72
|
+
jev needs a TypeSafe API key. You can get one at [console.typesafe.ai](https://console.typesafe.ai). jev-lens looks
|
|
73
|
+
for the key in this order:
|
|
69
74
|
|
|
70
75
|
1. `TYPESAFE_API_KEY` in the environment.
|
|
71
|
-
2. `/jev-lens key` inside pi
|
|
72
|
-
`~/.pi/agent/jev-lens.json`, readable only by you. jev is active from
|
|
73
|
-
|
|
76
|
+
2. The key that you stored with `/jev-lens key` inside pi. The command prompts for the key, or you can give it as
|
|
77
|
+
`/jev-lens key ts_...`. The key is stored in `~/.pi/agent/jev-lens.json`, readable only by you. jev is active from
|
|
78
|
+
the next tool result. You do not have to restart pi.
|
|
79
|
+
3. A `.env` file next to the installed package. This is for development.
|
|
74
80
|
|
|
75
|
-
|
|
76
|
-
|
|
81
|
+
If no key is found, the extension shows a warning at startup and runs a mock classifier that compresses nothing.
|
|
82
|
+
|
|
83
|
+
For development, clone the repository and load it directly:
|
|
77
84
|
|
|
78
85
|
```sh
|
|
79
86
|
git clone https://github.com/dizk/pi-jev-lens.git && cd pi-jev-lens && npm install
|
|
@@ -83,68 +90,73 @@ pi -e ./index.ts
|
|
|
83
90
|
|
|
84
91
|
## How it works
|
|
85
92
|
|
|
86
|
-
Every text tool result of at least 1200 estimated tokens (about 5 kB)
|
|
87
|
-
|
|
88
|
-
with line numbers and
|
|
93
|
+
Every text tool result of at least 1200 estimated tokens (about 5 kB) goes through pi's `tool_result` hook before
|
|
94
|
+
pi stores it or sends it. jev-lens never touches smaller results. Code builds the candidate views. Each view is a
|
|
95
|
+
subset of the lines of the output, with line numbers and markers for the omitted lines. No text is generated.
|
|
89
96
|
|
|
90
97
|
| view | for | keeps |
|
|
91
98
|
|---|---|---|
|
|
92
99
|
| `outline` | code, prose | imports, exports, signatures, headings, doc comments |
|
|
93
|
-
| `relevant` | code, command output | outline or section headers plus the full bodies jev says the agent will need (second jev step) |
|
|
94
|
-
| `sections` | command output | the first line of every section: grep match groups, JSON keys, headings, `COMMAND
|
|
100
|
+
| `relevant` | code, command output | the outline or the section headers, plus the full bodies that jev says the agent will need (second jev step) |
|
|
101
|
+
| `sections` | command output | the first line of every section: grep match groups, JSON keys, headings, markers like `COMMAND:`, paragraphs |
|
|
95
102
|
| `signals` | command output | errors, warnings, failing tests, summary lines, the tail |
|
|
96
103
|
| `testlog` | test output | failures, assertions, tracebacks and summaries |
|
|
97
|
-
| `matches` | search output | first matches per file, with
|
|
104
|
+
| `matches` | search output | the first matches per file, with a count of the omitted ones |
|
|
98
105
|
| `log` | repetitive output | representative repeated lines, errors and the tail |
|
|
99
|
-
| `tree` | directory listings | a sample of entries per directory, with
|
|
100
|
-
| `focus` | anything | lines
|
|
101
|
-
| `sample` | tabular or log-like data | header, a dozen rows, the count |
|
|
102
|
-
| `head_tail` | anything | first and last lines |
|
|
103
|
-
|
|
104
|
-
jev then answers two questions
|
|
105
|
-
|
|
106
|
-
yes
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
106
|
+
| `tree` | directory listings | a sample of entries per directory, with a count of the omitted ones |
|
|
107
|
+
| `focus` | anything | the lines that mention identifiers from the task and the tool call, with context |
|
|
108
|
+
| `sample` | tabular or log-like data | the header, a dozen rows, the count |
|
|
109
|
+
| `head_tail` | anything | the first and the last lines |
|
|
110
|
+
|
|
111
|
+
jev then answers two questions. It sees the task, the text that the assistant wrote before the call, and a preview of
|
|
112
|
+
each view. The questions are: which view is the smallest one that is still enough (a choice), and will the next step
|
|
113
|
+
need the exact full text (yes or no). If jev chose an outline or a `sections` view, a second request asks, for each
|
|
114
|
+
block or section, whether the agent will need its body. Those bodies go back into the view. If the result reaches
|
|
115
|
+
90 % of the original size, jev-lens sends the full text instead.
|
|
116
|
+
|
|
117
|
+
These rules make it safe for the agent to edit from a view:
|
|
118
|
+
|
|
119
|
+
- Views of code and prose keep every retained line exactly as it is. An edit whose old text was copied from the view
|
|
120
|
+
still matches the file. Views of command output shorten decorative bars and very long lines.
|
|
121
|
+
- Files that the agent reads through bash (`cat a.py b.py`, `sed -n '1,80p' x.ts`, `head`, brace groups, globs) count
|
|
122
|
+
as code or prose and get the same views as the `read` tool. If the command also does something else, the output
|
|
123
|
+
stays command output.
|
|
124
|
+
- jev-lens never reduces the results of the agent's own `edit` and `write` tools.
|
|
125
|
+
- jev-lens sends code in full unless jev is confident that a view is enough. This is the `gate` policy. The
|
|
126
|
+
`outline` policy always sends an outline plus expanded bodies. It saves more, but it missed 17 % of later edits on
|
|
127
|
+
real trajectories, so you must turn it on yourself.
|
|
128
|
+
|
|
129
|
+
The code structure comes from tree-sitter (grammars from `@vscode/tree-sitter-wasm` and
|
|
130
|
+
`@binclusive/tree-sitter-kotlin-wasm`): TypeScript, TSX, JavaScript, Kotlin, Java, Rust, Python, Go, C, C++, C#,
|
|
131
|
+
Ruby, PHP, Bash, CSS. Large classes are split into their members. For other languages, jev-lens uses regular
|
|
132
|
+
expressions that know the common declaration keywords.
|
|
133
|
+
|
|
134
|
+
When jev-lens compresses a result, it keeps the full output in the result's `details`. pi persists that in the
|
|
135
|
+
session but never sends it to the model. The footer names the `recall` tool, which serves the full output back by
|
|
136
|
+
id, by line range or by pattern. jev-lens logs every recall as a signal that a view was too small.
|
|
126
137
|
|
|
127
138
|
## In pi
|
|
128
139
|
|
|
129
|
-
The footer shows the share of the session's input tokens jev kept out of the prompt, and what it did:
|
|
140
|
+
The footer shows the share of the session's input tokens that jev kept out of the prompt, and what it did:
|
|
130
141
|
|
|
131
142
|
```
|
|
132
143
|
jev-lens −38% of input (presend −12.3k · 5/8 · 1 recalls)
|
|
133
144
|
```
|
|
134
145
|
|
|
135
|
-
The share is cut
|
|
136
|
-
every compressed result saved on every call it was part of.
|
|
146
|
+
The share is cut divided by sent plus cut. Sent is the provider's own count of input and cache-read tokens over all
|
|
147
|
+
calls. Cut is what every compressed result saved on every call that it was part of.
|
|
137
148
|
|
|
138
|
-
In the transcript a compressed result shows a header like `⌁ jev-lens outline · 179 of 1524 tokens (−88 %)
|
|
139
|
-
|
|
149
|
+
In the transcript, a compressed result shows a header like `⌁ jev-lens outline · 179 of 1524 tokens (−88 %)`. When
|
|
150
|
+
you expand it with ctrl+e, you see exactly what the model saw. These commands are available:
|
|
140
151
|
|
|
141
|
-
- `/jev-lens`
|
|
142
|
-
- `/jev-lens list` the latest 200 compressed results with tokens before and after
|
|
143
|
-
- `/jev-lens diff [n]` overlay
|
|
144
|
-
|
|
145
|
-
- `/jev-lens key`
|
|
152
|
+
- `/jev-lens` shows the statistics and where the key comes from.
|
|
153
|
+
- `/jev-lens list` lists the latest 200 compressed results with the tokens before and after.
|
|
154
|
+
- `/jev-lens diff [n]` opens an overlay for the n-th latest result. It shows the original with the lines that the
|
|
155
|
+
model did not get marked with `−`. Press `t` to see what was sent, and `Esc` to close.
|
|
156
|
+
- `/jev-lens key` stores the API key.
|
|
146
157
|
|
|
147
|
-
|
|
158
|
+
jev-lens logs every decision to `<project>/.pi/jev-lens.log` as JSON lines. Set `JEV_LENS_UI=0` to keep pi's own
|
|
159
|
+
tool rendering.
|
|
148
160
|
|
|
149
161
|
### Configuration (environment)
|
|
150
162
|
|
|
@@ -152,29 +164,34 @@ Every decision is logged to `<project>/.pi/jev-lens.log` (JSON lines). `JEV_LENS
|
|
|
152
164
|
|---|---|---|
|
|
153
165
|
| `JEV_LENS_PRESEND` | `1` | `0` turns compression off |
|
|
154
166
|
| `JEV_LENS_PRESEND_MIN_TOKENS` | `1200` | smaller results are always sent in full |
|
|
155
|
-
| `JEV_LENS_PRESEND_NEEDS_FULL_ABOVE` / `_FULL_MASS_ABOVE` | `0.5` / `0.5` | send full when P(needs full) or P(full view)
|
|
156
|
-
| `JEV_LENS_PRESEND_CODE_POLICY` | `gate` | `outline`: always send an outline plus expanded bodies (more savings, more
|
|
157
|
-
| `JEV_LENS_PRESEND_CODE_NEEDS_FULL_ABOVE` | `0.5` | code uses the
|
|
158
|
-
| `JEV_LENS_PRESEND_EXPAND_ABOVE` | `0.5` | expand a code block
|
|
159
|
-
| `JEV_LENS_PRESEND_COMMAND_NEEDS_FULL_ABOVE` | `0.65` | needs-full threshold for command output |
|
|
160
|
-
| `JEV_LENS_PRESEND_COMMAND_POLICY` | `sections` | when jev picks full for command output but needs-full is low, send section headers and expand the needed sections. `gate`: jev's choice
|
|
161
|
-
| `JEV_LENS_PRESEND_SECTION_EXPAND_ABOVE` | `0.5` | expand a section when P(needed)
|
|
162
|
-
| `JEV_LENS_PRESEND_SECTION_FLOOR` | `0.3` | send full when no section reaches this probability
|
|
163
|
-
| `JEV_LENS_PRESEND_MIN_CONFIDENCE` | `0` | send full below this choice confidence
|
|
164
|
-
| `JEV_LENS_MODEL` | `jev-latest` | jev model |
|
|
165
|
-
| `JEV_LENS_CLASSIFIER` | unset | `mock` forces the deterministic classifier, no API calls |
|
|
166
|
-
| `JEV_LENS_LOG` | `1` | `0`
|
|
167
|
-
| `JEV_LENS_UI` | `1` | `0`
|
|
168
|
-
| `JEV_LENS_VARIANT` | unset | JSON file with `config`, `prompts` and `views` overrides, as
|
|
167
|
+
| `JEV_LENS_PRESEND_NEEDS_FULL_ABOVE` / `_FULL_MASS_ABOVE` | `0.5` / `0.5` | send full when P(needs full) or P(full view) is above these |
|
|
168
|
+
| `JEV_LENS_PRESEND_CODE_POLICY` | `gate` | `outline`: always send an outline plus expanded bodies (more savings, more missed edits) |
|
|
169
|
+
| `JEV_LENS_PRESEND_CODE_NEEDS_FULL_ABOVE` | `0.5` | code uses the lower of this and the general needs-full threshold |
|
|
170
|
+
| `JEV_LENS_PRESEND_EXPAND_ABOVE` | `0.5` | expand the body of a code block when P(needed) is above this |
|
|
171
|
+
| `JEV_LENS_PRESEND_COMMAND_NEEDS_FULL_ABOVE` | `0.65` | the needs-full threshold for command output |
|
|
172
|
+
| `JEV_LENS_PRESEND_COMMAND_POLICY` | `sections` | when jev picks full for command output but needs-full is low, send the section headers and expand the needed sections. `gate`: keep jev's choice |
|
|
173
|
+
| `JEV_LENS_PRESEND_SECTION_EXPAND_ABOVE` | `0.5` | expand a section when P(needed) is above this |
|
|
174
|
+
| `JEV_LENS_PRESEND_SECTION_FLOOR` | `0.3` | send full when no section reaches this probability, because jev could not tell. `0` allows headers alone |
|
|
175
|
+
| `JEV_LENS_PRESEND_MIN_CONFIDENCE` | `0` | send full below this choice confidence. `0` turns the check off |
|
|
176
|
+
| `JEV_LENS_MODEL` | `jev-latest` | the jev model |
|
|
177
|
+
| `JEV_LENS_CLASSIFIER` | unset | `mock` forces the deterministic classifier, with no API calls |
|
|
178
|
+
| `JEV_LENS_LOG` | `1` | `0` turns logging off |
|
|
179
|
+
| `JEV_LENS_UI` | `1` | `0` turns the custom tool rendering off |
|
|
180
|
+
| `JEV_LENS_VARIANT` | unset | a JSON file with `config`, `prompts` and `views` overrides, as the autoresearch loop writes it |
|
|
169
181
|
| `JEV_LENS_MODE` | `off` | optional post-send pruning, see below |
|
|
170
182
|
|
|
171
183
|
## Evaluation
|
|
172
184
|
|
|
173
|
-
Every change
|
|
174
|
-
|
|
175
|
-
`eval/bench/fetch.sh`
|
|
176
|
-
|
|
177
|
-
|
|
185
|
+
Every change is scored against what the agent did next in a recorded trajectory. That is the only honest judge of
|
|
186
|
+
whether the agent needed the text. The benchmark uses real OpenHands trajectories in `eval/bench/`. The script
|
|
187
|
+
`eval/bench/fetch.sh` downloads the data. The metrics are:
|
|
188
|
+
|
|
189
|
+
- edit-miss: the agent later edited a line that the view had dropped.
|
|
190
|
+
- quote-miss: the agent quoted text that the view had dropped.
|
|
191
|
+
- ref-miss: the agent used an identifier that only existed in the dropped part.
|
|
192
|
+
|
|
193
|
+
An edit-miss counts five times in the objective, and edit-misses are rare. So you must score every change that
|
|
194
|
+
touches code views on the 500-trajectory slice, not only on the 100-trajectory holdout.
|
|
178
195
|
|
|
179
196
|
| slice | large results | saved | edit-miss | quote-miss | ref-miss |
|
|
180
197
|
|---|---|---|---|---|---|
|
|
@@ -183,52 +200,56 @@ the objective, and they are rare, so anything that touches code views must be sc
|
|
|
183
200
|
|
|
184
201
|
```sh
|
|
185
202
|
npm test # unit tests, mock classifier
|
|
186
|
-
node --import tsx eval/bench/run.ts --from 200 --to 300 # holdout,
|
|
187
|
-
node --import tsx eval/bench/run.ts --from 300 --to 800 # the 500-trajectory slice,
|
|
203
|
+
node --import tsx eval/bench/run.ts --from 200 --to 300 # the holdout, about 4 minutes
|
|
204
|
+
node --import tsx eval/bench/run.ts --from 300 --to 800 # the 500-trajectory slice, about 20 minutes
|
|
188
205
|
node --import tsx eval/presend-replay.ts <session dir> # replay your own pi sessions from ~/.pi/agent/sessions
|
|
189
|
-
node --import tsx eval/bench/autoresearch.ts --iterations 8 # a researcher model tunes prompts and thresholds
|
|
206
|
+
node --import tsx eval/bench/autoresearch.ts --iterations 8 # a researcher model tunes the prompts and thresholds
|
|
190
207
|
```
|
|
191
208
|
|
|
192
|
-
STATUS.md is the research log
|
|
193
|
-
|
|
194
|
-
until the slice was five times larger.
|
|
209
|
+
STATUS.md is the research log. It lists every variant that we tried, its numbers, and why the defaults are what they
|
|
210
|
+
are. In short: new code-built views moved the numbers, prompt wording did not, and the small holdout was wrong about
|
|
211
|
+
code until the slice was five times larger.
|
|
195
212
|
|
|
196
213
|
## Optional: post-send pruning
|
|
197
214
|
|
|
198
|
-
`JEV_LENS_MODE=budget` (or `rolling`, `batch`) turns on a second layer
|
|
199
|
-
jev judges whether
|
|
200
|
-
|
|
201
|
-
possible
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
`
|
|
207
|
-
|
|
215
|
+
`JEV_LENS_MODE=budget` (or `rolling`, or `batch`) turns on a second layer. After the agent reacted to a tool result,
|
|
216
|
+
jev judges whether the result is still needed. In later prompts, a result that is not needed is cut to its head and
|
|
217
|
+
tail, or replaced by a stub of one line. jev-lens persists each decision and freezes it after the first use, so the
|
|
218
|
+
cached prefix is rewritten as rarely as possible. The `budget` mode only rewrites when the pending cuts remove at least
|
|
219
|
+
half of the tail that they would touch. On real sessions, this layer frees context but does not save money under
|
|
220
|
+
prompt-cache pricing. That is why it is off by default.
|
|
221
|
+
|
|
222
|
+
Its settings are `JEV_LENS_BUDGET_FRACTION` and `JEV_LENS_BUDGET_MIN_TOKENS` (`0.5` and `1000`), `JEV_LENS_FORGET_BELOW`
|
|
223
|
+
(`0.25`), `JEV_LENS_TRIM_BELOW` and `JEV_LENS_TRIM_ABOVE` (`0.5` and `0.6`), `JEV_LENS_MIN_TOKENS` (`150`),
|
|
224
|
+
`JEV_LENS_TRIM_HEAD` and `JEV_LENS_TRIM_TAIL` (`15` and `15`), `JEV_LENS_CLASSIFY_WAIT_MS` (`2500`),
|
|
225
|
+
`JEV_LENS_CACHE_TTL_MS` (`300000`), `JEV_LENS_STATE_HEAD` and `JEV_LENS_STATE_TAIL` (`2500` and `800`), and
|
|
226
|
+
`JEV_LENS_DISABLED=1` (new decisions become `keep`). The command `/jev-lens decisions` lists the decisions. jev-lens
|
|
227
|
+
never removes a tool result. It only rewrites it.
|
|
208
228
|
|
|
209
229
|
## Using this as a reference
|
|
210
230
|
|
|
211
|
-
The pieces
|
|
231
|
+
The pieces do not depend on pi. You can lift them into another agent:
|
|
212
232
|
|
|
213
233
|
| piece | file | depends on |
|
|
214
234
|
|---|---|---|
|
|
215
|
-
| candidate views | `src/views.ts` | nothing
|
|
235
|
+
| candidate views | `src/views.ts` | nothing. The async code views can load `src/treesitter.ts` |
|
|
216
236
|
| tree-sitter blocks and signatures | `src/treesitter.ts` | `web-tree-sitter`, `@vscode/tree-sitter-wasm`, `@binclusive/tree-sitter-kotlin-wasm` |
|
|
217
|
-
| the jev questions, state shape, decision rule, block expansion | `src/presend.ts` | `@typesafe-ai/sdk` |
|
|
218
|
-
| bash display
|
|
219
|
-
| the hook wiring for pi (tool_result, recall tool, UI) | `index.ts`, `src/ui.ts` | pi |
|
|
220
|
-
| benchmark and metrics on real trajectories | `eval/presend-score.ts`, `eval/bench/` | run `eval/bench/fetch.sh` first |
|
|
237
|
+
| the jev questions, the state shape, the decision rule, block expansion | `src/presend.ts` | `@typesafe-ai/sdk` |
|
|
238
|
+
| the parser for bash display commands | `src/shell-display.ts` | nothing |
|
|
239
|
+
| the hook wiring for pi (tool_result, the recall tool, the UI) | `index.ts`, `src/ui.ts` | pi |
|
|
240
|
+
| the benchmark and the metrics on real trajectories | `eval/presend-score.ts`, `eval/bench/` | run `eval/bench/fetch.sh` first |
|
|
221
241
|
| post-send decisions and the frozen ledger | `src/classifier.ts`, `src/policy.ts`, `src/ledger.ts` | `@typesafe-ai/sdk` |
|
|
222
242
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
full text in the result
|
|
243
|
+
The sequence is this. When a large tool result arrives, code builds the views from the text. jev says which view is
|
|
244
|
+
enough and whether the exact text is needed. Code applies the selection policy. If needed, a second request expands
|
|
245
|
+
blocks or sections. If a reduced view wins, the content becomes that view plus a footer that names `recall`, and the
|
|
246
|
+
full text stays in the details of the result.
|
|
227
247
|
|
|
228
248
|
## Contributing and license
|
|
229
249
|
|
|
230
250
|
Issues and pull requests are welcome at [github.com/dizk/pi-jev-lens](https://github.com/dizk/pi-jev-lens).
|
|
231
|
-
`npm test` runs the unit tests with the mock classifier
|
|
232
|
-
or chosen
|
|
251
|
+
`npm test` runs the unit tests with the mock classifier. `npm run typecheck` runs tsc. A change to how views are
|
|
252
|
+
built or chosen must come with benchmark numbers. If the change touches code views, you must use the 500-trajectory
|
|
253
|
+
slice.
|
|
233
254
|
|
|
234
255
|
MIT, see LICENSE.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-jev-lens",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "pi extension that compresses large tool results before they reach the model: jev picks the view (outline, relevant blocks, sections, signals, testlog), full text stays recallable",
|
|
5
5
|
"author": "Didrik Rognstad",
|
|
6
6
|
"license": "MIT",
|