@lienat/pi-jev-compaction 0.1.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.
Files changed (41) hide show
  1. package/LICENSE +21 -0
  2. package/README.en.md +215 -0
  3. package/README.md +171 -0
  4. package/assets/tamarajtran-jev-compaction.gif +0 -0
  5. package/assets/tamarajtran-jev-compaction.mp4 +0 -0
  6. package/extensions/fast-jev-compaction.ts +94 -0
  7. package/node_modules/fast-jev-compaction/LICENSE +21 -0
  8. package/node_modules/fast-jev-compaction/README.md +276 -0
  9. package/node_modules/fast-jev-compaction/cli/jev-find.mjs +103 -0
  10. package/node_modules/fast-jev-compaction/cli/jev-qa.mjs +159 -0
  11. package/node_modules/fast-jev-compaction/dist/client.d.ts +21 -0
  12. package/node_modules/fast-jev-compaction/dist/client.d.ts.map +1 -0
  13. package/node_modules/fast-jev-compaction/dist/client.js +26 -0
  14. package/node_modules/fast-jev-compaction/dist/client.js.map +1 -0
  15. package/node_modules/fast-jev-compaction/dist/compact.d.ts +30 -0
  16. package/node_modules/fast-jev-compaction/dist/compact.d.ts.map +1 -0
  17. package/node_modules/fast-jev-compaction/dist/compact.js +234 -0
  18. package/node_modules/fast-jev-compaction/dist/compact.js.map +1 -0
  19. package/node_modules/fast-jev-compaction/dist/index.d.ts +7 -0
  20. package/node_modules/fast-jev-compaction/dist/index.d.ts.map +1 -0
  21. package/node_modules/fast-jev-compaction/dist/index.js +7 -0
  22. package/node_modules/fast-jev-compaction/dist/index.js.map +1 -0
  23. package/node_modules/fast-jev-compaction/dist/messages.d.ts +6 -0
  24. package/node_modules/fast-jev-compaction/dist/messages.d.ts.map +1 -0
  25. package/node_modules/fast-jev-compaction/dist/messages.js +7 -0
  26. package/node_modules/fast-jev-compaction/dist/messages.js.map +1 -0
  27. package/node_modules/fast-jev-compaction/dist/request.d.ts +20 -0
  28. package/node_modules/fast-jev-compaction/dist/request.d.ts.map +1 -0
  29. package/node_modules/fast-jev-compaction/dist/request.js +51 -0
  30. package/node_modules/fast-jev-compaction/dist/request.js.map +1 -0
  31. package/node_modules/fast-jev-compaction/dist/state.d.ts +29 -0
  32. package/node_modules/fast-jev-compaction/dist/state.d.ts.map +1 -0
  33. package/node_modules/fast-jev-compaction/dist/state.js +256 -0
  34. package/node_modules/fast-jev-compaction/dist/state.js.map +1 -0
  35. package/node_modules/fast-jev-compaction/dist/types.d.ts +178 -0
  36. package/node_modules/fast-jev-compaction/dist/types.d.ts.map +1 -0
  37. package/node_modules/fast-jev-compaction/dist/types.js +2 -0
  38. package/node_modules/fast-jev-compaction/dist/types.js.map +1 -0
  39. package/node_modules/fast-jev-compaction/package.json +39 -0
  40. package/package.json +42 -0
  41. package/src/adapter.ts +373 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jul1en-Lin
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.en.md ADDED
@@ -0,0 +1,215 @@
1
+ # pi-jev-compaction
2
+
3
+ A [Pi](https://github.com/badlogic/pi-mono) extension for context compaction.
4
+ The source code here is adapted from the native Claude Code plugin
5
+ [`fast-jev-compaction`](https://github.com/tamaratran/fast-jev-compaction) by
6
+ Tamara Tran, reworked to integrate with Pi. It filters out stale tool calls
7
+ and their results before Pi runs its native compaction summary.
8
+
9
+ This package is a **Pi adapter**, not a replacement for Pi's compaction system.
10
+ Jev makes the keep/drop/truncate decisions; Pi still creates the summary,
11
+ compaction entry, file-operation details, and retained recent context.
12
+
13
+ ## Demo
14
+
15
+ ![Jev instant compaction demo](./assets/tamarajtran-jev-compaction.gif)
16
+
17
+ Video source: [Tamara Tran's post on X](https://x.com/tamarajtran/status/2100694549362553153).
18
+ The GIF is included as demonstration material; all rights remain with the
19
+ original author.
20
+
21
+ ## How it works
22
+
23
+ For both manual `/compact` and automatic compaction:
24
+
25
+ ```text
26
+ Pi prepares a compaction
27
+ |
28
+ v
29
+ session_before_compact
30
+ |
31
+ v
32
+ Jev reviews eligible tool call/result pairs
33
+ |
34
+ +-- success --> replace only the two native message arrays
35
+ | |
36
+ | v
37
+ | Pi's native compact()
38
+ |
39
+ +-- timeout/error/invalid response --> leave preparation unchanged
40
+ |
41
+ v
42
+ Pi's native compact()
43
+ ```
44
+
45
+ Rather than serializing Jev's simplified transcript back into Pi, the adapter
46
+ maps Jev's decisions onto the original Pi messages. This means Pi's thinking
47
+ blocks, images, tool-call metadata, and other native message data are never
48
+ downgraded to plain text by the adapter.
49
+
50
+ The adapter only modifies:
51
+
52
+ - `messagesToSummarize`
53
+ - `turnPrefixMessages`
54
+
55
+ All other compaction metadata remains fully owned by Pi and is never touched
56
+ by this extension, including:
57
+
58
+ - `firstKeptEntryId`
59
+ - `tokensBefore`
60
+ - `previousSummary`
61
+ - `fileOps`
62
+ - `settings`
63
+ - `isSplitTurn`
64
+
65
+ ### What can be filtered
66
+
67
+ Only paired, text-only tool calls and tool results within the same native
68
+ compaction input are eligible. The adapter leaves the following untouched:
69
+
70
+ - user and assistant prose;
71
+ - thinking blocks and image content;
72
+ - image-bearing tool results;
73
+ - incomplete or duplicate call/result pairs;
74
+ - pairs crossing the two native input boundaries;
75
+ - Pi's separately retained recent region;
76
+ - tool results without a valid matching call.
77
+
78
+ A `drop_call` decision removes the call and its paired result. A
79
+ `drop_result` decision keeps the call and truncates the result to the first
80
+ 300 characters plus a note. Pi then summarizes the filtered native messages
81
+ normally.
82
+
83
+ ## Compatibility
84
+
85
+ - Pi `0.85.1`
86
+ - Node.js `>=24`
87
+ - `fast-jev-compaction` `0.4.0`
88
+
89
+ The extension has a strict Pi `0.85.1` version guard because the adapter
90
+ relies on the mutable `session_before_compact` preparation object introduced
91
+ in that release — this is not a formally documented extension API for
92
+ replacing native preparation arrays. On any other Pi version the extension
93
+ leaves the preparation untouched and Pi falls back to ordinary native
94
+ compaction.
95
+
96
+ This package does not modify Pi's source code or call Pi's exported
97
+ `compact()` function itself.
98
+
99
+ ## Installation
100
+
101
+ Install from Pi Package (npm):
102
+
103
+ ```sh
104
+ pi install npm:@lienat/pi-jev-compaction
105
+ ```
106
+
107
+ Install from the GitHub repository:
108
+
109
+ ```sh
110
+ pi install git:github.com/Jul1en-Lin/pi-jev-compaction@main
111
+ ```
112
+
113
+ Or install a local checkout for development:
114
+
115
+ ```sh
116
+ pi install /Users/lien/prj/pi-fast-jev-compaction
117
+ ```
118
+
119
+ Restart Pi after installation. Verify with:
120
+
121
+ ```sh
122
+ pi list
123
+ ```
124
+
125
+ To uninstall the GitHub version:
126
+
127
+ ```sh
128
+ pi remove git:github.com/Jul1en-Lin/pi-jev-compaction
129
+ ```
130
+
131
+ ## Configuration
132
+
133
+ The extension reaches the official TypeSafe Jev endpoint through the upstream
134
+ package. Set the API key in the environment of the terminal that starts Pi:
135
+
136
+ ```sh
137
+ export TYPESAFE_API_KEY='your-typesafe-key'
138
+ ```
139
+
140
+ The key is read at runtime and used only to authenticate Jev requests. It is
141
+ never written to the package, Pi settings, session files, or extension logs.
142
+ Do not commit it or paste it into a shared shell history.
143
+
144
+ The Jev decision payload can include conversation text and tool input, which
145
+ may contain source code, file paths, commands, or other sensitive data. Only
146
+ use this extension if you are comfortable sending that information to TypeSafe.
147
+
148
+ ### Timeout
149
+
150
+ `PI_FAST_JEV_TIMEOUT_MS` controls the total time allowed for a single Jev
151
+ attempt. It defaults to 15 seconds:
152
+
153
+ ```sh
154
+ export PI_FAST_JEV_TIMEOUT_MS=15000
155
+ ```
156
+
157
+ If the API key is missing, the Pi version is unsupported, Jev times out, the
158
+ request fails, or the response is invalid, the adapter prints a brief warning
159
+ and leaves the original preparation unchanged. Pi then runs its ordinary
160
+ native compaction. The extension never invokes `/compact` recursively.
161
+
162
+ When the user cancels a compaction, the cancellation signal is forwarded to
163
+ the Jev request and the native preparation is not replaced or modified.
164
+
165
+ ## Development
166
+
167
+ Install dependencies without running lifecycle scripts:
168
+
169
+ ```sh
170
+ npm install --ignore-scripts --no-audit --no-fund
171
+ ```
172
+
173
+ Run the checks:
174
+
175
+ ```sh
176
+ npm run typecheck
177
+ npm test
178
+ ```
179
+
180
+ Tests use injected Jev askers and timers and make no calls to TypeSafe or any
181
+ main model. Coverage includes message mapping, tool-call/result pairing, image
182
+ and thinking preservation, split compaction inputs, timeout and cancellation,
183
+ native fallback, and Pi hook behavior.
184
+
185
+ Build the package:
186
+
187
+ ```sh
188
+ npm run build
189
+ ```
190
+
191
+ Create a local npm tarball without publishing:
192
+
193
+ ```sh
194
+ npm pack --ignore-scripts
195
+ ```
196
+
197
+ ## Acknowledgements and attribution
198
+
199
+ This adapter is built on top of
200
+ [`fast-jev-compaction`](https://github.com/tamaratran/fast-jev-compaction) by
201
+ [Tamara Tran](https://github.com/tamaratran), and gratefully acknowledges her
202
+ work. The upstream project provides the Jev decision logic that this Pi
203
+ adapter integrates with native Pi compaction.
204
+
205
+ If you believe this repository contains material that infringes your rights,
206
+ or if the attribution needs to be corrected, please open an issue at
207
+ [github.com/Jul1en-Lin/pi-jev-compaction/issues](https://github.com/Jul1en-Lin/pi-jev-compaction/issues).
208
+ We will review the request and remove or revise the affected material where
209
+ appropriate.
210
+
211
+ ## License
212
+
213
+ This adapter is released under the MIT License. Please also review the
214
+ upstream project's license and attribution requirements:
215
+ [`fast-jev-compaction`](https://github.com/tamaratran/fast-jev-compaction).
package/README.md ADDED
@@ -0,0 +1,171 @@
1
+ # pi-jev-compaction
2
+
3
+
4
+ English version: [README.en.md](README.en.md)
5
+
6
+ 一个用于上下文压缩之前 [Pi](https://github.com/badlogic/pi-mono) 的扩展,此处的源码来源于[`fast-jev-compaction`](https://github.com/tamaratran/fast-jev-compaction)的原生 claude code 的插件,针对 pi 的情况进行了适配。它会在 Pi 执行原生上下文压缩前,筛选不再需要的工具调用和工具结果。
7
+
8
+ 本项目是 **Pi 适配层**,不是对 Pi 原生压缩系统的替换。Jev 只负责判断哪些工具调用应保留、删除或截短;最终摘要、压缩节点、文件操作信息和近期上下文仍由 Pi 原生 `compact()` 生成和管理。
9
+
10
+ ## 视频演示
11
+
12
+ ![Jev instant compaction demo](./assets/tamarajtran-jev-compaction.gif)
13
+
14
+ 视频来源:[Tamara Tran 在 X 发布的视频](https://x.com/tamarajtran/status/2100694549362553153)。GIF 仅作为项目演示素材保留,版权归原作者所有。
15
+
16
+ ## 工作方式
17
+
18
+ 手动执行 `/compact` 或 Pi 自动触发压缩时,流程如下:
19
+
20
+ ```text
21
+ Pi 准备压缩
22
+
23
+ session_before_compact
24
+
25
+ Jev 检查符合条件的工具调用/结果对
26
+ ├─ 成功:只替换 Pi 原生的待摘要消息数组
27
+ │ ↓
28
+ │ Pi 原生 compact()
29
+ └─ 超时、报错或响应无效:保持原始数组不变
30
+
31
+ Pi 原生 compact()
32
+ ```
33
+
34
+ 适配层不会把 Jev 的简化 transcript 重新拼回 Pi,而是将 Jev 的决策映射回原始 Pi 消息。因此,Pi 的 thinking、图片、工具调用元数据和其他原生消息数据不会因为适配而被转换成普通文字。
35
+
36
+ 适配层只会修改:
37
+
38
+ - `messagesToSummarize`
39
+ - `turnPrefixMessages`
40
+
41
+ 以下字段仍完全由 Pi 管理,不会被本扩展修改:
42
+
43
+ - `firstKeptEntryId`
44
+ - `tokensBefore`
45
+ - `previousSummary`
46
+ - `fileOps`
47
+ - `settings`
48
+ - `isSplitTurn`
49
+
50
+ ### 哪些内容可以被筛选
51
+
52
+ 只有位于同一个原生压缩输入中的、成对且纯文本的工具调用和工具结果才会参与筛选。以下内容会保持不变:
53
+
54
+ - 用户消息和助手正文;
55
+ - thinking 块和图片内容;
56
+ - 包含图片的工具结果;
57
+ - 缺少对应调用或结果的消息;
58
+ - 重复 ID 的调用/结果;
59
+ - 跨越两个原生输入边界的调用/结果对;
60
+ - Pi 单独保留的近期消息区域;
61
+ - 没有有效调用对应的工具结果。
62
+
63
+ 如果 Jev 返回 `drop_call`,扩展会删除调用及其对应结果。如果返回 `drop_result`,则保留调用,并将结果截短为前 300 个字符加上一条说明。处理完成后,Pi 仍会照常生成原生摘要。
64
+
65
+ ## 兼容性
66
+
67
+ - Pi `0.85.1`
68
+ - Node.js `>=24`
69
+ - `fast-jev-compaction` `0.4.0`
70
+
71
+ 扩展对 Pi 版本进行严格检查,因为当前适配依赖 Pi `0.85.1` 的 `session_before_compact` preparation 对象可变行为;这不是 Pi 正式承诺的“替换原生压缩输入”扩展接口。使用其他 Pi 版本时,扩展不会修改压缩输入,Pi 会安全地回退到原生压缩。
72
+
73
+ 本项目不修改 Pi 源码,也不会自行调用 Pi 导出的 `compact()` 函数。
74
+
75
+ ## 安装
76
+
77
+ 从 Pi Package(npm)安装:
78
+
79
+ ```sh
80
+ pi install npm:@lienat/pi-jev-compaction
81
+ ```
82
+
83
+ 从 GitHub 安装:
84
+
85
+ ```sh
86
+ pi install git:github.com/Jul1en-Lin/pi-jev-compaction@main
87
+ ```
88
+
89
+ 也可以安装本地 checkout:
90
+
91
+ ```sh
92
+ pi install /Users/lien/prj/pi-fast-jev-compaction
93
+ ```
94
+
95
+ 安装后重启 Pi。查看已安装包:
96
+
97
+ ```sh
98
+ pi list
99
+ ```
100
+
101
+ 卸载 GitHub 版本:
102
+
103
+ ```sh
104
+ pi remove git:github.com/Jul1en-Lin/pi-jev-compaction
105
+ ```
106
+
107
+ ## 配置
108
+
109
+ 扩展通过上游包访问官方 TypeSafe Jev 服务。请在启动 Pi 的终端中配置 API Key:
110
+
111
+ ```sh
112
+ export TYPESAFE_API_KEY='your-typesafe-key'
113
+ ```
114
+
115
+ API Key 只在运行时读取,并只用于认证 Jev 请求;不会写入本项目、Pi settings、会话文件或扩展日志。请不要提交 API Key,也不要把它放进共享的 shell 历史记录。
116
+
117
+ 发送给 Jev 的决策状态可能包含会话文本和工具输入,其中可能有源代码、文件路径、命令或其他敏感信息。只有在你接受这些信息发送到 TypeSafe 的情况下,才应使用本扩展。
118
+
119
+ ### 超时配置
120
+
121
+ `PI_FAST_JEV_TIMEOUT_MS` 控制一次 Jev 尝试的总时限,默认值为 15 秒:
122
+
123
+ ```sh
124
+ export PI_FAST_JEV_TIMEOUT_MS=15000
125
+ ```
126
+
127
+ 如果 API Key 缺失、Pi 版本不支持、Jev 超时、请求失败或响应无效,扩展会显示简短提示并保持原始压缩输入不变,然后由 Pi 执行普通原生压缩。扩展不会递归调用 `/compact`。
128
+
129
+ 用户主动取消压缩时,取消信号会传递给 Jev,扩展不会替换或修改原生压缩输入。
130
+
131
+ ## 开发
132
+
133
+ 安装依赖:
134
+
135
+ ```sh
136
+ npm install --ignore-scripts --no-audit --no-fund
137
+ ```
138
+
139
+ 执行检查:
140
+
141
+ ```sh
142
+ npm run typecheck
143
+ npm test
144
+ ```
145
+
146
+ 测试使用注入的 Jev asker 和计时器,不会访问 TypeSafe,也不会调用主模型。测试覆盖消息映射、工具调用/结果配对、图片和 thinking 保留、两组压缩输入、超时、取消、原生回退和 Pi hook 行为。
147
+
148
+ 构建:
149
+
150
+ ```sh
151
+ npm run build
152
+ ```
153
+
154
+ 创建本地 npm 压缩包(不会发布):
155
+
156
+ ```sh
157
+ npm pack --ignore-scripts
158
+ ```
159
+
160
+ ## 致谢与署名
161
+
162
+ 本适配层基于 [Tamara Tran](https://github.com/tamaratran) 的
163
+ [`fast-jev-compaction`](https://github.com/tamaratran/fast-jev-compaction) 项目,感谢原作者提供 Jev 决策逻辑。
164
+
165
+ 如果你认为本仓库包含侵犯你权利的内容,或署名信息需要修正,请在
166
+ [GitHub Issues](https://github.com/Jul1en-Lin/pi-jev-compaction/issues) 联系维护者。我们会审核请求,并在适当情况下删除或修订相关内容。
167
+
168
+ ## 许可证
169
+
170
+ 本适配层使用 MIT License。使用时也请查看上游
171
+ [`fast-jev-compaction`](https://github.com/tamaratran/fast-jev-compaction) 项目的许可证和署名要求。
@@ -0,0 +1,94 @@
1
+ import { VERSION, type ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ import {
3
+ createDeadline,
4
+ createJevAsker,
5
+ DEFAULT_TIMEOUT_MS,
6
+ filterPreparation,
7
+ type TimerApi,
8
+ } from "../src/adapter.js";
9
+ import type { JevAsker } from "fast-jev-compaction";
10
+
11
+ const SUPPORTED_PI_VERSION = "0.85.1";
12
+
13
+ export interface ExtensionDependencies {
14
+ apiKey?: string;
15
+ asker?: JevAsker;
16
+ timers?: TimerApi;
17
+ }
18
+
19
+ export function parseTimeout(value: string | undefined): number {
20
+ if (value === undefined || value === "") return DEFAULT_TIMEOUT_MS;
21
+ const timeout = Number(value);
22
+ return Number.isFinite(timeout) && timeout > 0 ? Math.floor(timeout) : DEFAULT_TIMEOUT_MS;
23
+ }
24
+
25
+ /** Short, transient console line: nothing here is written to the session or disk. */
26
+ export function formatElapsed(milliseconds: number): string {
27
+ return milliseconds < 1000 ? `${milliseconds}ms` : `${(milliseconds / 1000).toFixed(1)}s`;
28
+ }
29
+
30
+ export function install(pi: ExtensionAPI, dependencies: ExtensionDependencies = {}): void {
31
+ pi.on("session_before_compact", async (event, ctx) => {
32
+ if (VERSION !== SUPPORTED_PI_VERSION) {
33
+ ctx.ui.notify(
34
+ `[jev] skipped: Pi ${VERSION} is not ${SUPPORTED_PI_VERSION}; using Pi's native compaction.`,
35
+ "warning",
36
+ );
37
+ return;
38
+ }
39
+
40
+ const apiKey = dependencies.apiKey ?? process.env.TYPESAFE_API_KEY;
41
+ if (!apiKey && !dependencies.asker) {
42
+ ctx.ui.notify("[jev] skipped: TYPESAFE_API_KEY is not set; using Pi's native compaction.", "warning");
43
+ return;
44
+ }
45
+
46
+ const timeoutMs = parseTimeout(process.env.PI_FAST_JEV_TIMEOUT_MS);
47
+ const deadline = createDeadline(event.signal, timeoutMs, dependencies.timers);
48
+ const startedAt = Date.now();
49
+
50
+ try {
51
+ const asker = dependencies.asker ?? createJevAsker(apiKey as string, deadline.signal);
52
+ const filtered = await filterPreparation(
53
+ event.preparation.messagesToSummarize,
54
+ event.preparation.turnPrefixMessages,
55
+ { asker, signal: deadline.signal },
56
+ );
57
+
58
+ // User cancellation owns the outcome. Do not replace either input after it.
59
+ if (event.signal.aborted) return;
60
+
61
+ const elapsed = formatElapsed(Date.now() - startedAt);
62
+ if (!filtered.changed) {
63
+ ctx.ui.notify(
64
+ `[jev] ${filtered.candidateCalls} call(s) reviewed: nothing dropped · ${elapsed}; Pi will create the native summary.`,
65
+ "info",
66
+ );
67
+ return;
68
+ }
69
+
70
+ // These are the only preparation fields this extension changes. Pi still
71
+ // creates its own summary and compaction entry with its native metadata.
72
+ event.preparation.messagesToSummarize = filtered.messagesToSummarize;
73
+ event.preparation.turnPrefixMessages = filtered.turnPrefixMessages;
74
+ ctx.ui.notify(
75
+ `[jev] ${filtered.candidateCalls} call(s) reviewed: dropped ${filtered.droppedCalls}, shortened ${filtered.truncatedResults} · ${elapsed}; Pi will create the native summary.`,
76
+ "info",
77
+ );
78
+ } catch {
79
+ if (event.signal.aborted) return;
80
+ const elapsed = formatElapsed(Date.now() - startedAt);
81
+ if (deadline.timedOut()) {
82
+ ctx.ui.notify(`[jev] timed out after ${timeoutMs}ms · ${elapsed}; using Pi's native compaction.`, "warning");
83
+ } else {
84
+ ctx.ui.notify(`[jev] failed · ${elapsed}; using Pi's native compaction.`, "warning");
85
+ }
86
+ } finally {
87
+ deadline.dispose();
88
+ }
89
+ });
90
+ }
91
+
92
+ export default function fastJevCompaction(pi: ExtensionAPI): void {
93
+ install(pi);
94
+ }
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025
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.