@oh-my-pi/pi-ai 15.11.1 → 15.11.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,18 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [15.11.3] - 2026-06-11
|
|
6
|
+
### Fixed
|
|
7
|
+
|
|
8
|
+
- Fixed GitHub Copilot long-context model requests to use the upstream `requestModelId` when calling Anthropic, OpenAI Responses, and OpenAI Completions APIs
|
|
9
|
+
- Fixed GitHub Copilot model enablement to deduplicate catalog variants by upstream model ID when enabling all models
|
|
10
|
+
|
|
11
|
+
## [15.11.2] - 2026-06-11
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- Fixed Anthropic encoding of error tool results with whitespace-only content so requests no longer 400 with `tool_result: content cannot be empty if is_error is true`
|
|
16
|
+
|
|
5
17
|
## [15.11.1] - 2026-06-11
|
|
6
18
|
|
|
7
19
|
### Changed
|
|
@@ -3262,4 +3274,4 @@ _Dedicated to Peter's shoulder ([@steipete](https://twitter.com/steipete))_
|
|
|
3262
3274
|
|
|
3263
3275
|
## [0.9.4] - 2025-11-26
|
|
3264
3276
|
|
|
3265
|
-
Initial release with multi-provider LLM support.
|
|
3277
|
+
Initial release with multi-provider LLM support.
|
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.11.
|
|
4
|
+
"version": "15.11.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",
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@bufbuild/protobuf": "^2.12.0",
|
|
41
|
-
"@oh-my-pi/pi-catalog": "15.11.
|
|
42
|
-
"@oh-my-pi/pi-utils": "15.11.
|
|
41
|
+
"@oh-my-pi/pi-catalog": "15.11.3",
|
|
42
|
+
"@oh-my-pi/pi-utils": "15.11.3",
|
|
43
43
|
"openai": "^6.39.0",
|
|
44
44
|
"partial-json": "^0.1.7",
|
|
45
45
|
"zod": "4.4.3"
|
|
@@ -873,13 +873,7 @@ async function prepareAnthropicManyImageContext(context: Context, supportsImages
|
|
|
873
873
|
return { ...context, messages };
|
|
874
874
|
}
|
|
875
875
|
|
|
876
|
-
|
|
877
|
-
* Convert content blocks to Anthropic API format
|
|
878
|
-
*/
|
|
879
|
-
function convertContentBlocks(
|
|
880
|
-
content: (TextContent | ImageContent)[],
|
|
881
|
-
supportsImages = true,
|
|
882
|
-
):
|
|
876
|
+
type AnthropicToolResultContent =
|
|
883
877
|
| string
|
|
884
878
|
| Array<
|
|
885
879
|
| { type: "text"; text: string }
|
|
@@ -891,7 +885,15 @@ function convertContentBlocks(
|
|
|
891
885
|
data: string;
|
|
892
886
|
};
|
|
893
887
|
}
|
|
894
|
-
|
|
888
|
+
>;
|
|
889
|
+
|
|
890
|
+
/**
|
|
891
|
+
* Convert content blocks to Anthropic API format
|
|
892
|
+
*/
|
|
893
|
+
function convertContentBlocks(
|
|
894
|
+
content: (TextContent | ImageContent)[],
|
|
895
|
+
supportsImages = true,
|
|
896
|
+
): AnthropicToolResultContent {
|
|
895
897
|
const blocks: Array<
|
|
896
898
|
| { type: "text"; text: string }
|
|
897
899
|
| {
|
|
@@ -2814,7 +2816,7 @@ function buildParams(
|
|
|
2814
2816
|
// Build params in the canonical field order: model → messages → system → tools →
|
|
2815
2817
|
// metadata → max_tokens → thinking → context_management → output_config → stream.
|
|
2816
2818
|
const params: MessageCreateParamsStreaming = {
|
|
2817
|
-
model: model.id,
|
|
2819
|
+
model: model.requestModelId ?? model.id,
|
|
2818
2820
|
messages: convertAnthropicMessages(context.messages, model, isOAuthToken),
|
|
2819
2821
|
...(systemBlocks && { system: systemBlocks }),
|
|
2820
2822
|
...(tools !== undefined && { tools }),
|
|
@@ -2883,11 +2885,36 @@ function buildParams(
|
|
|
2883
2885
|
return params;
|
|
2884
2886
|
}
|
|
2885
2887
|
|
|
2888
|
+
const EMPTY_ERROR_TOOL_RESULT_TEXT = "Tool failed with no output.";
|
|
2889
|
+
|
|
2890
|
+
function isEmptyToolResultWireContent(content: AnthropicToolResultContent): boolean {
|
|
2891
|
+
if (typeof content === "string") {
|
|
2892
|
+
return content.trim().length === 0;
|
|
2893
|
+
}
|
|
2894
|
+
return content.length === 0;
|
|
2895
|
+
}
|
|
2896
|
+
|
|
2897
|
+
function ensureErrorToolResultWireContent(
|
|
2898
|
+
content: AnthropicToolResultContent,
|
|
2899
|
+
isError: boolean | undefined,
|
|
2900
|
+
): AnthropicToolResultContent {
|
|
2901
|
+
if (!isError || !isEmptyToolResultWireContent(content)) {
|
|
2902
|
+
return content;
|
|
2903
|
+
}
|
|
2904
|
+
return typeof content === "string"
|
|
2905
|
+
? EMPTY_ERROR_TOOL_RESULT_TEXT
|
|
2906
|
+
: [{ type: "text", text: EMPTY_ERROR_TOOL_RESULT_TEXT }];
|
|
2907
|
+
}
|
|
2908
|
+
|
|
2886
2909
|
function buildToolResultBlock(model: Model<"anthropic-messages">, msg: ToolResultMessage): ContentBlockParam {
|
|
2910
|
+
const content = ensureErrorToolResultWireContent(
|
|
2911
|
+
convertContentBlocks(msg.content, model.input.includes("image")),
|
|
2912
|
+
msg.isError,
|
|
2913
|
+
);
|
|
2887
2914
|
const block: ContentBlockParam = {
|
|
2888
2915
|
type: "tool_result",
|
|
2889
2916
|
tool_use_id: msg.toolCallId,
|
|
2890
|
-
content
|
|
2917
|
+
content,
|
|
2891
2918
|
is_error: msg.isError,
|
|
2892
2919
|
};
|
|
2893
2920
|
if (model.compat.requiresToolResultId) {
|
|
@@ -113,6 +113,8 @@ function resolveOpenAICompletionsModelId(
|
|
|
113
113
|
model: Model<"openai-completions">,
|
|
114
114
|
options: OpenAICompletionsOptions | undefined,
|
|
115
115
|
): string {
|
|
116
|
+
// Catalog variants (e.g. Copilot long-context `-1m` entries) pin the wire id.
|
|
117
|
+
if (model.requestModelId) return model.requestModelId;
|
|
116
118
|
if (model.provider === "firepass") return toFirepassWireModelId(model.id);
|
|
117
119
|
if (model.provider === "fireworks") return toFireworksWireModelId(model.id);
|
|
118
120
|
if (model.provider === "openrouter") return applyOpenRouterRoutingVariant(model.id, options?.openrouterVariant);
|
|
@@ -460,7 +460,7 @@ function buildParams(
|
|
|
460
460
|
const cacheRetention = resolveCacheRetention(options?.cacheRetention);
|
|
461
461
|
const promptCacheKey = getOpenAIResponsesPromptCacheKey(options);
|
|
462
462
|
const params: OpenAIResponsesSamplingParams = {
|
|
463
|
-
model: model.id,
|
|
463
|
+
model: model.requestModelId ?? model.id,
|
|
464
464
|
input: messages,
|
|
465
465
|
instructions: systemInstructions,
|
|
466
466
|
stream: true,
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { scheduler } from "node:timers/promises";
|
|
5
5
|
import { getBundledModels } from "@oh-my-pi/pi-catalog/models";
|
|
6
6
|
import {
|
|
7
|
+
COPILOT_API_HEADERS,
|
|
7
8
|
getGitHubCopilotBaseUrl,
|
|
8
9
|
isPublicGitHubHost,
|
|
9
10
|
normalizeDomain,
|
|
@@ -230,7 +231,7 @@ async function enableGitHubCopilotModel(
|
|
|
230
231
|
headers: {
|
|
231
232
|
"Content-Type": "application/json",
|
|
232
233
|
Authorization: `Bearer ${token}`,
|
|
233
|
-
...
|
|
234
|
+
...COPILOT_API_HEADERS,
|
|
234
235
|
"openai-intent": "chat-policy",
|
|
235
236
|
"x-interaction-type": "chat-policy",
|
|
236
237
|
},
|
|
@@ -252,14 +253,16 @@ async function enableAllGitHubCopilotModels(
|
|
|
252
253
|
fetchImpl: FetchImpl,
|
|
253
254
|
onProgress?: (model: string, success: boolean) => void,
|
|
254
255
|
): Promise<void> {
|
|
255
|
-
|
|
256
|
+
// Synthesized catalog variants (Copilot long-context `-1m` entries) share
|
|
257
|
+
// the upstream model id; enable each wire id exactly once.
|
|
258
|
+
const wireModelIds = [...new Set(getBundledModels("github-copilot").map(model => model.requestModelId ?? model.id))];
|
|
256
259
|
const BATCH_SIZE = 5;
|
|
257
|
-
for (let i = 0; i <
|
|
258
|
-
const batch =
|
|
260
|
+
for (let i = 0; i < wireModelIds.length; i += BATCH_SIZE) {
|
|
261
|
+
const batch = wireModelIds.slice(i, i + BATCH_SIZE);
|
|
259
262
|
await Promise.all(
|
|
260
|
-
batch.map(async
|
|
261
|
-
const success = await enableGitHubCopilotModel(token,
|
|
262
|
-
onProgress?.(
|
|
263
|
+
batch.map(async modelId => {
|
|
264
|
+
const success = await enableGitHubCopilotModel(token, modelId, fetchImpl, enterpriseDomain);
|
|
265
|
+
onProgress?.(modelId, success);
|
|
263
266
|
}),
|
|
264
267
|
);
|
|
265
268
|
}
|