@jeffreycao/copilot-api 1.13.11 → 1.13.14
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 +2 -2
- package/README.zh-CN.md +2 -2
- package/dist/main.js +1 -1
- package/dist/{server-JtVsUm_H.js → server-977yOyfA.js} +58 -45
- package/dist/server-977yOyfA.js.map +1 -0
- package/dist/{start-CDw9cq41.js → start-BP0GcUF7.js} +2 -2
- package/dist/{start-CDw9cq41.js.map → start-BP0GcUF7.js.map} +1 -1
- package/package.json +1 -1
- package/dist/server-JtVsUm_H.js.map +0 -1
package/README.md
CHANGED
|
@@ -553,9 +553,9 @@ Use `copilot-api auth login --provider custom` to add or update another third-pa
|
|
|
553
553
|
- `temperature` (optional): Default temperature value used when the request does not specify one.
|
|
554
554
|
- `topP` (optional): Default top_p value used when the request does not specify one.
|
|
555
555
|
- `topK` (optional): Default top_k value used when the request does not specify one.
|
|
556
|
-
- `extraBody` (optional): Dynamic fields merged into the upstream request body for that model. Request body fields with the same name take precedence. OpenAI-compatible providers can use this for fields such as `enable_thinking`, `preserve_thinking`, `reasoning_effort`. `thinking_budget` is a special OpenAI-compatible provider override: when configured in `extraBody`, it is forced after Anthropic `thinking.budget_tokens` translation and overrides the request-derived budget. For providers whose name is `dashscope` or whose `baseUrl` contains `aliyuncs.com`, the request-derived `thinking_budget` (from Anthropic `thinking.budget_tokens`) is forwarded upstream; for other OpenAI-compatible providers the request-derived `thinking_budget` is stripped, while an `extraBody` `thinking_budget` is still honored.
|
|
556
|
+
- `extraBody` (optional): Dynamic fields merged into the upstream request body for that model. Request body fields with the same name take precedence. OpenAI-compatible providers can use this for fields such as `enable_thinking`, `preserve_thinking`, `reasoning_effort`. `thinking_budget` is a special OpenAI-compatible provider override: when configured in `extraBody`, it is forced after Anthropic `thinking.budget_tokens` translation and overrides the request-derived budget. For providers whose name is `dashscope` or whose `baseUrl` contains `aliyuncs.com`, the request-derived `thinking_budget` (from Anthropic `thinking.budget_tokens`) is forwarded upstream; for other OpenAI-compatible providers the request-derived `thinking_budget` is stripped, while an `extraBody` `thinking_budget` is still honored. For DashScope providers, `preserve_thinking` defaults to `true` when not explicitly set in `extraBody` or the request body.
|
|
557
557
|
- `pricing` (optional): Per-model token prices, in the provider `pricingCurrency`, per 1M tokens. Supported fields are `input`, `output`, `cachedInput` (implicit cache read), `explicitCachedInput` (explicit cache read), and `cacheCreationInput`. Use `tiers` with `maxInputTokens` for input-size tiered pricing.
|
|
558
|
-
- `contextCache` (optional): Defaults to `true` for providers whose name is `dashscope` or whose `baseUrl` contains `aliyuncs.com`; defaults to `false` for other OpenAI-compatible providers. This enables Alibaba Cloud Model Studio/DashScope explicit context cache by injecting `cache_control: { "type": "ephemeral" }` on up to 4 content blocks using the Context Cache format. The cache breakpoint strategy matches opencode's main provider flow: the first 2 system messages plus the last 2 non-system messages. Marked string content is converted to text content part arrays for `system` / `user` / `assistant` / `tool` messages; existing array content is marked on the last part. Set this to `false` when the model already supports implicit caching, or when the upstream does not accept this explicit-cache extension field. Set this to `true` for non-DashScope providers that support the same explicit-cache extension.
|
|
558
|
+
- `contextCache` (optional): Defaults to `true` for providers whose name is `dashscope` or whose `baseUrl` contains `aliyuncs.com`; defaults to `false` for other OpenAI-compatible providers. This enables Alibaba Cloud Model Studio/DashScope explicit context cache by injecting `cache_control: { "type": "ephemeral" }` on up to 4 content blocks using the Context Cache format. The cache breakpoint strategy matches opencode's main provider flow: the first 2 system messages plus the last 2 non-system messages. Marked string content is converted to text content part arrays for `system` / `user` / `assistant` / `tool` messages; existing array content is marked on the last part. Set this to `false` when the model already supports implicit caching, or when the upstream does not accept this explicit-cache extension field. Set this to `true` for non-DashScope providers that support the same explicit-cache extension. Applied on both `/v1/messages` and `/v1/chat/completions` routes.
|
|
559
559
|
- `supportPdf` (optional): Controls whether the model supports PDF/document content. Defaults to `false`; unsupported PDFs are converted to a text notice. Set it to `true` to send PDF/document blocks as OpenAI Chat Completions file parts.
|
|
560
560
|
- `toolContentSupportType` (optional): Tool result content capabilities for that model, as an array of `array`, `image`, and `pdf`. Provider routes default to string-only tool content when omitted. If `supportPdf` is `true` but this list does not include `pdf`, file parts in tool results are moved to user role messages. This provider default does not change the Copilot main flow, which continues to support array + image and not PDF.
|
|
561
561
|
- `type` (optional): Per-model override of the provider protocol type. Supports `anthropic`, `openai-compatible`, and `openai-responses`. When set, the provider's `/v1/messages` route uses this model's type instead of the provider-level type for request routing, auth header resolution, and upstream endpoint selection. This is useful for providers like OpenCode Go whose upstream supports both OpenAI-compatible and Anthropic Messages APIs for different models. When the type is overridden, the auth header is resolved from the overridden type's default (Anthropic defaults to `x-api-key`; OpenAI-compatible/Responses default to `authorization`).
|
package/README.zh-CN.md
CHANGED
|
@@ -559,9 +559,9 @@ Copilot API 现在使用子命令结构,主要命令包括:
|
|
|
559
559
|
- `temperature`:可选,当请求未指定时使用的默认温度。
|
|
560
560
|
- `topP`:可选,当请求未指定时使用的默认 `top_p`。
|
|
561
561
|
- `topK`:可选,当请求未指定时使用的默认 `top_k`。
|
|
562
|
-
- `extraBody`:可选,按模型合入上游请求体的动态字段;请求体显式同名字段优先。OpenAI 兼容 provider 可用它配置 `enable_thinking`、`preserve_thinking`、`reasoning_effort` 等字段。`thinking_budget` 是 OpenAI 兼容 provider 的特殊覆盖项:配置在 `extraBody` 后,会在 Anthropic `thinking.budget_tokens` 翻译之后强制写入,并覆盖请求派生出的预算值。对于 provider name 为 `dashscope` 或 `baseUrl` 包含 `aliyuncs.com` 的 provider,请求派生的 `thinking_budget`(来自 Anthropic `thinking.budget_tokens`)会转发给上游;其他 OpenAI 兼容 provider 会移除请求派生的 `thinking_budget`,但 `extraBody` 中的 `thinking_budget`
|
|
562
|
+
- `extraBody`:可选,按模型合入上游请求体的动态字段;请求体显式同名字段优先。OpenAI 兼容 provider 可用它配置 `enable_thinking`、`preserve_thinking`、`reasoning_effort` 等字段。`thinking_budget` 是 OpenAI 兼容 provider 的特殊覆盖项:配置在 `extraBody` 后,会在 Anthropic `thinking.budget_tokens` 翻译之后强制写入,并覆盖请求派生出的预算值。对于 provider name 为 `dashscope` 或 `baseUrl` 包含 `aliyuncs.com` 的 provider,请求派生的 `thinking_budget`(来自 Anthropic `thinking.budget_tokens`)会转发给上游;其他 OpenAI 兼容 provider 会移除请求派生的 `thinking_budget`,但 `extraBody` 中的 `thinking_budget` 仍然生效。对于 DashScope provider,当 `preserve_thinking` 未在 `extraBody` 或请求体中显式设置时,默认为 `true`。
|
|
563
563
|
- `pricing`:可选,按模型配置 token 单价,币种使用 provider 的 `pricingCurrency`,单位为每 100 万 tokens。支持 `input`、`output`、`cachedInput`(隐式缓存读)、`explicitCachedInput`(显式缓存读)和 `cacheCreationInput`。如需按输入 token 总量分档,可用带 `maxInputTokens` 的 `tiers`。
|
|
564
|
-
- `contextCache`:可选,provider name 为 `dashscope` 或 `baseUrl` 包含 `aliyuncs.com` 时默认 `true`,其他 OpenAI 兼容 provider 默认 `false`。用于启用阿里云百炼/DashScope 的显式缓存(explicit context cache),会按其 Context Cache 格式在最多 4 个 content block 上注入 `cache_control: { "type": "ephemeral" }`。缓存断点策略与 opencode 主链路保持一致:前 2 条 system 消息 + 最后 2 条非 system 消息。标记字符串 content 时会把 `system` / `user` / `assistant` / `tool` 消息转换为 text content part 数组;已有数组 content 则标记最后一个 part。如果模型本身已经支持隐式缓存,或上游不支持该显式缓存扩展字段,可在模型配置中设为 `false`。支持相同显式缓存扩展的非 DashScope provider 可设为 `true
|
|
564
|
+
- `contextCache`:可选,provider name 为 `dashscope` 或 `baseUrl` 包含 `aliyuncs.com` 时默认 `true`,其他 OpenAI 兼容 provider 默认 `false`。用于启用阿里云百炼/DashScope 的显式缓存(explicit context cache),会按其 Context Cache 格式在最多 4 个 content block 上注入 `cache_control: { "type": "ephemeral" }`。缓存断点策略与 opencode 主链路保持一致:前 2 条 system 消息 + 最后 2 条非 system 消息。标记字符串 content 时会把 `system` / `user` / `assistant` / `tool` 消息转换为 text content part 数组;已有数组 content 则标记最后一个 part。如果模型本身已经支持隐式缓存,或上游不支持该显式缓存扩展字段,可在模型配置中设为 `false`。支持相同显式缓存扩展的非 DashScope provider 可设为 `true`。同时适用于 `/v1/messages` 和 `/v1/chat/completions` 路由。
|
|
565
565
|
- `supportPdf`:可选,控制该模型是否支持 PDF/document content。默认 `false`,不支持时会把 PDF 转成提示文本;设为 `true` 时会把 PDF/document 转成 OpenAI Chat Completions 的 file part。
|
|
566
566
|
- `toolContentSupportType`:可选,配置该模型的 tool result content 支持能力,值为 `array`、`image`、`pdf` 的数组。provider 侧未配置时默认只发送 string tool content。若 `supportPdf` 为 `true` 但这里不包含 `pdf`,tool result 里的 file part 会被转成 user role 消息。Copilot 主链路不使用这个 provider 默认,仍按 array + image 且不支持 PDF 的能力处理。
|
|
567
567
|
- `type`:可选,按模型覆盖 provider 的协议类型。支持 `anthropic`、`openai-compatible` 和 `openai-responses`。设置后,provider 的 `/v1/messages` 路由会使用该模型的 type 替代 provider 级别的 type 进行请求路由、认证头解析和上游端点选择。适用于 OpenCode Go 等上游对不同模型同时支持 OpenAI 兼容和 Anthropic Messages API 的 provider。覆盖 type 时,认证头按覆盖后 type 的默认值解析(Anthropic 默认 `x-api-key`;OpenAI 兼容/Responses 默认 `authorization`)。
|
package/dist/main.js
CHANGED
|
@@ -25,7 +25,7 @@ bindElectronFetch();
|
|
|
25
25
|
const { auth } = await import("./auth-CfRmN-aH.js");
|
|
26
26
|
const { debug } = await import("./debug-JJUz1hBb.js");
|
|
27
27
|
const { mcp } = await import("./mcp-BseuqgHR.js");
|
|
28
|
-
const { start } = await import("./start-
|
|
28
|
+
const { start } = await import("./start-BP0GcUF7.js");
|
|
29
29
|
await runMain(defineCommand({
|
|
30
30
|
meta: {
|
|
31
31
|
name: "copilot-api",
|
|
@@ -1342,6 +1342,55 @@ function mergeAnthropicUsage(current, next) {
|
|
|
1342
1342
|
};
|
|
1343
1343
|
}
|
|
1344
1344
|
//#endregion
|
|
1345
|
+
//#region src/lib/dashscope.ts
|
|
1346
|
+
const OPENAI_COMPATIBLE_CONTEXT_CACHE_MARKER_LIMIT = 4;
|
|
1347
|
+
const OPENAI_COMPATIBLE_CONTEXT_CACHE_CONTROL = { type: "ephemeral" };
|
|
1348
|
+
const OPENAI_COMPATIBLE_CONTEXT_CACHE_ROLES = new Set([
|
|
1349
|
+
"system",
|
|
1350
|
+
"user",
|
|
1351
|
+
"assistant",
|
|
1352
|
+
"tool"
|
|
1353
|
+
]);
|
|
1354
|
+
const isDashScopeAliyunProvider = (providerConfig) => providerConfig.name === "dashscope" || providerConfig.baseUrl.includes("aliyuncs.com");
|
|
1355
|
+
const applyDashScopePreserveThinkingDefault = (payload, providerConfig) => {
|
|
1356
|
+
if (!isDashScopeAliyunProvider(providerConfig)) return;
|
|
1357
|
+
if (!Object.hasOwn(payload, "preserve_thinking")) payload.preserve_thinking = true;
|
|
1358
|
+
};
|
|
1359
|
+
const applyOpenAICompatibleContextCache = (payload) => {
|
|
1360
|
+
const messageIndexes = selectContextCacheMessageIndexes(payload.messages);
|
|
1361
|
+
for (const messageIndex of messageIndexes) applyContextCacheControl(payload.messages[messageIndex]);
|
|
1362
|
+
};
|
|
1363
|
+
const selectContextCacheMessageIndexes = (messages) => {
|
|
1364
|
+
const cacheableIndexes = messages.flatMap((message, index) => isContextCacheMarkerEligible(message) ? [index] : []);
|
|
1365
|
+
const systemIndexes = cacheableIndexes.filter((index) => messages[index]?.role === "system").slice(0, 2);
|
|
1366
|
+
const finalIndexes = cacheableIndexes.filter((index) => messages[index]?.role !== "system").slice(-1);
|
|
1367
|
+
return uniqueIndexes$1([...systemIndexes, ...finalIndexes]).sort((a, b) => a - b);
|
|
1368
|
+
};
|
|
1369
|
+
const uniqueIndexes$1 = (indexes) => [...new Set(indexes)].slice(0, OPENAI_COMPATIBLE_CONTEXT_CACHE_MARKER_LIMIT);
|
|
1370
|
+
const isContextCacheMarkerEligible = (message) => {
|
|
1371
|
+
if (!OPENAI_COMPATIBLE_CONTEXT_CACHE_ROLES.has(message.role)) return false;
|
|
1372
|
+
if (typeof message.content === "string") return message.content.length > 0;
|
|
1373
|
+
return Array.isArray(message.content) && message.content.length > 0;
|
|
1374
|
+
};
|
|
1375
|
+
const applyContextCacheControl = (message) => {
|
|
1376
|
+
if (!message) return;
|
|
1377
|
+
if (typeof message.content === "string") {
|
|
1378
|
+
message.content = [{
|
|
1379
|
+
type: "text",
|
|
1380
|
+
text: message.content,
|
|
1381
|
+
cache_control: { ...OPENAI_COMPATIBLE_CONTEXT_CACHE_CONTROL }
|
|
1382
|
+
}];
|
|
1383
|
+
return;
|
|
1384
|
+
}
|
|
1385
|
+
if (!Array.isArray(message.content)) return;
|
|
1386
|
+
const lastPart = message.content.at(-1);
|
|
1387
|
+
if (!lastPart) return;
|
|
1388
|
+
setContextCacheControl(lastPart);
|
|
1389
|
+
};
|
|
1390
|
+
const setContextCacheControl = (part) => {
|
|
1391
|
+
part.cache_control = { ...OPENAI_COMPATIBLE_CONTEXT_CACHE_CONTROL };
|
|
1392
|
+
};
|
|
1393
|
+
//#endregion
|
|
1345
1394
|
//#region src/lib/provider-resolver.ts
|
|
1346
1395
|
function isMissingCodexCredentialsError(error) {
|
|
1347
1396
|
return error instanceof Error && error.message === "Codex credentials not found. Run `copilot-api auth login --provider codex` first.";
|
|
@@ -1455,6 +1504,8 @@ async function handleProviderChatCompletionsForProvider(c, options) {
|
|
|
1455
1504
|
applyProviderModelDefaults(payload, modelConfig);
|
|
1456
1505
|
applyMissingExtraBody$1(payload, { extraBody: modelConfig?.extraBody });
|
|
1457
1506
|
applyProviderStreamOptions(payload);
|
|
1507
|
+
applyDashScopePreserveThinkingDefault(payload, providerConfig);
|
|
1508
|
+
applyProviderContextCache(payload, modelConfig, providerConfig);
|
|
1458
1509
|
debugJson(logger$9, "provider.chat_completions.request", {
|
|
1459
1510
|
payload,
|
|
1460
1511
|
provider
|
|
@@ -1493,6 +1544,10 @@ const applyProviderStreamOptions = (payload) => {
|
|
|
1493
1544
|
include_usage: true
|
|
1494
1545
|
};
|
|
1495
1546
|
};
|
|
1547
|
+
const applyProviderContextCache = (payload, modelConfig, providerConfig) => {
|
|
1548
|
+
const isDashScopeProvider = isDashScopeAliyunProvider(providerConfig);
|
|
1549
|
+
if (modelConfig?.contextCache ?? isDashScopeProvider) applyOpenAICompatibleContextCache(payload);
|
|
1550
|
+
};
|
|
1496
1551
|
const createProviderChatCompletionsUsageRecorder = (payload, provider, modelConfig, pricingCurrency) => createProviderTokenUsageRecorder({
|
|
1497
1552
|
endpoint: "chat_completions",
|
|
1498
1553
|
model: payload.model,
|
|
@@ -5094,15 +5149,6 @@ function getModels() {
|
|
|
5094
5149
|
//#endregion
|
|
5095
5150
|
//#region src/routes/provider/messages/handler.ts
|
|
5096
5151
|
const logger$6 = createHandlerLogger("provider-messages-handler");
|
|
5097
|
-
const OPENAI_COMPATIBLE_CONTEXT_CACHE_MARKER_LIMIT = 4;
|
|
5098
|
-
const OPENAI_COMPATIBLE_CONTEXT_CACHE_CONTROL = { type: "ephemeral" };
|
|
5099
|
-
const OPENAI_COMPATIBLE_CONTEXT_CACHE_ROLES = new Set([
|
|
5100
|
-
"system",
|
|
5101
|
-
"user",
|
|
5102
|
-
"assistant",
|
|
5103
|
-
"tool"
|
|
5104
|
-
]);
|
|
5105
|
-
const isDashScopeAliyunProvider = (providerConfig) => providerConfig.name === "dashscope" || providerConfig.baseUrl.includes("aliyuncs.com");
|
|
5106
5152
|
async function handleProviderMessages(c) {
|
|
5107
5153
|
const provider = c.req.param("provider");
|
|
5108
5154
|
return await handleProviderMessagesForProvider(c, {
|
|
@@ -5373,6 +5419,7 @@ const createOpenAICompatiblePayload = (payload, modelConfig, providerConfig) =>
|
|
|
5373
5419
|
});
|
|
5374
5420
|
applyMissingExtraBody(openAIPayload, { extraBody: modelConfig?.extraBody });
|
|
5375
5421
|
applyOpenAICompatibleExtraBodyThinkingBudget(openAIPayload, { extraBody: modelConfig?.extraBody });
|
|
5422
|
+
applyDashScopePreserveThinkingDefault(openAIPayload, providerConfig);
|
|
5376
5423
|
if (!Object.hasOwn(openAIPayload, "parallel_tool_calls")) openAIPayload.parallel_tool_calls = true;
|
|
5377
5424
|
if (modelConfig?.contextCache ?? isDashScopeProvider) applyOpenAICompatibleContextCache(openAIPayload);
|
|
5378
5425
|
return openAIPayload;
|
|
@@ -5389,40 +5436,6 @@ const applyOpenAICompatibleRequestOverrides = (payload, options) => {
|
|
|
5389
5436
|
const allowedKeys = new Set(Object.keys(options.extraBody ?? {}));
|
|
5390
5437
|
for (const key of allowedKeys) if (Object.hasOwn(options.source, key)) payload[key] = options.source[key];
|
|
5391
5438
|
};
|
|
5392
|
-
const applyOpenAICompatibleContextCache = (payload) => {
|
|
5393
|
-
const messageIndexes = selectContextCacheMessageIndexes(payload.messages);
|
|
5394
|
-
for (const messageIndex of messageIndexes) applyContextCacheControl(payload.messages[messageIndex]);
|
|
5395
|
-
};
|
|
5396
|
-
const selectContextCacheMessageIndexes = (messages) => {
|
|
5397
|
-
const cacheableIndexes = messages.flatMap((message, index) => isContextCacheMarkerEligible(message) ? [index] : []);
|
|
5398
|
-
const systemIndexes = cacheableIndexes.filter((index) => messages[index]?.role === "system").slice(0, 2);
|
|
5399
|
-
const finalIndexes = cacheableIndexes.filter((index) => messages[index]?.role !== "system").slice(-2);
|
|
5400
|
-
return uniqueIndexes$1([...systemIndexes, ...finalIndexes]).sort((a, b) => a - b);
|
|
5401
|
-
};
|
|
5402
|
-
const uniqueIndexes$1 = (indexes) => [...new Set(indexes)].slice(0, OPENAI_COMPATIBLE_CONTEXT_CACHE_MARKER_LIMIT);
|
|
5403
|
-
const isContextCacheMarkerEligible = (message) => {
|
|
5404
|
-
if (!OPENAI_COMPATIBLE_CONTEXT_CACHE_ROLES.has(message.role)) return false;
|
|
5405
|
-
if (typeof message.content === "string") return message.content.length > 0;
|
|
5406
|
-
return Array.isArray(message.content) && message.content.length > 0;
|
|
5407
|
-
};
|
|
5408
|
-
const applyContextCacheControl = (message) => {
|
|
5409
|
-
if (!message) return;
|
|
5410
|
-
if (typeof message.content === "string") {
|
|
5411
|
-
message.content = [{
|
|
5412
|
-
type: "text",
|
|
5413
|
-
text: message.content,
|
|
5414
|
-
cache_control: { ...OPENAI_COMPATIBLE_CONTEXT_CACHE_CONTROL }
|
|
5415
|
-
}];
|
|
5416
|
-
return;
|
|
5417
|
-
}
|
|
5418
|
-
if (!Array.isArray(message.content)) return;
|
|
5419
|
-
const lastPart = message.content.at(-1);
|
|
5420
|
-
if (!lastPart) return;
|
|
5421
|
-
setContextCacheControl(lastPart);
|
|
5422
|
-
};
|
|
5423
|
-
const setContextCacheControl = (part) => {
|
|
5424
|
-
part.cache_control = { ...OPENAI_COMPATIBLE_CONTEXT_CACHE_CONTROL };
|
|
5425
|
-
};
|
|
5426
5439
|
const streamProviderMessages = ({ c, modelConfig, payload, pricingCurrency, provider, upstreamResponse }) => {
|
|
5427
5440
|
logger$6.debug("provider.messages.streaming");
|
|
5428
5441
|
const recordUsage = createProviderMessagesUsageRecorder(payload, provider, modelConfig, pricingCurrency);
|
|
@@ -5696,7 +5709,7 @@ const createMessages = async (payload, anthropicBetaHeader, options) => {
|
|
|
5696
5709
|
//#endregion
|
|
5697
5710
|
//#region src/routes/messages/api-flows.ts
|
|
5698
5711
|
const COPILOT_CONTEXT_CACHE_SYSTEM_MARKER_LIMIT = 2;
|
|
5699
|
-
const COPILOT_CONTEXT_CACHE_NON_SYSTEM_MARKER_LIMIT =
|
|
5712
|
+
const COPILOT_CONTEXT_CACHE_NON_SYSTEM_MARKER_LIMIT = 1;
|
|
5700
5713
|
const COPILOT_CONTEXT_CACHE_CONTROL = { type: "ephemeral" };
|
|
5701
5714
|
const messagesApiFlowDependencies = {
|
|
5702
5715
|
createChatCompletions,
|
|
@@ -6661,4 +6674,4 @@ server.route("/:provider/v1/models", providerModelRoutes);
|
|
|
6661
6674
|
//#endregion
|
|
6662
6675
|
export { server };
|
|
6663
6676
|
|
|
6664
|
-
//# sourceMappingURL=server-
|
|
6677
|
+
//# sourceMappingURL=server-977yOyfA.js.map
|