@diegopetrucci/pi-extensions 0.1.66 → 0.1.68

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.
@@ -23,6 +23,7 @@ const THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh", "ma
23
23
  type ThinkingLevel = (typeof THINKING_LEVELS)[number];
24
24
  type ThinkingLevelMap = Partial<Record<ThinkingLevel, unknown | null>>;
25
25
  const CODE_REVIEWER_MODEL_PREFERENCES = [
26
+ "gpt-6-astra",
26
27
  "gpt-5.6-sol",
27
28
  "gpt-5.6-terra",
28
29
  "gpt-5.6-luna",
@@ -56,8 +57,9 @@ const PROVIDER_MODEL_PREFERENCES: Record<string, string[]> = {
56
57
  "claude-sonnet-4-6",
57
58
  "claude-sonnet-4-5",
58
59
  ],
59
- openai: ["gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna", "gpt-5.5", "gpt-5", "gpt-4.1", "o3", "o4-mini"],
60
+ openai: ["gpt-6-astra", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna", "gpt-5.5", "gpt-5", "gpt-4.1", "o3", "o4-mini"],
60
61
  "openai-codex": [
62
+ "gpt-6-astra",
61
63
  "gpt-5.6-sol",
62
64
  "gpt-5.6-terra",
63
65
  "gpt-5.6-luna",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diegopetrucci/pi-code-reviewer",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "A standalone pi extension that adds a read-only code_reviewer subagent tool for isolated code reviews.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -105,6 +105,7 @@ const CONTRARIAN_STATUS_ID = "contrarian";
105
105
  const CONTRARIAN_WIDGET_ID = "contrarian";
106
106
  const CONTRARIAN_CONFIG_FILE = "contrarian.json";
107
107
  const CONTRARIAN_MODEL_PREFERENCES = [
108
+ "gpt-6-astra",
108
109
  "gpt-5.6-sol",
109
110
  "gpt-5.6-terra",
110
111
  "gpt-5.6-luna",
@@ -247,21 +248,16 @@ const PROVIDER_MODEL_PREFERENCES: Record<string, string[]> = {
247
248
  "claude-fable-5",
248
249
  "claude-opus-4.8",
249
250
  "claude-opus-4.7",
250
- "claude-opus-4.6",
251
- "claude-opus-4.5",
251
+ "gpt-6-astra",
252
252
  "gpt-5.6-sol",
253
253
  "gpt-5.6-terra",
254
254
  "gpt-5.6-luna",
255
255
  "gpt-5.5",
256
256
  "gpt-5.4",
257
257
  "gpt-5.3-codex",
258
- "gpt-5.2-codex",
259
- "gpt-5.2",
260
- "gemini-3.1-pro-preview",
261
258
  "gemini-3.5-flash",
262
259
  "claude-sonnet-5",
263
260
  "claude-sonnet-4.6",
264
- "claude-sonnet-4.5",
265
261
  "gpt-5-mini",
266
262
  "kimi-k3",
267
263
  "kimi-k2.7-code",
@@ -323,6 +319,7 @@ const PROVIDER_MODEL_PREFERENCES: Record<string, string[]> = {
323
319
  "zai-glm-5-2",
324
320
  ],
325
321
  openai: [
322
+ "gpt-6-astra",
326
323
  "gpt-5.6-sol",
327
324
  "gpt-5.6-terra",
328
325
  "gpt-5.6-luna",
@@ -342,6 +339,7 @@ const PROVIDER_MODEL_PREFERENCES: Record<string, string[]> = {
342
339
  "gpt-5-mini",
343
340
  ],
344
341
  "openai-codex": [
342
+ "gpt-6-astra",
345
343
  "gpt-5.6-sol",
346
344
  "gpt-5.6-terra",
347
345
  "gpt-5.6-luna",
@@ -400,9 +398,7 @@ const PROVIDER_MODEL_PREFERENCES: Record<string, string[]> = {
400
398
  "anthropic/claude-fable-5",
401
399
  "~anthropic/claude-fable-latest",
402
400
  "anthropic/claude-opus-4.8",
403
- "anthropic/claude-opus-4.8-fast",
404
401
  "anthropic/claude-opus-4.7",
405
- "anthropic/claude-opus-4.7-fast",
406
402
  "anthropic/claude-opus-4.6",
407
403
  "anthropic/claude-opus-4.5",
408
404
  "anthropic/claude-opus-4.1",
@@ -528,7 +524,6 @@ const PROVIDER_MODEL_PREFERENCES: Record<string, string[]> = {
528
524
  "grok-4.6",
529
525
  "grok-4.5",
530
526
  "grok-4.3",
531
- "grok-build-0.1",
532
527
  ],
533
528
  xiaomi: ["mimo-v2.5-pro-ultraspeed", "mimo-v2.5-pro", "mimo-v2.5"],
534
529
  "xiaomi-token-plan-ams": ["mimo-v2.5-pro", "mimo-v2.5"],
@@ -541,9 +536,7 @@ const PROVIDER_MODEL_PREFERENCES: Record<string, string[]> = {
541
536
  "deepseek-ai/deepseek-v4-pro-0813",
542
537
  "moonshotai/kimi-k2.6",
543
538
  "minimaxai/minimax-m3",
544
- "openai/gpt-oss-120b",
545
539
  "nvidia/nemotron-3-nano-omni-30b-a3b-reasoning",
546
- "nvidia/nemotron-3-nano-30b-a3b",
547
540
  ],
548
541
  zai: [
549
542
  "glm-5.3",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diegopetrucci/pi-contrarian",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "A read-only contrarian subagent extension for pi that stress-tests plans, designs, assumptions, and conclusions.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -130,10 +130,10 @@ Where `r` is `gate.cachedPriceRatio` — the fraction of full price still paid
130
130
  for cached tokens (default `0.1`, i.e. cached tokens cost ~10% of fresh
131
131
  tokens). `breakEvenCalls` is how many subsequent LLM calls are needed to
132
132
  recoup the one-time cache-bust cost via the recurring saving. The gate accepts
133
- a batch of candidates only if `breakEvenCalls <= gate.breakEvenThreshold`
134
- (default `22`, calibrated from the representative-corpus benchmark — see the
135
- calibration note under [Configuration](#configuration) and the
136
- [Roadmap](#roadmap) evidence).
133
+ a batch of candidates only if `breakEvenCalls` is at most the effective
134
+ threshold for the current state (`idle=22`, `mid_loop=1` by default,
135
+ calibrated from the representative-corpus benchmark — see the calibration
136
+ note under [Configuration](#configuration) and the [Roadmap](#roadmap) evidence).
137
137
 
138
138
  All candidates proposed in the same `context` call share one cache bust (since
139
139
  a prompt cache is a single linear prefix), so they're evaluated and
@@ -179,7 +179,7 @@ branch:
179
179
  /context-pruning gate <on|off|always-apply>
180
180
  ```
181
181
 
182
- - `status`: enabled state, gate mode/threshold/ratio, per-strategy on/off
182
+ - `status`: enabled state, gate mode/effective per-state thresholds/ratio, per-strategy on/off
183
183
  state, protection counts, last call's raw/effective/saved token snapshot,
184
184
  and current context usage.
185
185
  - `stats`: cumulative tokens saved, overall and per strategy.
@@ -223,7 +223,7 @@ never required to exist. Full shape, with defaults:
223
223
  "mode": "on",
224
224
  "cachedPriceRatio": 0.1,
225
225
  "breakEvenThreshold": 22,
226
- "breakEvenThresholdByState": { "idle": 22, "mid_loop": 22 }
226
+ "breakEvenThresholdByState": { "idle": 22, "mid_loop": 1 }
227
227
  }
228
228
  }
229
229
  ```
@@ -243,7 +243,8 @@ Notes:
243
243
  break-even math (`gate.*`), which is a separate, later check on whatever
244
244
  survives this floor.
245
245
  - `gate.breakEvenThresholdByState` lets `idle` vs `mid_loop` agent states use
246
- different thresholds; both default to `gate.breakEvenThreshold`. Real
246
+ different thresholds; `idle` defaults to `22` and
247
+ `mid_loop` defaults to `1`. Real
247
248
  mid-loop/idle detection is wired through the `context` event handler
248
249
  (pe-zy4s): the state is classified straight from the message payload —
249
250
  `idle` if the most recent relevant message is a user message (this is the
@@ -253,9 +254,15 @@ Notes:
253
254
  runtime-observable definition and found the state-split REVERSED from an
254
255
  earlier turn-end-based analysis: at r=0.1, `idle` candidates now carry
255
256
  essentially all the realized net benefit and `mid_loop` candidates carry
256
- essentially none. Since `idle` is not the worthless state under this
257
- definition, both states are kept at parity (`22`/`22`) rather than forcing
258
- a stricter default in either direction.
257
+ essentially none. At r=0.1, the measured corpus therefore supports a
258
+ conservative `mid_loop=1` default, while `idle` remains `22`. Mid-loop
259
+ pruning can amortize over enough subsequent calls, but the observed
260
+ candidates did not justify a more permissive threshold. Turn-start
261
+ classification does not imply the provider cache is cold. The reported
262
+ field capture (2026-09-08: a mid_loop prune at `T=22` invalidated 81% of a
263
+ warm request prefix between consecutive LLM calls separated only by a
264
+ toolResult) illustrates cache invalidation, not proof that amortization is
265
+ impossible. Set `mid_loop` back to `22` to restore the old parity behavior.
259
266
  - `gate.breakEvenThreshold`'s default of `22` is calibrated from the
260
267
  representative-corpus benchmark at `cachedPriceRatio` r=0.1 (aggressive
261
268
  prompt caching, the common case) — see [Roadmap](#roadmap) for the full
@@ -448,11 +455,13 @@ re-derived on the representative corpus (460 gate-eligible candidates on the
448
455
  current `~/.the-last-harness/agent/sessions` corpus). The split **reverses**:
449
456
  at r=0.1, `idle` (T=22, ~20.6k realized net benefit) now carries essentially
450
457
  all the value, and `mid_loop` (T=1, ~0 realized net benefit) carries
451
- essentially none. Per the decision rule (stricter idle default only if idle
452
- is shown ~worthless), this evidence does **not** support a stricter idle
453
- default — parity (`22`/`22`) is kept. The table above is retained as the
454
- historical turn-END-definition record; it no longer reflects how the runtime
455
- classifies agent state.
458
+ essentially none. Under that ticket's decision rule (stricter idle default
459
+ only if idle is shown ~worthless), parity (`22`/`22`) was retained at the time.
460
+ The 2026-09-08 follow-up supersedes that default with `idle=22` / `mid_loop=1`,
461
+ using the measured mid-loop result to choose a conservative threshold (see
462
+ [Configuration](#configuration) for the evidence and limitations). The table
463
+ above is retained as the historical turn-END-definition record; it no longer
464
+ reflects how the runtime classifies agent state.
456
465
 
457
466
  **This reframes, rather than weakens, the case for v2.** Small deterministic
458
467
  removals (dedupe/error-purge/superseded-file-ops) structurally cannot beat
@@ -114,6 +114,22 @@ const DEFAULT_CACHED_PRICE_RATIO = 0.1;
114
114
  */
115
115
  const DEFAULT_BREAK_EVEN_THRESHOLD = 22;
116
116
 
117
+ /**
118
+ * Default mid_loop break-even threshold (pe-zy4s follow-up). The package's own
119
+ * representative-corpus benchmark (turn-START state definition — the same one
120
+ * the runtime `context` handler uses) favored rejecting mid_loop candidates
121
+ * at cachedPriceRatio r=0.1 (mid_loop-optimal T=1, total realized
122
+ * net benefit ~0.0). This supports a conservative default for the measured
123
+ * corpus, not a universal claim that mid_loop pruning cannot pay off.
124
+ * The reported 2026-09-08 byte-level capture (a mid_loop prune at T=22
125
+ * invalidating 81% of a warm request prefix) illustrates cache invalidation,
126
+ * not an inability to amortize it: enough subsequent calls can recoup a
127
+ * one-time bust. Idle keeps T=22; turn-start classification does not imply
128
+ * the provider cache is cold. Users who want the old behavior can override
129
+ * via gate.breakEvenThresholdByState.mid_loop.
130
+ */
131
+ const DEFAULT_MID_LOOP_BREAK_EVEN_THRESHOLD = 1;
132
+
117
133
  /** Tool names never pruned by default: orchestration/subagent-style tools and todo-like state. */
118
134
  const DEFAULT_PROTECTED_TOOL_NAMES = [
119
135
  "todo",
@@ -222,20 +238,19 @@ export type GateMode = "on" | "off" | "always-apply";
222
238
  * turn-START "idle" population (calls made at the start of a turn) carries
223
239
  * essentially ALL the realized net benefit (idle-optimal T=22, total realized
224
240
  * net benefit ~20,594 token-units), while "mid_loop" carries essentially NONE
225
- * (mid_loop-optimal T=1, total realized net benefit ~0.0 -- i.e. no mid_loop
226
- * candidate is ever worth accepting at r=0.1 under this definition). This is
241
+ * (mid_loop-optimal T=1, total realized net benefit ~0.0 on this corpus). This is
227
242
  * the OPPOSITE of what the pe-c5n9 evidence (measured under the old,
228
243
  * non-runtime-observable turn-END definition) suggested.
229
244
  *
230
245
  * Per the pe-zy4s decision rule (stricter idle default only if idle itself is
231
246
  * shown to be ~worthless): idle is NOT worthless here -- it is the ONLY state
232
- * carrying value at r=0.1 -- so no state-conditioned strictness is justified
233
- * in either direction. The per-state split is therefore kept at PARITY
234
- * (`breakEvenThresholdByState: { idle: DEFAULT_BREAK_EVEN_THRESHOLD, mid_loop:
235
- * DEFAULT_BREAK_EVEN_THRESHOLD }`), both config-overridable. A future ticket
236
- * could consider a stricter mid_loop default given this evidence, but that is
237
- * a new, unreviewed direction outside this ticket's authorized decision rule
238
- * and is left for a follow-up.
247
+ * carrying value at r=0.1 -- so the idle default stays at
248
+ * DEFAULT_BREAK_EVEN_THRESHOLD. The mid_loop default, by the same benchmark,
249
+ * is now DEFAULT_MID_LOOP_BREAK_EVEN_THRESHOLD (=1): the measured candidates
250
+ * did not justify a more permissive threshold at r=0.1. Mid_loop pruning can
251
+ * still amortize over enough subsequent calls; state alone does not establish
252
+ * cache warmth or profitability. Both defaults remain config-overridable via
253
+ * gate.breakEvenThresholdByState.
239
254
  */
240
255
  export type AgentState = "idle" | "mid_loop";
241
256
 
@@ -285,7 +300,7 @@ export function defaultConfig(): DynamicContextPruningConfig {
285
300
  mode: "on",
286
301
  cachedPriceRatio: DEFAULT_CACHED_PRICE_RATIO,
287
302
  breakEvenThreshold: DEFAULT_BREAK_EVEN_THRESHOLD,
288
- breakEvenThresholdByState: { idle: DEFAULT_BREAK_EVEN_THRESHOLD, mid_loop: DEFAULT_BREAK_EVEN_THRESHOLD },
303
+ breakEvenThresholdByState: { idle: DEFAULT_BREAK_EVEN_THRESHOLD, mid_loop: DEFAULT_MID_LOOP_BREAK_EVEN_THRESHOLD },
289
304
  },
290
305
  };
291
306
  }
@@ -2410,7 +2425,7 @@ export function formatStatusReport(input: StatusReportInput): string[] {
2410
2425
  const lines: string[] = [];
2411
2426
  lines.push(`Dynamic context pruning: ${config.enabled ? "ENABLED" : "disabled"}`);
2412
2427
  lines.push(
2413
- `Gate: mode=${config.gate.mode} threshold=${config.gate.breakEvenThreshold} cachedPriceRatio=${config.gate.cachedPriceRatio}`,
2428
+ `Gate: mode=${config.gate.mode} thresholds={idle:${resolveBreakEvenThreshold(config.gate, "idle")}, mid_loop:${resolveBreakEvenThreshold(config.gate, "mid_loop")}} cachedPriceRatio=${config.gate.cachedPriceRatio}`,
2414
2429
  );
2415
2430
  lines.push("Strategies:");
2416
2431
  lines.push(` dedupe: ${config.strategies.dedupe.enabled ? "on" : "off"}`);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-dynamic-context-pruning",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "type": "module",
5
5
  "description": "A pi extension that dynamically prunes stale context to keep sessions lean.",
6
6
  "keywords": [
@@ -230,21 +230,16 @@ const PROVIDER_MODEL_PREFERENCES: Record<string, string[]> = {
230
230
  "claude-fable-5",
231
231
  "claude-opus-4.8",
232
232
  "claude-opus-4.7",
233
- "claude-opus-4.6",
234
- "claude-opus-4.5",
233
+ "gpt-6-astra",
235
234
  "gpt-5.6-sol",
236
235
  "gpt-5.6-terra",
237
236
  "gpt-5.6-luna",
238
237
  "gpt-5.5",
239
238
  "gpt-5.4",
240
239
  "gpt-5.3-codex",
241
- "gpt-5.2-codex",
242
- "gpt-5.2",
243
- "gemini-3.1-pro-preview",
244
240
  "gemini-3.5-flash",
245
241
  "claude-sonnet-5",
246
242
  "claude-sonnet-4.6",
247
- "claude-sonnet-4.5",
248
243
  "gpt-5-mini",
249
244
  "kimi-k3",
250
245
  "kimi-k2.7-code",
@@ -306,6 +301,7 @@ const PROVIDER_MODEL_PREFERENCES: Record<string, string[]> = {
306
301
  "zai-glm-5-2",
307
302
  ],
308
303
  openai: [
304
+ "gpt-6-astra",
309
305
  "gpt-5.6-sol",
310
306
  "gpt-5.6-terra",
311
307
  "gpt-5.6-luna",
@@ -325,6 +321,7 @@ const PROVIDER_MODEL_PREFERENCES: Record<string, string[]> = {
325
321
  "gpt-5-mini",
326
322
  ],
327
323
  "openai-codex": [
324
+ "gpt-6-astra",
328
325
  "gpt-5.6-sol",
329
326
  "gpt-5.6-terra",
330
327
  "gpt-5.6-luna",
@@ -383,9 +380,7 @@ const PROVIDER_MODEL_PREFERENCES: Record<string, string[]> = {
383
380
  "anthropic/claude-fable-5",
384
381
  "~anthropic/claude-fable-latest",
385
382
  "anthropic/claude-opus-4.8",
386
- "anthropic/claude-opus-4.8-fast",
387
383
  "anthropic/claude-opus-4.7",
388
- "anthropic/claude-opus-4.7-fast",
389
384
  "anthropic/claude-opus-4.6",
390
385
  "anthropic/claude-opus-4.5",
391
386
  "anthropic/claude-opus-4.1",
@@ -511,7 +506,6 @@ const PROVIDER_MODEL_PREFERENCES: Record<string, string[]> = {
511
506
  "grok-4.6",
512
507
  "grok-4.5",
513
508
  "grok-4.3",
514
- "grok-build-0.1",
515
509
  ],
516
510
  xiaomi: ["mimo-v2.5-pro-ultraspeed", "mimo-v2.5-pro", "mimo-v2.5"],
517
511
  "xiaomi-token-plan-ams": ["mimo-v2.5-pro", "mimo-v2.5"],
@@ -524,9 +518,7 @@ const PROVIDER_MODEL_PREFERENCES: Record<string, string[]> = {
524
518
  "deepseek-ai/deepseek-v4-pro-0813",
525
519
  "moonshotai/kimi-k2.6",
526
520
  "minimaxai/minimax-m3",
527
- "openai/gpt-oss-120b",
528
521
  "nvidia/nemotron-3-nano-omni-30b-a3b-reasoning",
529
- "nvidia/nemotron-3-nano-30b-a3b",
530
522
  ],
531
523
  zai: [
532
524
  "glm-5.3",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diegopetrucci/pi-oracle",
3
- "version": "0.1.26",
3
+ "version": "0.1.27",
4
4
  "description": "An Amp-style oracle extension for pi that consults the strongest reasoning model on your current provider.",
5
5
  "keywords": [
6
6
  "pi-package",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diegopetrucci/pi-extensions",
3
- "version": "0.1.66",
3
+ "version": "0.1.68",
4
4
  "description": "A collection of pi extensions and skills for annotation UIs, context management, workflow audits, contrarian review, review-comment triage, notifications, brrr push alerts, safety guards, GitHub research, repo-local knowledge, todos, tool rendering, model/provider helpers, and Xiaohei-style article illustrations.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -71,9 +71,9 @@
71
71
  ]
72
72
  },
73
73
  "devDependencies": {
74
- "@earendil-works/pi-ai": "^0.84.4",
75
- "@earendil-works/pi-coding-agent": "^0.84.4",
76
- "@earendil-works/pi-tui": "^0.84.4",
74
+ "@earendil-works/pi-ai": "^0.85.1",
75
+ "@earendil-works/pi-coding-agent": "^0.85.1",
76
+ "@earendil-works/pi-tui": "^0.85.1",
77
77
  "@types/node": "^25.9.1",
78
78
  "husky": "^9.1.7",
79
79
  "typebox": "^1.3.6",