pi-goosedump 0.12.17 → 0.12.18

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 (3) hide show
  1. package/README.md +11 -11
  2. package/dist/index.ts +78 -14
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -93,17 +93,17 @@ Optional settings live under `goosedump` in:
93
93
  ```
94
94
 
95
95
  `turnsBeforeCompact` is an integer from 0 to 255. `0` disables scheduled
96
- compaction. Each completed model response counts as one turn, including responses
97
- that call tools. The countdown is restored when a session resumes and appears in
98
- the footer with a status dot (green when >25% turns remain, yellow when ≤25%, red
99
- when ≤12.5%) followed by a hexadecimal countdown. `● GD:0A` means ten turns
100
- remain, `● GD:00` is ready to compact, and `● GD:--` is disabled. The footer
101
- adds `queued` while compaction is waiting for the active agent run to settle and
102
- `compacting` while the summary is being built. Pi remains the sole scheduler for
103
- its normal context threshold. Whichever limit is reached first compacts once,
104
- and every successful compaction resets the countdown. A failed or cancelled
105
- compaction leaves the counter armed at zero and is not retried in the same
106
- settlement.
96
+ compaction. Each fully settled agent run counts as one turn; intermediate model
97
+ responses that call tools do not. The countdown is restored when a session
98
+ resumes and appears in the footer with a status dot (green when >25% turns
99
+ remain, yellow when ≤25%, red when ≤12.5%) followed by a hexadecimal countdown.
100
+ `● GD:0A` means ten turns remain, `● GD:00` is ready to compact, and `● GD:--`
101
+ is disabled. The footer adds `queued` while compaction is waiting for the active
102
+ agent run to settle and `compacting` while the summary is being built. Pi remains
103
+ the sole scheduler for its normal context threshold. Whichever limit is reached
104
+ first compacts once, and every successful compaction resets the countdown. A
105
+ failed or cancelled compaction leaves the counter armed at zero and is not
106
+ retried in the same settlement.
107
107
 
108
108
  `summaryMaxTokens` is an integer from 512 to 65536 (default 4096). The effective
109
109
  summary budget is the lower of this value and 80% of Pi's `compaction.reserveTokens`,
package/dist/index.ts CHANGED
@@ -590,11 +590,26 @@ function currentSessionTarget(ctx) {
590
590
  function isCompactionEntry(entry) {
591
591
  return entry.type === "compaction";
592
592
  }
593
+ var COMPLETED_AGENT_RUN_ENTRY = "goosedump-completed-agent-run";
593
594
  function isMessageEntry(entry) {
594
595
  return entry.type === "message";
595
596
  }
596
- function isCompletedAssistant(message) {
597
- return message.role === "assistant" && message.stopReason !== "error" && message.stopReason !== "aborted";
597
+ function isTerminalAssistant(message) {
598
+ if (message.role !== "assistant")
599
+ return false;
600
+ if (message.stopReason !== "stop" && message.stopReason !== "length")
601
+ return false;
602
+ return !(Array.isArray(message.content) && message.content.some((part) => isRecord(part) && part.type === "toolCall"));
603
+ }
604
+ function completedAgentRunData(entry) {
605
+ if (entry.type !== "custom" || entry.customType !== COMPLETED_AGENT_RUN_ENTRY)
606
+ return;
607
+ if (!isRecord(entry.data) || entry.data.version !== 1)
608
+ return;
609
+ const startedAfterEntryId = entry.data.startedAfterEntryId;
610
+ if (startedAfterEntryId !== null && typeof startedAfterEntryId !== "string")
611
+ return;
612
+ return { version: 1, startedAfterEntryId };
598
613
  }
599
614
  var SUMMARIZABLE_ENTRY_TYPES = new Set(["message", "custom_message", "branch_summary"]);
600
615
  function piKeepRecentTokens(cwd, includeProject) {
@@ -666,7 +681,7 @@ function activeHistoryStartIndex(branchEntries) {
666
681
  const compaction = latestCompaction(branchEntries);
667
682
  return compaction ? compactionBoundaryStartIndex(branchEntries, compaction) : 0;
668
683
  }
669
- function completedTurnsSinceCompaction(branchEntries) {
684
+ function completedRunsSinceCompaction(branchEntries) {
670
685
  let start = 0;
671
686
  for (let i = branchEntries.length - 1;i >= 0; i -= 1) {
672
687
  if (isCompactionEntry(branchEntries[i])) {
@@ -674,10 +689,27 @@ function completedTurnsSinceCompaction(branchEntries) {
674
689
  break;
675
690
  }
676
691
  }
692
+ const firstMarkerIndex = branchEntries.findIndex((entry, index) => index >= start && completedAgentRunData(entry) !== undefined);
693
+ if (firstMarkerIndex < 0) {
694
+ let completed2 = 0;
695
+ for (let i = start;i < branchEntries.length; i += 1) {
696
+ const entry = branchEntries[i];
697
+ if (isMessageEntry(entry) && isTerminalAssistant(entry.message))
698
+ completed2 += 1;
699
+ }
700
+ return completed2;
701
+ }
702
+ const firstMarker = completedAgentRunData(branchEntries[firstMarkerIndex]);
703
+ const boundaryIndex = firstMarker?.startedAfterEntryId ? branchEntries.findIndex((entry) => entry.id === firstMarker.startedAfterEntryId) : start - 1;
704
+ const legacyEnd = boundaryIndex >= start ? boundaryIndex + 1 : start;
677
705
  let completed = 0;
678
- for (let i = start;i < branchEntries.length; i += 1) {
706
+ for (let i = start;i < legacyEnd; i += 1) {
679
707
  const entry = branchEntries[i];
680
- if (isMessageEntry(entry) && isCompletedAssistant(entry.message))
708
+ if (isMessageEntry(entry) && isTerminalAssistant(entry.message))
709
+ completed += 1;
710
+ }
711
+ for (let i = firstMarkerIndex;i < branchEntries.length; i += 1) {
712
+ if (completedAgentRunData(branchEntries[i]) !== undefined)
681
713
  completed += 1;
682
714
  }
683
715
  return completed;
@@ -845,7 +877,7 @@ async function runSettingsEditor(ctx) {
845
877
  const specs = [
846
878
  {
847
879
  key: "turnsBeforeCompact",
848
- description: "LLM turns before compaction; 0 disables.",
880
+ description: "Completed agent runs before compaction; 0 disables.",
849
881
  min: TURNS_BEFORE_COMPACT_MIN,
850
882
  max: TURNS_BEFORE_COMPACT_MAX
851
883
  },
@@ -1411,6 +1443,8 @@ function createGoosedumpIntegration(options = {}) {
1411
1443
  let operationGeneration = 0;
1412
1444
  let activeSessionFile = null;
1413
1445
  let sessionActive = false;
1446
+ let agentRunObserved = false;
1447
+ let agentRunStartEntryId = null;
1414
1448
  const rememberQueue = [];
1415
1449
  let rememberRunning = null;
1416
1450
  function enqueueRemember(target, reportError) {
@@ -1448,9 +1482,9 @@ function createGoosedumpIntegration(options = {}) {
1448
1482
  }
1449
1483
  function syncCompactCounters(ctx) {
1450
1484
  compactSettings = resolveGoosedumpSettings(ctx.cwd, projectSettingsTrusted(ctx));
1451
- const completedTurns = completedTurnsSinceCompaction(ctx.sessionManager.getBranch());
1452
- turnsRemaining = Math.max(0, compactSettings.turnsBeforeCompact - completedTurns);
1453
- counterTriggered = compactSettings.turnsBeforeCompact > 0 && completedTurns >= compactSettings.turnsBeforeCompact;
1485
+ const completedRuns = completedRunsSinceCompaction(ctx.sessionManager.getBranch());
1486
+ turnsRemaining = Math.max(0, compactSettings.turnsBeforeCompact - completedRuns);
1487
+ counterTriggered = compactSettings.turnsBeforeCompact > 0 && completedRuns >= compactSettings.turnsBeforeCompact;
1454
1488
  }
1455
1489
  function updateStatus(ctx) {
1456
1490
  if (!goosedumpAvailable)
@@ -1475,7 +1509,7 @@ function createGoosedumpIntegration(options = {}) {
1475
1509
  compactionState = state;
1476
1510
  updateStatus(ctx);
1477
1511
  }
1478
- function noteCompletedTurn(ctx) {
1512
+ function noteCompletedRun(ctx) {
1479
1513
  if (!goosedumpAvailable || !shouldOverrideDefaultCompaction)
1480
1514
  return;
1481
1515
  syncCompactCounters(ctx);
@@ -1978,6 +2012,8 @@ ${lines.join(`
1978
2012
  settlementGeneration = 0;
1979
2013
  activeSessionFile = ctx.sessionManager.getSessionFile?.() ?? null;
1980
2014
  sessionActive = true;
2015
+ agentRunObserved = false;
2016
+ agentRunStartEntryId = null;
1981
2017
  compactionState = { phase: "idle" };
1982
2018
  goosedumpAvailable = checkGoosedump(ctx);
1983
2019
  notifyInvalidSettings(ctx);
@@ -1991,9 +2027,28 @@ ${lines.join(`
1991
2027
  settlementGeneration = 0;
1992
2028
  activeSessionFile = null;
1993
2029
  sessionActive = false;
2030
+ agentRunObserved = false;
2031
+ agentRunStartEntryId = null;
1994
2032
  compactionState = { phase: "idle" };
1995
2033
  });
2034
+ pi.on("session_tree", async (_event, ctx) => {
2035
+ sessionGeneration += 1;
2036
+ settlementGeneration = 0;
2037
+ activeSessionFile = ctx.sessionManager.getSessionFile?.() ?? null;
2038
+ sessionActive = true;
2039
+ agentRunObserved = false;
2040
+ agentRunStartEntryId = null;
2041
+ compactionState = { phase: "idle" };
2042
+ syncCompactCounters(ctx);
2043
+ updateStatus(ctx);
2044
+ queueTurnCompaction(ctx, 1);
2045
+ deferQueuedCompaction(ctx);
2046
+ });
1996
2047
  pi.on("agent_start", async (_event, ctx) => {
2048
+ if (!agentRunObserved) {
2049
+ agentRunObserved = true;
2050
+ agentRunStartEntryId = ctx.sessionManager.getBranch().at(-1)?.id ?? null;
2051
+ }
1997
2052
  if (compactionState.phase !== "running" || compactionState.owner !== "pi")
1998
2053
  return;
1999
2054
  const request = compactionState.request;
@@ -2002,11 +2057,20 @@ ${lines.join(`
2002
2057
  request: { ...request, eligibleSettlement: settlementGeneration + 1 }
2003
2058
  } : { phase: "idle" });
2004
2059
  });
2005
- pi.on("turn_end", async (event, ctx) => {
2006
- if (isCompletedAssistant(event.message))
2007
- noteCompletedTurn(ctx);
2008
- });
2009
2060
  pi.on("agent_settled", async (_event, ctx) => {
2061
+ if (agentRunObserved) {
2062
+ const countRun = shouldOverrideDefaultCompaction && compactSettings.turnsBeforeCompact > 0;
2063
+ if (countRun) {
2064
+ pi.appendEntry(COMPLETED_AGENT_RUN_ENTRY, {
2065
+ version: 1,
2066
+ startedAfterEntryId: agentRunStartEntryId
2067
+ });
2068
+ }
2069
+ agentRunObserved = false;
2070
+ agentRunStartEntryId = null;
2071
+ if (countRun)
2072
+ noteCompletedRun(ctx);
2073
+ }
2010
2074
  handleAgentSettled(ctx);
2011
2075
  });
2012
2076
  pi.on("session_before_compact", async (event, ctx) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-goosedump",
3
- "version": "0.12.17",
3
+ "version": "0.12.18",
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.17",
41
+ "@jarkkojs/goosedump": "^0.12.18",
42
42
  "@sinclair/typebox": "^0.34.49"
43
43
  },
44
44
  "devDependencies": {