codex-imagegen-mcp 0.1.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/CHANGELOG.md +96 -0
- package/LICENSE +201 -0
- package/NOTICE +19 -0
- package/README.md +373 -0
- package/dist/src/auth/borrowed.js +77 -0
- package/dist/src/auth/borrowed.js.map +1 -0
- package/dist/src/auth/browser-login.js +179 -0
- package/dist/src/auth/browser-login.js.map +1 -0
- package/dist/src/auth/device-login.js +39 -0
- package/dist/src/auth/device-login.js.map +1 -0
- package/dist/src/auth/jwt.js +69 -0
- package/dist/src/auth/jwt.js.map +1 -0
- package/dist/src/auth/manager.js +289 -0
- package/dist/src/auth/manager.js.map +1 -0
- package/dist/src/auth/oauth.js +246 -0
- package/dist/src/auth/oauth.js.map +1 -0
- package/dist/src/auth/pages.js +39 -0
- package/dist/src/auth/pages.js.map +1 -0
- package/dist/src/auth/pkce.js +14 -0
- package/dist/src/auth/pkce.js.map +1 -0
- package/dist/src/auth/store.js +75 -0
- package/dist/src/auth/store.js.map +1 -0
- package/dist/src/backend/images-client.js +223 -0
- package/dist/src/backend/images-client.js.map +1 -0
- package/dist/src/backend/ratelimits.js +183 -0
- package/dist/src/backend/ratelimits.js.map +1 -0
- package/dist/src/cli.js +407 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/config.js +87 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/constants.js +52 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/doctor.js +122 -0
- package/dist/src/doctor.js.map +1 -0
- package/dist/src/errors.js +76 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/generation.js +183 -0
- package/dist/src/generation.js.map +1 -0
- package/dist/src/history.js +47 -0
- package/dist/src/history.js.map +1 -0
- package/dist/src/images/chroma.js +200 -0
- package/dist/src/images/chroma.js.map +1 -0
- package/dist/src/images/codec.js +159 -0
- package/dist/src/images/codec.js.map +1 -0
- package/dist/src/images/inputs.js +83 -0
- package/dist/src/images/inputs.js.map +1 -0
- package/dist/src/images/output.js +100 -0
- package/dist/src/images/output.js.map +1 -0
- package/dist/src/images/preview.js +20 -0
- package/dist/src/images/preview.js.map +1 -0
- package/dist/src/images/resize.js +135 -0
- package/dist/src/images/resize.js.map +1 -0
- package/dist/src/install/opencode.js +138 -0
- package/dist/src/install/opencode.js.map +1 -0
- package/dist/src/install/skill.js +128 -0
- package/dist/src/install/skill.js.map +1 -0
- package/dist/src/install/snippets.js +127 -0
- package/dist/src/install/snippets.js.map +1 -0
- package/dist/src/log.js +58 -0
- package/dist/src/log.js.map +1 -0
- package/dist/src/remove-background.js +101 -0
- package/dist/src/remove-background.js.map +1 -0
- package/dist/src/server/context.js +2 -0
- package/dist/src/server/context.js.map +1 -0
- package/dist/src/server/index.js +94 -0
- package/dist/src/server/index.js.map +1 -0
- package/dist/src/server/instructions.js +20 -0
- package/dist/src/server/instructions.js.map +1 -0
- package/dist/src/server/login-coordinator.js +73 -0
- package/dist/src/server/login-coordinator.js.map +1 -0
- package/dist/src/server/progress.js +33 -0
- package/dist/src/server/progress.js.map +1 -0
- package/dist/src/server/prompts.js +45 -0
- package/dist/src/server/prompts.js.map +1 -0
- package/dist/src/server/resources.js +73 -0
- package/dist/src/server/resources.js.map +1 -0
- package/dist/src/server/tools.js +338 -0
- package/dist/src/server/tools.js.map +1 -0
- package/dist/src/server/workspace.js +45 -0
- package/dist/src/server/workspace.js.map +1 -0
- package/dist/src/status.js +86 -0
- package/dist/src/status.js.map +1 -0
- package/dist/src/util/format.js +36 -0
- package/dist/src/util/format.js.map +1 -0
- package/dist/src/util/fs.js +117 -0
- package/dist/src/util/fs.js.map +1 -0
- package/dist/src/util/http.js +65 -0
- package/dist/src/util/http.js.map +1 -0
- package/dist/src/util/invocation.js +43 -0
- package/dist/src/util/invocation.js.map +1 -0
- package/dist/src/util/open.js +41 -0
- package/dist/src/util/open.js.map +1 -0
- package/docs/ARCHITECTURE.md +123 -0
- package/docs/AUTH.md +242 -0
- package/docs/BACKEND.md +169 -0
- package/docs/CLIENTS.md +154 -0
- package/docs/DEVELOPMENT.md +171 -0
- package/docs/README.md +84 -0
- package/docs/TOOLS.md +221 -0
- package/package.json +67 -0
- package/skill/imagegen/LICENSE.txt +201 -0
- package/skill/imagegen/SKILL.md +189 -0
- package/skill/imagegen/references/prompting.md +112 -0
- package/skill/imagegen/references/sample-prompts.md +418 -0
- package/skill/imagegen/references/tools.md +90 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ImagegenError } from "../errors.js";
|
|
2
|
+
import { deviceRedirectUri, exchangeAuthorizationCode, pollDeviceAuthorization, requestDeviceCode, } from "./oauth.js";
|
|
3
|
+
/** Start OpenAI's device-code flow (for headless/remote machines where a browser redirect can't reach us). */
|
|
4
|
+
export async function startDeviceLogin(client, signal) {
|
|
5
|
+
const device = await requestDeviceCode(client, signal);
|
|
6
|
+
const controller = new AbortController();
|
|
7
|
+
const onAbort = () => controller.abort(new ImagegenError("login_cancelled", "Device-code sign-in was cancelled."));
|
|
8
|
+
if (signal?.aborted)
|
|
9
|
+
onAbort();
|
|
10
|
+
else
|
|
11
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
12
|
+
const result = (async () => {
|
|
13
|
+
try {
|
|
14
|
+
const auth = await pollDeviceAuthorization(client, device, controller.signal);
|
|
15
|
+
return await exchangeAuthorizationCode(client, {
|
|
16
|
+
code: auth.authorizationCode,
|
|
17
|
+
redirectUri: deviceRedirectUri(client.issuer),
|
|
18
|
+
codeVerifier: auth.codeVerifier,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
if (controller.signal.aborted)
|
|
23
|
+
throw new ImagegenError("login_cancelled", "Device-code sign-in was cancelled.");
|
|
24
|
+
throw err;
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
signal?.removeEventListener("abort", onAbort);
|
|
28
|
+
}
|
|
29
|
+
})();
|
|
30
|
+
result.catch(() => undefined);
|
|
31
|
+
return {
|
|
32
|
+
verificationUrl: device.verificationUrl,
|
|
33
|
+
userCode: device.userCode,
|
|
34
|
+
expiresAt: device.expiresAt,
|
|
35
|
+
result,
|
|
36
|
+
cancel: onAbort,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=device-login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-login.js","sourceRoot":"","sources":["../../../src/auth/device-login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EACL,iBAAiB,EACjB,yBAAyB,EACzB,uBAAuB,EACvB,iBAAiB,GAElB,MAAM,YAAY,CAAC;AAWpB,8GAA8G;AAC9G,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAAmB,EAAE,MAAoB;IAC9E,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,aAAa,CAAC,iBAAiB,EAAE,oCAAoC,CAAC,CAAC,CAAC;IACnH,IAAI,MAAM,EAAE,OAAO;QAAE,OAAO,EAAE,CAAC;;QAC1B,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAEhE,MAAM,MAAM,GAAG,CAAC,KAAK,IAAuB,EAAE;QAC5C,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;YAC9E,OAAO,MAAM,yBAAyB,CAAC,MAAM,EAAE;gBAC7C,IAAI,EAAE,IAAI,CAAC,iBAAiB;gBAC5B,WAAW,EAAE,iBAAiB,CAAC,MAAM,CAAC,MAAM,CAAC;gBAC7C,YAAY,EAAE,IAAI,CAAC,YAAY;aAChC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO;gBAAE,MAAM,IAAI,aAAa,CAAC,iBAAiB,EAAE,oCAAoC,CAAC,CAAC;YAChH,MAAM,GAAG,CAAC;QACZ,CAAC;gBAAS,CAAC;YACT,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAChD,CAAC;IACH,CAAC,CAAC,EAAE,CAAC;IACL,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAE9B,OAAO;QACL,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,MAAM;QACN,MAAM,EAAE,OAAO;KAChB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { isRecord, str } from "../util/http.js";
|
|
2
|
+
const AUTH_CLAIM = "https://api.openai.com/auth";
|
|
3
|
+
const PROFILE_CLAIM = "https://api.openai.com/profile";
|
|
4
|
+
/**
|
|
5
|
+
* Decode a JWT payload WITHOUT verifying the signature. That is fine here: tokens come straight
|
|
6
|
+
* from OpenAI's token endpoint (or the user's own credential files) and are only read for
|
|
7
|
+
* display/expiry; the backend is what validates them. Mirrors codex-rs/login/src/token_data.rs.
|
|
8
|
+
*/
|
|
9
|
+
export function decodeJwtPayload(token) {
|
|
10
|
+
if (!token)
|
|
11
|
+
return undefined;
|
|
12
|
+
const parts = token.split(".");
|
|
13
|
+
if (parts.length < 2 || !parts[1])
|
|
14
|
+
return undefined;
|
|
15
|
+
try {
|
|
16
|
+
const value = JSON.parse(Buffer.from(parts[1], "base64url").toString("utf8"));
|
|
17
|
+
return isRecord(value) ? value : undefined;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/** `exp` claim in epoch milliseconds, if present. */
|
|
24
|
+
export function jwtExpiryMs(token) {
|
|
25
|
+
const exp = decodeJwtPayload(token)?.exp;
|
|
26
|
+
return typeof exp === "number" && Number.isFinite(exp) ? exp * 1000 : undefined;
|
|
27
|
+
}
|
|
28
|
+
function readIdentity(payload) {
|
|
29
|
+
if (!payload)
|
|
30
|
+
return {};
|
|
31
|
+
const auth = isRecord(payload[AUTH_CLAIM]) ? payload[AUTH_CLAIM] : {};
|
|
32
|
+
const profile = isRecord(payload[PROFILE_CLAIM]) ? payload[PROFILE_CLAIM] : {};
|
|
33
|
+
const out = {};
|
|
34
|
+
const email = str(payload.email) ?? str(profile.email);
|
|
35
|
+
if (email)
|
|
36
|
+
out.email = email;
|
|
37
|
+
const plan = str(auth.chatgpt_plan_type);
|
|
38
|
+
if (plan)
|
|
39
|
+
out.planType = plan;
|
|
40
|
+
const account = str(auth.chatgpt_account_id);
|
|
41
|
+
if (account)
|
|
42
|
+
out.accountId = account;
|
|
43
|
+
const user = str(auth.chatgpt_user_id) ?? str(auth.user_id);
|
|
44
|
+
if (user)
|
|
45
|
+
out.userId = user;
|
|
46
|
+
if (auth.chatgpt_account_is_fedramp === true)
|
|
47
|
+
out.isFedramp = true;
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
/** Identity from the id_token, with access-token claims as fallback for missing fields. */
|
|
51
|
+
export function identityFromTokens(idToken, accessToken) {
|
|
52
|
+
const fromId = readIdentity(decodeJwtPayload(idToken));
|
|
53
|
+
const fromAccess = readIdentity(decodeJwtPayload(accessToken));
|
|
54
|
+
const merged = { isFedramp: Boolean(fromId.isFedramp ?? fromAccess.isFedramp) };
|
|
55
|
+
const email = fromId.email ?? fromAccess.email;
|
|
56
|
+
if (email)
|
|
57
|
+
merged.email = email;
|
|
58
|
+
const planType = fromId.planType ?? fromAccess.planType;
|
|
59
|
+
if (planType)
|
|
60
|
+
merged.planType = planType;
|
|
61
|
+
const accountId = fromId.accountId ?? fromAccess.accountId;
|
|
62
|
+
if (accountId)
|
|
63
|
+
merged.accountId = accountId;
|
|
64
|
+
const userId = fromId.userId ?? fromAccess.userId;
|
|
65
|
+
if (userId)
|
|
66
|
+
merged.userId = userId;
|
|
67
|
+
return merged;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=jwt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../../src/auth/jwt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import { ACCESS_TOKEN_REFRESH_WINDOW_MS, BORROWED_TOKEN_MIN_VALIDITY_MS, FALLBACK_REFRESH_INTERVAL_MS, } from "../constants.js";
|
|
2
|
+
import { ImagegenError, loginHint, toImagegenError } from "../errors.js";
|
|
3
|
+
import { formatWhen } from "../util/format.js";
|
|
4
|
+
import { withFileLock } from "../util/fs.js";
|
|
5
|
+
import { readCodexCredential, readOpencodeCredential } from "./borrowed.js";
|
|
6
|
+
import { identityFromTokens, jwtExpiryMs } from "./jwt.js";
|
|
7
|
+
import { refreshAccessToken, revokeToken } from "./oauth.js";
|
|
8
|
+
import { buildStoredAuth, deleteStoredAuth, readStoredAuth, writeStoredAuth, } from "./store.js";
|
|
9
|
+
export const SOURCE_LABELS = {
|
|
10
|
+
own: "codex-imagegen-mcp sign-in",
|
|
11
|
+
codex: "Codex sign-in (borrowed, read-only)",
|
|
12
|
+
opencode: "opencode ChatGPT sign-in (borrowed, read-only)",
|
|
13
|
+
};
|
|
14
|
+
const OWNER_APP = { codex: "Codex", opencode: "opencode" };
|
|
15
|
+
export function authOptionsFromConfig(config, logger, fetchImpl) {
|
|
16
|
+
const oauth = { issuer: config.issuer, clientId: config.clientId, userAgent: config.userAgent };
|
|
17
|
+
if (fetchImpl)
|
|
18
|
+
oauth.fetchImpl = fetchImpl;
|
|
19
|
+
return {
|
|
20
|
+
mode: config.credentialMode,
|
|
21
|
+
authFile: config.authFile,
|
|
22
|
+
lockFile: config.lockFile,
|
|
23
|
+
codexAuthFile: config.codexAuthFile,
|
|
24
|
+
opencodeAuthFile: config.opencodeAuthFile,
|
|
25
|
+
oauth,
|
|
26
|
+
originator: config.originator,
|
|
27
|
+
logger,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Resolves credentials for the ChatGPT backend from, in order:
|
|
32
|
+
* 1. our own sign-in (`login`), refreshed automatically under a cross-process lock;
|
|
33
|
+
* 2. the Codex CLI/app sign-in (read-only, never refreshed by us);
|
|
34
|
+
* 3. the opencode ChatGPT sign-in (read-only, never refreshed by us).
|
|
35
|
+
* `CODEX_IMAGEGEN_CREDENTIALS=own|codex|opencode` pins a single source.
|
|
36
|
+
*/
|
|
37
|
+
export class AuthManager {
|
|
38
|
+
o;
|
|
39
|
+
/** Access tokens the backend rejected with 401 during this process's lifetime. */
|
|
40
|
+
rejected = new Set();
|
|
41
|
+
constructor(o) {
|
|
42
|
+
this.o = o;
|
|
43
|
+
}
|
|
44
|
+
get mode() {
|
|
45
|
+
return this.o.mode;
|
|
46
|
+
}
|
|
47
|
+
get oauthClient() {
|
|
48
|
+
return this.o.oauth;
|
|
49
|
+
}
|
|
50
|
+
enabledSources() {
|
|
51
|
+
return this.o.mode === "auto" ? ["own", "codex", "opencode"] : [this.o.mode];
|
|
52
|
+
}
|
|
53
|
+
now() {
|
|
54
|
+
return this.o.now?.() ?? Date.now();
|
|
55
|
+
}
|
|
56
|
+
/** Return credentials that are valid right now (refreshing our own tokens if needed). */
|
|
57
|
+
async getCredentials() {
|
|
58
|
+
const reasons = [];
|
|
59
|
+
const errors = [];
|
|
60
|
+
for (const source of this.enabledSources()) {
|
|
61
|
+
try {
|
|
62
|
+
const r = await this.resolve(source);
|
|
63
|
+
if ("credentials" in r)
|
|
64
|
+
return r.credentials;
|
|
65
|
+
reasons.push(`${SOURCE_LABELS[source]}: ${r.reason}`);
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
const e = toImagegenError(err);
|
|
69
|
+
if (e.kind === "cancelled")
|
|
70
|
+
throw e;
|
|
71
|
+
errors.push(e);
|
|
72
|
+
reasons.push(`${SOURCE_LABELS[source]}: ${e.message}`);
|
|
73
|
+
this.o.logger.warn("credential source failed", { source, kind: e.kind, message: e.message });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const expired = errors.find((e) => e.kind === "session_expired");
|
|
77
|
+
if (expired) {
|
|
78
|
+
throw new ImagegenError("session_expired", `${expired.message} ${loginHint()}`, { details: { sources: reasons }, cause: expired });
|
|
79
|
+
}
|
|
80
|
+
const transient = errors.find((e) => e.retryable);
|
|
81
|
+
if (transient)
|
|
82
|
+
throw transient;
|
|
83
|
+
throw new ImagegenError("not_signed_in", `Not signed in to ChatGPT. ${loginHint()} (Checked — ${reasons.join("; ")}.)`, {
|
|
84
|
+
details: { sources: reasons },
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Called after the backend answered 401 for `failed`. Marks that token as rejected and returns a
|
|
89
|
+
* different usable credential (refreshed own token, a re-read borrowed token, or the next source).
|
|
90
|
+
*/
|
|
91
|
+
async recoverFromUnauthorized(failed) {
|
|
92
|
+
this.rejected.add(failed.accessToken);
|
|
93
|
+
try {
|
|
94
|
+
const next = await this.getCredentials();
|
|
95
|
+
return next.accessToken === failed.accessToken ? undefined : next;
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
this.o.logger.warn("could not recover from 401", { message: toImagegenError(err).message });
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
async resolve(source) {
|
|
103
|
+
if (source === "own")
|
|
104
|
+
return this.resolveOwn();
|
|
105
|
+
const read = source === "codex" ? await readCodexCredential(this.o.codexAuthFile) : await readOpencodeCredential(this.o.opencodeAuthFile);
|
|
106
|
+
return this.resolveBorrowed(source, read);
|
|
107
|
+
}
|
|
108
|
+
resolveBorrowed(source, read) {
|
|
109
|
+
if (!read.ok)
|
|
110
|
+
return { reason: read.reason };
|
|
111
|
+
const c = read.credential;
|
|
112
|
+
if (this.rejected.has(c.accessToken)) {
|
|
113
|
+
return { reason: `ChatGPT rejected its access token; open ${OWNER_APP[source]} once so it refreshes the sign-in` };
|
|
114
|
+
}
|
|
115
|
+
if (c.expiresAt !== undefined && c.expiresAt - this.now() < BORROWED_TOKEN_MIN_VALIDITY_MS) {
|
|
116
|
+
return { reason: `its access token expired ${formatWhen(c.expiresAt, this.now())}; open ${OWNER_APP[source]} once to refresh it` };
|
|
117
|
+
}
|
|
118
|
+
const credentials = { source, file: c.file, accessToken: c.accessToken, identity: c.identity };
|
|
119
|
+
if (c.accountId)
|
|
120
|
+
credentials.accountId = c.accountId;
|
|
121
|
+
if (c.expiresAt !== undefined)
|
|
122
|
+
credentials.expiresAt = c.expiresAt;
|
|
123
|
+
return { credentials };
|
|
124
|
+
}
|
|
125
|
+
ownToCredentials(stored) {
|
|
126
|
+
const identity = identityFromTokens(stored.tokens.id_token, stored.tokens.access_token);
|
|
127
|
+
const credentials = {
|
|
128
|
+
source: "own",
|
|
129
|
+
file: this.o.authFile,
|
|
130
|
+
accessToken: stored.tokens.access_token,
|
|
131
|
+
identity,
|
|
132
|
+
};
|
|
133
|
+
const accountId = stored.tokens.account_id ?? identity.accountId;
|
|
134
|
+
if (accountId)
|
|
135
|
+
credentials.accountId = accountId;
|
|
136
|
+
const exp = jwtExpiryMs(stored.tokens.access_token);
|
|
137
|
+
if (exp !== undefined)
|
|
138
|
+
credentials.expiresAt = exp;
|
|
139
|
+
return credentials;
|
|
140
|
+
}
|
|
141
|
+
needsRefresh(stored) {
|
|
142
|
+
if (this.rejected.has(stored.tokens.access_token))
|
|
143
|
+
return true;
|
|
144
|
+
const exp = jwtExpiryMs(stored.tokens.access_token);
|
|
145
|
+
if (exp !== undefined)
|
|
146
|
+
return exp - this.now() <= ACCESS_TOKEN_REFRESH_WINDOW_MS;
|
|
147
|
+
const last = Date.parse(stored.last_refresh);
|
|
148
|
+
return !Number.isFinite(last) || this.now() - last >= FALLBACK_REFRESH_INTERVAL_MS;
|
|
149
|
+
}
|
|
150
|
+
async resolveOwn() {
|
|
151
|
+
const stored = await readStoredAuth(this.o.authFile);
|
|
152
|
+
if (!stored)
|
|
153
|
+
return { reason: "not signed in" };
|
|
154
|
+
if (!this.needsRefresh(stored))
|
|
155
|
+
return { credentials: this.ownToCredentials(stored) };
|
|
156
|
+
return { credentials: await this.refreshOwn(stored.tokens.access_token) };
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Refresh under a cross-process lock. After acquiring it we re-read the file: if another process
|
|
160
|
+
* already rotated the tokens we adopt its result instead of spending the (single-use) refresh
|
|
161
|
+
* token again — which would invalidate the whole sign-in with `refresh_token_reused`.
|
|
162
|
+
*/
|
|
163
|
+
async refreshOwn(staleAccessToken) {
|
|
164
|
+
return withFileLock(this.o.lockFile, async () => {
|
|
165
|
+
const latest = await readStoredAuth(this.o.authFile);
|
|
166
|
+
if (!latest)
|
|
167
|
+
throw new ImagegenError("not_signed_in", "You were signed out while the sign-in was being refreshed.");
|
|
168
|
+
if (latest.tokens.access_token !== staleAccessToken && !this.needsRefresh(latest)) {
|
|
169
|
+
this.o.logger.debug("adopting tokens refreshed by another process");
|
|
170
|
+
return this.ownToCredentials(latest);
|
|
171
|
+
}
|
|
172
|
+
let fresh;
|
|
173
|
+
try {
|
|
174
|
+
fresh = await refreshAccessToken(this.o.oauth, { refreshToken: latest.tokens.refresh_token, originator: this.o.originator });
|
|
175
|
+
}
|
|
176
|
+
catch (err) {
|
|
177
|
+
const e = toImagegenError(err);
|
|
178
|
+
const exp = jwtExpiryMs(latest.tokens.access_token);
|
|
179
|
+
const stillUsable = exp !== undefined && exp - this.now() > 30_000 && !this.rejected.has(latest.tokens.access_token);
|
|
180
|
+
if (e.kind !== "session_expired" && stillUsable) {
|
|
181
|
+
this.o.logger.warn("token refresh failed; using the current access token until it expires", { message: e.message });
|
|
182
|
+
return this.ownToCredentials(latest);
|
|
183
|
+
}
|
|
184
|
+
throw e;
|
|
185
|
+
}
|
|
186
|
+
const next = { ...latest, tokens: { ...latest.tokens }, last_refresh: new Date(this.now()).toISOString() };
|
|
187
|
+
if (fresh.accessToken)
|
|
188
|
+
next.tokens.access_token = fresh.accessToken;
|
|
189
|
+
if (fresh.refreshToken)
|
|
190
|
+
next.tokens.refresh_token = fresh.refreshToken;
|
|
191
|
+
if (fresh.idToken)
|
|
192
|
+
next.tokens.id_token = fresh.idToken;
|
|
193
|
+
if (!next.tokens.account_id) {
|
|
194
|
+
const accountId = identityFromTokens(next.tokens.id_token, next.tokens.access_token).accountId;
|
|
195
|
+
if (accountId)
|
|
196
|
+
next.tokens.account_id = accountId;
|
|
197
|
+
}
|
|
198
|
+
await writeStoredAuth(this.o.authFile, next);
|
|
199
|
+
this.o.logger.info("refreshed ChatGPT access token");
|
|
200
|
+
return this.ownToCredentials(next);
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
/** Persist a fresh login (replacing and revoking any previous one of ours). */
|
|
204
|
+
async saveLogin(tokens, method) {
|
|
205
|
+
return withFileLock(this.o.lockFile, async () => {
|
|
206
|
+
const previous = await readStoredAuth(this.o.authFile).catch(() => undefined);
|
|
207
|
+
const stored = buildStoredAuth(tokens, method, new Date(this.now()));
|
|
208
|
+
await writeStoredAuth(this.o.authFile, stored);
|
|
209
|
+
this.rejected.clear();
|
|
210
|
+
let revokedPrevious = false;
|
|
211
|
+
if (previous && previous.tokens.refresh_token !== stored.tokens.refresh_token) {
|
|
212
|
+
revokedPrevious = await revokeToken(this.o.oauth, previous.tokens.refresh_token, "refresh_token");
|
|
213
|
+
}
|
|
214
|
+
return { stored, identity: identityFromTokens(stored.tokens.id_token, stored.tokens.access_token), revokedPrevious };
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
/** Remove our own credentials (never touches Codex/opencode files). */
|
|
218
|
+
async logout(options) {
|
|
219
|
+
return withFileLock(this.o.lockFile, async () => {
|
|
220
|
+
const stored = await readStoredAuth(this.o.authFile).catch(() => undefined);
|
|
221
|
+
let revoked = false;
|
|
222
|
+
if (stored && options.revoke)
|
|
223
|
+
revoked = await revokeToken(this.o.oauth, stored.tokens.refresh_token, "refresh_token");
|
|
224
|
+
const removed = await deleteStoredAuth(this.o.authFile);
|
|
225
|
+
return { hadCredentials: Boolean(stored), removed, revoked };
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
/** Describe every credential source without refreshing anything. */
|
|
229
|
+
async inspect() {
|
|
230
|
+
const enabled = new Set(this.enabledSources());
|
|
231
|
+
const disabledDetail = `disabled (CODEX_IMAGEGEN_CREDENTIALS=${this.o.mode})`;
|
|
232
|
+
const own = await this.inspectOwn();
|
|
233
|
+
const codex = this.inspectBorrowed("codex", this.o.codexAuthFile, await readCodexCredential(this.o.codexAuthFile));
|
|
234
|
+
const opencode = this.inspectBorrowed("opencode", this.o.opencodeAuthFile, await readOpencodeCredential(this.o.opencodeAuthFile));
|
|
235
|
+
return [own, codex, opencode].map((r) => (enabled.has(r.source) ? r : { ...r, state: "disabled", detail: disabledDetail }));
|
|
236
|
+
}
|
|
237
|
+
/** The source `getCredentials()` would pick, based on an `inspect()` report. */
|
|
238
|
+
static activeSource(reports) {
|
|
239
|
+
return reports.find((r) => r.state === "ready" || r.state === "refreshable");
|
|
240
|
+
}
|
|
241
|
+
async inspectOwn() {
|
|
242
|
+
const base = { source: "own", label: SOURCE_LABELS.own, file: this.o.authFile };
|
|
243
|
+
let stored;
|
|
244
|
+
try {
|
|
245
|
+
stored = await readStoredAuth(this.o.authFile);
|
|
246
|
+
}
|
|
247
|
+
catch (err) {
|
|
248
|
+
return { ...base, state: "unusable", detail: toImagegenError(err).message };
|
|
249
|
+
}
|
|
250
|
+
if (!stored)
|
|
251
|
+
return { ...base, state: "missing", detail: "not signed in" };
|
|
252
|
+
const identity = identityFromTokens(stored.tokens.id_token, stored.tokens.access_token);
|
|
253
|
+
const report = {
|
|
254
|
+
...base,
|
|
255
|
+
state: "ready",
|
|
256
|
+
detail: "signed in",
|
|
257
|
+
identity,
|
|
258
|
+
lastRefresh: stored.last_refresh,
|
|
259
|
+
loginMethod: stored.login_method,
|
|
260
|
+
};
|
|
261
|
+
const exp = jwtExpiryMs(stored.tokens.access_token);
|
|
262
|
+
if (exp !== undefined)
|
|
263
|
+
report.expiresAt = exp;
|
|
264
|
+
if (this.needsRefresh(stored)) {
|
|
265
|
+
report.state = "refreshable";
|
|
266
|
+
report.detail = "access token expired or expiring; it is refreshed automatically on next use";
|
|
267
|
+
}
|
|
268
|
+
return report;
|
|
269
|
+
}
|
|
270
|
+
inspectBorrowed(source, file, read) {
|
|
271
|
+
const base = { source, label: SOURCE_LABELS[source], file };
|
|
272
|
+
if (!read.ok)
|
|
273
|
+
return { ...base, state: read.missing ? "missing" : "unusable", detail: read.reason };
|
|
274
|
+
const c = read.credential;
|
|
275
|
+
const report = { ...base, state: "ready", detail: "signed in", identity: c.identity };
|
|
276
|
+
if (c.expiresAt !== undefined)
|
|
277
|
+
report.expiresAt = c.expiresAt;
|
|
278
|
+
if (this.rejected.has(c.accessToken)) {
|
|
279
|
+
report.state = "unusable";
|
|
280
|
+
report.detail = `ChatGPT rejected this token; open ${OWNER_APP[source]} once to refresh it`;
|
|
281
|
+
}
|
|
282
|
+
else if (c.expiresAt !== undefined && c.expiresAt - this.now() < BORROWED_TOKEN_MIN_VALIDITY_MS) {
|
|
283
|
+
report.state = "expired";
|
|
284
|
+
report.detail = `access token expired ${formatWhen(c.expiresAt, this.now())}; open ${OWNER_APP[source]} once to refresh it`;
|
|
285
|
+
}
|
|
286
|
+
return report;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../../src/auth/manager.ts"],"names":[],"mappings":"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"}
|