@oh-my-pi/pi-ai 15.10.2 → 15.10.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,14 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [15.10.3] - 2026-06-08
6
+
7
+ ### Removed
8
+
9
+ - Removed the synthetic `<turn-aborted>` developer guidance note that `transformMessages` injected after an aborted/errored assistant turn (and its `turn-aborted-guidance.md` prompt). The per-call synthetic `"aborted"` tool results already tell the model the turn's tools were terminated, so the extra "verify current state before retrying" note was redundant — and it biased the model toward second-guessing a deliberate user interrupt when the turn was resumed.
10
+ - Removed the legacy Anthropic first-user-message skip for `<system-reminder>` blocks now that synthetic reminders no longer travel as user messages.
11
+
12
+
5
13
  ## [15.10.2] - 2026-06-08
6
14
  ### Added
7
15
 
@@ -7,6 +7,5 @@ import type { Api, AssistantMessage, Message, Model } from "../types";
7
7
  * For aborted/errored turns, this function:
8
8
  * - Preserves tool call structure (unlike converting to text summaries)
9
9
  * - Injects synthetic "aborted" tool results
10
- * - Adds a <turn-aborted> guidance marker for the model
11
10
  */
12
11
  export declare function transformMessages<TApi extends Api>(messages: Message[], model: Model<TApi>, normalizeToolCallId?: (id: string, model: Model<TApi>, source: AssistantMessage) => string, maxNormalizedToolCallIdLength?: number, duplicateToolCallIdSuffixPrefix?: string): Message[];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-ai",
4
- "version": "15.10.2",
4
+ "version": "15.10.3",
5
5
  "description": "Unified LLM API with automatic model discovery and provider configuration",
6
6
  "homepage": "https://omp.sh",
7
7
  "author": "Can Boluk",
@@ -39,7 +39,7 @@
39
39
  },
40
40
  "dependencies": {
41
41
  "@bufbuild/protobuf": "^2.12.0",
42
- "@oh-my-pi/pi-utils": "15.10.2",
42
+ "@oh-my-pi/pi-utils": "15.10.3",
43
43
  "openai": "^6.39.0",
44
44
  "partial-json": "^0.1.7",
45
45
  "zod": "4.4.3"
@@ -2271,33 +2271,16 @@ function resolveAnthropicAdaptiveEffort(
2271
2271
  return mapEffortToAnthropicAdaptiveEffort(model, requestedEffort);
2272
2272
  }
2273
2273
 
2274
- function startsWithAfterAsciiWhitespace(value: string, prefix: string): boolean {
2275
- let index = 0;
2276
- while (index < value.length) {
2277
- const code = value.charCodeAt(index);
2278
- if (code !== 9 && code !== 10 && code !== 13 && code !== 32) break;
2279
- index++;
2280
- }
2281
- return value.startsWith(prefix, index);
2282
- }
2283
-
2284
- function isClaudeSyntheticUserText(value: string): boolean {
2285
- return startsWithAfterAsciiWhitespace(value, "<system-reminder>");
2286
- }
2287
-
2288
2274
  function extractClaudeCodeFirstUserMessageText(messages: readonly Message[]): string {
2289
2275
  for (const message of messages) {
2290
2276
  if (message.role !== "user") continue;
2291
2277
  const { content } = message;
2292
2278
  if (typeof content === "string") return content;
2293
2279
  if (!Array.isArray(content)) return "";
2294
- let fallback: string | undefined;
2295
2280
  for (const block of content) {
2296
- if (block.type !== "text") continue;
2297
- fallback ??= block.text;
2298
- if (!isClaudeSyntheticUserText(block.text)) return block.text;
2281
+ if (block.type === "text") return block.text;
2299
2282
  }
2300
- return fallback ?? "";
2283
+ return "";
2301
2284
  }
2302
2285
  return "";
2303
2286
  }
@@ -1,14 +1,4 @@
1
- import turnAbortedGuidance from "../prompts/turn-aborted-guidance.md" with { type: "text" };
2
- import type {
3
- Api,
4
- AssistantMessage,
5
- DeveloperMessage,
6
- Message,
7
- Model,
8
- ToolCall,
9
- ToolResultMessage,
10
- UserMessage,
11
- } from "../types";
1
+ import type { Api, AssistantMessage, Message, Model, ToolCall, ToolResultMessage, UserMessage } from "../types";
12
2
 
13
3
  const enum ToolCallStatus {
14
4
  /** A tool result has already been emitted for this tool call; later duplicates must be skipped. */
@@ -142,7 +132,6 @@ function getLatestSurvivingAssistantIndex(messages: readonly Message[]): number
142
132
  * For aborted/errored turns, this function:
143
133
  * - Preserves tool call structure (unlike converting to text summaries)
144
134
  * - Injects synthetic "aborted" tool results
145
- * - Adds a <turn-aborted> guidance marker for the model
146
135
  */
147
136
  export function transformMessages<TApi extends Api>(
148
137
  messages: Message[],
@@ -345,11 +334,6 @@ export function transformMessages<TApi extends Api>(
345
334
  } as ToolResultMessage);
346
335
  toolCallStatus.set(tc.id, ToolCallStatus.Aborted);
347
336
  }
348
- result.push({
349
- role: "developer",
350
- content: turnAbortedGuidance,
351
- timestamp: pendingAbortedTimestamp + 1,
352
- } as DeveloperMessage);
353
337
  pendingAbortedToolCalls = new Map();
354
338
  pendingAbortedTimestamp = undefined;
355
339
  };
@@ -378,11 +362,6 @@ export function transformMessages<TApi extends Api>(
378
362
  // (OpenAI completions `reasoning_text`, Google signed thought parts).
379
363
  const originalMsg = messages[i]!;
380
364
  if (originalMsg.role === "assistant" && shouldDropTruncatedThinkingOnlyAssistant(originalMsg)) {
381
- if (assistantMsg.stopReason === "error" || assistantMsg.stopReason === "aborted") {
382
- // Still arm the aborted-turn note so downstream guidance fires.
383
- pendingAbortedToolCalls = new Map();
384
- pendingAbortedTimestamp = assistantMsg.timestamp;
385
- }
386
365
  continue;
387
366
  }
388
367
 
@@ -1,4 +0,0 @@
1
- <turn-aborted>
2
- The previous turn was aborted. Any running tools/commands were terminated.
3
- If tools were aborted, they may have partially executed; verify current state before retrying.
4
- </turn-aborted>