@henryqw/pi-auto-compact 0.2.0 → 0.3.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/README.md +15 -7
- package/extensions/auto-compact.ts +210 -27
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# `@henryqw/pi-auto-compact`
|
|
2
2
|
|
|
3
|
-
Pi extension that compacts context before it reaches 50% of current model context, then resumes current task.
|
|
3
|
+
Pi extension that compacts context before it reaches 50% of current model context, then resumes current task. Requires Pi Coding Agent 0.80.7+.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -28,23 +28,31 @@ pi remove npm:@henryqw/pi-auto-compact
|
|
|
28
28
|
|
|
29
29
|
## Configure
|
|
30
30
|
|
|
31
|
-
Run `/auto-compact`, then
|
|
31
|
+
Run `/auto-compact`, then choose:
|
|
32
|
+
|
|
33
|
+
- `Model`: use current session model or select an available text model and its supported thinking level.
|
|
34
|
+
- `Threshold`: set compaction percentage.
|
|
35
|
+
|
|
36
|
+
Config lives in `~/.pi/agent/config/pi-auto-compact.json`:
|
|
32
37
|
|
|
33
38
|
```json
|
|
34
39
|
{
|
|
35
|
-
"autoCompactThreshold": 50
|
|
40
|
+
"autoCompactThreshold": 50,
|
|
41
|
+
"compactionModel": "openai-codex/gpt-5.6-terra",
|
|
42
|
+
"compactionThinkingLevel": "max"
|
|
36
43
|
}
|
|
37
44
|
```
|
|
38
45
|
|
|
39
|
-
Threshold must be at least 25% and below 100%; lower values are not meaningful. Missing config defaults to 50%. Restart or `/reload` after manual edits;
|
|
46
|
+
`compactionModel` is optional and must name Pi-known `provider/model`; omit it to compact with current session model. `compactionThinkingLevel` accepts `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, or `max`, requires a dedicated model, and defaults to `off` when omitted. Threshold must be at least 25% and below 100%; lower values are not meaningful. Missing config defaults to 50%. Restart or `/reload` after manual edits; menu changes apply immediately.
|
|
40
47
|
|
|
41
48
|
## Behavior
|
|
42
49
|
|
|
43
50
|
- Refuses activation with an error when Pi's effective `compaction.enabled` setting is not `false`; competing automatic compactors can start duplicate summaries.
|
|
44
|
-
- Checks `turn_start`, tool-call `turn_end`, `context`, and resumed/forked `session_start`.
|
|
45
|
-
- Uses Pi's
|
|
51
|
+
- Checks `turn_start`, tool-call `turn_end`, `agent_end`, `context`, and resumed/forked `session_start`.
|
|
52
|
+
- Uses Pi's native summary and session persistence; optional `compactionModel` runs automatic summaries with selected model and thinking level. Manual `/compact` keeps using current session model.
|
|
53
|
+
- Falls back to current session model when configured compaction model is unavailable, cannot authenticate, or fails.
|
|
46
54
|
- Keeps newest 15% as temporary emergency context while compaction runs.
|
|
47
|
-
- Sends a follow-up message after compaction so task execution continues.
|
|
55
|
+
- Sends a follow-up message after mid-task compaction so task execution continues; final-answer compaction stays idle.
|
|
48
56
|
- Compacts above configured `autoCompactThreshold` percentage (50% by default).
|
|
49
57
|
|
|
50
58
|
`ctx.compact()` aborts current low-level run. Extension hides that empty internal abort message, then starts new run with current task resume message. Other aborts and provider errors remain visible.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
3
|
import {
|
|
4
|
+
compact,
|
|
4
5
|
estimateTokens,
|
|
5
6
|
getAgentDir,
|
|
6
7
|
SettingsManager,
|
|
@@ -11,25 +12,59 @@ import type {
|
|
|
11
12
|
} from "@earendil-works/pi-coding-agent";
|
|
12
13
|
|
|
13
14
|
type AgentMessage = Parameters<typeof estimateTokens>[0];
|
|
15
|
+
type ThinkingLevel = NonNullable<Parameters<typeof compact>[6]>;
|
|
16
|
+
type TextModel = ReturnType<ExtensionContext["modelRegistry"]["getAvailable"]>[number];
|
|
14
17
|
|
|
15
18
|
/**
|
|
16
|
-
* Proactive compaction runs at
|
|
19
|
+
* Proactive compaction runs at four points:
|
|
17
20
|
* - turn_start: catch sessions already over threshold before next request.
|
|
18
21
|
* - turn_end: catch growth caused by tool results before next LLM turn.
|
|
22
|
+
* - agent_end: catch growth from the final provider turn.
|
|
19
23
|
* - context: last-resort guard with a temporary keep-recent context.
|
|
20
24
|
*
|
|
21
|
-
* Pi's ctx.compact() aborts active low-level run internally.
|
|
22
|
-
*
|
|
25
|
+
* Pi's ctx.compact() aborts active low-level run internally. Mid-task
|
|
26
|
+
* compaction sends a follow-up user message to resume work after summary.
|
|
23
27
|
*/
|
|
24
28
|
const DEFAULT_COMPACT_THRESHOLD_PERCENT = 50;
|
|
25
29
|
const MIN_COMPACT_THRESHOLD_PERCENT = 25;
|
|
30
|
+
const THINKING_LEVELS: ThinkingLevel[] = ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
26
31
|
const configPath = () => join(getAgentDir(), "config", "pi-auto-compact.json");
|
|
27
32
|
|
|
33
|
+
type Config = {
|
|
34
|
+
autoCompactThreshold: number;
|
|
35
|
+
compactionModel?: string;
|
|
36
|
+
compactionThinkingLevel?: ThinkingLevel;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
type ModelReference = { provider: string; modelId: string };
|
|
40
|
+
|
|
28
41
|
function isValidThreshold(value: unknown): value is number {
|
|
29
42
|
return typeof value === "number" && Number.isFinite(value) && value >= MIN_COMPACT_THRESHOLD_PERCENT && value < 100;
|
|
30
43
|
}
|
|
31
44
|
|
|
32
|
-
function
|
|
45
|
+
function isValidThinkingLevel(value: unknown): value is ThinkingLevel {
|
|
46
|
+
return typeof value === "string" && THINKING_LEVELS.includes(value as ThinkingLevel);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function supportedThinkingLevels(model: TextModel): ThinkingLevel[] {
|
|
50
|
+
if (!model.reasoning) return ["off"];
|
|
51
|
+
return THINKING_LEVELS.filter((level) => {
|
|
52
|
+
const mapped = model.thinkingLevelMap?.[level];
|
|
53
|
+
return mapped !== null && ((level !== "xhigh" && level !== "max") || mapped !== undefined);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function parseModelReference(value: unknown): ModelReference | undefined {
|
|
58
|
+
if (typeof value !== "string") return undefined;
|
|
59
|
+
const separator = value.indexOf("/");
|
|
60
|
+
if (separator <= 0 || separator === value.length - 1) return undefined;
|
|
61
|
+
|
|
62
|
+
const provider = value.slice(0, separator).trim();
|
|
63
|
+
const modelId = value.slice(separator + 1).trim();
|
|
64
|
+
return provider && modelId ? { provider, modelId } : undefined;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function readConfig(): Config {
|
|
33
68
|
let value: unknown;
|
|
34
69
|
try {
|
|
35
70
|
value = JSON.parse(readFileSync(configPath(), "utf8"));
|
|
@@ -42,21 +77,43 @@ function readConfig(): { autoCompactThreshold: number } {
|
|
|
42
77
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
43
78
|
throw new Error("Config must be an object.");
|
|
44
79
|
}
|
|
45
|
-
const
|
|
80
|
+
const config = value as Record<string, unknown>;
|
|
81
|
+
const threshold = config.autoCompactThreshold ?? DEFAULT_COMPACT_THRESHOLD_PERCENT;
|
|
46
82
|
if (!isValidThreshold(threshold)) {
|
|
47
83
|
throw new Error(`autoCompactThreshold must be at least ${MIN_COMPACT_THRESHOLD_PERCENT} and below 100.`);
|
|
48
84
|
}
|
|
49
|
-
|
|
85
|
+
if (config.compactionModel !== undefined && !parseModelReference(config.compactionModel)) {
|
|
86
|
+
throw new Error("compactionModel must be a provider/model string.");
|
|
87
|
+
}
|
|
88
|
+
const thinkingLevel = config.compactionThinkingLevel;
|
|
89
|
+
if (thinkingLevel !== undefined && !isValidThinkingLevel(thinkingLevel)) {
|
|
90
|
+
throw new Error("compactionThinkingLevel is invalid.");
|
|
91
|
+
}
|
|
92
|
+
if (thinkingLevel !== undefined && config.compactionModel === undefined) {
|
|
93
|
+
throw new Error("compactionThinkingLevel requires compactionModel.");
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
autoCompactThreshold: threshold,
|
|
97
|
+
compactionModel: typeof config.compactionModel === "string" ? config.compactionModel.trim() : undefined,
|
|
98
|
+
compactionThinkingLevel: thinkingLevel,
|
|
99
|
+
};
|
|
50
100
|
}
|
|
51
101
|
|
|
52
|
-
function writeConfig(
|
|
102
|
+
function writeConfig(config: Config): void {
|
|
53
103
|
const file = configPath();
|
|
54
104
|
mkdirSync(dirname(file), { recursive: true });
|
|
55
|
-
writeFileSync(file, `${JSON.stringify(
|
|
105
|
+
writeFileSync(file, `${JSON.stringify(config, null, 2)}\n`);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function withoutDeletedHeaders(headers: Record<string, string | null> | undefined): Record<string, string> | undefined {
|
|
109
|
+
return headers
|
|
110
|
+
? Object.fromEntries(Object.entries(headers).filter((entry): entry is [string, string] => entry[1] !== null))
|
|
111
|
+
: undefined;
|
|
56
112
|
}
|
|
57
113
|
|
|
58
114
|
// Emergency context guard keeps recent messages while default compaction runs.
|
|
59
115
|
const KEEP_RECENT_PERCENT = 15;
|
|
116
|
+
const COMPACTION_INSTRUCTIONS = "Preserve current task to be resumed after compaction.";
|
|
60
117
|
const RESUME_MESSAGE = "Auto-compact ran. Continue the current task.";
|
|
61
118
|
const COMPACTION_ABORT_ERROR = "This operation was aborted";
|
|
62
119
|
const ACTIVATION_ERROR =
|
|
@@ -119,16 +176,20 @@ function hasToolCall(message: AgentMessage): boolean {
|
|
|
119
176
|
export default function (pi: ExtensionAPI) {
|
|
120
177
|
let active = false;
|
|
121
178
|
let autoCompactThreshold = DEFAULT_COMPACT_THRESHOLD_PERCENT;
|
|
122
|
-
|
|
179
|
+
let compactionModel: string | undefined;
|
|
180
|
+
let compactionThinkingLevel: ThinkingLevel | undefined;
|
|
181
|
+
// Prevent lifecycle hooks from starting duplicate summaries.
|
|
123
182
|
let compactionPending = false;
|
|
124
183
|
let compactionAbortExpected = false;
|
|
125
184
|
|
|
126
|
-
const runCompaction = (ctx: ExtensionContext) => {
|
|
185
|
+
const runCompaction = (ctx: ExtensionContext, resumeTask = true) => {
|
|
127
186
|
compactionAbortExpected = Boolean(ctx.signal && !ctx.signal.aborted);
|
|
128
187
|
ctx.compact({
|
|
188
|
+
customInstructions: COMPACTION_INSTRUCTIONS,
|
|
129
189
|
onComplete: () => {
|
|
130
190
|
compactionPending = false;
|
|
131
191
|
compactionAbortExpected = false;
|
|
192
|
+
if (!resumeTask) return;
|
|
132
193
|
// Pi may flush queued input during compaction_end. Wait one macrotask
|
|
133
194
|
// before checking idle, otherwise follow-up can race that flush.
|
|
134
195
|
setImmediate(() => {
|
|
@@ -142,14 +203,14 @@ export default function (pi: ExtensionAPI) {
|
|
|
142
203
|
});
|
|
143
204
|
};
|
|
144
205
|
|
|
145
|
-
const compactIfNeeded = (ctx: ExtensionContext) => {
|
|
206
|
+
const compactIfNeeded = (ctx: ExtensionContext, resumeTask = true) => {
|
|
146
207
|
if (!active || compactionPending) return;
|
|
147
208
|
|
|
148
209
|
const usage = ctx.getContextUsage();
|
|
149
210
|
if (usage?.percent == null || usage.percent <= autoCompactThreshold) return;
|
|
150
211
|
|
|
151
212
|
compactionPending = true;
|
|
152
|
-
runCompaction(ctx);
|
|
213
|
+
runCompaction(ctx, resumeTask);
|
|
153
214
|
};
|
|
154
215
|
|
|
155
216
|
// Hide only empty abort produced when ctx.compact() cancels active run.
|
|
@@ -176,12 +237,14 @@ export default function (pi: ExtensionAPI) {
|
|
|
176
237
|
// Pre-turn catches resumed/queued work before provider request starts.
|
|
177
238
|
pi.on("turn_start", (_event, ctx) => compactIfNeeded(ctx));
|
|
178
239
|
|
|
179
|
-
// Only tool-call turns need mid-run compaction.
|
|
180
|
-
// receive an unsolicited continuation message.
|
|
240
|
+
// Only tool-call turns need mid-run compaction.
|
|
181
241
|
pi.on("turn_end", (event, ctx) => {
|
|
182
242
|
if (hasToolCall(event.message)) compactIfNeeded(ctx);
|
|
183
243
|
});
|
|
184
244
|
|
|
245
|
+
// Catch threshold crossings caused by the final provider turn.
|
|
246
|
+
pi.on("agent_end", (_event, ctx) => compactIfNeeded(ctx, false));
|
|
247
|
+
|
|
185
248
|
// Runs before every provider request. Temporary truncation protects request
|
|
186
249
|
// size while asynchronous default compaction summarizes persisted history.
|
|
187
250
|
pi.on("context", (event, ctx) => {
|
|
@@ -205,19 +268,75 @@ export default function (pi: ExtensionAPI) {
|
|
|
205
268
|
});
|
|
206
269
|
|
|
207
270
|
pi.registerCommand("auto-compact", {
|
|
208
|
-
description: "
|
|
209
|
-
handler: async (
|
|
210
|
-
|
|
271
|
+
description: "configure automatic compaction",
|
|
272
|
+
handler: async (args, ctx) => {
|
|
273
|
+
if (args.trim()) {
|
|
274
|
+
ctx.ui.notify("Usage: /auto-compact", "error");
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
let config: Config;
|
|
211
279
|
try {
|
|
212
|
-
|
|
280
|
+
config = readConfig();
|
|
213
281
|
} catch {
|
|
214
282
|
ctx.ui.notify("Couldn't read pi-auto-compact config.", "error");
|
|
215
283
|
return;
|
|
216
284
|
}
|
|
285
|
+
const save = (next: Config) => {
|
|
286
|
+
try {
|
|
287
|
+
writeConfig(next);
|
|
288
|
+
return true;
|
|
289
|
+
} catch {
|
|
290
|
+
ctx.ui.notify("Couldn't save pi-auto-compact config.", "error");
|
|
291
|
+
return false;
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
const thresholdOption = `Threshold · ${config.autoCompactThreshold}%`;
|
|
296
|
+
const modelOption = `Model · ${config.compactionModel
|
|
297
|
+
? `${config.compactionModel} (${config.compactionThinkingLevel ?? "off"})`
|
|
298
|
+
: "current session"}`;
|
|
299
|
+
const setting = await ctx.ui.select("Configure auto-compact", [modelOption, thresholdOption]);
|
|
300
|
+
if (!setting) return;
|
|
301
|
+
|
|
302
|
+
if (setting === modelOption) {
|
|
303
|
+
const models = ctx.modelRegistry
|
|
304
|
+
.getAvailable()
|
|
305
|
+
.filter((model) => model.input.includes("text"))
|
|
306
|
+
.sort((a, b) => `${a.provider}/${a.id}`.localeCompare(`${b.provider}/${b.id}`));
|
|
307
|
+
const currentModel = "Current session model";
|
|
308
|
+
const selected = await ctx.ui.select("Auto-compact model", [
|
|
309
|
+
currentModel,
|
|
310
|
+
...models.map((model) => `${model.provider}/${model.id}`),
|
|
311
|
+
]);
|
|
312
|
+
if (!selected) return;
|
|
313
|
+
|
|
314
|
+
if (selected === currentModel) {
|
|
315
|
+
if (!save({ ...config, compactionModel: undefined, compactionThinkingLevel: undefined })) return;
|
|
316
|
+
compactionModel = undefined;
|
|
317
|
+
compactionThinkingLevel = undefined;
|
|
318
|
+
ctx.ui.notify("Auto-compact model set to current session model.", "info");
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const model = models.find((candidate) => `${candidate.provider}/${candidate.id}` === selected);
|
|
323
|
+
if (!model) return;
|
|
324
|
+
const thinkingLevels = supportedThinkingLevels(model);
|
|
325
|
+
const thinkingLevel = thinkingLevels.length === 1
|
|
326
|
+
? thinkingLevels[0]
|
|
327
|
+
: await ctx.ui.select(`Thinking level · ${selected}`, thinkingLevels);
|
|
328
|
+
if (!isValidThinkingLevel(thinkingLevel)) return;
|
|
329
|
+
|
|
330
|
+
if (!save({ ...config, compactionModel: selected, compactionThinkingLevel: thinkingLevel })) return;
|
|
331
|
+
compactionModel = selected;
|
|
332
|
+
compactionThinkingLevel = thinkingLevel;
|
|
333
|
+
ctx.ui.notify(`Auto-compact model set to ${selected} (${thinkingLevel}).`, "info");
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
217
336
|
|
|
218
337
|
const input = await ctx.ui.input(
|
|
219
|
-
`Auto-compact threshold (%) · current: ${
|
|
220
|
-
"Enter a number
|
|
338
|
+
`Auto-compact threshold (%) · current: ${config.autoCompactThreshold}`,
|
|
339
|
+
"Enter a number at least 25 and below 100",
|
|
221
340
|
);
|
|
222
341
|
if (input === undefined) return;
|
|
223
342
|
|
|
@@ -231,12 +350,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
231
350
|
return;
|
|
232
351
|
}
|
|
233
352
|
|
|
234
|
-
|
|
235
|
-
writeConfig(threshold);
|
|
236
|
-
} catch {
|
|
237
|
-
ctx.ui.notify("Couldn't save pi-auto-compact config.", "error");
|
|
238
|
-
return;
|
|
239
|
-
}
|
|
353
|
+
if (!save({ ...config, autoCompactThreshold: threshold })) return;
|
|
240
354
|
autoCompactThreshold = threshold;
|
|
241
355
|
ctx.ui.notify(`Auto-compact threshold set to ${threshold}%.`, "info");
|
|
242
356
|
},
|
|
@@ -246,9 +360,14 @@ export default function (pi: ExtensionAPI) {
|
|
|
246
360
|
// activation unless effective global/project settings disable it.
|
|
247
361
|
pi.on("session_start", (event, ctx) => {
|
|
248
362
|
try {
|
|
249
|
-
|
|
363
|
+
const config = readConfig();
|
|
364
|
+
autoCompactThreshold = config.autoCompactThreshold;
|
|
365
|
+
compactionModel = config.compactionModel;
|
|
366
|
+
compactionThinkingLevel = config.compactionThinkingLevel;
|
|
250
367
|
} catch {
|
|
251
368
|
autoCompactThreshold = DEFAULT_COMPACT_THRESHOLD_PERCENT;
|
|
369
|
+
compactionModel = undefined;
|
|
370
|
+
compactionThinkingLevel = undefined;
|
|
252
371
|
ctx.ui.notify("Couldn't read pi-auto-compact config; using 50%.", "error");
|
|
253
372
|
}
|
|
254
373
|
|
|
@@ -260,4 +379,68 @@ export default function (pi: ExtensionAPI) {
|
|
|
260
379
|
// Resume/fork can load an already-large session before first turn.
|
|
261
380
|
if (event.reason === "resume" || event.reason === "fork") compactIfNeeded(ctx);
|
|
262
381
|
});
|
|
382
|
+
|
|
383
|
+
pi.on("session_before_compact", async (event, ctx) => {
|
|
384
|
+
if (
|
|
385
|
+
!active ||
|
|
386
|
+
!compactionPending ||
|
|
387
|
+
event.customInstructions !== COMPACTION_INSTRUCTIONS
|
|
388
|
+
) return;
|
|
389
|
+
|
|
390
|
+
// Pi omits details from prior extension compactions when preparing next run.
|
|
391
|
+
const previous = [...event.branchEntries].reverse().find((entry) => entry.type === "compaction");
|
|
392
|
+
if (previous?.details && typeof previous.details === "object") {
|
|
393
|
+
const details = previous.details as { readFiles?: unknown; modifiedFiles?: unknown };
|
|
394
|
+
if (Array.isArray(details.readFiles)) {
|
|
395
|
+
for (const path of details.readFiles) {
|
|
396
|
+
if (typeof path === "string") event.preparation.fileOps.read.add(path);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
if (Array.isArray(details.modifiedFiles)) {
|
|
400
|
+
for (const path of details.modifiedFiles) {
|
|
401
|
+
if (typeof path === "string") event.preparation.fileOps.edited.add(path);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
if (!compactionModel) return;
|
|
407
|
+
const reference = parseModelReference(compactionModel);
|
|
408
|
+
if (!reference) return;
|
|
409
|
+
const model = ctx.modelRegistry.find(reference.provider, reference.modelId);
|
|
410
|
+
if (!model) {
|
|
411
|
+
ctx.ui.notify("Configured compaction model not found; using current session model.", "error");
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
if (compactionThinkingLevel && !supportedThinkingLevels(model).includes(compactionThinkingLevel)) {
|
|
415
|
+
ctx.ui.notify("Configured thinking level is unsupported; using current session model.", "error");
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
try {
|
|
420
|
+
const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);
|
|
421
|
+
if (!auth.ok) {
|
|
422
|
+
ctx.ui.notify("Couldn't authenticate configured compaction model; using current session model.", "error");
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
const requestModel = auth.baseUrl ? { ...model, baseUrl: auth.baseUrl } : model;
|
|
427
|
+
return {
|
|
428
|
+
compaction: await compact(
|
|
429
|
+
event.preparation,
|
|
430
|
+
requestModel,
|
|
431
|
+
auth.apiKey,
|
|
432
|
+
withoutDeletedHeaders(auth.headers),
|
|
433
|
+
event.customInstructions,
|
|
434
|
+
event.signal,
|
|
435
|
+
compactionThinkingLevel,
|
|
436
|
+
undefined,
|
|
437
|
+
auth.env,
|
|
438
|
+
),
|
|
439
|
+
};
|
|
440
|
+
} catch {
|
|
441
|
+
if (!event.signal.aborted) {
|
|
442
|
+
ctx.ui.notify("Configured compaction model failed; using current session model.", "error");
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
});
|
|
263
446
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@henryqw/pi-auto-compact",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Proactively compact Pi context at a configurable threshold and resume the current task.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"pack:check": "npm pack --dry-run"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
|
-
"@earendil-works/pi-coding-agent": "
|
|
28
|
+
"@earendil-works/pi-coding-agent": ">=0.80.7"
|
|
29
29
|
},
|
|
30
30
|
"repository": {
|
|
31
31
|
"type": "git",
|