@tnnevol/dsh-codex-auth 0.1.2-rc.1.4 → 0.1.7-rc.2
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 +19 -2
- package/compatibility.json +15 -6
- package/lib/{auth-DQlapSCa.js → auth-BQNZ__ZK.js} +15 -3
- package/lib/auth-paths.d.ts +4 -1
- package/lib/auth-paths.js +4 -1
- package/lib/auth.js +1 -1
- package/lib/client.js +2895 -2514
- package/lib/index.d.ts +14 -0
- package/lib/index.js +50 -7
- package/lib/style.css +1 -1
- package/package.json +61 -69
package/lib/index.d.ts
CHANGED
|
@@ -100,10 +100,24 @@ declare class CodexWebAuth {
|
|
|
100
100
|
private challenge;
|
|
101
101
|
private challengeWaiters;
|
|
102
102
|
private challengeTimer;
|
|
103
|
+
/** 用户点「取消」后由 `cancel()` 独占最终状态写入。 */
|
|
104
|
+
private cancelled;
|
|
103
105
|
constructor(store: CodexCredentialStore, challengeTimeoutMs?: number, mirror?: CodexCredentialMirror | undefined);
|
|
104
106
|
status(): Promise<CodexWebAuthStatus>;
|
|
105
107
|
signIn(): Promise<CodexLoginChallenge>;
|
|
106
108
|
signOut(): Promise<void>;
|
|
109
|
+
/**
|
|
110
|
+
* Stop an in-flight sign-in without touching stored credentials.
|
|
111
|
+
*
|
|
112
|
+
* 与 `signOut()` 的区别:这里只回收本次未完成的授权(中止 device-code
|
|
113
|
+
* 轮询、拒绝还在等的 challenge 请求、清掉一次性授权码),不删除已保存的
|
|
114
|
+
* 凭据。用户点「取消」时走这条路径——他们放弃的是**这次**登录,不是已经
|
|
115
|
+
* 登录的账号。
|
|
116
|
+
*
|
|
117
|
+
* 只有用户主动取消才会调用它。授权窗口自行关闭**不是**放弃信号:授权成功
|
|
118
|
+
* 后授权页会自己关闭,若据此取消就会中止正在进行的轮询并丢掉刚取得的凭据。
|
|
119
|
+
*/
|
|
120
|
+
cancel(): Promise<void>;
|
|
107
121
|
dispose(): Promise<void>;
|
|
108
122
|
private start;
|
|
109
123
|
private onEvent;
|
package/lib/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
import { CODEX_AUTH_LOGIN_PATH, CODEX_AUTH_LOGOUT_PATH, CODEX_AUTH_STATUS_PATH, CODEX_GLOBAL_MODEL_PATH, CODEX_MODEL_REFRESH_PATH, CODEX_USAGE_PATH } from "./auth-paths.js";
|
|
1
|
+
import { a as CODEX_PROVIDER, i as CodexCredentialStore, n as loginCodex, r as logoutCodex, t as codexAuthStatus } from "./auth-BQNZ__ZK.js";
|
|
2
|
+
import { CODEX_AUTH_CANCEL_PATH, CODEX_AUTH_LOGIN_PATH, CODEX_AUTH_LOGOUT_PATH, CODEX_AUTH_STATUS_PATH, CODEX_GLOBAL_MODEL_PATH, CODEX_MODEL_REFRESH_PATH, CODEX_USAGE_PATH } from "./auth-paths.js";
|
|
3
3
|
import { createModels, defaultProviderAuthContext } from "@earendil-works/pi-ai";
|
|
4
4
|
import { openaiCodexProvider } from "@earendil-works/pi-ai/providers/openai-codex";
|
|
5
5
|
import { credentialRef } from "@deepseek-ai/dsh-credentials";
|
|
@@ -332,7 +332,13 @@ async function refreshCodexModelCatalog(store, fetchImpl = fetch) {
|
|
|
332
332
|
}
|
|
333
333
|
//#endregion
|
|
334
334
|
//#region src/host/auth-routes.ts
|
|
335
|
-
|
|
335
|
+
/**
|
|
336
|
+
* 等 OpenAI 返回设备授权码(授权 URL)的上限。
|
|
337
|
+
*
|
|
338
|
+
* 拿到设备码后这个计时器就清掉了(见 `onEvent`),因此它**不**约束用户在浏览器
|
|
339
|
+
* 里完成授权的时间——那段由 pi-ai 自己的设备码轮询窗口兜底。
|
|
340
|
+
*/
|
|
341
|
+
const CODEX_AUTH_URL_TIMEOUT_MS = 12e4;
|
|
336
342
|
const REMOTE_WEB_ORIGIN_NOT_TRUSTED = "remote-web-origin-not-trusted";
|
|
337
343
|
const CODEX_USAGE_UNAVAILABLE = "codex-usage-unavailable";
|
|
338
344
|
const CODEX_GLOBAL_MODEL_INVALID = "codex-global-model-invalid";
|
|
@@ -368,6 +374,8 @@ var CodexWebAuth = class {
|
|
|
368
374
|
challenge;
|
|
369
375
|
challengeWaiters = [];
|
|
370
376
|
challengeTimer;
|
|
377
|
+
/** 用户点「取消」后由 `cancel()` 独占最终状态写入。 */
|
|
378
|
+
cancelled = false;
|
|
371
379
|
constructor(store, challengeTimeoutMs = CODEX_AUTH_URL_TIMEOUT_MS, mirror) {
|
|
372
380
|
this.store = store;
|
|
373
381
|
this.challengeTimeoutMs = challengeTimeoutMs;
|
|
@@ -396,13 +404,30 @@ var CodexWebAuth = class {
|
|
|
396
404
|
});
|
|
397
405
|
}
|
|
398
406
|
async signOut() {
|
|
399
|
-
this.
|
|
400
|
-
await this.operation?.catch(() => void 0);
|
|
407
|
+
await this.cancel();
|
|
401
408
|
await logoutCodex(this.store);
|
|
402
409
|
await this.mirror?.clear();
|
|
403
|
-
this.challenge = void 0;
|
|
404
410
|
this.state = { status: "signed-out" };
|
|
405
411
|
}
|
|
412
|
+
/**
|
|
413
|
+
* Stop an in-flight sign-in without touching stored credentials.
|
|
414
|
+
*
|
|
415
|
+
* 与 `signOut()` 的区别:这里只回收本次未完成的授权(中止 device-code
|
|
416
|
+
* 轮询、拒绝还在等的 challenge 请求、清掉一次性授权码),不删除已保存的
|
|
417
|
+
* 凭据。用户点「取消」时走这条路径——他们放弃的是**这次**登录,不是已经
|
|
418
|
+
* 登录的账号。
|
|
419
|
+
*
|
|
420
|
+
* 只有用户主动取消才会调用它。授权窗口自行关闭**不是**放弃信号:授权成功
|
|
421
|
+
* 后授权页会自己关闭,若据此取消就会中止正在进行的轮询并丢掉刚取得的凭据。
|
|
422
|
+
*/
|
|
423
|
+
async cancel() {
|
|
424
|
+
this.cancelled = true;
|
|
425
|
+
this.cancelSignIn(/* @__PURE__ */ new Error("Codex sign-in cancelled"));
|
|
426
|
+
this.challenge = void 0;
|
|
427
|
+
await this.operation?.catch(() => void 0);
|
|
428
|
+
const stored = await codexAuthStatus(this.store);
|
|
429
|
+
this.state = stored.authenticated ? signedInStatus(stored.expiresAt) : { status: "signed-out" };
|
|
430
|
+
}
|
|
406
431
|
async dispose() {
|
|
407
432
|
this.cancelSignIn(/* @__PURE__ */ new Error("Codex auth plugin disposed"));
|
|
408
433
|
await this.operation?.catch(() => void 0);
|
|
@@ -410,6 +435,7 @@ var CodexWebAuth = class {
|
|
|
410
435
|
start() {
|
|
411
436
|
const cancellation = new AbortController();
|
|
412
437
|
this.cancellation = cancellation;
|
|
438
|
+
this.cancelled = false;
|
|
413
439
|
this.challenge = void 0;
|
|
414
440
|
this.state = { status: "signing-in" };
|
|
415
441
|
this.challengeTimer = setTimeout(() => {
|
|
@@ -426,6 +452,7 @@ var CodexWebAuth = class {
|
|
|
426
452
|
this.onEvent(event);
|
|
427
453
|
}
|
|
428
454
|
}, this.store).then(async () => {
|
|
455
|
+
if (this.cancelled) return;
|
|
429
456
|
if (this.challenge === void 0) {
|
|
430
457
|
const error = /* @__PURE__ */ new Error("Codex sign-in finished without an authorization code");
|
|
431
458
|
this.rejectChallenge(error);
|
|
@@ -440,6 +467,7 @@ var CodexWebAuth = class {
|
|
|
440
467
|
this.state = stored.authenticated ? signedInStatus(stored.expiresAt) : { status: "signed-out" };
|
|
441
468
|
}, (error) => {
|
|
442
469
|
this.rejectChallenge(error);
|
|
470
|
+
if (this.cancelled) return;
|
|
443
471
|
this.state = {
|
|
444
472
|
status: "error",
|
|
445
473
|
message: safeMessage(error)
|
|
@@ -691,6 +719,20 @@ function registerCodexAuthRoutes(ctx, store, mirror) {
|
|
|
691
719
|
}
|
|
692
720
|
}
|
|
693
721
|
}),
|
|
722
|
+
ctx.webServer.register({
|
|
723
|
+
kind: "exact",
|
|
724
|
+
path: CODEX_AUTH_CANCEL_PATH,
|
|
725
|
+
handler: async (req, res) => {
|
|
726
|
+
if (req.method !== "POST") return json(res, 405, { error: "method not allowed" });
|
|
727
|
+
if (!authorize(req, res)) return;
|
|
728
|
+
try {
|
|
729
|
+
await auth.cancel();
|
|
730
|
+
json(res, 200, { ok: true });
|
|
731
|
+
} catch (error) {
|
|
732
|
+
json(res, 500, { error: safeMessage(error) });
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
}),
|
|
694
736
|
ctx.webServer.register({
|
|
695
737
|
kind: "exact",
|
|
696
738
|
path: CODEX_AUTH_LOGOUT_PATH,
|
|
@@ -823,7 +865,8 @@ function createCodexAdapter(credentials, resolveAttachments) {
|
|
|
823
865
|
requestImageMaxBytes: CODEX_REQUEST_IMAGE_MAX_BYTES,
|
|
824
866
|
retryPolicy: resolveRetryPolicy(void 0, "dsh-codex-auth-plugin retryPolicy"),
|
|
825
867
|
configuredMaxTokens: /* @__PURE__ */ new Map(),
|
|
826
|
-
piProvider: requestProvider(provider)
|
|
868
|
+
piProvider: requestProvider(provider),
|
|
869
|
+
modelErrors: /* @__PURE__ */ new Map()
|
|
827
870
|
}]]);
|
|
828
871
|
const models = createModels({ credentials });
|
|
829
872
|
models.setProvider(provider);
|