@oh-my-pi/pi-agent-core 18.13.2 → 18.13.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
@@ -2,6 +2,16 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [18.13.3] - 2026-10-28
6
+
7
+ ### Changed
8
+
9
+ - Updated Bun engine requirement to ≥1.4.4
10
+
11
+ ### Fixed
12
+
13
+ - Fixed chat-completions context estimates counting past thinking that the request drops (no reasoning replay), which triggered compaction far below the threshold ([#15797](https://github.com/can1357/oh-my-pi/issues/15797), [#17231](https://github.com/can1357/oh-my-pi/pull/17231) by [@ghisguth](https://github.com/ghisguth))
14
+
5
15
  ## [18.13.2] - 2026-10-27
6
16
 
7
17
  ### Added
@@ -9,6 +9,7 @@ export declare function tokenizerEncodingForModel(model: Pick<Model, "tokenizer"
9
9
  type TokenizerModel = Pick<Model, "tokenizer"> & snapcompact.ShapeTarget & {
10
10
  compat?: Model["compat"];
11
11
  thinking?: Model["thinking"];
12
+ reasoning?: boolean;
12
13
  };
13
14
  /** Identity of the reader whose replayed reasoning a {@link Tokenizer} counts; equal keys count it alike. */
14
15
  export declare function reasoningReplayKey(model: TokenizerModel | null | undefined): string;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-agent-core",
4
- "version": "18.13.2",
4
+ "version": "18.13.3",
5
5
  "description": "General-purpose agent with transport abstraction, state management, and attachment support",
6
6
  "homepage": "https://omp.sh",
7
7
  "author": {
@@ -38,22 +38,22 @@
38
38
  "fmt": "oxfmt --no-error-on-unmatched-pattern 'src/**/*.{ts,tsx}' '{test,bench,examples,scripts}/**/*.ts' '*.ts'"
39
39
  },
40
40
  "dependencies": {
41
- "@oh-my-pi/pi-ai": "18.13.2",
42
- "@oh-my-pi/pi-catalog": "18.13.2",
43
- "@oh-my-pi/pi-natives": "18.13.2",
44
- "@oh-my-pi/pi-utils": "18.13.2",
45
- "@oh-my-pi/pi-wire": "18.13.2",
46
- "@oh-my-pi/snapcompact": "18.13.2",
41
+ "@oh-my-pi/pi-ai": "18.13.3",
42
+ "@oh-my-pi/pi-catalog": "18.13.3",
43
+ "@oh-my-pi/pi-natives": "18.13.3",
44
+ "@oh-my-pi/pi-utils": "18.13.3",
45
+ "@oh-my-pi/pi-wire": "18.13.3",
46
+ "@oh-my-pi/snapcompact": "18.13.3",
47
47
  "@opentelemetry/api": "^1.9.1"
48
48
  },
49
49
  "devDependencies": {
50
- "@oh-my-pi/omptype": "18.13.2",
50
+ "@oh-my-pi/omptype": "18.13.3",
51
51
  "@opentelemetry/context-async-hooks": "^2.9.0",
52
52
  "@opentelemetry/sdk-trace-base": "^2.9.0",
53
53
  "@types/bun": "^1.3.14"
54
54
  },
55
55
  "engines": {
56
- "bun": ">=1.3.14"
56
+ "bun": ">=1.4.4"
57
57
  },
58
58
  "files": [
59
59
  "src",
package/src/tokenizer.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { AssistantMessage, Model } from "@oh-my-pi/pi-ai";
2
2
  import { renderDemotedThinking } from "@oh-my-pi/pi-ai/dialect/demotion";
3
3
  import { ollamaChatDropsOwnThinking } from "@oh-my-pi/pi-ai/providers/ollama";
4
+ import { completionsDropsOwnThinking, isLiteLLMThinkingSignature } from "@oh-my-pi/pi-ai/providers/openai-completions";
4
5
  import { isColdReplayableResponsesTurn } from "@oh-my-pi/pi-ai/providers/openai-shared";
5
6
  import {
6
7
  isSameModelTurn,
@@ -41,7 +42,7 @@ export function tokenizerEncodingForModel(model: Pick<Model, "tokenizer"> | null
41
42
  }
42
43
 
43
44
  type TokenizerModel = Pick<Model, "tokenizer"> &
44
- snapcompact.ShapeTarget & { compat?: Model["compat"]; thinking?: Model["thinking"] };
45
+ snapcompact.ShapeTarget & { compat?: Model["compat"]; thinking?: Model["thinking"]; reasoning?: boolean };
45
46
 
46
47
  /** The model an assistant turn's native reasoning (signed thinking, Responses history) is replayed to. */
47
48
  interface ReasoningReplayReader {
@@ -213,6 +214,7 @@ export class Tokenizer {
213
214
  readonly frameBillingKey: string;
214
215
  readonly #reasoningReader: ReasoningReplayReader | undefined;
215
216
  readonly #dropsOllamaThinking: boolean;
217
+ readonly #dropsCompletionsThinking: boolean;
216
218
  /** Claude's own API and prefix-bound hosts keep another model's signature from their deployment. */
217
219
  readonly #readsDeploymentSignatures: boolean;
218
220
  readonly reasoningReplayKey: string;
@@ -251,6 +253,7 @@ export class Tokenizer {
251
253
  this.frameBillingKey = snapcompact.frameBillingKey(this.#frameBilling);
252
254
  this.#reasoningReader = reasoningReplayReader(model);
253
255
  this.#dropsOllamaThinking = ollamaChatDropsOwnThinking(model);
256
+ this.#dropsCompletionsThinking = completionsDropsOwnThinking(model);
254
257
  const compat = model?.compat;
255
258
  this.#readsDeploymentSignatures =
256
259
  model?.api === "anthropic-messages" &&
@@ -424,6 +427,9 @@ export class Tokenizer {
424
427
  const replayedReasoning = this.#replayedReasoningTokens(message);
425
428
  const ollamaReader = this.#reasoningReader?.api === "ollama-chat" ? this.#reasoningReader : undefined;
426
429
  const ownOllamaTurn = ollamaReader !== undefined && isSameModelTurn(message, ollamaReader);
430
+ const completionsReader = this.#dropsCompletionsThinking ? this.#reasoningReader : undefined;
431
+ const ownDroppedCompletionsTurn =
432
+ completionsReader !== undefined && isSameModelTurn(message, completionsReader);
427
433
  if (typeof replayedReasoning === "number") extra += replayedReasoning;
428
434
  const signaturesPriced = this.thinkingReplayTokens === "signature";
429
435
  // The replay's signature rule (`transformMessages`): an aborted or
@@ -457,6 +463,8 @@ export class Tokenizer {
457
463
  continue;
458
464
  }
459
465
  if (this.#dropsOllamaThinking && ownOllamaTurn) continue;
466
+ // Chat-completions drops it unless LiteLLM replays it in `thinking_blocks`.
467
+ if (ownDroppedCompletionsTurn && !isLiteLLMThinkingSignature(block.thinkingSignature)) continue;
460
468
  fragments.push(block.thinking);
461
469
  // Providers charge for the opaque signature/reasoning payload that
462
470
  // rides alongside the thinking text (OpenAI Responses encrypted
@@ -578,6 +586,7 @@ export class Tokenizer {
578
586
  reasoningReplayKey(model) === this.reasoningReplayKey &&
579
587
  resolveThinkingReplayTokens(model ?? {}) === this.thinkingReplayTokens &&
580
588
  ollamaChatDropsOwnThinking(model) === this.#dropsOllamaThinking &&
589
+ completionsDropsOwnThinking(model) === this.#dropsCompletionsThinking &&
581
590
  (options?.nativeHistoryReplay ?? true) === this.nativeHistoryReplay
582
591
  );
583
592
  }