@nick3/copilot-api 1.2.7 → 1.3.1
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/README.md +183 -34
- package/dist/{accounts-manager-iJwqQUkM.js → accounts-manager-BeKvbv0T.js} +2 -4
- package/dist/accounts-manager-BeKvbv0T.js.map +1 -0
- package/dist/main.js +2 -2
- package/dist/{server-BgJ8vqcw.js → server-D3A61KAx.js} +95 -48
- package/dist/server-D3A61KAx.js.map +1 -0
- package/package.json +1 -1
- package/dist/accounts-manager-iJwqQUkM.js.map +0 -1
- package/dist/server-BgJ8vqcw.js.map +0 -1
package/dist/main.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { HTTPError, PATHS, accountsManager, addAccountToRegistry, cacheMacMachineId, cacheVSCodeVersion, cacheVsCodeSessionId, ensurePaths, getCopilotUsage, getGitHubUser, getModelRefreshIntervalMs, getOauthAppConfig, getOauthUrls, isFreeModelLoadBalancingEnabled, listAccountsFromRegistry, loadAccountToken, mergeConfigWithDefaults, removeAccountFromRegistry, removeAccountToken, saveAccountToken, saveRegistry, sleep, state } from "./accounts-manager-
|
|
2
|
+
import { HTTPError, PATHS, accountsManager, addAccountToRegistry, cacheMacMachineId, cacheVSCodeVersion, cacheVsCodeSessionId, ensurePaths, getCopilotUsage, getGitHubUser, getModelRefreshIntervalMs, getOauthAppConfig, getOauthUrls, isFreeModelLoadBalancingEnabled, listAccountsFromRegistry, loadAccountToken, mergeConfigWithDefaults, removeAccountFromRegistry, removeAccountToken, saveAccountToken, saveRegistry, sleep, state } from "./accounts-manager-BeKvbv0T.js";
|
|
3
3
|
import { defineCommand, runMain } from "citty";
|
|
4
4
|
import consola from "consola";
|
|
5
5
|
import fs from "node:fs/promises";
|
|
@@ -639,7 +639,7 @@ async function runServer(options) {
|
|
|
639
639
|
}
|
|
640
640
|
}
|
|
641
641
|
consola.box(`🌐 Admin UI: ${serverUrl}/admin`);
|
|
642
|
-
const { server } = await import("./server-
|
|
642
|
+
const { server } = await import("./server-D3A61KAx.js");
|
|
643
643
|
serve({
|
|
644
644
|
fetch: server.fetch,
|
|
645
645
|
port: options.port,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HTTPError, PATHS, accountFromState, accountsManager, copilotBaseUrl, copilotHeaders, forwardError, generateRequestIdFromPayload, getAliasTargetSet, getConfig, getCopilotUsage, getExtraPromptForModel, getModelAliases, getModelAliasesInfo, getModelRefreshIntervalMs, getProviderConfig, getReasoningEffortForModel, getRootSessionId, getSmallModel, getUUID, isForceAgentEnabled, isFreeModelLoadBalancingEnabled, isMessageStartInputTokensFallbackEnabled, isNullish, isResponsesApiContextManagementModel, listAccountsFromRegistry, mergeConfigWithDefaults, prepareInteractionHeaders, shouldCompactUseSmallModel, sleep, state } from "./accounts-manager-
|
|
1
|
+
import { HTTPError, PATHS, accountFromState, accountsManager, copilotBaseUrl, copilotHeaders, forwardError, generateRequestIdFromPayload, getAliasTargetSet, getConfig, getCopilotUsage, getExtraPromptForModel, getModelAliases, getModelAliasesInfo, getModelRefreshIntervalMs, getProviderConfig, getReasoningEffortForModel, getRootSessionId, getSmallModel, getUUID, isForceAgentEnabled, isFreeModelLoadBalancingEnabled, isMessageStartInputTokensFallbackEnabled, isNullish, isResponsesApiContextManagementModel, listAccountsFromRegistry, mergeConfigWithDefaults, prepareInteractionHeaders, shouldCompactUseSmallModel, sleep, state } from "./accounts-manager-BeKvbv0T.js";
|
|
2
2
|
import consola from "consola";
|
|
3
3
|
import fs, { readFile } from "node:fs/promises";
|
|
4
4
|
import * as path$1 from "node:path";
|
|
@@ -3314,6 +3314,57 @@ async function runEmbeddingsWithAccount({ c, store, ctx, payload, clientModel, s
|
|
|
3314
3314
|
}
|
|
3315
3315
|
}
|
|
3316
3316
|
|
|
3317
|
+
//#endregion
|
|
3318
|
+
//#region src/lib/models.ts
|
|
3319
|
+
const findEndpointModel = (sdkModelId) => {
|
|
3320
|
+
const models = state.models?.data ?? [];
|
|
3321
|
+
const exactMatch = models.find((m) => m.id === sdkModelId);
|
|
3322
|
+
if (exactMatch) return exactMatch;
|
|
3323
|
+
const normalized = _normalizeSdkModelId(sdkModelId);
|
|
3324
|
+
if (!normalized) return;
|
|
3325
|
+
const modelName = `claude-${normalized.family}-${normalized.version}`;
|
|
3326
|
+
const model = models.find((m) => m.id === modelName);
|
|
3327
|
+
if (model) return model;
|
|
3328
|
+
};
|
|
3329
|
+
/**
|
|
3330
|
+
* Normalizes an SDK model ID to extract the model family and version.
|
|
3331
|
+
* this method from github copilot extension
|
|
3332
|
+
* Examples:
|
|
3333
|
+
* - "claude-opus-4-5-20251101" -> { family: "opus", version: "4.5" }
|
|
3334
|
+
* - "claude-3-5-sonnet-20241022" -> { family: "sonnet", version: "3.5" }
|
|
3335
|
+
* - "claude-sonnet-4-20250514" -> { family: "sonnet", version: "4" }
|
|
3336
|
+
* - "claude-haiku-3-5-20250514" -> { family: "haiku", version: "3.5" }
|
|
3337
|
+
* - "claude-haiku-4.5" -> { family: "haiku", version: "4.5" }
|
|
3338
|
+
*/
|
|
3339
|
+
const _normalizeSdkModelId = (sdkModelId) => {
|
|
3340
|
+
const withoutDate = sdkModelId.toLowerCase().replace(/-\d{8}$/, "");
|
|
3341
|
+
const pattern1 = withoutDate.match(/^claude-(\w+)-(\d+)-(\d+)$/);
|
|
3342
|
+
if (pattern1) return {
|
|
3343
|
+
family: pattern1[1],
|
|
3344
|
+
version: `${pattern1[2]}.${pattern1[3]}`
|
|
3345
|
+
};
|
|
3346
|
+
const pattern2 = withoutDate.match(/^claude-(\d+)-(\d+)-(\w+)$/);
|
|
3347
|
+
if (pattern2) return {
|
|
3348
|
+
family: pattern2[3],
|
|
3349
|
+
version: `${pattern2[1]}.${pattern2[2]}`
|
|
3350
|
+
};
|
|
3351
|
+
const pattern3 = withoutDate.match(/^claude-(\w+)-(\d+)\.(\d+)$/);
|
|
3352
|
+
if (pattern3) return {
|
|
3353
|
+
family: pattern3[1],
|
|
3354
|
+
version: `${pattern3[2]}.${pattern3[3]}`
|
|
3355
|
+
};
|
|
3356
|
+
const pattern4 = withoutDate.match(/^claude-(\w+)-(\d+)$/);
|
|
3357
|
+
if (pattern4) return {
|
|
3358
|
+
family: pattern4[1],
|
|
3359
|
+
version: pattern4[2]
|
|
3360
|
+
};
|
|
3361
|
+
const pattern5 = withoutDate.match(/^claude-(\d+)-(\w+)$/);
|
|
3362
|
+
if (pattern5) return {
|
|
3363
|
+
family: pattern5[2],
|
|
3364
|
+
version: pattern5[1]
|
|
3365
|
+
};
|
|
3366
|
+
};
|
|
3367
|
+
|
|
3317
3368
|
//#endregion
|
|
3318
3369
|
//#region src/routes/messages/utils.ts
|
|
3319
3370
|
function mapOpenAIStopReasonToAnthropic(finishReason) {
|
|
@@ -3438,7 +3489,7 @@ const maybeBlockOriginalModelName = (context) => {
|
|
|
3438
3489
|
//#region src/routes/messages/non-stream-translation.ts
|
|
3439
3490
|
const THINKING_TEXT = "Thinking...";
|
|
3440
3491
|
function translateToOpenAI(payload) {
|
|
3441
|
-
const modelId =
|
|
3492
|
+
const modelId = payload.model;
|
|
3442
3493
|
const model = state.models?.data.find((m) => m.id === modelId);
|
|
3443
3494
|
const thinkingBudget = getThinkingBudget(payload, model);
|
|
3444
3495
|
return {
|
|
@@ -3459,56 +3510,27 @@ function getThinkingBudget(payload, model) {
|
|
|
3459
3510
|
const thinking = payload.thinking;
|
|
3460
3511
|
if (model && thinking) {
|
|
3461
3512
|
const maxThinkingBudget = Math.min(model.capabilities.supports.max_thinking_budget ?? 0, (model.capabilities.limits.max_output_tokens ?? 0) - 1);
|
|
3462
|
-
|
|
3513
|
+
thinking.budget_tokens ??= maxThinkingBudget;
|
|
3514
|
+
if (maxThinkingBudget > 0) {
|
|
3463
3515
|
const budgetTokens = Math.min(thinking.budget_tokens, maxThinkingBudget);
|
|
3464
3516
|
return Math.max(budgetTokens, model.capabilities.supports.min_thinking_budget ?? 1024);
|
|
3465
3517
|
}
|
|
3466
3518
|
}
|
|
3467
3519
|
}
|
|
3468
|
-
function
|
|
3469
|
-
|
|
3470
|
-
else if (model.startsWith("claude-opus-4-")) return model.replace(/^claude-opus-4-.*/, "claude-opus-4");
|
|
3471
|
-
return model;
|
|
3472
|
-
}
|
|
3473
|
-
function translateAnthropicMessagesToOpenAI(payload, modelId, thinkingBudget) {
|
|
3474
|
-
const systemMessages = handleSystemPrompt(payload.system, modelId, thinkingBudget);
|
|
3520
|
+
function translateAnthropicMessagesToOpenAI(payload, modelId, _thinkingBudget) {
|
|
3521
|
+
const systemMessages = handleSystemPrompt(payload.system);
|
|
3475
3522
|
const otherMessages = payload.messages.flatMap((message) => message.role === "user" ? handleUserMessage(message) : handleAssistantMessage(message, modelId));
|
|
3476
|
-
if (modelId.startsWith("claude") && thinkingBudget) {
|
|
3477
|
-
const reminder = "<system-reminder>you MUST follow interleaved_thinking_protocol</system-reminder>";
|
|
3478
|
-
const firstUserIndex = otherMessages.findIndex((m) => m.role === "user");
|
|
3479
|
-
if (firstUserIndex !== -1) {
|
|
3480
|
-
const userMessage = otherMessages[firstUserIndex];
|
|
3481
|
-
if (typeof userMessage.content === "string") userMessage.content = reminder + "\n\n" + userMessage.content;
|
|
3482
|
-
else if (Array.isArray(userMessage.content)) userMessage.content = [{
|
|
3483
|
-
type: "text",
|
|
3484
|
-
text: reminder
|
|
3485
|
-
}, ...userMessage.content];
|
|
3486
|
-
}
|
|
3487
|
-
}
|
|
3488
3523
|
return [...systemMessages, ...otherMessages];
|
|
3489
3524
|
}
|
|
3490
|
-
function handleSystemPrompt(system
|
|
3525
|
+
function handleSystemPrompt(system) {
|
|
3491
3526
|
if (!system) return [];
|
|
3492
|
-
let extraPrompt = "";
|
|
3493
|
-
if (modelId.startsWith("claude") && thinkingBudget) extraPrompt = `
|
|
3494
|
-
<interleaved_thinking_protocol>
|
|
3495
|
-
ABSOLUTE REQUIREMENT - NON-NEGOTIABLE:
|
|
3496
|
-
The current thinking_mode is interleaved, Whenever you have the result of a function call, think carefully , MUST output a thinking block
|
|
3497
|
-
RULES:
|
|
3498
|
-
Tool result → thinking block (ALWAYS, no exceptions)
|
|
3499
|
-
This is NOT optional - it is a hard requirement
|
|
3500
|
-
The thinking block must contain substantive reasoning (minimum 3-5 sentences)
|
|
3501
|
-
Think about: what the results mean, what to do next, how to answer the user
|
|
3502
|
-
NEVER skip this step, even if the result seems simple or obvious
|
|
3503
|
-
</interleaved_thinking_protocol>`;
|
|
3504
3527
|
if (typeof system === "string") return [{
|
|
3505
3528
|
role: "system",
|
|
3506
|
-
content: system
|
|
3529
|
+
content: system
|
|
3507
3530
|
}];
|
|
3508
3531
|
else return [{
|
|
3509
3532
|
role: "system",
|
|
3510
|
-
content: system.map((block
|
|
3511
|
-
if (index === 0) return block.text + extraPrompt;
|
|
3533
|
+
content: system.map((block) => {
|
|
3512
3534
|
return block.text;
|
|
3513
3535
|
}).join("\n\n")
|
|
3514
3536
|
}];
|
|
@@ -3680,7 +3702,8 @@ async function handleCountTokens(c) {
|
|
|
3680
3702
|
const anthropicBeta = c.req.header("anthropic-beta");
|
|
3681
3703
|
const anthropicPayload = await c.req.json();
|
|
3682
3704
|
const openAIPayload = translateToOpenAI(anthropicPayload);
|
|
3683
|
-
const selectedModel =
|
|
3705
|
+
const selectedModel = findEndpointModel(anthropicPayload.model);
|
|
3706
|
+
anthropicPayload.model = selectedModel?.id ?? anthropicPayload.model;
|
|
3684
3707
|
if (!selectedModel) {
|
|
3685
3708
|
consola.warn("Model not found, returning default token count");
|
|
3686
3709
|
return c.json({ input_tokens: 1 });
|
|
@@ -4618,17 +4641,19 @@ async function handleCompletion(c) {
|
|
|
4618
4641
|
if (blockedResponse) return blockedResponse;
|
|
4619
4642
|
const openAIPayload = translateToOpenAI(anthropicPayload);
|
|
4620
4643
|
const fallbackInitiator = initiatorOverride ?? getChatInitiator(openAIPayload.messages);
|
|
4644
|
+
const endpointModel = findEndpointModel(clientModel);
|
|
4645
|
+
const resolvedClientModel = endpointModel?.id ?? clientModel;
|
|
4621
4646
|
const selection = await accountsManager.selectAccountForRequest([
|
|
4622
4647
|
{
|
|
4623
|
-
modelId:
|
|
4648
|
+
modelId: resolvedClientModel,
|
|
4624
4649
|
endpoint: MESSAGES_ENDPOINT
|
|
4625
4650
|
},
|
|
4626
4651
|
{
|
|
4627
|
-
modelId:
|
|
4652
|
+
modelId: resolvedClientModel,
|
|
4628
4653
|
endpoint: RESPONSES_ENDPOINT$1
|
|
4629
4654
|
},
|
|
4630
4655
|
{
|
|
4631
|
-
modelId: openAIPayload.model,
|
|
4656
|
+
modelId: endpointModel?.id ?? openAIPayload.model,
|
|
4632
4657
|
endpoint: CHAT_COMPLETIONS_ENDPOINT
|
|
4633
4658
|
}
|
|
4634
4659
|
]);
|
|
@@ -5396,6 +5421,18 @@ const FORWARDABLE_HEADERS = [
|
|
|
5396
5421
|
"accept",
|
|
5397
5422
|
"user-agent"
|
|
5398
5423
|
];
|
|
5424
|
+
const STRIPPED_RESPONSE_HEADERS = [
|
|
5425
|
+
"connection",
|
|
5426
|
+
"content-encoding",
|
|
5427
|
+
"content-length",
|
|
5428
|
+
"keep-alive",
|
|
5429
|
+
"proxy-authenticate",
|
|
5430
|
+
"proxy-authorization",
|
|
5431
|
+
"te",
|
|
5432
|
+
"trailer",
|
|
5433
|
+
"transfer-encoding",
|
|
5434
|
+
"upgrade"
|
|
5435
|
+
];
|
|
5399
5436
|
function buildProviderUpstreamHeaders(providerConfig, requestHeaders) {
|
|
5400
5437
|
const headers = {
|
|
5401
5438
|
"content-type": "application/json",
|
|
@@ -5408,6 +5445,15 @@ function buildProviderUpstreamHeaders(providerConfig, requestHeaders) {
|
|
|
5408
5445
|
}
|
|
5409
5446
|
return headers;
|
|
5410
5447
|
}
|
|
5448
|
+
function createProviderProxyResponse(upstreamResponse) {
|
|
5449
|
+
const headers = new Headers(upstreamResponse.headers);
|
|
5450
|
+
for (const headerName of STRIPPED_RESPONSE_HEADERS) headers.delete(headerName);
|
|
5451
|
+
return new Response(upstreamResponse.body, {
|
|
5452
|
+
headers,
|
|
5453
|
+
status: upstreamResponse.status,
|
|
5454
|
+
statusText: upstreamResponse.statusText
|
|
5455
|
+
});
|
|
5456
|
+
}
|
|
5411
5457
|
async function forwardProviderMessages(providerConfig, payload, requestHeaders) {
|
|
5412
5458
|
return await fetch(`${providerConfig.baseUrl}/v1/messages`, {
|
|
5413
5459
|
method: "POST",
|
|
@@ -5434,9 +5480,10 @@ async function handleProviderMessages(c) {
|
|
|
5434
5480
|
} }, 404);
|
|
5435
5481
|
try {
|
|
5436
5482
|
const payload = await c.req.json();
|
|
5437
|
-
|
|
5438
|
-
payload.
|
|
5439
|
-
payload.
|
|
5483
|
+
const modelConfig = providerConfig.models?.[payload.model];
|
|
5484
|
+
payload.temperature ??= modelConfig?.temperature;
|
|
5485
|
+
payload.top_p ??= modelConfig?.topP;
|
|
5486
|
+
payload.top_k ??= modelConfig?.topK;
|
|
5440
5487
|
logger$3.debug("provider.messages.request", JSON.stringify({
|
|
5441
5488
|
payload,
|
|
5442
5489
|
provider
|
|
@@ -5457,7 +5504,7 @@ async function handleProviderMessages(c) {
|
|
|
5457
5504
|
}
|
|
5458
5505
|
});
|
|
5459
5506
|
}
|
|
5460
|
-
return upstreamResponse;
|
|
5507
|
+
return createProviderProxyResponse(upstreamResponse);
|
|
5461
5508
|
} catch (error) {
|
|
5462
5509
|
logger$3.error("provider.messages.error", {
|
|
5463
5510
|
provider,
|
|
@@ -5502,7 +5549,7 @@ providerModelRoutes.get("/", async (c) => {
|
|
|
5502
5549
|
provider,
|
|
5503
5550
|
statusCode: upstreamResponse.status
|
|
5504
5551
|
});
|
|
5505
|
-
return upstreamResponse;
|
|
5552
|
+
return createProviderProxyResponse(upstreamResponse);
|
|
5506
5553
|
} catch (error) {
|
|
5507
5554
|
logger$2.error("provider.models.error", {
|
|
5508
5555
|
provider,
|
|
@@ -6097,4 +6144,4 @@ server.route("/:provider/v1/models", providerModelRoutes);
|
|
|
6097
6144
|
|
|
6098
6145
|
//#endregion
|
|
6099
6146
|
export { server };
|
|
6100
|
-
//# sourceMappingURL=server-
|
|
6147
|
+
//# sourceMappingURL=server-D3A61KAx.js.map
|