@oh-my-pi/pi-ai 16.1.15 → 16.1.16
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 +7 -0
- package/package.json +4 -4
- package/src/providers/anthropic.ts +41 -7
- package/src/utils.ts +14 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [16.1.16] - 2026-06-23
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Fixed Anthropic-compatible thinking requests sending replayed thinking blocks without `context_management.keep: "all"`, preserving multi-turn reasoning context for API-key providers. API-key requests now also advertise the required `context-management-2025-06-27` beta header so the field is honored instead of rejected. Injected SDK clients, GitHub Copilot's Anthropic proxy, and Vertex rawPredict are excluded because this code path cannot add the beta to caller-owned clients, Copilot strips Anthropic betas and demotes thinking blocks to text upstream, and Vertex expects betas in the JSON body rather than the Anthropic HTTP beta header. ([#3288](https://github.com/can1357/oh-my-pi/issues/3288))
|
|
10
|
+
- Fixed OpenRouter Responses native history replay leaking Gemini reasoning item `format` metadata back into follow-up requests, which caused HTTP 400 rejections while preserving encrypted reasoning replay.
|
|
11
|
+
|
|
5
12
|
## [16.1.15] - 2026-06-22
|
|
6
13
|
|
|
7
14
|
### Fixed
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-ai",
|
|
4
|
-
"version": "16.1.
|
|
4
|
+
"version": "16.1.16",
|
|
5
5
|
"description": "Unified LLM API with automatic model discovery and provider configuration",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -38,9 +38,9 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@bufbuild/protobuf": "^2.12.0",
|
|
41
|
-
"@oh-my-pi/pi-catalog": "16.1.
|
|
42
|
-
"@oh-my-pi/pi-utils": "16.1.
|
|
43
|
-
"@oh-my-pi/pi-wire": "16.1.
|
|
41
|
+
"@oh-my-pi/pi-catalog": "16.1.16",
|
|
42
|
+
"@oh-my-pi/pi-utils": "16.1.16",
|
|
43
|
+
"@oh-my-pi/pi-wire": "16.1.16",
|
|
44
44
|
"arktype": "^2.2.0",
|
|
45
45
|
"zod": "^4"
|
|
46
46
|
},
|
|
@@ -120,10 +120,11 @@ export function buildBetaHeader(baseBetas: readonly string[], extraBetas: readon
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
const midConversationSystemBeta = "mid-conversation-system-2026-04-07";
|
|
123
|
+
const contextManagementBeta = "context-management-2025-06-27";
|
|
123
124
|
const claudeCodeUtilityBetaDefaults = [
|
|
124
125
|
"oauth-2025-04-20",
|
|
125
126
|
"interleaved-thinking-2025-05-14",
|
|
126
|
-
|
|
127
|
+
contextManagementBeta,
|
|
127
128
|
"prompt-caching-scope-2026-01-05",
|
|
128
129
|
"structured-outputs-2025-12-15",
|
|
129
130
|
] as const;
|
|
@@ -131,7 +132,7 @@ const claudeCodeAgentBetaDefaults = [
|
|
|
131
132
|
"claude-code-20250219",
|
|
132
133
|
"oauth-2025-04-20",
|
|
133
134
|
"interleaved-thinking-2025-05-14",
|
|
134
|
-
|
|
135
|
+
contextManagementBeta,
|
|
135
136
|
"prompt-caching-scope-2026-01-05",
|
|
136
137
|
midConversationSystemBeta,
|
|
137
138
|
"advanced-tool-use-2025-11-20",
|
|
@@ -1680,6 +1681,22 @@ const streamAnthropicOnce = (
|
|
|
1680
1681
|
// carry it in the Claude Code list).
|
|
1681
1682
|
extraBetas.push(midConversationSystemBeta);
|
|
1682
1683
|
}
|
|
1684
|
+
// `context_management.clear_thinking_20251015` requires this beta. OAuth
|
|
1685
|
+
// requests carry it in `claudeCodeAgentBetaDefaults`; API-key requests
|
|
1686
|
+
// need it added explicitly so the field is honored instead of rejected
|
|
1687
|
+
// (#3288). Skip transports where this package cannot deliver the beta
|
|
1688
|
+
// in the form their adapter accepts: Copilot strips Anthropic betas,
|
|
1689
|
+
// and Vertex rawPredict needs betas in the body (`anthropic_beta`),
|
|
1690
|
+
// not as an `anthropic-beta` HTTP header.
|
|
1691
|
+
if (
|
|
1692
|
+
model.reasoning &&
|
|
1693
|
+
options?.thinkingEnabled &&
|
|
1694
|
+
model.provider !== "github-copilot" &&
|
|
1695
|
+
model.provider !== "google-vertex" &&
|
|
1696
|
+
!extraBetas.includes(contextManagementBeta)
|
|
1697
|
+
) {
|
|
1698
|
+
extraBetas.push(contextManagementBeta);
|
|
1699
|
+
}
|
|
1683
1700
|
|
|
1684
1701
|
const created = createClient(model, {
|
|
1685
1702
|
model,
|
|
@@ -2944,11 +2961,28 @@ function buildParams(
|
|
|
2944
2961
|
}
|
|
2945
2962
|
}
|
|
2946
2963
|
|
|
2947
|
-
// Pre-compute context_management
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2964
|
+
// Pre-compute context_management. Send keep: "all" for every enabled or
|
|
2965
|
+
// adaptive thinking request (OAuth + API-key) — not just OAuth. Without
|
|
2966
|
+
// this directive Anthropic-compatible backends (Z.AI, Kimi, DeepSeek, …)
|
|
2967
|
+
// strip the replayed thinking blocks `replayUnsignedThinking` puts back
|
|
2968
|
+
// on the wire, so the model loses the prior reasoning chain across turns
|
|
2969
|
+
// and the KV cache misses every turn (#3288). Narrowing this guard back
|
|
2970
|
+
// to `isOAuthToken` regresses every API-key thinking provider. Skip
|
|
2971
|
+
// injected clients because this code cannot add the required
|
|
2972
|
+
// `context-management-2025-06-27` beta to caller-owned SDK clients. Skip
|
|
2973
|
+
// Copilot because its proxy strips Anthropic betas and demotes thinking
|
|
2974
|
+
// blocks to text upstream, so `keep: "all"` is a no-op that risks proxy
|
|
2975
|
+
// rejection of an unrecognized field. Skip Vertex rawPredict because that
|
|
2976
|
+
// adapter requires betas in the JSON body (`anthropic_beta`) instead of the
|
|
2977
|
+
// Anthropic HTTP beta header this code can add.
|
|
2978
|
+
const shouldKeepThinkingContext =
|
|
2979
|
+
!options?.client &&
|
|
2980
|
+
model.provider !== "github-copilot" &&
|
|
2981
|
+
model.provider !== "google-vertex" &&
|
|
2982
|
+
(thinking?.type === "adaptive" || thinking?.type === "enabled");
|
|
2983
|
+
const contextManagement = shouldKeepThinkingContext
|
|
2984
|
+
? { edits: [{ type: "clear_thinking_20251015" as const, keep: "all" as const }] }
|
|
2985
|
+
: undefined;
|
|
2952
2986
|
|
|
2953
2987
|
// Pre-compute output_config.
|
|
2954
2988
|
const outputConfigEntries: AnthropicOutputConfig = {};
|
package/src/utils.ts
CHANGED
|
@@ -78,6 +78,7 @@ function sanitizeOpenAIResponsesHistoryItemForReplay(
|
|
|
78
78
|
): OpenAIResponsesReplayItem | undefined {
|
|
79
79
|
if (item.type === "item_reference") return undefined;
|
|
80
80
|
if (item.type === "image_generation_call") return sanitizeOpenAIResponsesImageGenerationCallForReplay(item);
|
|
81
|
+
if (item.type === "reasoning") return sanitizeOpenAIResponsesReasoningItemForReplay(item);
|
|
81
82
|
|
|
82
83
|
// providerPayload stores raw output items; replay strips item ids and keeps only normalized call_id.
|
|
83
84
|
const { id: _id, ...sanitizedItem } = item;
|
|
@@ -88,6 +89,19 @@ function sanitizeOpenAIResponsesHistoryItemForReplay(
|
|
|
88
89
|
return sanitizedItem as unknown as OpenAIResponsesReplayItem;
|
|
89
90
|
}
|
|
90
91
|
|
|
92
|
+
function sanitizeOpenAIResponsesReasoningItemForReplay(item: Record<string, unknown>): OpenAIResponsesReplayItem {
|
|
93
|
+
const sanitizedItem: Record<string, unknown> = { type: "reasoning" };
|
|
94
|
+
if (Array.isArray(item.summary)) sanitizedItem.summary = item.summary;
|
|
95
|
+
if (Array.isArray(item.content)) sanitizedItem.content = item.content;
|
|
96
|
+
if (typeof item.encrypted_content === "string" || item.encrypted_content === null) {
|
|
97
|
+
sanitizedItem.encrypted_content = item.encrypted_content;
|
|
98
|
+
}
|
|
99
|
+
if (item.status === "in_progress" || item.status === "completed" || item.status === "incomplete") {
|
|
100
|
+
sanitizedItem.status = item.status;
|
|
101
|
+
}
|
|
102
|
+
return sanitizedItem as unknown as OpenAIResponsesReplayItem;
|
|
103
|
+
}
|
|
104
|
+
|
|
91
105
|
function sanitizeOpenAIResponsesImageGenerationCallForReplay(
|
|
92
106
|
item: Record<string, unknown>,
|
|
93
107
|
): ResponseInputItem.ImageGenerationCall | undefined {
|