xiaodcs-copilot-api 2.3.9-public.1 → 2.3.9-public.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/README.md +37 -40
- package/README.zh-CN.md +36 -39
- package/dist/{auth-CjmmJgDK.js → auth-BiVetBYt.js} +1 -1
- package/dist/auth-Bu4MXadr.js +2 -0
- package/dist/main.js +2 -2
- package/dist/{models-CoULksS5.js → models-YMUf33c-.js} +1 -1
- package/dist/{server-BCVUMIDI.js → server-CFQmvoAJ.js} +276 -143
- package/dist/{start-CoLFu4xs.js → start-FFVCi8su.js} +4 -4
- package/dist/{token-rjUSsykd.js → token-D9svRIYW.js} +73 -453
- package/package.json +4 -3
- package/dist/auth-GVwXd8KL.js +0 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { F as ensurePaths, M as mergeConfigWithDefaults, i as listEnabledProviders } from "./config-SytZjLq8.js";
|
|
2
|
-
import {
|
|
3
|
-
import { i as runProviderSetup } from "./auth-
|
|
4
|
-
import { n as getLatestModelForFamily } from "./models-
|
|
2
|
+
import { K as state, S as initOpencodeVersion, _ as copilotModelsHeaders, h as copilotBaseUrl, i as setupCopilotToken, j as getMissingApiKeysMessage, m as readGitHubToken, q as HTTPError, t as logUser } from "./token-D9svRIYW.js";
|
|
3
|
+
import { i as runProviderSetup } from "./auth-BiVetBYt.js";
|
|
4
|
+
import { n as getLatestModelForFamily } from "./models-YMUf33c-.js";
|
|
5
5
|
import { defineCommand } from "citty";
|
|
6
6
|
import consola from "consola";
|
|
7
7
|
import { createHash, randomUUID } from "node:crypto";
|
|
@@ -466,7 +466,7 @@ async function runServer(options) {
|
|
|
466
466
|
if (githubToken) await setupCopilotMode(githubToken, Boolean(options.githubToken), serverUrl, options.claudeCode);
|
|
467
467
|
else await setupProviderMode(serverUrl, options.claudeCode);
|
|
468
468
|
consola.box(`🌐 Usage Viewer: ${serverUrl}/usage-viewer?endpoint=${serverUrl}/usage`);
|
|
469
|
-
const { server } = await import("./server-
|
|
469
|
+
const { server } = await import("./server-CFQmvoAJ.js");
|
|
470
470
|
serve({
|
|
471
471
|
fetch: server.fetch,
|
|
472
472
|
port: options.port,
|
|
@@ -260,7 +260,7 @@ const schedulePooledWebSocketIdleClose = (poolKey, entry) => {
|
|
|
260
260
|
entry.idleTimer = setTimeout(() => {
|
|
261
261
|
removePooledWebSocketEntry(poolKey, entry);
|
|
262
262
|
}, entry.poolIdleTimeoutMs);
|
|
263
|
-
unrefTimer
|
|
263
|
+
unrefTimer(entry.idleTimer);
|
|
264
264
|
};
|
|
265
265
|
const clearPooledWebSocketIdleState = (entry) => {
|
|
266
266
|
if (entry.idleTimer) {
|
|
@@ -467,7 +467,7 @@ const closeWebSocket = (websocket) => {
|
|
|
467
467
|
} catch {}
|
|
468
468
|
};
|
|
469
469
|
const getProxyUrl = (url) => getProxyForUrl(url.replace(/^wss:/u, "https:").replace(/^ws:/u, "http:"));
|
|
470
|
-
const unrefTimer
|
|
470
|
+
const unrefTimer = (timer) => {
|
|
471
471
|
if (typeof timer === "object" && "unref" in timer && typeof timer.unref === "function") timer.unref();
|
|
472
472
|
};
|
|
473
473
|
//#endregion
|
|
@@ -694,453 +694,6 @@ const toError = (value) => {
|
|
|
694
694
|
return new Error(String(value));
|
|
695
695
|
};
|
|
696
696
|
//#endregion
|
|
697
|
-
//#region src/lib/utils.ts
|
|
698
|
-
const sleep = (ms) => new Promise((resolve) => {
|
|
699
|
-
setTimeout(resolve, ms);
|
|
700
|
-
});
|
|
701
|
-
const isNullish = (value) => value === null || value === void 0;
|
|
702
|
-
const isAsyncIterable = (value) => Boolean(value) && typeof value[Symbol.asyncIterator] === "function";
|
|
703
|
-
const isResponsesStream = (value) => isAsyncIterable(value);
|
|
704
|
-
const isRecord = (value) => typeof value === "object" && value !== null;
|
|
705
|
-
const getUserIdJsonField = (userIdPayload, field) => {
|
|
706
|
-
const value = userIdPayload?.[field];
|
|
707
|
-
return typeof value === "string" && value.length > 0 ? value : null;
|
|
708
|
-
};
|
|
709
|
-
const parseJsonUserId = (userId) => {
|
|
710
|
-
try {
|
|
711
|
-
const parsed = JSON.parse(userId);
|
|
712
|
-
return isRecord(parsed) ? parsed : null;
|
|
713
|
-
} catch {
|
|
714
|
-
return null;
|
|
715
|
-
}
|
|
716
|
-
};
|
|
717
|
-
const parseUserIdMetadata = (userId) => {
|
|
718
|
-
if (!userId || typeof userId !== "string") return {
|
|
719
|
-
safetyIdentifier: null,
|
|
720
|
-
sessionId: null
|
|
721
|
-
};
|
|
722
|
-
const legacySafetyIdentifier = userId.match(/user_([^_]+)_account/)?.[1] ?? null;
|
|
723
|
-
const legacySessionId = userId.match(/_session_(.+)$/)?.[1] ?? null;
|
|
724
|
-
const parsedUserId = legacySafetyIdentifier && legacySessionId ? null : parseJsonUserId(userId);
|
|
725
|
-
return {
|
|
726
|
-
safetyIdentifier: legacySafetyIdentifier ?? getUserIdJsonField(parsedUserId, "device_id") ?? getUserIdJsonField(parsedUserId, "account_uuid"),
|
|
727
|
-
sessionId: legacySessionId ?? getUserIdJsonField(parsedUserId, "session_id")
|
|
728
|
-
};
|
|
729
|
-
};
|
|
730
|
-
const findLastUserContent = (messages) => {
|
|
731
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
732
|
-
const msg = messages[i];
|
|
733
|
-
if (msg.role === "user" && msg.content) {
|
|
734
|
-
if (typeof msg.content === "string") return msg.content;
|
|
735
|
-
else if (Array.isArray(msg.content)) {
|
|
736
|
-
const array = msg.content.filter((n) => n.type !== "tool_result").map((n) => ({
|
|
737
|
-
...n,
|
|
738
|
-
cache_control: void 0
|
|
739
|
-
}));
|
|
740
|
-
if (array.length > 0) return JSON.stringify(array);
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
return null;
|
|
745
|
-
};
|
|
746
|
-
const generateRequestIdFromPayload = (payload, sessionId) => {
|
|
747
|
-
const messages = payload.messages;
|
|
748
|
-
if (messages) {
|
|
749
|
-
const lastUserContent = typeof messages === "string" ? messages : findLastUserContent(messages);
|
|
750
|
-
if (lastUserContent) return getUUID((sessionId ?? "") + (state.macMachineId ?? "") + lastUserContent);
|
|
751
|
-
}
|
|
752
|
-
return randomUUID();
|
|
753
|
-
};
|
|
754
|
-
const getRootSessionId = (anthropicPayload, c) => {
|
|
755
|
-
const userId = anthropicPayload.metadata?.user_id;
|
|
756
|
-
const sessionId = userId ? parseUserIdMetadata(userId).sessionId || void 0 : c.req.header("x-session-id");
|
|
757
|
-
return sessionId ? getUUID(sessionId) : sessionId;
|
|
758
|
-
};
|
|
759
|
-
const getUUID = (content) => {
|
|
760
|
-
const uuidBytes = createHash("sha256").update(content).digest().subarray(0, 16);
|
|
761
|
-
uuidBytes[6] = uuidBytes[6] & 15 | 64;
|
|
762
|
-
uuidBytes[8] = uuidBytes[8] & 63 | 128;
|
|
763
|
-
const uuidHex = uuidBytes.toString("hex");
|
|
764
|
-
return `${uuidHex.slice(0, 8)}-${uuidHex.slice(8, 12)}-${uuidHex.slice(12, 16)}-${uuidHex.slice(16, 20)}-${uuidHex.slice(20)}`;
|
|
765
|
-
};
|
|
766
|
-
//#endregion
|
|
767
|
-
//#region src/services/model-traffic-control.ts
|
|
768
|
-
const PUBLIC_MODEL_TRAFFIC_POLICY = {
|
|
769
|
-
failureRate: .05,
|
|
770
|
-
jitterMaxMs: 900,
|
|
771
|
-
jitterMinMs: 300,
|
|
772
|
-
maxConcurrent: 4,
|
|
773
|
-
maxQueueSize: 16,
|
|
774
|
-
queueTimeoutMs: 45e3,
|
|
775
|
-
requestsPerMinute: 20,
|
|
776
|
-
requestsPerSecond: 1
|
|
777
|
-
};
|
|
778
|
-
const TEST_MODEL_TRAFFIC_POLICY = {
|
|
779
|
-
failureRate: 0,
|
|
780
|
-
jitterMaxMs: 0,
|
|
781
|
-
jitterMinMs: 0,
|
|
782
|
-
maxConcurrent: 1e3,
|
|
783
|
-
maxQueueSize: 1e4,
|
|
784
|
-
queueTimeoutMs: 6e4,
|
|
785
|
-
requestsPerMinute: 1e5,
|
|
786
|
-
requestsPerSecond: 1e3
|
|
787
|
-
};
|
|
788
|
-
const RATE_LIMIT_STATUS = 429;
|
|
789
|
-
const DEFAULT_RETRY_AFTER_SECONDS = 5;
|
|
790
|
-
const RESULT_START_TIMEOUT_MS = 3e4;
|
|
791
|
-
const SECOND_WINDOW_MS = 1e3;
|
|
792
|
-
const MINUTE_WINDOW_MS = 6e4;
|
|
793
|
-
var ModelTrafficController = class {
|
|
794
|
-
#minuteWindowMs;
|
|
795
|
-
#now;
|
|
796
|
-
#policy;
|
|
797
|
-
#random;
|
|
798
|
-
#secondWindowMs;
|
|
799
|
-
#active = 0;
|
|
800
|
-
#pumpTimer = null;
|
|
801
|
-
#queue = [];
|
|
802
|
-
#startTimes = [];
|
|
803
|
-
constructor(policy, options = {}) {
|
|
804
|
-
validatePolicy(policy);
|
|
805
|
-
this.#policy = policy;
|
|
806
|
-
this.#minuteWindowMs = options.minuteWindowMs ?? MINUTE_WINDOW_MS;
|
|
807
|
-
this.#now = options.now ?? Date.now;
|
|
808
|
-
this.#random = options.random ?? Math.random;
|
|
809
|
-
this.#secondWindowMs = options.secondWindowMs ?? SECOND_WINDOW_MS;
|
|
810
|
-
}
|
|
811
|
-
acquire(signal) {
|
|
812
|
-
if (signal?.aborted) return Promise.reject(toAbortError(signal.reason));
|
|
813
|
-
if (this.#queue.length >= this.#policy.maxQueueSize) return Promise.reject(createTrafficControlError("The public request queue is full. Retry later.", "queue-full"));
|
|
814
|
-
return new Promise((resolve, reject) => {
|
|
815
|
-
const entry = {
|
|
816
|
-
readyAt: this.#now() + this.#randomJitterMs(),
|
|
817
|
-
reject,
|
|
818
|
-
resolve,
|
|
819
|
-
settled: false,
|
|
820
|
-
signal
|
|
821
|
-
};
|
|
822
|
-
entry.timeout = setTimeout(() => {
|
|
823
|
-
if (entry.settled) return;
|
|
824
|
-
entry.settled = true;
|
|
825
|
-
this.#removeEntry(entry);
|
|
826
|
-
this.#cleanupQueuedEntry(entry);
|
|
827
|
-
reject(createTrafficControlError("The public request waited too long for capacity. Retry later.", "queue-timeout"));
|
|
828
|
-
this.#pump();
|
|
829
|
-
}, this.#policy.queueTimeoutMs);
|
|
830
|
-
if (signal) {
|
|
831
|
-
entry.abortHandler = () => {
|
|
832
|
-
if (entry.settled) return;
|
|
833
|
-
entry.settled = true;
|
|
834
|
-
this.#removeEntry(entry);
|
|
835
|
-
this.#cleanupQueuedEntry(entry);
|
|
836
|
-
reject(toAbortError(signal.reason));
|
|
837
|
-
this.#pump();
|
|
838
|
-
};
|
|
839
|
-
signal.addEventListener("abort", entry.abortHandler, { once: true });
|
|
840
|
-
}
|
|
841
|
-
this.#queue.push(entry);
|
|
842
|
-
this.#pump();
|
|
843
|
-
});
|
|
844
|
-
}
|
|
845
|
-
snapshot() {
|
|
846
|
-
this.#pruneStartTimes(this.#now());
|
|
847
|
-
return {
|
|
848
|
-
active: this.#active,
|
|
849
|
-
queued: this.#queue.length,
|
|
850
|
-
recentStarts: this.#startTimes.length
|
|
851
|
-
};
|
|
852
|
-
}
|
|
853
|
-
#cleanupQueuedEntry(entry) {
|
|
854
|
-
if (entry.timeout) clearTimeout(entry.timeout);
|
|
855
|
-
if (entry.signal && entry.abortHandler) entry.signal.removeEventListener("abort", entry.abortHandler);
|
|
856
|
-
}
|
|
857
|
-
#createLease() {
|
|
858
|
-
let released = false;
|
|
859
|
-
const release = () => {
|
|
860
|
-
if (released) return;
|
|
861
|
-
released = true;
|
|
862
|
-
this.#active = Math.max(0, this.#active - 1);
|
|
863
|
-
this.#pump();
|
|
864
|
-
};
|
|
865
|
-
return { release };
|
|
866
|
-
}
|
|
867
|
-
#nextRateDelayMs(now) {
|
|
868
|
-
this.#pruneStartTimes(now);
|
|
869
|
-
const secondDelay = getWindowDelay(this.#startTimes.filter((startedAt) => now - startedAt < this.#secondWindowMs), this.#policy.requestsPerSecond, this.#secondWindowMs, now);
|
|
870
|
-
const minuteDelay = getWindowDelay(this.#startTimes, this.#policy.requestsPerMinute, this.#minuteWindowMs, now);
|
|
871
|
-
return Math.max(secondDelay, minuteDelay);
|
|
872
|
-
}
|
|
873
|
-
#pruneStartTimes(now) {
|
|
874
|
-
this.#startTimes = this.#startTimes.filter((startedAt) => now - startedAt < this.#minuteWindowMs);
|
|
875
|
-
}
|
|
876
|
-
#pump() {
|
|
877
|
-
if (this.#pumpTimer || this.#active >= this.#policy.maxConcurrent) return;
|
|
878
|
-
const entry = this.#queue[0];
|
|
879
|
-
if (!entry) return;
|
|
880
|
-
if (entry.settled) {
|
|
881
|
-
this.#queue.shift();
|
|
882
|
-
this.#pump();
|
|
883
|
-
return;
|
|
884
|
-
}
|
|
885
|
-
const now = this.#now();
|
|
886
|
-
const delayMs = Math.max(0, entry.readyAt - now, this.#nextRateDelayMs(now));
|
|
887
|
-
if (delayMs > 0) {
|
|
888
|
-
this.#pumpTimer = setTimeout(() => {
|
|
889
|
-
this.#pumpTimer = null;
|
|
890
|
-
this.#pump();
|
|
891
|
-
}, Math.ceil(delayMs));
|
|
892
|
-
return;
|
|
893
|
-
}
|
|
894
|
-
this.#queue.shift();
|
|
895
|
-
entry.settled = true;
|
|
896
|
-
this.#cleanupQueuedEntry(entry);
|
|
897
|
-
this.#startTimes.push(now);
|
|
898
|
-
if (this.#random() < this.#policy.failureRate) {
|
|
899
|
-
entry.reject(createTrafficControlError("Public capacity is temporarily unavailable. Retry later.", "load-shed"));
|
|
900
|
-
queueMicrotask(() => this.#pump());
|
|
901
|
-
return;
|
|
902
|
-
}
|
|
903
|
-
this.#active += 1;
|
|
904
|
-
entry.resolve(this.#createLease());
|
|
905
|
-
queueMicrotask(() => this.#pump());
|
|
906
|
-
}
|
|
907
|
-
#randomJitterMs() {
|
|
908
|
-
const { jitterMaxMs, jitterMinMs } = this.#policy;
|
|
909
|
-
if (jitterMaxMs <= jitterMinMs) return jitterMinMs;
|
|
910
|
-
return jitterMinMs + Math.floor(this.#random() * (jitterMaxMs - jitterMinMs + 1));
|
|
911
|
-
}
|
|
912
|
-
#removeEntry(entry) {
|
|
913
|
-
const index = this.#queue.indexOf(entry);
|
|
914
|
-
if (index < 0) return;
|
|
915
|
-
this.#queue.splice(index, 1);
|
|
916
|
-
if (index === 0 && this.#pumpTimer) {
|
|
917
|
-
clearTimeout(this.#pumpTimer);
|
|
918
|
-
this.#pumpTimer = null;
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
};
|
|
922
|
-
const getWindowDelay = (starts, limit, windowMs, now) => {
|
|
923
|
-
if (starts.length < limit) return 0;
|
|
924
|
-
const oldestRelevantStart = starts[starts.length - limit];
|
|
925
|
-
return Math.max(0, oldestRelevantStart + windowMs - now);
|
|
926
|
-
};
|
|
927
|
-
const validatePolicy = (policy) => {
|
|
928
|
-
for (const field of [
|
|
929
|
-
"maxConcurrent",
|
|
930
|
-
"maxQueueSize",
|
|
931
|
-
"queueTimeoutMs",
|
|
932
|
-
"requestsPerMinute",
|
|
933
|
-
"requestsPerSecond"
|
|
934
|
-
]) if (!Number.isInteger(policy[field]) || policy[field] <= 0) throw new TypeError(`${field} must be a positive integer`);
|
|
935
|
-
if (!Number.isInteger(policy.jitterMinMs) || !Number.isInteger(policy.jitterMaxMs) || policy.jitterMinMs < 0 || policy.jitterMaxMs < policy.jitterMinMs) throw new TypeError("jitter bounds must be non-negative integers");
|
|
936
|
-
if (!Number.isFinite(policy.failureRate) || policy.failureRate < 0 || policy.failureRate > 1) throw new TypeError("failureRate must be between 0 and 1");
|
|
937
|
-
};
|
|
938
|
-
const createTrafficControlError = (message, reason) => new HTTPError(message, new Response(message, {
|
|
939
|
-
headers: {
|
|
940
|
-
"content-type": "text/plain; charset=utf-8",
|
|
941
|
-
"retry-after": String(DEFAULT_RETRY_AFTER_SECONDS),
|
|
942
|
-
"x-copilot-api-rejection": reason
|
|
943
|
-
},
|
|
944
|
-
status: RATE_LIMIT_STATUS
|
|
945
|
-
}));
|
|
946
|
-
const toAbortError = (reason) => {
|
|
947
|
-
if (reason instanceof Error) return reason;
|
|
948
|
-
const error = /* @__PURE__ */ new Error("The request was aborted before admission");
|
|
949
|
-
error.name = "AbortError";
|
|
950
|
-
return error;
|
|
951
|
-
};
|
|
952
|
-
const isSourceTestRuntime = process.env.NODE_ENV === "test" && import.meta.url.endsWith("/src/services/model-traffic-control.ts");
|
|
953
|
-
const modelTrafficController = new ModelTrafficController(isSourceTestRuntime ? TEST_MODEL_TRAFFIC_POLICY : PUBLIC_MODEL_TRAFFIC_POLICY);
|
|
954
|
-
let policyLogged = false;
|
|
955
|
-
async function withModelTrafficControl(operation, signal) {
|
|
956
|
-
if (!policyLogged && !isSourceTestRuntime) {
|
|
957
|
-
policyLogged = true;
|
|
958
|
-
consola.info(`Public traffic policy active: max ${PUBLIC_MODEL_TRAFFIC_POLICY.maxConcurrent} concurrent, ${PUBLIC_MODEL_TRAFFIC_POLICY.requestsPerSecond} QPS, ${PUBLIC_MODEL_TRAFFIC_POLICY.requestsPerMinute} QPM`);
|
|
959
|
-
}
|
|
960
|
-
return await withTrafficController(modelTrafficController, operation, signal);
|
|
961
|
-
}
|
|
962
|
-
async function withTrafficController(controller, operation, signal, options = {}) {
|
|
963
|
-
const lease = await controller.acquire(signal);
|
|
964
|
-
try {
|
|
965
|
-
if (signal?.aborted) throw toAbortError(signal.reason);
|
|
966
|
-
const result = await operation();
|
|
967
|
-
if (isAsyncIterable(result)) return releaseWhenIterableEnds(result, lease, signal, options);
|
|
968
|
-
if (isResponseLike(result)) return releaseWhenResponseEnds(result, lease, signal, options);
|
|
969
|
-
lease.release();
|
|
970
|
-
return result;
|
|
971
|
-
} catch (error) {
|
|
972
|
-
lease.release();
|
|
973
|
-
throw error;
|
|
974
|
-
}
|
|
975
|
-
}
|
|
976
|
-
const releaseWhenIterableEnds = (source, lease, signal, options = {}) => {
|
|
977
|
-
const iterator = source[Symbol.asyncIterator]();
|
|
978
|
-
let finished = false;
|
|
979
|
-
let started = false;
|
|
980
|
-
let terminalError = null;
|
|
981
|
-
const finish = async (closeSource) => {
|
|
982
|
-
if (finished) return;
|
|
983
|
-
finished = true;
|
|
984
|
-
clearTimeout(startTimeout);
|
|
985
|
-
signal?.removeEventListener("abort", abort);
|
|
986
|
-
try {
|
|
987
|
-
if (closeSource) await iterator.return?.();
|
|
988
|
-
} finally {
|
|
989
|
-
lease.release();
|
|
990
|
-
}
|
|
991
|
-
};
|
|
992
|
-
const expire = (error) => {
|
|
993
|
-
if (finished) return;
|
|
994
|
-
terminalError = error;
|
|
995
|
-
finish(true).catch(() => {});
|
|
996
|
-
};
|
|
997
|
-
const startTimeout = setTimeout(() => {
|
|
998
|
-
if (started) return;
|
|
999
|
-
expire(/* @__PURE__ */ new Error("Model response stream was not consumed before the start deadline"));
|
|
1000
|
-
}, options.resultStartTimeoutMs ?? RESULT_START_TIMEOUT_MS);
|
|
1001
|
-
unrefTimer(startTimeout);
|
|
1002
|
-
const abort = () => expire(toAbortError(signal?.reason));
|
|
1003
|
-
signal?.addEventListener("abort", abort, { once: true });
|
|
1004
|
-
if (signal?.aborted) abort();
|
|
1005
|
-
const start = () => {
|
|
1006
|
-
if (!started) {
|
|
1007
|
-
started = true;
|
|
1008
|
-
clearTimeout(startTimeout);
|
|
1009
|
-
}
|
|
1010
|
-
if (terminalError) throw terminalError;
|
|
1011
|
-
};
|
|
1012
|
-
const wrapped = {
|
|
1013
|
-
[Symbol.asyncIterator]: () => wrapped,
|
|
1014
|
-
async next() {
|
|
1015
|
-
start();
|
|
1016
|
-
if (finished) return {
|
|
1017
|
-
done: true,
|
|
1018
|
-
value: void 0
|
|
1019
|
-
};
|
|
1020
|
-
try {
|
|
1021
|
-
const result = await iterator.next();
|
|
1022
|
-
if (result.done) await finish(false);
|
|
1023
|
-
return result;
|
|
1024
|
-
} catch (error) {
|
|
1025
|
-
await finish(true);
|
|
1026
|
-
throw error;
|
|
1027
|
-
}
|
|
1028
|
-
},
|
|
1029
|
-
async return() {
|
|
1030
|
-
started = true;
|
|
1031
|
-
clearTimeout(startTimeout);
|
|
1032
|
-
await finish(true);
|
|
1033
|
-
return {
|
|
1034
|
-
done: true,
|
|
1035
|
-
value: void 0
|
|
1036
|
-
};
|
|
1037
|
-
},
|
|
1038
|
-
async throw(error) {
|
|
1039
|
-
start();
|
|
1040
|
-
if (!iterator.throw) {
|
|
1041
|
-
await finish(true);
|
|
1042
|
-
throw error;
|
|
1043
|
-
}
|
|
1044
|
-
try {
|
|
1045
|
-
const result = await iterator.throw(error);
|
|
1046
|
-
if (result.done) await finish(false);
|
|
1047
|
-
return result;
|
|
1048
|
-
} catch (thrown) {
|
|
1049
|
-
await finish(true);
|
|
1050
|
-
throw thrown;
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
};
|
|
1054
|
-
return wrapped;
|
|
1055
|
-
};
|
|
1056
|
-
const isResponseLike = (value) => {
|
|
1057
|
-
if (typeof value !== "object" || value === null) return false;
|
|
1058
|
-
const candidate = value;
|
|
1059
|
-
return typeof candidate.status === "number" && typeof candidate.statusText === "string" && candidate.headers !== void 0 && (candidate.body === null || typeof candidate.body === "object" && candidate.body !== null && "getReader" in candidate.body && typeof candidate.body.getReader === "function");
|
|
1060
|
-
};
|
|
1061
|
-
const releaseWhenResponseEnds = (response, lease, signal, options = {}) => {
|
|
1062
|
-
if (!response.body) {
|
|
1063
|
-
lease.release();
|
|
1064
|
-
return new Response(null, {
|
|
1065
|
-
headers: new Headers(response.headers),
|
|
1066
|
-
status: response.status,
|
|
1067
|
-
statusText: response.statusText
|
|
1068
|
-
});
|
|
1069
|
-
}
|
|
1070
|
-
const reader = response.body.getReader();
|
|
1071
|
-
let finished = false;
|
|
1072
|
-
let started = false;
|
|
1073
|
-
let terminalError = null;
|
|
1074
|
-
let readerReleased = false;
|
|
1075
|
-
const releaseReader = () => {
|
|
1076
|
-
if (readerReleased) return;
|
|
1077
|
-
readerReleased = true;
|
|
1078
|
-
reader.releaseLock();
|
|
1079
|
-
};
|
|
1080
|
-
const finish = async (cancelSource, reason) => {
|
|
1081
|
-
if (finished) return;
|
|
1082
|
-
finished = true;
|
|
1083
|
-
clearTimeout(startTimeout);
|
|
1084
|
-
signal?.removeEventListener("abort", abort);
|
|
1085
|
-
try {
|
|
1086
|
-
if (cancelSource) await reader.cancel(reason);
|
|
1087
|
-
} finally {
|
|
1088
|
-
releaseReader();
|
|
1089
|
-
lease.release();
|
|
1090
|
-
}
|
|
1091
|
-
};
|
|
1092
|
-
const expire = (error) => {
|
|
1093
|
-
if (finished) return;
|
|
1094
|
-
terminalError = error;
|
|
1095
|
-
finish(true, error).catch(() => {});
|
|
1096
|
-
};
|
|
1097
|
-
const startTimeout = setTimeout(() => {
|
|
1098
|
-
if (started) return;
|
|
1099
|
-
expire(/* @__PURE__ */ new Error("Model response body was not consumed before the start deadline"));
|
|
1100
|
-
}, options.resultStartTimeoutMs ?? RESULT_START_TIMEOUT_MS);
|
|
1101
|
-
unrefTimer(startTimeout);
|
|
1102
|
-
const abort = () => expire(toAbortError(signal?.reason));
|
|
1103
|
-
signal?.addEventListener("abort", abort, { once: true });
|
|
1104
|
-
if (signal?.aborted) abort();
|
|
1105
|
-
const start = () => {
|
|
1106
|
-
if (!started) {
|
|
1107
|
-
started = true;
|
|
1108
|
-
clearTimeout(startTimeout);
|
|
1109
|
-
}
|
|
1110
|
-
if (terminalError) throw terminalError;
|
|
1111
|
-
};
|
|
1112
|
-
const body = new ReadableStream({
|
|
1113
|
-
async pull(controller) {
|
|
1114
|
-
try {
|
|
1115
|
-
start();
|
|
1116
|
-
const result = await reader.read();
|
|
1117
|
-
if (result.done || result.value === void 0) {
|
|
1118
|
-
await finish(false);
|
|
1119
|
-
controller.close();
|
|
1120
|
-
return;
|
|
1121
|
-
}
|
|
1122
|
-
controller.enqueue(result.value);
|
|
1123
|
-
} catch (error) {
|
|
1124
|
-
await finish(false);
|
|
1125
|
-
controller.error(error);
|
|
1126
|
-
}
|
|
1127
|
-
},
|
|
1128
|
-
async cancel(reason) {
|
|
1129
|
-
started = true;
|
|
1130
|
-
clearTimeout(startTimeout);
|
|
1131
|
-
await finish(true, reason);
|
|
1132
|
-
}
|
|
1133
|
-
}, { highWaterMark: 0 });
|
|
1134
|
-
return new Response(body, {
|
|
1135
|
-
headers: new Headers(response.headers),
|
|
1136
|
-
status: response.status,
|
|
1137
|
-
statusText: response.statusText
|
|
1138
|
-
});
|
|
1139
|
-
};
|
|
1140
|
-
const unrefTimer = (timer) => {
|
|
1141
|
-
timer.unref?.();
|
|
1142
|
-
};
|
|
1143
|
-
//#endregion
|
|
1144
697
|
//#region src/lib/request-context.ts
|
|
1145
698
|
const TRACE_ID_MAX_LENGTH = 64;
|
|
1146
699
|
const TRACE_ID_PATTERN = /^\w[\w.-]*$/;
|
|
@@ -1262,9 +815,6 @@ function prepareCodexResponsesWebSocketRequest(payload, requestHeaders, baseUrl
|
|
|
1262
815
|
};
|
|
1263
816
|
}
|
|
1264
817
|
async function forwardCodexResponses(payload, requestHeaders, baseUrl = CODEX_API_BASE_URL, options = {}) {
|
|
1265
|
-
return await withModelTrafficControl(() => forwardCodexResponsesUpstream(payload, requestHeaders, baseUrl, options), options.signal);
|
|
1266
|
-
}
|
|
1267
|
-
async function forwardCodexResponsesUpstream(payload, requestHeaders, baseUrl, options) {
|
|
1268
818
|
consola.log(`<-- model: ${payload.model}`);
|
|
1269
819
|
const transport = resolveCodexResponsesTransport(options.transport);
|
|
1270
820
|
if (payload.stream && transport === "websocket") return forwardCodexResponsesOverWebSocket(payload, requestHeaders, baseUrl, options.signal);
|
|
@@ -2102,6 +1652,76 @@ async function getDeviceCode() {
|
|
|
2102
1652
|
return await response.json();
|
|
2103
1653
|
}
|
|
2104
1654
|
//#endregion
|
|
1655
|
+
//#region src/lib/utils.ts
|
|
1656
|
+
const sleep = (ms) => new Promise((resolve) => {
|
|
1657
|
+
setTimeout(resolve, ms);
|
|
1658
|
+
});
|
|
1659
|
+
const isNullish = (value) => value === null || value === void 0;
|
|
1660
|
+
const isAsyncIterable = (value) => Boolean(value) && typeof value[Symbol.asyncIterator] === "function";
|
|
1661
|
+
const isResponsesStream = (value) => isAsyncIterable(value);
|
|
1662
|
+
const isRecord = (value) => typeof value === "object" && value !== null;
|
|
1663
|
+
const getUserIdJsonField = (userIdPayload, field) => {
|
|
1664
|
+
const value = userIdPayload?.[field];
|
|
1665
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
1666
|
+
};
|
|
1667
|
+
const parseJsonUserId = (userId) => {
|
|
1668
|
+
try {
|
|
1669
|
+
const parsed = JSON.parse(userId);
|
|
1670
|
+
return isRecord(parsed) ? parsed : null;
|
|
1671
|
+
} catch {
|
|
1672
|
+
return null;
|
|
1673
|
+
}
|
|
1674
|
+
};
|
|
1675
|
+
const parseUserIdMetadata = (userId) => {
|
|
1676
|
+
if (!userId || typeof userId !== "string") return {
|
|
1677
|
+
safetyIdentifier: null,
|
|
1678
|
+
sessionId: null
|
|
1679
|
+
};
|
|
1680
|
+
const legacySafetyIdentifier = userId.match(/user_([^_]+)_account/)?.[1] ?? null;
|
|
1681
|
+
const legacySessionId = userId.match(/_session_(.+)$/)?.[1] ?? null;
|
|
1682
|
+
const parsedUserId = legacySafetyIdentifier && legacySessionId ? null : parseJsonUserId(userId);
|
|
1683
|
+
return {
|
|
1684
|
+
safetyIdentifier: legacySafetyIdentifier ?? getUserIdJsonField(parsedUserId, "device_id") ?? getUserIdJsonField(parsedUserId, "account_uuid"),
|
|
1685
|
+
sessionId: legacySessionId ?? getUserIdJsonField(parsedUserId, "session_id")
|
|
1686
|
+
};
|
|
1687
|
+
};
|
|
1688
|
+
const findLastUserContent = (messages) => {
|
|
1689
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
1690
|
+
const msg = messages[i];
|
|
1691
|
+
if (msg.role === "user" && msg.content) {
|
|
1692
|
+
if (typeof msg.content === "string") return msg.content;
|
|
1693
|
+
else if (Array.isArray(msg.content)) {
|
|
1694
|
+
const array = msg.content.filter((n) => n.type !== "tool_result").map((n) => ({
|
|
1695
|
+
...n,
|
|
1696
|
+
cache_control: void 0
|
|
1697
|
+
}));
|
|
1698
|
+
if (array.length > 0) return JSON.stringify(array);
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
return null;
|
|
1703
|
+
};
|
|
1704
|
+
const generateRequestIdFromPayload = (payload, sessionId) => {
|
|
1705
|
+
const messages = payload.messages;
|
|
1706
|
+
if (messages) {
|
|
1707
|
+
const lastUserContent = typeof messages === "string" ? messages : findLastUserContent(messages);
|
|
1708
|
+
if (lastUserContent) return getUUID((sessionId ?? "") + (state.macMachineId ?? "") + lastUserContent);
|
|
1709
|
+
}
|
|
1710
|
+
return randomUUID();
|
|
1711
|
+
};
|
|
1712
|
+
const getRootSessionId = (anthropicPayload, c) => {
|
|
1713
|
+
const userId = anthropicPayload.metadata?.user_id;
|
|
1714
|
+
const sessionId = userId ? parseUserIdMetadata(userId).sessionId || void 0 : c.req.header("x-session-id");
|
|
1715
|
+
return sessionId ? getUUID(sessionId) : sessionId;
|
|
1716
|
+
};
|
|
1717
|
+
const getUUID = (content) => {
|
|
1718
|
+
const uuidBytes = createHash("sha256").update(content).digest().subarray(0, 16);
|
|
1719
|
+
uuidBytes[6] = uuidBytes[6] & 15 | 64;
|
|
1720
|
+
uuidBytes[8] = uuidBytes[8] & 63 | 128;
|
|
1721
|
+
const uuidHex = uuidBytes.toString("hex");
|
|
1722
|
+
return `${uuidHex.slice(0, 8)}-${uuidHex.slice(8, 12)}-${uuidHex.slice(12, 16)}-${uuidHex.slice(16, 20)}-${uuidHex.slice(20)}`;
|
|
1723
|
+
};
|
|
1724
|
+
//#endregion
|
|
2105
1725
|
//#region src/services/github/poll-access-token.ts
|
|
2106
1726
|
async function pollAccessToken(deviceCode) {
|
|
2107
1727
|
const { clientId, headers } = getOauthAppConfig();
|
|
@@ -2327,4 +1947,4 @@ async function logUser() {
|
|
|
2327
1947
|
state.tokenBasedBilling = copilotUser.token_based_billing;
|
|
2328
1948
|
}
|
|
2329
1949
|
//#endregion
|
|
2330
|
-
export {
|
|
1950
|
+
export { getConfiguredApiKeys as A, fetchResponsesWithLifecycle as B, compactAutoContinuePromptStarts as C, compactTextOnlyGuard as D, compactSystemPromptStarts as E, forwardCodexResponses as F, createWebSocketUrl as G, encodePoolKeyPart as H, generateTraceId as I, forwardError as J, state as K, requestContext as L, loginCodex as M, CODEX_API_BASE_URL as N, createAuthMiddleware as O, buildCodexRequestHeaders as P, resolveTraceId as R, initOpencodeVersion as S, compactSummaryPromptStart as T, isTerminalResponsesStreamChunk as U, createResponsesSafeStream as V, createPooledWebSocketStream as W, copilotModelsHeaders as _, setupGitHubToken as a, prepareInteractionHeaders as b, getUUID as c, isResponsesStream as d, parseUserIdMetadata as f, copilotHeaders as g, copilotBaseUrl as h, setupCopilotToken as i, getMissingApiKeysMessage as j, getConfiguredAdminApiKeys as k, isAsyncIterable as l, readGitHubToken as m, persistCodexCredentials as n, generateRequestIdFromPayload as o, getCopilotUsage as p, HTTPError as q, setupCodexToken as r, getRootSessionId as s, logUser as t, isNullish as u, copilotWebSocketHeaders as v, compactMessageSections as w, prepareMessageProxyHeaders as x, prepareForCompact as y, createResponsesHttpEventStream as z };
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "xiaodcs-copilot-api",
|
|
4
|
-
"version": "2.3.9-public.
|
|
5
|
-
"description": "XiaoDcs
|
|
4
|
+
"version": "2.3.9-public.3",
|
|
5
|
+
"description": "XiaoDcs copilot-api package built from the same Edge source with Responses recovery and Codex integrations.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"github-copilot",
|
|
8
8
|
"codex",
|
|
@@ -92,5 +92,6 @@
|
|
|
92
92
|
},
|
|
93
93
|
"engines": {
|
|
94
94
|
"node": ">=20"
|
|
95
|
-
}
|
|
95
|
+
},
|
|
96
|
+
"gitHead": "ea1d517754230221b0984334920ee45b4f3d2127"
|
|
96
97
|
}
|
package/dist/auth-GVwXd8KL.js
DELETED