pi-goosedump 0.12.21 → 0.12.22
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 +14 -13
- package/dist/index.ts +43 -43
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -92,19 +92,20 @@ Optional settings live under `goosedump` in:
|
|
|
92
92
|
}
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
-
`turnsBeforeCompact` is an integer from 0 to 255. `0` disables
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
95
|
+
`turnsBeforeCompact` is an integer from 0 to 255. `0` disables the turn-based
|
|
96
|
+
trigger. Pi's `compaction.enabled` setting controls all automatic compaction, including
|
|
97
|
+
the turn-based trigger. Each completed model response counts as one turn, including
|
|
98
|
+
responses that call tools. The countdown is restored when a session resumes and
|
|
99
|
+
appears in the footer with a status dot (green when >25% turns remain, yellow when
|
|
100
|
+
≤25%, red when ≤12.5%) followed by a hexadecimal countdown. `● GD:0A` means ten
|
|
101
|
+
turns remain, `● GD:00` is ready to compact, and `● GD:--` means the turn trigger is
|
|
102
|
+
disabled. The footer adds `queued` while compaction is waiting to start and
|
|
103
|
+
`compacting` while the summary is being built. When the counter hits zero mid
|
|
104
|
+
tool-loop, compaction starts immediately after the current tool batch is persisted
|
|
105
|
+
and the task is resumed automatically. When the counter hits zero on a terminal
|
|
106
|
+
turn, compaction starts after the agent has settled. Pi remains the scheduler for
|
|
107
|
+
its context threshold. Whichever enabled limit is reached first compacts once, and
|
|
108
|
+
every successful compaction resets the countdown. A failed or cancelled compaction
|
|
108
109
|
leaves the counter armed at zero and retries on the next tool turn or settlement.
|
|
109
110
|
|
|
110
111
|
`summaryMaxTokens` is an integer from 512 to 65536 (default 4096). The effective
|
package/dist/index.ts
CHANGED
|
@@ -607,6 +607,16 @@ function piKeepRecentTokens(cwd, includeProject) {
|
|
|
607
607
|
}
|
|
608
608
|
return DEFAULT_COMPACTION_SETTINGS.keepRecentTokens;
|
|
609
609
|
}
|
|
610
|
+
function piCompactionEnabled(cwd, includeProject) {
|
|
611
|
+
const paths = includeProject ? [projectSettingsPath(cwd), globalSettingsPath()] : [globalSettingsPath()];
|
|
612
|
+
for (const path of paths) {
|
|
613
|
+
const compaction = readJsonObject(path).compaction;
|
|
614
|
+
if (isRecord(compaction) && typeof compaction.enabled === "boolean") {
|
|
615
|
+
return compaction.enabled;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
return DEFAULT_COMPACTION_SETTINGS.enabled;
|
|
619
|
+
}
|
|
610
620
|
function piReserveTokens(cwd, includeProject) {
|
|
611
621
|
const paths = includeProject ? [projectSettingsPath(cwd), globalSettingsPath()] : [globalSettingsPath()];
|
|
612
622
|
for (const path of paths) {
|
|
@@ -845,13 +855,11 @@ async function runSettingsEditor(ctx) {
|
|
|
845
855
|
const specs = [
|
|
846
856
|
{
|
|
847
857
|
key: "turnsBeforeCompact",
|
|
848
|
-
description: "LLM turns before compaction; 0 disables.",
|
|
849
858
|
min: TURNS_BEFORE_COMPACT_MIN,
|
|
850
859
|
max: TURNS_BEFORE_COMPACT_MAX
|
|
851
860
|
},
|
|
852
861
|
{
|
|
853
862
|
key: "summaryMaxTokens",
|
|
854
|
-
description: "Maximum estimated tokens in each summary.",
|
|
855
863
|
min: SUMMARY_MAX_TOKENS_MIN,
|
|
856
864
|
max: SUMMARY_MAX_TOKENS_MAX
|
|
857
865
|
}
|
|
@@ -964,11 +972,6 @@ async function runSettingsEditor(ctx) {
|
|
|
964
972
|
const cursor = selected ? accent("›") : " ";
|
|
965
973
|
content.push(`${cursor} ${renderedValue} ${text(spec.key)}`);
|
|
966
974
|
}
|
|
967
|
-
const selectedSpec = specs[selectedSetting];
|
|
968
|
-
if (selectedSpec) {
|
|
969
|
-
const inherited = scope === "project" && projectSettings[selectedSpec.key] === undefined;
|
|
970
|
-
content.push("", dim(inherited ? `${selectedSpec.description} Using the Global value.` : selectedSpec.description));
|
|
971
|
-
}
|
|
972
975
|
const effective = resolveGoosedumpSettings(location, projectTrusted);
|
|
973
976
|
content.push("", dim(`Effective: turns=${formatCompactSetting(effective.turnsBeforeCompact)} · summary=${effectiveSummaryMaxTokens(location, projectTrusted)} tokens`));
|
|
974
977
|
}
|
|
@@ -1403,6 +1406,7 @@ function createGoosedumpIntegration(options = {}) {
|
|
|
1403
1406
|
const nativeExecutablePath = options.nativeExecutablePath;
|
|
1404
1407
|
let goosedumpAvailable = false;
|
|
1405
1408
|
let compactSettings = DEFAULT_GOOSEDUMP_SETTINGS;
|
|
1409
|
+
let piAutoCompactionEnabled = DEFAULT_COMPACTION_SETTINGS.enabled;
|
|
1406
1410
|
let turnsRemaining = 0;
|
|
1407
1411
|
let counterTriggered = false;
|
|
1408
1412
|
let compactionState = { phase: "idle" };
|
|
@@ -1448,15 +1452,27 @@ function createGoosedumpIntegration(options = {}) {
|
|
|
1448
1452
|
await rememberRunning;
|
|
1449
1453
|
}
|
|
1450
1454
|
function syncCompactCounters(ctx) {
|
|
1451
|
-
|
|
1455
|
+
const projectTrusted = projectSettingsTrusted(ctx);
|
|
1456
|
+
compactSettings = resolveGoosedumpSettings(ctx.cwd, projectTrusted);
|
|
1457
|
+
piAutoCompactionEnabled = piCompactionEnabled(ctx.cwd, projectTrusted);
|
|
1452
1458
|
const completedTurns = completedTurnsSinceCompaction(ctx.sessionManager.getBranch());
|
|
1453
1459
|
turnsRemaining = Math.max(0, compactSettings.turnsBeforeCompact - completedTurns);
|
|
1454
1460
|
counterTriggered = compactSettings.turnsBeforeCompact > 0 && completedTurns >= compactSettings.turnsBeforeCompact;
|
|
1455
1461
|
}
|
|
1462
|
+
function turnCompactionEnabled() {
|
|
1463
|
+
return shouldOverrideDefaultCompaction && piAutoCompactionEnabled && compactSettings.turnsBeforeCompact > 0;
|
|
1464
|
+
}
|
|
1465
|
+
function turnRequestIsEligible(request) {
|
|
1466
|
+
return request.origin !== "turn" || turnCompactionEnabled() && counterTriggered;
|
|
1467
|
+
}
|
|
1468
|
+
function requeueRequest(request, eligibleSettlement) {
|
|
1469
|
+
const queued = { ...request, eligibleSettlement };
|
|
1470
|
+
return requestIsCurrent(queued) && turnRequestIsEligible(queued) ? { phase: "queued", request: queued } : { phase: "idle" };
|
|
1471
|
+
}
|
|
1456
1472
|
function updateStatus(ctx) {
|
|
1457
1473
|
if (!goosedumpAvailable)
|
|
1458
1474
|
return;
|
|
1459
|
-
const active =
|
|
1475
|
+
const active = turnCompactionEnabled();
|
|
1460
1476
|
let dotColor = "success";
|
|
1461
1477
|
if (active) {
|
|
1462
1478
|
const remainingRatio = turnsRemaining / compactSettings.turnsBeforeCompact;
|
|
@@ -1493,7 +1509,7 @@ function createGoosedumpIntegration(options = {}) {
|
|
|
1493
1509
|
}, { triggerTurn: true });
|
|
1494
1510
|
}
|
|
1495
1511
|
function tryMidRunCounterCompaction(ctx) {
|
|
1496
|
-
if (!goosedumpAvailable || !
|
|
1512
|
+
if (!goosedumpAvailable || !turnCompactionEnabled())
|
|
1497
1513
|
return false;
|
|
1498
1514
|
if (!counterTriggered)
|
|
1499
1515
|
return false;
|
|
@@ -1503,14 +1519,10 @@ function createGoosedumpIntegration(options = {}) {
|
|
|
1503
1519
|
return false;
|
|
1504
1520
|
if (compactionState.phase === "idle") {
|
|
1505
1521
|
queueTurnCompaction(ctx, settlementGeneration);
|
|
1506
|
-
} else if (compactionState.phase === "queued") {
|
|
1507
|
-
setCompactionState(ctx,
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
...compactionState.request,
|
|
1511
|
-
eligibleSettlement: Math.min(compactionState.request.eligibleSettlement, settlementGeneration)
|
|
1512
|
-
}
|
|
1513
|
-
});
|
|
1522
|
+
} else if (compactionState.phase === "queued" && compactionState.request.origin === "turn") {
|
|
1523
|
+
setCompactionState(ctx, requeueRequest(compactionState.request, Math.min(compactionState.request.eligibleSettlement, settlementGeneration)));
|
|
1524
|
+
} else {
|
|
1525
|
+
return false;
|
|
1514
1526
|
}
|
|
1515
1527
|
return startQueuedCompaction(ctx, { resumeAfter: true, allowActiveRun: true });
|
|
1516
1528
|
}
|
|
@@ -1538,20 +1550,14 @@ function createGoosedumpIntegration(options = {}) {
|
|
|
1538
1550
|
signal?.addEventListener("abort", () => {
|
|
1539
1551
|
if (!runningOperationIsCurrent(operation, generation, sessionFile))
|
|
1540
1552
|
return;
|
|
1541
|
-
setCompactionState(ctx, reason !== "manual" && request
|
|
1542
|
-
phase: "queued",
|
|
1543
|
-
request: {
|
|
1544
|
-
...request,
|
|
1545
|
-
eligibleSettlement: Math.max(request.eligibleSettlement, settlementGeneration + 2)
|
|
1546
|
-
}
|
|
1547
|
-
} : { phase: "idle" });
|
|
1553
|
+
setCompactionState(ctx, reason !== "manual" && request ? requeueRequest(request, Math.max(request.eligibleSettlement, settlementGeneration + 2)) : { phase: "idle" });
|
|
1548
1554
|
}, { once: true });
|
|
1549
1555
|
}
|
|
1550
1556
|
function requestHasCompactableHistory(ctx, keep) {
|
|
1551
1557
|
return keep === null ? hasCompactableHistory(ctx) : keepBoundaryId(ctx.sessionManager.getBranch(), keep) !== undefined;
|
|
1552
1558
|
}
|
|
1553
1559
|
function queueTurnCompaction(ctx, eligibleSettlement) {
|
|
1554
|
-
if (!counterTriggered || compactionState.phase !== "idle")
|
|
1560
|
+
if (!turnCompactionEnabled() || !counterTriggered || compactionState.phase !== "idle")
|
|
1555
1561
|
return;
|
|
1556
1562
|
if (!hasCompactableHistory(ctx))
|
|
1557
1563
|
return;
|
|
@@ -1559,6 +1565,7 @@ function createGoosedumpIntegration(options = {}) {
|
|
|
1559
1565
|
phase: "queued",
|
|
1560
1566
|
request: {
|
|
1561
1567
|
keep: null,
|
|
1568
|
+
origin: "turn",
|
|
1562
1569
|
sessionGeneration,
|
|
1563
1570
|
sessionFile: activeSessionFile,
|
|
1564
1571
|
eligibleSettlement
|
|
@@ -1569,7 +1576,9 @@ function createGoosedumpIntegration(options = {}) {
|
|
|
1569
1576
|
if (compactionState.phase !== "queued")
|
|
1570
1577
|
return false;
|
|
1571
1578
|
const request = compactionState.request;
|
|
1572
|
-
if (
|
|
1579
|
+
if (request.origin === "turn")
|
|
1580
|
+
syncCompactCounters(ctx);
|
|
1581
|
+
if (!requestIsCurrent(request) || !turnRequestIsEligible(request)) {
|
|
1573
1582
|
setCompactionState(ctx, { phase: "idle" });
|
|
1574
1583
|
return false;
|
|
1575
1584
|
}
|
|
@@ -1636,6 +1645,7 @@ function createGoosedumpIntegration(options = {}) {
|
|
|
1636
1645
|
phase: "queued",
|
|
1637
1646
|
request: {
|
|
1638
1647
|
keep,
|
|
1648
|
+
origin: "manual",
|
|
1639
1649
|
sessionGeneration,
|
|
1640
1650
|
sessionFile: activeSessionFile,
|
|
1641
1651
|
eligibleSettlement: settlementGeneration + 1
|
|
@@ -2000,13 +2010,10 @@ ${lines.join(`
|
|
|
2000
2010
|
updateStatus(ctx);
|
|
2001
2011
|
if (compactionState.phase === "running" && compactionState.owner === "pi") {
|
|
2002
2012
|
const request = compactionState.request;
|
|
2003
|
-
setCompactionState(ctx, request
|
|
2004
|
-
phase: "queued",
|
|
2005
|
-
request: { ...request, eligibleSettlement: settlementGeneration + 1 }
|
|
2006
|
-
} : { phase: "idle" });
|
|
2013
|
+
setCompactionState(ctx, request ? requeueRequest(request, settlementGeneration + 1) : { phase: "idle" });
|
|
2007
2014
|
return;
|
|
2008
2015
|
}
|
|
2009
|
-
if (compactionState.phase === "queued" && !requestIsCurrent(compactionState.request)) {
|
|
2016
|
+
if (compactionState.phase === "queued" && (!requestIsCurrent(compactionState.request) || !turnRequestIsEligible(compactionState.request))) {
|
|
2010
2017
|
setCompactionState(ctx, { phase: "idle" });
|
|
2011
2018
|
}
|
|
2012
2019
|
if (compactionState.phase === "idle") {
|
|
@@ -2051,10 +2058,9 @@ ${lines.join(`
|
|
|
2051
2058
|
if (compactionState.phase !== "running" || compactionState.owner !== "pi")
|
|
2052
2059
|
return;
|
|
2053
2060
|
const request = compactionState.request;
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
} : { phase: "idle" });
|
|
2061
|
+
if (request?.origin === "turn")
|
|
2062
|
+
syncCompactCounters(ctx);
|
|
2063
|
+
setCompactionState(ctx, request ? requeueRequest(request, settlementGeneration + 1) : { phase: "idle" });
|
|
2058
2064
|
});
|
|
2059
2065
|
pi.on("turn_end", async (event, ctx) => {
|
|
2060
2066
|
if (isCompletedAssistant(event.message))
|
|
@@ -2071,13 +2077,7 @@ ${lines.join(`
|
|
|
2071
2077
|
const signal = event.signal;
|
|
2072
2078
|
if (signal?.aborted) {
|
|
2073
2079
|
if (compactionState.phase === "queued" && requestIsCurrent(compactionState.request)) {
|
|
2074
|
-
setCompactionState(ctx, event.reason === "manual" ? { phase: "idle" } :
|
|
2075
|
-
phase: "queued",
|
|
2076
|
-
request: {
|
|
2077
|
-
...compactionState.request,
|
|
2078
|
-
eligibleSettlement: Math.max(compactionState.request.eligibleSettlement, settlementGeneration + 2)
|
|
2079
|
-
}
|
|
2080
|
-
});
|
|
2080
|
+
setCompactionState(ctx, event.reason === "manual" ? { phase: "idle" } : requeueRequest(compactionState.request, Math.max(compactionState.request.eligibleSettlement, settlementGeneration + 2)));
|
|
2081
2081
|
}
|
|
2082
2082
|
return { cancel: true };
|
|
2083
2083
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-goosedump",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.22",
|
|
4
4
|
"description": "Pi extension for goosedump session search, durable memory, and compaction",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"compaction",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@earendil-works/pi-tui": "^0.82.1",
|
|
41
|
-
"@jarkkojs/goosedump": "^0.12.
|
|
41
|
+
"@jarkkojs/goosedump": "^0.12.22",
|
|
42
42
|
"@sinclair/typebox": "^0.34.49"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|