@openhoo/hoopilot 0.5.4 → 0.5.6
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 +13 -8
- package/dist/cli.js +95 -17
- package/dist/cli.js.map +1 -1
- package/dist/codexx.js +11 -2
- package/dist/codexx.js.map +1 -1
- package/dist/index.cjs +99 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +97 -17
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/codexx.js
CHANGED
|
@@ -20,12 +20,21 @@ function buildCodexxInvocation(argv, env = process.env) {
|
|
|
20
20
|
const baseUrl = env.CODEXX_BASE_URL ?? DEFAULT_BASE_URL;
|
|
21
21
|
const apiKey = env.CODEXX_API_KEY ?? env.HOOPILOT_API_KEY ?? env.OPENAI_API_KEY ?? DEFAULT_API_KEY;
|
|
22
22
|
const command = env.CODEXX_CODEX_BIN ?? DEFAULT_CODEX_BIN;
|
|
23
|
+
const providerConfig = [
|
|
24
|
+
'{ name = "Hoopilot"',
|
|
25
|
+
`base_url = ${JSON.stringify(baseUrl)}`,
|
|
26
|
+
'env_key = "OPENAI_API_KEY"',
|
|
27
|
+
'wire_api = "responses"',
|
|
28
|
+
"supports_websockets = false }"
|
|
29
|
+
].join(", ");
|
|
23
30
|
return {
|
|
24
31
|
args: [
|
|
25
32
|
"--disable",
|
|
26
33
|
"network_proxy",
|
|
27
34
|
"-c",
|
|
28
|
-
|
|
35
|
+
'model_provider="hoopilot"',
|
|
36
|
+
"-c",
|
|
37
|
+
`model_providers.hoopilot=${providerConfig}`,
|
|
29
38
|
...argv
|
|
30
39
|
],
|
|
31
40
|
command,
|
|
@@ -80,7 +89,7 @@ Environment:
|
|
|
80
89
|
OPENAI_API_KEY Used as the API key when both CODEXX_API_KEY and HOOPILOT_API_KEY are unset.
|
|
81
90
|
CODEXX_CODEX_BIN Codex executable to run. Default: ${DEFAULT_CODEX_BIN}
|
|
82
91
|
|
|
83
|
-
codexx does not start Hoopilot and does not change your shell environment. It disables Codex's network_proxy feature and removes proxy variables only from the spawned Codex process.`;
|
|
92
|
+
codexx does not start Hoopilot and does not change your shell environment. It selects a temporary Hoopilot model provider with Responses WebSockets disabled, disables Codex's network_proxy feature, and removes proxy variables only from the spawned Codex process.`;
|
|
84
93
|
}
|
|
85
94
|
function signalNumber(signal) {
|
|
86
95
|
return osConstants.signals[signal] ?? 1;
|
package/dist/codexx.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/codexx.ts"],"sourcesContent":["#!/usr/bin/env bun\n\nimport { spawn } from \"node:child_process\";\nimport { constants as osConstants } from \"node:os\";\n\nconst DEFAULT_BASE_URL = \"http://127.0.0.1:4141/v1\";\nconst DEFAULT_API_KEY = \"local-key\";\nconst DEFAULT_CODEX_BIN = \"codex\";\nconst PROXY_ENV_KEYS = [\n \"ALL_PROXY\",\n \"HTTPS_PROXY\",\n \"HTTP_PROXY\",\n \"NO_PROXY\",\n \"all_proxy\",\n \"https_proxy\",\n \"http_proxy\",\n \"no_proxy\",\n];\n\nexport interface CodexxInvocation {\n args: string[];\n command: string;\n env: NodeJS.ProcessEnv;\n}\n\nexport function buildCodexxInvocation(\n argv: string[],\n env: NodeJS.ProcessEnv = process.env,\n): CodexxInvocation {\n const baseUrl = env.CODEXX_BASE_URL ?? DEFAULT_BASE_URL;\n const apiKey =\n env.CODEXX_API_KEY ?? env.HOOPILOT_API_KEY ?? env.OPENAI_API_KEY ?? DEFAULT_API_KEY;\n const command = env.CODEXX_CODEX_BIN ?? DEFAULT_CODEX_BIN;\n\n return {\n args: [\n \"--disable\",\n \"network_proxy\",\n \"-c\",\n `
|
|
1
|
+
{"version":3,"sources":["../src/codexx.ts"],"sourcesContent":["#!/usr/bin/env bun\n\nimport { spawn } from \"node:child_process\";\nimport { constants as osConstants } from \"node:os\";\n\nconst DEFAULT_BASE_URL = \"http://127.0.0.1:4141/v1\";\nconst DEFAULT_API_KEY = \"local-key\";\nconst DEFAULT_CODEX_BIN = \"codex\";\nconst PROXY_ENV_KEYS = [\n \"ALL_PROXY\",\n \"HTTPS_PROXY\",\n \"HTTP_PROXY\",\n \"NO_PROXY\",\n \"all_proxy\",\n \"https_proxy\",\n \"http_proxy\",\n \"no_proxy\",\n];\n\nexport interface CodexxInvocation {\n args: string[];\n command: string;\n env: NodeJS.ProcessEnv;\n}\n\nexport function buildCodexxInvocation(\n argv: string[],\n env: NodeJS.ProcessEnv = process.env,\n): CodexxInvocation {\n const baseUrl = env.CODEXX_BASE_URL ?? DEFAULT_BASE_URL;\n const apiKey =\n env.CODEXX_API_KEY ?? env.HOOPILOT_API_KEY ?? env.OPENAI_API_KEY ?? DEFAULT_API_KEY;\n const command = env.CODEXX_CODEX_BIN ?? DEFAULT_CODEX_BIN;\n const providerConfig = [\n '{ name = \"Hoopilot\"',\n `base_url = ${JSON.stringify(baseUrl)}`,\n 'env_key = \"OPENAI_API_KEY\"',\n 'wire_api = \"responses\"',\n \"supports_websockets = false }\",\n ].join(\", \");\n\n return {\n args: [\n \"--disable\",\n \"network_proxy\",\n \"-c\",\n 'model_provider=\"hoopilot\"',\n \"-c\",\n `model_providers.hoopilot=${providerConfig}`,\n ...argv,\n ],\n command,\n env: withoutProxyEnv({\n ...env,\n OPENAI_API_KEY: apiKey,\n }),\n };\n}\n\nfunction withoutProxyEnv(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n const next = { ...env };\n for (const key of PROXY_ENV_KEYS) {\n delete next[key];\n }\n return next;\n}\n\nexport async function main(argv = Bun.argv.slice(2), env = process.env): Promise<void> {\n if (argv.length === 1 && (argv[0] === \"--help\" || argv[0] === \"-h\")) {\n console.log(helpText());\n return;\n }\n\n const invocation = buildCodexxInvocation(argv, env);\n const child = spawn(invocation.command, invocation.args, {\n env: invocation.env,\n shell: process.platform === \"win32\",\n stdio: \"inherit\",\n });\n\n const exitCode = await new Promise<number>((resolve, reject) => {\n child.once(\"error\", reject);\n child.once(\"exit\", (code, signal) => {\n if (typeof code === \"number\") {\n resolve(code);\n return;\n }\n resolve(signal ? 128 + signalNumber(signal) : 1);\n });\n });\n\n process.exitCode = exitCode;\n}\n\nfunction helpText(): string {\n return `codexx\n\nRun Codex against an already-running local Hoopilot server.\n\nUsage:\n codexx [codex options] [prompt]\n\nEnvironment:\n CODEXX_BASE_URL OpenAI-compatible base URL. Default: ${DEFAULT_BASE_URL}\n CODEXX_API_KEY API key sent to the local Hoopilot server.\n HOOPILOT_API_KEY Used as the API key when CODEXX_API_KEY is unset.\n OPENAI_API_KEY Used as the API key when both CODEXX_API_KEY and HOOPILOT_API_KEY are unset.\n CODEXX_CODEX_BIN Codex executable to run. Default: ${DEFAULT_CODEX_BIN}\n\ncodexx does not start Hoopilot and does not change your shell environment. It selects a temporary Hoopilot model provider with Responses WebSockets disabled, disables Codex's network_proxy feature, and removes proxy variables only from the spawned Codex process.`;\n}\n\nfunction signalNumber(signal: NodeJS.Signals): number {\n return osConstants.signals[signal] ?? 1;\n}\n\nif (import.meta.main) {\n main().catch((error: unknown) => {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n });\n}\n"],"mappings":";;;AAEA,SAAS,aAAa;AACtB,SAAS,aAAa,mBAAmB;AAEzC,IAAM,mBAAmB;AACzB,IAAM,kBAAkB;AACxB,IAAM,oBAAoB;AAC1B,IAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAQO,SAAS,sBACd,MACA,MAAyB,QAAQ,KACf;AAClB,QAAM,UAAU,IAAI,mBAAmB;AACvC,QAAM,SACJ,IAAI,kBAAkB,IAAI,oBAAoB,IAAI,kBAAkB;AACtE,QAAM,UAAU,IAAI,oBAAoB;AACxC,QAAM,iBAAiB;AAAA,IACrB;AAAA,IACA,cAAc,KAAK,UAAU,OAAO,CAAC;AAAA,IACrC;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AAEX,SAAO;AAAA,IACL,MAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,4BAA4B,cAAc;AAAA,MAC1C,GAAG;AAAA,IACL;AAAA,IACA;AAAA,IACA,KAAK,gBAAgB;AAAA,MACnB,GAAG;AAAA,MACH,gBAAgB;AAAA,IAClB,CAAC;AAAA,EACH;AACF;AAEA,SAAS,gBAAgB,KAA2C;AAClE,QAAM,OAAO,EAAE,GAAG,IAAI;AACtB,aAAW,OAAO,gBAAgB;AAChC,WAAO,KAAK,GAAG;AAAA,EACjB;AACA,SAAO;AACT;AAEA,eAAsB,KAAK,OAAO,IAAI,KAAK,MAAM,CAAC,GAAG,MAAM,QAAQ,KAAoB;AACrF,MAAI,KAAK,WAAW,MAAM,KAAK,CAAC,MAAM,YAAY,KAAK,CAAC,MAAM,OAAO;AACnE,YAAQ,IAAI,SAAS,CAAC;AACtB;AAAA,EACF;AAEA,QAAM,aAAa,sBAAsB,MAAM,GAAG;AAClD,QAAM,QAAQ,MAAM,WAAW,SAAS,WAAW,MAAM;AAAA,IACvD,KAAK,WAAW;AAAA,IAChB,OAAO,QAAQ,aAAa;AAAA,IAC5B,OAAO;AAAA,EACT,CAAC;AAED,QAAM,WAAW,MAAM,IAAI,QAAgB,CAAC,SAAS,WAAW;AAC9D,UAAM,KAAK,SAAS,MAAM;AAC1B,UAAM,KAAK,QAAQ,CAAC,MAAM,WAAW;AACnC,UAAI,OAAO,SAAS,UAAU;AAC5B,gBAAQ,IAAI;AACZ;AAAA,MACF;AACA,cAAQ,SAAS,MAAM,aAAa,MAAM,IAAI,CAAC;AAAA,IACjD,CAAC;AAAA,EACH,CAAC;AAED,UAAQ,WAAW;AACrB;AAEA,SAAS,WAAmB;AAC1B,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,8DAQqD,gBAAgB;AAAA;AAAA;AAAA;AAAA,2DAInB,iBAAiB;AAAA;AAAA;AAG5E;AAEA,SAAS,aAAa,QAAgC;AACpD,SAAO,YAAY,QAAQ,MAAM,KAAK;AACxC;AAEA,IAAI,YAAY,MAAM;AACpB,OAAK,EAAE,MAAM,CAAC,UAAmB;AAC/B,YAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AACpE,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACH;","names":[]}
|
package/dist/index.cjs
CHANGED
|
@@ -45,7 +45,9 @@ __export(index_exports, {
|
|
|
45
45
|
fallbackModels: () => fallbackModels,
|
|
46
46
|
githubCopilotDeviceLogin: () => githubCopilotDeviceLogin,
|
|
47
47
|
noopLogger: () => noopLogger,
|
|
48
|
+
normalizeChatCompletionRequest: () => normalizeChatCompletionRequest,
|
|
48
49
|
normalizeModelsResponse: () => normalizeModelsResponse,
|
|
50
|
+
normalizeRequestedModel: () => normalizeRequestedModel,
|
|
49
51
|
parseLogFormat: () => parseLogFormat,
|
|
50
52
|
parseLogLevel: () => parseLogLevel,
|
|
51
53
|
readStoredCopilotAuth: () => readStoredCopilotAuth,
|
|
@@ -172,16 +174,6 @@ var CopilotClient = class {
|
|
|
172
174
|
signal
|
|
173
175
|
});
|
|
174
176
|
}
|
|
175
|
-
async forwardChatCompletions(body, signal) {
|
|
176
|
-
return this.fetchCopilot("/chat/completions", {
|
|
177
|
-
body,
|
|
178
|
-
headers: {
|
|
179
|
-
"content-type": "application/json"
|
|
180
|
-
},
|
|
181
|
-
method: "POST",
|
|
182
|
-
signal
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
177
|
async models(signal) {
|
|
186
178
|
return this.fetchCopilot("/models", {
|
|
187
179
|
headers: {
|
|
@@ -431,6 +423,10 @@ function isLogLevel(value) {
|
|
|
431
423
|
|
|
432
424
|
// src/openai.ts
|
|
433
425
|
var DEFAULT_MODEL = "gpt-4.1";
|
|
426
|
+
var MODEL_ALIASES = {
|
|
427
|
+
"gpt-5.5": DEFAULT_MODEL,
|
|
428
|
+
"gpt-5.5-codex": DEFAULT_MODEL
|
|
429
|
+
};
|
|
434
430
|
function responsesRequestToChatCompletion(request) {
|
|
435
431
|
const messages = [];
|
|
436
432
|
const instructions = contentToText(request.instructions);
|
|
@@ -445,7 +441,7 @@ function responsesRequestToChatCompletion(request) {
|
|
|
445
441
|
max_tokens: request.max_output_tokens ?? request.max_tokens,
|
|
446
442
|
messages,
|
|
447
443
|
metadata: request.metadata,
|
|
448
|
-
model:
|
|
444
|
+
model: normalizeRequestedModel(request.model),
|
|
449
445
|
presence_penalty: request.presence_penalty,
|
|
450
446
|
reasoning_effort: asRecord(request.reasoning).effort,
|
|
451
447
|
response_format: asRecord(request.text).format,
|
|
@@ -457,16 +453,29 @@ function responsesRequestToChatCompletion(request) {
|
|
|
457
453
|
top_p: request.top_p
|
|
458
454
|
});
|
|
459
455
|
}
|
|
456
|
+
function normalizeChatCompletionRequest(request) {
|
|
457
|
+
return removeUndefined({
|
|
458
|
+
...request,
|
|
459
|
+
model: normalizeRequestedModel(request.model)
|
|
460
|
+
});
|
|
461
|
+
}
|
|
460
462
|
function completionsRequestToChatCompletion(request) {
|
|
461
463
|
return removeUndefined({
|
|
462
464
|
max_tokens: request.max_tokens,
|
|
463
465
|
messages: [{ content: promptToText(request.prompt), role: "user" }],
|
|
464
|
-
model:
|
|
466
|
+
model: normalizeRequestedModel(request.model),
|
|
465
467
|
stream: request.stream === true,
|
|
466
468
|
temperature: request.temperature,
|
|
467
469
|
top_p: request.top_p
|
|
468
470
|
});
|
|
469
471
|
}
|
|
472
|
+
function normalizeRequestedModel(model) {
|
|
473
|
+
const requested = contentToText(model).trim();
|
|
474
|
+
if (!requested) {
|
|
475
|
+
return DEFAULT_MODEL;
|
|
476
|
+
}
|
|
477
|
+
return MODEL_ALIASES[requested.toLowerCase()] ?? requested;
|
|
478
|
+
}
|
|
470
479
|
function chatCompletionToResponse(completion, responseId) {
|
|
471
480
|
const id = responseId ?? `resp_${randomId()}`;
|
|
472
481
|
const choice = firstChoice(completion);
|
|
@@ -999,6 +1008,13 @@ function createHoopilotHandler(options = {}) {
|
|
|
999
1008
|
{ logger: requestLogger, requestId, startedAt }
|
|
1000
1009
|
);
|
|
1001
1010
|
}
|
|
1011
|
+
if (request.method === "GET" && apiPath === "/v1/responses") {
|
|
1012
|
+
return finishResponse(websocketUnsupportedResponse(), {
|
|
1013
|
+
logger: requestLogger,
|
|
1014
|
+
requestId,
|
|
1015
|
+
startedAt
|
|
1016
|
+
});
|
|
1017
|
+
}
|
|
1002
1018
|
if (request.method === "GET" && apiPath === "/v1/models") {
|
|
1003
1019
|
return finishResponse(await handleModels(client, request.signal, requestLogger), {
|
|
1004
1020
|
logger: requestLogger,
|
|
@@ -1108,7 +1124,9 @@ async function handleModels(client, signal, logger) {
|
|
|
1108
1124
|
return jsonResponse(normalizeModelsResponse(await upstream.json()));
|
|
1109
1125
|
}
|
|
1110
1126
|
async function handleChatCompletions(client, request, logger) {
|
|
1111
|
-
const
|
|
1127
|
+
const chatRequest = normalizeChatCompletionRequest(await readJson(request));
|
|
1128
|
+
const result = await sendChatCompletions(client, chatRequest, request.signal, logger);
|
|
1129
|
+
const upstream = result.upstream;
|
|
1112
1130
|
if (!upstream.ok) {
|
|
1113
1131
|
return proxyError(upstream, logger);
|
|
1114
1132
|
}
|
|
@@ -1117,10 +1135,13 @@ async function handleChatCompletions(client, request, logger) {
|
|
|
1117
1135
|
}
|
|
1118
1136
|
async function handleCompletions(client, request, logger) {
|
|
1119
1137
|
const body = await readJson(request);
|
|
1120
|
-
const
|
|
1138
|
+
const result = await sendChatCompletions(
|
|
1139
|
+
client,
|
|
1121
1140
|
completionsRequestToChatCompletion(body),
|
|
1122
|
-
request.signal
|
|
1141
|
+
request.signal,
|
|
1142
|
+
logger
|
|
1123
1143
|
);
|
|
1144
|
+
const upstream = result.upstream;
|
|
1124
1145
|
if (!upstream.ok) {
|
|
1125
1146
|
return proxyError(upstream, logger);
|
|
1126
1147
|
}
|
|
@@ -1130,7 +1151,8 @@ async function handleCompletions(client, request, logger) {
|
|
|
1130
1151
|
async function handleResponses(client, request, logger) {
|
|
1131
1152
|
const body = await readJson(request);
|
|
1132
1153
|
const chatRequest = responsesRequestToChatCompletion(body);
|
|
1133
|
-
const
|
|
1154
|
+
const result = await sendChatCompletions(client, chatRequest, request.signal, logger);
|
|
1155
|
+
const upstream = result.upstream;
|
|
1134
1156
|
if (!upstream.ok) {
|
|
1135
1157
|
return proxyError(upstream, logger);
|
|
1136
1158
|
}
|
|
@@ -1138,7 +1160,7 @@ async function handleResponses(client, request, logger) {
|
|
|
1138
1160
|
if (body.stream === true && upstream.body) {
|
|
1139
1161
|
return new Response(
|
|
1140
1162
|
responsesStreamFromChatStream(upstream.body, {
|
|
1141
|
-
model:
|
|
1163
|
+
model: result.model
|
|
1142
1164
|
}),
|
|
1143
1165
|
{
|
|
1144
1166
|
headers: {
|
|
@@ -1152,6 +1174,52 @@ async function handleResponses(client, request, logger) {
|
|
|
1152
1174
|
}
|
|
1153
1175
|
return jsonResponse(chatCompletionToResponse(await upstream.json()));
|
|
1154
1176
|
}
|
|
1177
|
+
async function sendChatCompletions(client, chatRequest, signal, logger) {
|
|
1178
|
+
const model = requestModel(chatRequest);
|
|
1179
|
+
const upstream = await client.chatCompletions(chatRequest, signal);
|
|
1180
|
+
if (upstream.ok || isUpstreamAuthStatus(upstream.status)) {
|
|
1181
|
+
return { model, upstream };
|
|
1182
|
+
}
|
|
1183
|
+
const text = await upstream.text();
|
|
1184
|
+
if (!shouldRetryWithDefaultModel(upstream.status, text, model)) {
|
|
1185
|
+
return { model, upstream: textResponse(upstream, text) };
|
|
1186
|
+
}
|
|
1187
|
+
logger.warn(
|
|
1188
|
+
{
|
|
1189
|
+
event: "copilot.model.fallback",
|
|
1190
|
+
fallbackModel: DEFAULT_MODEL,
|
|
1191
|
+
upstreamPath: "/chat/completions",
|
|
1192
|
+
upstreamStatus: upstream.status
|
|
1193
|
+
},
|
|
1194
|
+
"retrying chat completion with fallback model"
|
|
1195
|
+
);
|
|
1196
|
+
return {
|
|
1197
|
+
model: DEFAULT_MODEL,
|
|
1198
|
+
upstream: await client.chatCompletions({ ...chatRequest, model: DEFAULT_MODEL }, signal)
|
|
1199
|
+
};
|
|
1200
|
+
}
|
|
1201
|
+
function shouldRetryWithDefaultModel(status, text, model) {
|
|
1202
|
+
if (model === DEFAULT_MODEL || status < 400 || status >= 500) {
|
|
1203
|
+
return false;
|
|
1204
|
+
}
|
|
1205
|
+
const normalized = text.toLowerCase();
|
|
1206
|
+
return normalized.includes("model") && (normalized.includes("not supported") || normalized.includes("unsupported") || normalized.includes("invalid model"));
|
|
1207
|
+
}
|
|
1208
|
+
function requestModel(request) {
|
|
1209
|
+
return typeof request.model === "string" && request.model.trim() ? request.model : DEFAULT_MODEL;
|
|
1210
|
+
}
|
|
1211
|
+
function textResponse(upstream, text) {
|
|
1212
|
+
const headers = new Headers();
|
|
1213
|
+
const contentType = upstream.headers.get("content-type");
|
|
1214
|
+
if (contentType) {
|
|
1215
|
+
headers.set("content-type", contentType);
|
|
1216
|
+
}
|
|
1217
|
+
return new Response(text, {
|
|
1218
|
+
headers,
|
|
1219
|
+
status: upstream.status,
|
|
1220
|
+
statusText: upstream.statusText
|
|
1221
|
+
});
|
|
1222
|
+
}
|
|
1155
1223
|
async function proxyError(upstream, logger) {
|
|
1156
1224
|
const text = await upstream.text();
|
|
1157
1225
|
if (isUpstreamAuthStatus(upstream.status)) {
|
|
@@ -1210,6 +1278,15 @@ function jsonError(status, code, message) {
|
|
|
1210
1278
|
status
|
|
1211
1279
|
);
|
|
1212
1280
|
}
|
|
1281
|
+
function websocketUnsupportedResponse() {
|
|
1282
|
+
const response = jsonError(
|
|
1283
|
+
426,
|
|
1284
|
+
"websocket_not_supported",
|
|
1285
|
+
"Hoopilot does not support Responses WebSocket transport; retry with HTTP Responses API."
|
|
1286
|
+
);
|
|
1287
|
+
response.headers.set("upgrade", "websocket");
|
|
1288
|
+
return response;
|
|
1289
|
+
}
|
|
1213
1290
|
function corsHeaders() {
|
|
1214
1291
|
return {
|
|
1215
1292
|
"access-control-allow-headers": "authorization, content-type, x-api-key",
|
|
@@ -1319,6 +1396,9 @@ function routeFor(method, path) {
|
|
|
1319
1396
|
if (method === "POST" && path === "/v1/responses") {
|
|
1320
1397
|
return "responses";
|
|
1321
1398
|
}
|
|
1399
|
+
if (method === "GET" && path === "/v1/responses") {
|
|
1400
|
+
return "responses_websocket";
|
|
1401
|
+
}
|
|
1322
1402
|
return "not_found";
|
|
1323
1403
|
}
|
|
1324
1404
|
function isStreamingResponse(response) {
|
|
@@ -1361,7 +1441,9 @@ function errorDetails(error) {
|
|
|
1361
1441
|
fallbackModels,
|
|
1362
1442
|
githubCopilotDeviceLogin,
|
|
1363
1443
|
noopLogger,
|
|
1444
|
+
normalizeChatCompletionRequest,
|
|
1364
1445
|
normalizeModelsResponse,
|
|
1446
|
+
normalizeRequestedModel,
|
|
1365
1447
|
parseLogFormat,
|
|
1366
1448
|
parseLogLevel,
|
|
1367
1449
|
readStoredCopilotAuth,
|