mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-15 07:04:45 +00:00
Fix tool call ID normalization for cross-provider switches to Anthropic/GitHub Copilot
This commit is contained in:
parent
3690137ecc
commit
3c60ffa677
6 changed files with 131 additions and 7 deletions
21
Dockerfile.gh-build
Normal file
21
Dockerfile.gh-build
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
FROM ubuntu:24.04
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y curl unzip git xz-utils ca-certificates \
|
||||
&& curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
|
||||
&& apt-get install -y nodejs \
|
||||
&& BUN_VERSION=1.2.20 \
|
||||
&& ARCH=$(dpkg --print-architecture) \
|
||||
&& if [ "$ARCH" = "amd64" ]; then BUN_ARCH="linux-x64"; else BUN_ARCH="linux-aarch64"; fi \
|
||||
&& curl -fsSL "https://github.com/oven-sh/bun/releases/download/bun-v${BUN_VERSION}/bun-${BUN_ARCH}.zip" -o /tmp/bun.zip \
|
||||
&& unzip /tmp/bun.zip -d /tmp \
|
||||
&& mv /tmp/bun-${BUN_ARCH}/bun /usr/local/bin/bun \
|
||||
&& chmod +x /usr/local/bin/bun \
|
||||
&& rm -rf /tmp/bun.zip /tmp/bun-linux-x64 \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /repo
|
||||
|
||||
ENTRYPOINT ["/bin/bash", "-lc"]
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
import type { Api, AssistantMessage, Message, Model, ToolCall, ToolResultMessage } from "../types.js";
|
||||
|
||||
/**
|
||||
* Normalize tool call ID for GitHub Copilot cross-API compatibility.
|
||||
* Normalize tool call ID for cross-provider compatibility.
|
||||
* OpenAI Responses API generates IDs that are 450+ chars with special characters like `|`.
|
||||
* Other APIs (Claude, etc.) require max 40 chars and only alphanumeric + underscore + hyphen.
|
||||
* Anthropic APIs require IDs matching ^[a-zA-Z0-9_-]+$ (max 64 chars).
|
||||
*/
|
||||
function normalizeCopilotToolCallId(id: string): string {
|
||||
function normalizeToolCallId(id: string): string {
|
||||
return id.replace(/[^a-zA-Z0-9_-]/g, "").slice(0, 40);
|
||||
}
|
||||
|
||||
|
|
@ -38,11 +38,17 @@ export function transformMessages<TApi extends Api>(messages: Message[], model:
|
|||
return msg;
|
||||
}
|
||||
|
||||
// Check if we need to normalize tool call IDs (github-copilot cross-API)
|
||||
const needsToolCallIdNormalization =
|
||||
// Check if we need to normalize tool call IDs
|
||||
// Anthropic APIs require IDs matching ^[a-zA-Z0-9_-]+$ (max 64 chars)
|
||||
// OpenAI Responses API generates IDs with `|` and 450+ chars
|
||||
// GitHub Copilot routes to Anthropic for Claude models
|
||||
const targetRequiresStrictIds = model.api === "anthropic-messages" || model.provider === "github-copilot";
|
||||
const crossProviderSwitch = assistantMsg.provider !== model.provider;
|
||||
const copilotCrossApiSwitch =
|
||||
assistantMsg.provider === "github-copilot" &&
|
||||
model.provider === "github-copilot" &&
|
||||
assistantMsg.api !== model.api;
|
||||
const needsToolCallIdNormalization = targetRequiresStrictIds && (crossProviderSwitch || copilotCrossApiSwitch);
|
||||
|
||||
// Transform message from different provider/model
|
||||
const transformedContent = assistantMsg.content.flatMap((block) => {
|
||||
|
|
@ -54,10 +60,10 @@ export function transformMessages<TApi extends Api>(messages: Message[], model:
|
|||
text: block.thinking,
|
||||
};
|
||||
}
|
||||
// Normalize tool call IDs for github-copilot cross-API switches
|
||||
// Normalize tool call IDs when target API requires strict format
|
||||
if (block.type === "toolCall" && needsToolCallIdNormalization) {
|
||||
const toolCall = block as ToolCall;
|
||||
const normalizedId = normalizeCopilotToolCallId(toolCall.id);
|
||||
const normalizedId = normalizeToolCallId(toolCall.id);
|
||||
if (normalizedId !== toolCall.id) {
|
||||
toolCallIdMap.set(toolCall.id, normalizedId);
|
||||
return { ...toolCall, id: normalizedId };
|
||||
|
|
|
|||
1
packages/coding-agent/.gitignore
vendored
Normal file
1
packages/coding-agent/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
*.bun-build
|
||||
|
|
@ -33,6 +33,12 @@ function getAliases(): Record<string, string> {
|
|||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const packageIndex = path.resolve(__dirname, "../..", "index.js");
|
||||
|
||||
// Debug: log what we're resolving
|
||||
if (process.env.DEBUG_EXTENSIONS) {
|
||||
console.error("[DEBUG] import.meta.url:", import.meta.url);
|
||||
console.error("[DEBUG] __dirname:", __dirname);
|
||||
}
|
||||
|
||||
const typeboxEntry = require.resolve("@sinclair/typebox");
|
||||
const typeboxRoot = typeboxEntry.replace(/\/build\/cjs\/index\.js$/, "");
|
||||
|
||||
|
|
@ -43,6 +49,11 @@ function getAliases(): Record<string, string> {
|
|||
"@mariozechner/pi-ai": require.resolve("@mariozechner/pi-ai"),
|
||||
"@sinclair/typebox": typeboxRoot,
|
||||
};
|
||||
|
||||
if (process.env.DEBUG_EXTENSIONS) {
|
||||
console.error("[DEBUG] aliases:", JSON.stringify(_aliases, null, 2));
|
||||
}
|
||||
|
||||
return _aliases;
|
||||
}
|
||||
|
||||
|
|
|
|||
40
scripts/gh-build-docker.sh
Executable file
40
scripts/gh-build-docker.sh
Executable file
|
|
@ -0,0 +1,40 @@
|
|||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
echo "=== Versions ==="
|
||||
node --version
|
||||
bun --version
|
||||
npm --version
|
||||
|
||||
echo "=== Install dependencies ==="
|
||||
npm ci
|
||||
|
||||
echo "=== Install cross-platform bindings ==="
|
||||
npm install --no-save --force \
|
||||
@mariozechner/clipboard-darwin-arm64@0.3.0 \
|
||||
@mariozechner/clipboard-darwin-x64@0.3.0 \
|
||||
@mariozechner/clipboard-linux-x64-gnu@0.3.0 \
|
||||
@mariozechner/clipboard-linux-arm64-gnu@0.3.0 \
|
||||
@mariozechner/clipboard-win32-x64-msvc@0.3.0
|
||||
|
||||
npm install --no-save --force \
|
||||
@img/sharp-darwin-arm64@0.34.5 \
|
||||
@img/sharp-darwin-x64@0.34.5 \
|
||||
@img/sharp-linux-x64@0.34.5 \
|
||||
@img/sharp-linux-arm64@0.34.5 \
|
||||
@img/sharp-win32-x64@0.34.5 \
|
||||
@img/sharp-libvips-darwin-arm64@1.2.4 \
|
||||
@img/sharp-libvips-darwin-x64@1.2.4 \
|
||||
@img/sharp-libvips-linux-x64@1.2.4 \
|
||||
@img/sharp-libvips-linux-arm64@1.2.4
|
||||
|
||||
echo "=== Build all packages ==="
|
||||
npm run build
|
||||
|
||||
echo "=== Build darwin-arm64 binary ==="
|
||||
mkdir -p /repo/.tmp
|
||||
cd packages/coding-agent
|
||||
bun build --compile --target=bun-darwin-arm64 ./dist/cli.js --outfile /repo/.tmp/pi-darwin-arm64
|
||||
|
||||
echo "=== Done ==="
|
||||
ls -la /repo/.tmp/pi-darwin-arm64
|
||||
45
scripts/test-gh-build.sh
Normal file
45
scripts/test-gh-build.sh
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Simulate GH Actions build locally
|
||||
|
||||
cd /Users/badlogic/workspaces/pi-mono
|
||||
|
||||
echo "=== Cleaning node_modules ==="
|
||||
rm -rf node_modules packages/*/node_modules
|
||||
|
||||
echo "=== npm ci ==="
|
||||
npm ci
|
||||
|
||||
echo "=== Install cross-platform bindings (like GH Actions) ==="
|
||||
npm install --no-save --force \
|
||||
@mariozechner/clipboard-darwin-arm64@0.3.0 \
|
||||
@mariozechner/clipboard-darwin-x64@0.3.0 \
|
||||
@mariozechner/clipboard-linux-x64-gnu@0.3.0 \
|
||||
@mariozechner/clipboard-linux-arm64-gnu@0.3.0 \
|
||||
@mariozechner/clipboard-win32-x64-msvc@0.3.0
|
||||
|
||||
npm install --no-save --force \
|
||||
@img/sharp-darwin-arm64@0.34.5 \
|
||||
@img/sharp-darwin-x64@0.34.5 \
|
||||
@img/sharp-linux-x64@0.34.5 \
|
||||
@img/sharp-linux-arm64@0.34.5 \
|
||||
@img/sharp-win32-x64@0.34.5 \
|
||||
@img/sharp-libvips-darwin-arm64@1.2.4 \
|
||||
@img/sharp-libvips-darwin-x64@1.2.4 \
|
||||
@img/sharp-libvips-linux-x64@1.2.4 \
|
||||
@img/sharp-libvips-linux-arm64@1.2.4
|
||||
|
||||
echo "=== Build all packages ==="
|
||||
npm run build
|
||||
|
||||
echo "=== Build binary with cross-compile flag ==="
|
||||
cd packages/coding-agent
|
||||
bun build --compile --target=bun-darwin-arm64 ./dist/cli.js --outfile /tmp/pi-gh-sim/pi
|
||||
cp package.json /tmp/pi-gh-sim/
|
||||
|
||||
echo "=== Test the binary ==="
|
||||
/tmp/pi-gh-sim/pi -e /Users/badlogic/workspaces/pi-doom --help 2>&1 | head -5
|
||||
|
||||
echo "=== Binary size ==="
|
||||
ls -la /tmp/pi-gh-sim/pi
|
||||
Loading…
Add table
Add a link
Reference in a new issue