@henryqw/pi-auto-compact 1.1.10 → 2.0.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 +8 -6
- package/extensions/auto-compact.ts +18 -23
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -30,9 +30,9 @@ Restart Pi after install or settings changes. Trusted project settings in `.pi/s
|
|
|
30
30
|
|
|
31
31
|
This package requires `@henryqw/pi-task-models` for shared compaction routes.
|
|
32
32
|
|
|
33
|
-
`~/.pi/agent/config/pi-task-models.json` is shared and owned by `@henryqw/pi-task-models`. The local `pi-auto-compact/autoCompact` declaration defaults to `fast`. A task entry is an explicit user override.
|
|
33
|
+
`~/.pi/agent/config/pi-task-models/config.json` is shared and owned by `@henryqw/pi-task-models`. The local `pi-auto-compact/autoCompact` declaration defaults to `fast`. A task entry is an explicit user override.
|
|
34
34
|
|
|
35
|
-
Malformed shared
|
|
35
|
+
Malformed shared config is reported and left unchanged. Compaction then uses the current session model.
|
|
36
36
|
|
|
37
37
|
## Use
|
|
38
38
|
|
|
@@ -46,16 +46,18 @@ Use `/auto-compact` to set the compaction threshold.
|
|
|
46
46
|
|
|
47
47
|
## Config
|
|
48
48
|
|
|
49
|
-
Package-owned: `~/.pi/agent/config/pi-auto-compact.json`
|
|
49
|
+
Package-owned: `~/.pi/agent/config/pi-auto-compact/config.json`
|
|
50
50
|
|
|
51
51
|
```json
|
|
52
52
|
{
|
|
53
|
-
"autoCompactThreshold":
|
|
53
|
+
"autoCompactThreshold": 70
|
|
54
54
|
}
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
-
`autoCompactThreshold` is optional. It must be a number that is at least 25 and below 100. The default is `
|
|
57
|
+
`autoCompactThreshold` is optional. It must be a number that is at least 25 and below 100. The default is `70`.
|
|
58
58
|
|
|
59
59
|
Unknown fields are ignored. Legacy model fields are obsolete. `/auto-compact` writes this file.
|
|
60
60
|
|
|
61
|
-
A missing file uses
|
|
61
|
+
A missing file uses 70%. Reads do not create it. A malformed or invalid file fails visibly at session start, falls back to 70%, and stays unchanged.
|
|
62
|
+
|
|
63
|
+
Only `/auto-compact` writes this file. Its write is atomic.
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { dirname, join } from "node:path";
|
|
3
1
|
import {
|
|
4
2
|
compact,
|
|
5
3
|
estimateTokens,
|
|
6
4
|
getAgentDir,
|
|
7
5
|
SettingsManager,
|
|
8
6
|
} from "@earendil-works/pi-coding-agent";
|
|
7
|
+
import { createConfigStore } from "@henryqw/pi-config-store";
|
|
9
8
|
import type {
|
|
10
9
|
ExtensionAPI,
|
|
11
10
|
ExtensionContext,
|
|
@@ -30,7 +29,7 @@ type AgentMessage = Parameters<typeof estimateTokens>[0];
|
|
|
30
29
|
* Pi's ctx.compact() aborts active low-level run internally. Mid-task
|
|
31
30
|
* compaction sends a follow-up user message to resume work after summary.
|
|
32
31
|
*/
|
|
33
|
-
const DEFAULT_COMPACT_THRESHOLD_PERCENT =
|
|
32
|
+
const DEFAULT_COMPACT_THRESHOLD_PERCENT = 70;
|
|
34
33
|
const MIN_COMPACT_THRESHOLD_PERCENT = 25;
|
|
35
34
|
export const AUTO_COMPACT_TASK = {
|
|
36
35
|
id: "pi-auto-compact/autoCompact",
|
|
@@ -38,22 +37,13 @@ export const AUTO_COMPACT_TASK = {
|
|
|
38
37
|
purpose: "Compact session context before it is exhausted.",
|
|
39
38
|
defaultProfile: "fast",
|
|
40
39
|
} as const satisfies ModelTask;
|
|
41
|
-
|
|
40
|
+
type AutoCompactConfig = { autoCompactThreshold: number };
|
|
42
41
|
|
|
43
42
|
function isValidThreshold(value: unknown): value is number {
|
|
44
43
|
return typeof value === "number" && Number.isFinite(value) && value >= MIN_COMPACT_THRESHOLD_PERCENT && value < 100;
|
|
45
44
|
}
|
|
46
45
|
|
|
47
|
-
function
|
|
48
|
-
let value: unknown;
|
|
49
|
-
try {
|
|
50
|
-
value = JSON.parse(readFileSync(configPath(), "utf8"));
|
|
51
|
-
} catch (error) {
|
|
52
|
-
if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
|
|
53
|
-
return DEFAULT_COMPACT_THRESHOLD_PERCENT;
|
|
54
|
-
}
|
|
55
|
-
throw error;
|
|
56
|
-
}
|
|
46
|
+
function parseAutoCompactConfig(value: unknown): AutoCompactConfig {
|
|
57
47
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
58
48
|
throw new Error("Config must be an object.");
|
|
59
49
|
}
|
|
@@ -61,13 +51,15 @@ function readConfig(): number {
|
|
|
61
51
|
if (!isValidThreshold(threshold)) {
|
|
62
52
|
throw new Error(`autoCompactThreshold must be at least ${MIN_COMPACT_THRESHOLD_PERCENT} and below 100.`);
|
|
63
53
|
}
|
|
64
|
-
return threshold;
|
|
54
|
+
return { autoCompactThreshold: threshold };
|
|
65
55
|
}
|
|
66
56
|
|
|
67
|
-
function
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
57
|
+
function createAutoCompactConfigStore() {
|
|
58
|
+
return createConfigStore<AutoCompactConfig>({
|
|
59
|
+
extensionId: "pi-auto-compact",
|
|
60
|
+
defaults: () => ({ autoCompactThreshold: DEFAULT_COMPACT_THRESHOLD_PERCENT }),
|
|
61
|
+
parse: parseAutoCompactConfig,
|
|
62
|
+
});
|
|
71
63
|
}
|
|
72
64
|
|
|
73
65
|
function configuredTaskRoutes(ctx: ExtensionContext): ResolvedTaskRoute[] {
|
|
@@ -75,6 +67,7 @@ function configuredTaskRoutes(ctx: ExtensionContext): ResolvedTaskRoute[] {
|
|
|
75
67
|
return resolveConfiguredTaskRoutes(ctx, AUTO_COMPACT_TASK);
|
|
76
68
|
} catch (error) {
|
|
77
69
|
const { taskRouteCode, profileName } = error as TaskRouteError;
|
|
70
|
+
if (taskRouteCode === "config-missing") return [];
|
|
78
71
|
const cause = taskRouteCode === "profile-missing"
|
|
79
72
|
? `Task model profile ${profileName} is not configured`
|
|
80
73
|
: taskRouteCode === "no-route"
|
|
@@ -155,6 +148,7 @@ function hasToolCall(message: AgentMessage): boolean {
|
|
|
155
148
|
|
|
156
149
|
export default function (pi: ExtensionAPI) {
|
|
157
150
|
registerModelTask(pi, AUTO_COMPACT_TASK);
|
|
151
|
+
const configStore = createAutoCompactConfigStore();
|
|
158
152
|
let active = false;
|
|
159
153
|
let autoCompactThreshold = DEFAULT_COMPACT_THRESHOLD_PERCENT;
|
|
160
154
|
// Prevent lifecycle hooks from starting duplicate summaries.
|
|
@@ -256,7 +250,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
256
250
|
|
|
257
251
|
let currentThreshold: number;
|
|
258
252
|
try {
|
|
259
|
-
currentThreshold =
|
|
253
|
+
currentThreshold = configStore.loadSync().value.autoCompactThreshold;
|
|
260
254
|
} catch {
|
|
261
255
|
ctx.ui.notify("Couldn't read pi-auto-compact config.", "error");
|
|
262
256
|
return;
|
|
@@ -275,7 +269,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
275
269
|
}
|
|
276
270
|
|
|
277
271
|
try {
|
|
278
|
-
|
|
272
|
+
await configStore.save({ autoCompactThreshold: threshold });
|
|
279
273
|
} catch {
|
|
280
274
|
ctx.ui.notify("Couldn't save pi-auto-compact config.", "error");
|
|
281
275
|
return;
|
|
@@ -289,10 +283,11 @@ export default function (pi: ExtensionAPI) {
|
|
|
289
283
|
// activation unless effective global/project settings disable it.
|
|
290
284
|
pi.on("session_start", (event, ctx) => {
|
|
291
285
|
try {
|
|
292
|
-
|
|
286
|
+
const config = configStore.loadSync();
|
|
287
|
+
autoCompactThreshold = config.value.autoCompactThreshold;
|
|
293
288
|
} catch {
|
|
294
289
|
autoCompactThreshold = DEFAULT_COMPACT_THRESHOLD_PERCENT;
|
|
295
|
-
ctx.ui.notify(
|
|
290
|
+
ctx.ui.notify(`Couldn't read pi-auto-compact config; using ${DEFAULT_COMPACT_THRESHOLD_PERCENT}%.`, "error");
|
|
296
291
|
}
|
|
297
292
|
|
|
298
293
|
active = !SettingsManager.create(ctx.cwd, getAgentDir(), {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@henryqw/pi-auto-compact",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Proactively compact Pi context at a configurable threshold and resume the current task.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
]
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@henryqw/pi-
|
|
47
|
+
"@henryqw/pi-config-store": "^0.1.0",
|
|
48
|
+
"@henryqw/pi-task-models": "^4.0.0"
|
|
48
49
|
}
|
|
49
50
|
}
|