pi-context-map 0.7.2 → 0.7.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.7.3] - 2026-06-15
4
+ ### Bug Fixes
5
+ - **Fixed insights context window**: Removed hardcoded "128k" from all insight messages. Now shows actual window size (e.g., "your 200k context window").
6
+ - **Fixed stale file count**: Insight now counts both "legacy" AND "stale" files (all inactive), matching what the files section shows.
7
+ - **Fixed composition bar**: Used largest-remainder method to ensure segment percentages always sum to exactly 100%. No more gaps.
8
+
3
9
  ## [0.7.2] - 2026-06-15
4
10
  ### Bug Fixes
5
11
  - **Fixed insights context window**: Now uses the actual context window from Pi (e.g., 200k) instead of hardcoded 128k. Critical insight no longer shows wrong percentages.
@@ -50,7 +50,7 @@ export interface ContextComposition {
50
50
  export class ContextAnalyzer {
51
51
  public analyzeByType(
52
52
  messages: any[],
53
- currentTurn: number,
53
+ _currentTurn: number,
54
54
  systemPrompt?: string,
55
55
  ): ContextComposition {
56
56
  const fileRegistry = new Map<string, FileContext>();
@@ -243,9 +243,30 @@ export class ContextAnalyzer {
243
243
  const totalTokens =
244
244
  systemTokens + toolTokens + historyTokens + fileTokens + summaryTokens;
245
245
 
246
- const mk = (tokens: number): ContextSlice => ({
246
+ // Calculate exact percentages, then use largest-remainder to ensure sum = 100
247
+ const raw = [
248
+ { key: "system", tokens: systemTokens },
249
+ { key: "tools", tokens: toolTokens },
250
+ { key: "history", tokens: historyTokens },
251
+ { key: "files", tokens: fileTokens },
252
+ { key: "summaries", tokens: summaryTokens },
253
+ ];
254
+ const floored = raw.map((r) => ({
255
+ ...r,
256
+ pct: totalTokens > 0 ? Math.floor((r.tokens / totalTokens) * 100) : 0,
257
+ remainder: totalTokens > 0 ? ((r.tokens / totalTokens) * 100) % 1 : 0,
258
+ }));
259
+ let sum = floored.reduce((s, r) => s + r.pct, 0);
260
+ const sorted = [...floored].sort((a, b) => b.remainder - a.remainder);
261
+ for (let i = 0; sum < 100 && i < sorted.length; i++) {
262
+ sorted[i].pct++;
263
+ sum++;
264
+ }
265
+ const pctMap = new Map(floored.map((r) => [r.key, r.pct]));
266
+
267
+ const mk = (key: string, tokens: number): ContextSlice => ({
247
268
  tokens: Math.ceil(tokens),
248
- percent: totalTokens > 0 ? Math.round((tokens / totalTokens) * 100) : 0,
269
+ percent: pctMap.get(key) || 0,
249
270
  });
250
271
 
251
272
  const files_detail = Array.from(fileRegistry.values())
@@ -253,19 +274,19 @@ export class ContextAnalyzer {
253
274
  .slice(0, 100);
254
275
 
255
276
  return {
256
- system: mk(systemTokens),
257
- tools: mk(toolTokens),
258
- history: mk(historyTokens),
259
- files: mk(fileTokens),
260
- summaries: mk(summaryTokens),
261
- total: mk(totalTokens),
277
+ system: mk("system", systemTokens),
278
+ tools: mk("tools", toolTokens),
279
+ history: mk("history", historyTokens),
280
+ files: mk("files", fileTokens),
281
+ summaries: mk("summaries", summaryTokens),
282
+ total: { tokens: Math.ceil(totalTokens), percent: 100 },
262
283
  files_detail,
263
284
  };
264
285
  }
265
286
 
266
287
  /** Backward-compatible wrapper. */
267
- public analyze(messages: any[], currentTurn: number): ContextComposition {
268
- return this.analyzeByType(messages, currentTurn);
288
+ public analyze(messages: any[], _currentTurn: number): ContextComposition {
289
+ return this.analyzeByType(messages, _currentTurn);
269
290
  }
270
291
 
271
292
  private extractPath(toolName: string, args: any): string | null {
@@ -37,17 +37,17 @@ export class InsightEngine {
37
37
  });
38
38
  }
39
39
 
40
- // Rule 2: Stale files
40
+ // Rule 2: Stale/legacy files
41
41
  const staleFiles = composition.files_detail.filter(
42
- (f) => f.status === "legacy",
42
+ (f) => f.status === "legacy" || f.status === "stale",
43
43
  );
44
44
  if (staleFiles.length > 0) {
45
45
  const totalStaleTokens = staleFiles.reduce((sum, f) => sum + f.weight, 0);
46
46
  insights.push({
47
47
  id: "stale-files",
48
48
  severity: staleFiles.length > 5 ? "warning" : "info",
49
- title: `${staleFiles.length} stale file(s) in context`,
50
- message: `Files accessed more than 10 turns ago are still in context (~${totalStaleTokens.toLocaleString()} tokens). They are unlikely to be needed.`,
49
+ title: `${staleFiles.length} inactive file(s) in context`,
50
+ message: `${staleFiles.length} file(s) accessed earlier in the session are still in context (~${totalStaleTokens.toLocaleString()} tokens). They are unlikely to be needed.`,
51
51
  });
52
52
  }
53
53
 
@@ -58,7 +58,7 @@ export class InsightEngine {
58
58
  id: "high-usage",
59
59
  severity: "critical",
60
60
  title: "Context window nearly full",
61
- message: `You are at ${usagePercent}% of a typical 128k context window. Compaction or summarization is strongly recommended.`,
61
+ message: `You are at ${usagePercent}% of your ${(windowSize / 1000).toFixed(0)}k context window. Compaction or summarization is strongly recommended.`,
62
62
  command: "/ultra-compact",
63
63
  });
64
64
  } else if (usagePercent > 60) {
@@ -66,7 +66,7 @@ export class InsightEngine {
66
66
  id: "moderate-usage",
67
67
  severity: "warning",
68
68
  title: "Context usage is high",
69
- message: `You are at ${usagePercent}% of a typical 128k context window. Plan to compact before adding more files.`,
69
+ message: `You are at ${usagePercent}% of your ${(windowSize / 1000).toFixed(0)}k context window. Plan to compact before adding more files.`,
70
70
  });
71
71
  }
72
72
 
@@ -107,7 +107,7 @@ export class InsightEngine {
107
107
  id: "healthy-context",
108
108
  severity: "info",
109
109
  title: "Context looks healthy",
110
- message: `Your context composition is balanced and under ${usagePercent}% of a typical window.`,
110
+ message: `Your context composition is balanced and under ${usagePercent}% of your ${(windowSize / 1000).toFixed(0)}k window.`,
111
111
  });
112
112
  }
113
113
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-context-map",
3
- "version": "0.7.2",
3
+ "version": "0.7.3",
4
4
  "description": "Professional context profiler for Pi that visualizes the session context window, token distribution, and integrates with Nexus packages for actionable insights.",
5
5
  "keywords": [
6
6
  "pi-package",