@agentdocumentformat/cli 0.7.8 → 0.8.1
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 +1 -1
- package/dist/adf.mjs +59 -8
- package/dist/chunks/{APEv2Parser-2CNNHMXV.mjs → APEv2Parser-WIXRJLHB.mjs} +2 -2
- package/dist/chunks/{AiffParser-7BR4RL6G.mjs → AiffParser-ZC4QFOVJ.mjs} +5 -5
- package/dist/chunks/{App-7RIIOHJJ.mjs → App-4AZZJNN2.mjs} +917 -826
- package/dist/chunks/{DsdiffParser-CMD4AX7A.mjs → DsdiffParser-UAPAJHFX.mjs} +5 -5
- package/dist/chunks/{DsfParser-UOGZDS2M.mjs → DsfParser-NNYZK2QX.mjs} +6 -6
- package/dist/chunks/{FlacParser-HB3T3CD4.mjs → FlacParser-MW2W4LO3.mjs} +6 -6
- package/dist/chunks/{MP4Parser-66HBRUSX.mjs → MP4Parser-Z57SYOOQ.mjs} +4 -4
- package/dist/chunks/{MpegParser-YW6LIUEW.mjs → MpegParser-XIIPAZVM.mjs} +7 -7
- package/dist/chunks/{MusepackParser-PAUSXP7D.mjs → MusepackParser-QWNDEYHJ.mjs} +6 -6
- package/dist/chunks/{OggParser-NUBV3GWC.mjs → OggParser-WRX53F77.mjs} +9 -9
- package/dist/chunks/{WavPackParser-WQAGT7TC.mjs → WavPackParser-MJ7WCSJ5.mjs} +2 -2
- package/dist/chunks/{WaveParser-EWLQVDX4.mjs → WaveParser-RAVLHZ5S.mjs} +7 -7
- package/dist/chunks/{adf-schema-US4NFHMR.mjs → adf-schema-AIPBQTR2.mjs} +9 -3
- package/dist/chunks/auth-manager-AJ32FZWS.mjs +19 -0
- package/dist/chunks/auth-manager-C5OBEQK2.mjs +18 -0
- package/dist/chunks/auth-manager-TBNKCJ45.mjs +17 -0
- package/dist/chunks/{chatgpt-subscription-E4MXTIAT.mjs → chatgpt-subscription-MMGNW5KJ.mjs} +5 -2
- package/dist/chunks/chunk-2Z7X3UUR.mjs +678 -0
- package/dist/chunks/chunk-3UGZFWIF.mjs +26 -0
- package/dist/chunks/{chunk-XNPZBLYL.mjs → chunk-75DC5EWN.mjs} +13 -2
- package/dist/chunks/{chunk-5PO5PKRV.mjs → chunk-7JZXMDDF.mjs} +158 -67
- package/dist/chunks/chunk-AEAJDCVK.mjs +517 -0
- package/dist/chunks/{chunk-6VQEXLE2.mjs → chunk-BHY7QDCM.mjs} +41 -3
- package/dist/chunks/{chunk-CD3ATSXE.mjs → chunk-BR3AD5QZ.mjs} +8 -2
- package/dist/chunks/chunk-BS3USVEA.mjs +301 -0
- package/dist/chunks/chunk-C2S64Y6F.mjs +203 -0
- package/dist/chunks/chunk-D7A77SNL.mjs +976 -0
- package/dist/chunks/chunk-DDTTSKGG.mjs +2443 -0
- package/dist/chunks/{chunk-VAUOM3IN.mjs → chunk-DLWCKKIO.mjs} +1 -1
- package/dist/chunks/{chunk-G6PH7RPW.mjs → chunk-E7LC6SHP.mjs} +3 -3
- package/dist/chunks/{chunk-ZESQMP66.mjs → chunk-F3WSCAJD.mjs} +3 -3
- package/dist/chunks/{chunk-KXEF4F4E.mjs → chunk-GAZO6UMI.mjs} +1 -1
- package/dist/chunks/{chunk-XYTWGHFS.mjs → chunk-H3XLRWVE.mjs} +1 -1
- package/dist/chunks/{chunk-7T2YMTWL.mjs → chunk-H4C65MTP.mjs} +4 -4
- package/dist/chunks/chunk-HBOFZRUS.mjs +738 -0
- package/dist/chunks/{chunk-VN7UH7I5.mjs → chunk-IMVMSU3A.mjs} +251 -68
- package/dist/chunks/{chunk-XYV3VCIX.mjs → chunk-JZFONJSL.mjs} +79 -20
- package/dist/chunks/chunk-KCIRFUZH.mjs +12799 -0
- package/dist/chunks/chunk-KDDVQKCG.mjs +65 -0
- package/dist/chunks/chunk-KRPKWOMB.mjs +290 -0
- package/dist/chunks/chunk-LKFHERRV.mjs +145 -0
- package/dist/chunks/chunk-LTX74NU6.mjs +29 -0
- package/dist/chunks/{chunk-HSBV6YFU.mjs → chunk-LVF2DRBR.mjs} +634 -99
- package/dist/chunks/chunk-M2F7C2UJ.mjs +425 -0
- package/dist/chunks/{chunk-62NE4LG4.mjs → chunk-MQAMI5BF.mjs} +5 -5
- package/dist/chunks/chunk-MZRXFWPQ.mjs +278 -0
- package/dist/chunks/{chunk-PRMGZZM5.mjs → chunk-NZLEPJ5M.mjs} +2 -0
- package/dist/chunks/{chunk-I3UYSITV.mjs → chunk-O7XKQ6CH.mjs} +1 -1
- package/dist/chunks/chunk-P3RG5LQA.mjs +244 -0
- package/dist/chunks/chunk-PAK5JCO2.mjs +48 -0
- package/dist/chunks/chunk-PC63YFB7.mjs +34 -0
- package/dist/chunks/{daemon-control-HKFVSQTQ.mjs → chunk-RHBGCOS3.mjs} +67 -26
- package/dist/chunks/{chunk-J74STFKE.mjs → chunk-RJDOVMM4.mjs} +362 -58
- package/dist/chunks/{chunk-QPLEAE6V.mjs → chunk-SOSPQPEN.mjs} +167 -650
- package/dist/chunks/{chunk-LFMB4PAA.mjs → chunk-TKXIH27X.mjs} +974 -113
- package/dist/chunks/{chunk-5W7KES6P.mjs → chunk-UZPDETEU.mjs} +1 -1
- package/dist/chunks/chunk-V3MM6PCH.mjs +366 -0
- package/dist/chunks/chunk-VENQBMOA.mjs +62 -0
- package/dist/chunks/chunk-WJGPNHGX.mjs +67 -0
- package/dist/chunks/{chunk-Y5ZLKFLE.mjs → chunk-XNNJQCZP.mjs} +196 -165
- package/dist/chunks/{chunk-HDBPBORT.mjs → chunk-YRBFIDLB.mjs} +46 -10
- package/dist/chunks/{chunk-BNXUAOO4.mjs → chunk-ZGXUOAWZ.mjs} +3186 -959
- package/dist/chunks/chunk-ZPB3HYM7.mjs +45 -0
- package/dist/chunks/claude-subscription-EB4LAAVV.mjs +29 -0
- package/dist/chunks/{cli-NMFIAR7Z.mjs → cli-PCVFB6B4.mjs} +797 -56
- package/dist/chunks/{commands-KPJWFRUE.mjs → commands-KOMPXJZS.mjs} +4 -3
- package/dist/chunks/{daemon-YDIK3AAM.mjs → daemon-BVDB565V.mjs} +83142 -64424
- package/dist/chunks/daemon-control-MKN7G5M3.mjs +59 -0
- package/dist/chunks/{daemon-token-WRSULP7G.mjs → daemon-token-L5QKTHU5.mjs} +3 -1
- package/dist/chunks/{discord-DSP4HUWI.mjs → discord-IR62565M.mjs} +3 -52
- package/dist/chunks/{email-BRG7KUO2.mjs → email-KHHTJBDW.mjs} +4 -2
- package/dist/chunks/{grok-subscription-4PYX7TBF.mjs → grok-subscription-E74FS5EG.mjs} +5 -2
- package/dist/chunks/{layout-EPJQNFAI.mjs → layout-ECWGJF6M.mjs} +2 -2
- package/dist/chunks/{lib-N7FCZWKH.mjs → lib-L27L5PXM.mjs} +22 -22
- package/dist/chunks/{open-VAU7PXT6.mjs → open-3OR6WT4T.mjs} +6 -6
- package/dist/chunks/{parser-JVY2PWSM.mjs → parser-7GARNT5L.mjs} +1 -1
- package/dist/chunks/{pipeline-executor-O77NTGLP.mjs → pipeline-executor-DRYEEFDR.mjs} +6 -5
- package/dist/chunks/prompt-RRHZX4YT.mjs +13 -0
- package/dist/chunks/remote-access-cli-GLEEP7DI.mjs +268 -0
- package/dist/chunks/remote-hello-UFWUBDQI.mjs +37 -0
- package/dist/chunks/sdk-OJOAF4DP.mjs +30014 -0
- package/dist/chunks/{slack-OCNNF4DX.mjs → slack-IYC5RAB5.mjs} +3 -4
- package/dist/chunks/{store-HUVDJPYN.mjs → store-55CQSAOX.mjs} +7 -3
- package/dist/chunks/tailscale-WLJATFMB.mjs +25 -0
- package/dist/chunks/{theme-SFE3JMA2.mjs → theme-HLBDTF6F.mjs} +1 -1
- package/dist/chunks/{themes-YLXLOIJF.mjs → themes-BQ72P446.mjs} +2 -2
- package/dist/chunks/{token-6G3HCMNX.mjs → token-6D22WECM.mjs} +20 -16
- package/dist/chunks/{token-util-UXYSDQIW.mjs → token-util-YF3ZWBZ4.mjs} +1 -2
- package/dist/chunks/{tui-UQJLK7XI.mjs → tui-RAUVFOYY.mjs} +21 -18
- package/dist/chunks/{welcome-XHXFV7SH.mjs → welcome-J5JZZAM5.mjs} +1 -1
- package/dist/chunks/{whatsapp-AJMRQBT7.mjs → whatsapp-YJFFVN4Q.mjs} +9 -9
- package/package.json +1 -1
- package/dist/chunks/chunk-GKKCMXIZ.mjs +0 -94
- package/dist/chunks/chunk-IHDDCZBS.mjs +0 -112
- package/dist/chunks/chunk-KWFOS5WC.mjs +0 -41
- package/dist/chunks/chunk-UEZR2CNS.mjs +0 -65
- package/dist/chunks/chunk-VMHTYDH4.mjs +0 -172
- package/dist/chunks/chunk-Y2QA53AN.mjs +0 -259
- package/dist/chunks/{chunk-NBTUWMGP.mjs → chunk-2MTE22CR.mjs} +3 -3
- package/dist/chunks/{chunk-APRU6PHC.mjs → chunk-JZ7AQNPM.mjs} +3 -3
- package/dist/chunks/{telegram-2EFGKIVK.mjs → telegram-JYY2VDTI.mjs} +5 -5
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { createRequire as __adfCreateRequire } from 'node:module';
|
|
2
|
+
import { fileURLToPath as __adfFileURLToPath } from 'node:url';
|
|
3
|
+
import { dirname as __adfDirname } from 'node:path';
|
|
4
|
+
const require = __adfCreateRequire(import.meta.url);
|
|
5
|
+
const __filename = __adfFileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = __adfDirname(__filename);
|
|
7
|
+
import {
|
|
8
|
+
__commonJS
|
|
9
|
+
} from "./chunk-M2RX3S2T.mjs";
|
|
10
|
+
|
|
11
|
+
// node_modules/fast-deep-equal/es6/index.js
|
|
12
|
+
var require_es6 = __commonJS({
|
|
13
|
+
"node_modules/fast-deep-equal/es6/index.js"(exports, module) {
|
|
14
|
+
"use strict";
|
|
15
|
+
module.exports = function equal(a, b) {
|
|
16
|
+
if (a === b) return !0;
|
|
17
|
+
if (a && b && typeof a == "object" && typeof b == "object") {
|
|
18
|
+
if (a.constructor !== b.constructor) return !1;
|
|
19
|
+
var length, i, keys;
|
|
20
|
+
if (Array.isArray(a)) {
|
|
21
|
+
if (length = a.length, length != b.length) return !1;
|
|
22
|
+
for (i = length; i-- !== 0; )
|
|
23
|
+
if (!equal(a[i], b[i])) return !1;
|
|
24
|
+
return !0;
|
|
25
|
+
}
|
|
26
|
+
if (a instanceof Map && b instanceof Map) {
|
|
27
|
+
if (a.size !== b.size) return !1;
|
|
28
|
+
for (i of a.entries())
|
|
29
|
+
if (!b.has(i[0])) return !1;
|
|
30
|
+
for (i of a.entries())
|
|
31
|
+
if (!equal(i[1], b.get(i[0]))) return !1;
|
|
32
|
+
return !0;
|
|
33
|
+
}
|
|
34
|
+
if (a instanceof Set && b instanceof Set) {
|
|
35
|
+
if (a.size !== b.size) return !1;
|
|
36
|
+
for (i of a.entries())
|
|
37
|
+
if (!b.has(i[0])) return !1;
|
|
38
|
+
return !0;
|
|
39
|
+
}
|
|
40
|
+
if (ArrayBuffer.isView(a) && ArrayBuffer.isView(b)) {
|
|
41
|
+
if (length = a.length, length != b.length) return !1;
|
|
42
|
+
for (i = length; i-- !== 0; )
|
|
43
|
+
if (a[i] !== b[i]) return !1;
|
|
44
|
+
return !0;
|
|
45
|
+
}
|
|
46
|
+
if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
|
|
47
|
+
if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
|
|
48
|
+
if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();
|
|
49
|
+
if (keys = Object.keys(a), length = keys.length, length !== Object.keys(b).length) return !1;
|
|
50
|
+
for (i = length; i-- !== 0; )
|
|
51
|
+
if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return !1;
|
|
52
|
+
for (i = length; i-- !== 0; ) {
|
|
53
|
+
var key = keys[i];
|
|
54
|
+
if (!equal(a[key], b[key])) return !1;
|
|
55
|
+
}
|
|
56
|
+
return !0;
|
|
57
|
+
}
|
|
58
|
+
return a !== a && b !== b;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
export {
|
|
64
|
+
require_es6
|
|
65
|
+
};
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { createRequire as __adfCreateRequire } from 'node:module';
|
|
2
|
+
import { fileURLToPath as __adfFileURLToPath } from 'node:url';
|
|
3
|
+
import { dirname as __adfDirname } from 'node:path';
|
|
4
|
+
const require = __adfCreateRequire(import.meta.url);
|
|
5
|
+
const __filename = __adfFileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = __adfDirname(__filename);
|
|
7
|
+
import {
|
|
8
|
+
startCallbackServer
|
|
9
|
+
} from "./chunk-2NAP2ZF7.mjs";
|
|
10
|
+
import {
|
|
11
|
+
createSubscriptionTokenStore
|
|
12
|
+
} from "./chunk-C2S64Y6F.mjs";
|
|
13
|
+
import {
|
|
14
|
+
__require
|
|
15
|
+
} from "./chunk-M2RX3S2T.mjs";
|
|
16
|
+
|
|
17
|
+
// src/main/providers/chatgpt-subscription/auth-manager.ts
|
|
18
|
+
import crypto from "crypto";
|
|
19
|
+
|
|
20
|
+
// src/main/providers/chatgpt-subscription/token-store.ts
|
|
21
|
+
var store = createSubscriptionTokenStore("chatgpt-subscription");
|
|
22
|
+
function readTokens() {
|
|
23
|
+
return store.readTokens();
|
|
24
|
+
}
|
|
25
|
+
function writeTokens(tokens) {
|
|
26
|
+
store.writeTokens(tokens);
|
|
27
|
+
}
|
|
28
|
+
function clearTokens() {
|
|
29
|
+
store.clearTokens();
|
|
30
|
+
}
|
|
31
|
+
function noteSignIn(accountId) {
|
|
32
|
+
store.signedIn(accountId);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// src/main/providers/chatgpt-subscription/auth-manager.ts
|
|
36
|
+
var CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann", AUTH_URL = "https://auth.openai.com/oauth/authorize", TOKEN_URL = "https://auth.openai.com/oauth/token", SCOPE = "openid profile email offline_access api.connectors.read api.connectors.invoke", REFRESH_BUFFER_MS = 300 * 1e3, RELAY_FLOW_TTL_MS = 600 * 1e3;
|
|
37
|
+
function base64url(buf) {
|
|
38
|
+
return buf.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
39
|
+
}
|
|
40
|
+
function generateCodeVerifier() {
|
|
41
|
+
let bytes = crypto.getRandomValues(new Uint8Array(64));
|
|
42
|
+
return base64url(Buffer.from(bytes));
|
|
43
|
+
}
|
|
44
|
+
function generateCodeChallenge(verifier) {
|
|
45
|
+
let hash = crypto.createHash("sha256").update(verifier).digest();
|
|
46
|
+
return base64url(hash);
|
|
47
|
+
}
|
|
48
|
+
function generateState() {
|
|
49
|
+
return base64url(Buffer.from(crypto.getRandomValues(new Uint8Array(32))));
|
|
50
|
+
}
|
|
51
|
+
function decodeJwtPayload(token) {
|
|
52
|
+
let parts = token.split(".");
|
|
53
|
+
if (parts.length < 2) return {};
|
|
54
|
+
try {
|
|
55
|
+
let payload = Buffer.from(parts[1], "base64url").toString("utf-8");
|
|
56
|
+
return JSON.parse(payload);
|
|
57
|
+
} catch {
|
|
58
|
+
return {};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function chatgptAccountIdFromJwt(token) {
|
|
62
|
+
if (!token) return "";
|
|
63
|
+
let claims = decodeJwtPayload(token), auth = claims["https://api.openai.com/auth"], id = (auth && typeof auth == "object" ? auth.chatgpt_account_id : void 0) ?? claims.chatgpt_account_id;
|
|
64
|
+
return typeof id == "string" ? id : "";
|
|
65
|
+
}
|
|
66
|
+
async function openExternal(url) {
|
|
67
|
+
try {
|
|
68
|
+
let electron = __require("electron");
|
|
69
|
+
if (electron.shell?.openExternal) {
|
|
70
|
+
await electron.shell.openExternal(url);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
} catch {
|
|
74
|
+
}
|
|
75
|
+
console.log(`[ChatGPT Auth] Open this URL to sign in: ${url}`);
|
|
76
|
+
}
|
|
77
|
+
function assertLoopbackRedirect(redirectUri) {
|
|
78
|
+
let parsed;
|
|
79
|
+
try {
|
|
80
|
+
parsed = new URL(redirectUri);
|
|
81
|
+
} catch {
|
|
82
|
+
throw new Error(`Invalid redirectUri: ${redirectUri}`);
|
|
83
|
+
}
|
|
84
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:")
|
|
85
|
+
throw new Error("redirectUri must be an http(s) URL");
|
|
86
|
+
if (!["localhost", "127.0.0.1", "[::1]", "::1"].includes(parsed.hostname))
|
|
87
|
+
throw new Error("redirectUri must target localhost \u2014 the OAuth callback runs on the machine with the browser");
|
|
88
|
+
}
|
|
89
|
+
var ChatGptAuthManager = class {
|
|
90
|
+
refreshPromise = null;
|
|
91
|
+
cachedTokens = null;
|
|
92
|
+
email;
|
|
93
|
+
activeAuthFlow = null;
|
|
94
|
+
relayFlows = /* @__PURE__ */ new Map();
|
|
95
|
+
constructor() {
|
|
96
|
+
this.syncFromDisk();
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Re-read the token file, picking up writes from other processes.
|
|
100
|
+
*
|
|
101
|
+
* Each surface has its own file (see subscription-token-store), but several
|
|
102
|
+
* processes can share one — e.g. an installed and a dev Studio, or a CLI
|
|
103
|
+
* next to its daemon — and OpenAI rotates the refresh token on every
|
|
104
|
+
* refresh, so acting on a cached copy can invalidate a sibling's session. Always reading is what prevents that; the file is
|
|
105
|
+
* well under a kilobyte and this runs once per LLM request.
|
|
106
|
+
*/
|
|
107
|
+
syncFromDisk() {
|
|
108
|
+
let tokens = readTokens();
|
|
109
|
+
return tokens?.access_token !== this.cachedTokens?.access_token && (this.email = void 0), this.cachedTokens = tokens, tokens;
|
|
110
|
+
}
|
|
111
|
+
persist(tokens) {
|
|
112
|
+
writeTokens(tokens), this.cachedTokens = tokens;
|
|
113
|
+
}
|
|
114
|
+
async startAuthFlow() {
|
|
115
|
+
await (await this.startAuthFlowDetached()).completion;
|
|
116
|
+
}
|
|
117
|
+
async startAuthFlowDetached() {
|
|
118
|
+
if (this.activeAuthFlow) return this.activeAuthFlow;
|
|
119
|
+
let codeVerifier = generateCodeVerifier(), codeChallenge = generateCodeChallenge(codeVerifier), state = generateState(), server = await startCallbackServer(), redirectUri = `http://localhost:${server.port}/auth/callback`, params = new URLSearchParams({
|
|
120
|
+
client_id: CLIENT_ID,
|
|
121
|
+
redirect_uri: redirectUri,
|
|
122
|
+
response_type: "code",
|
|
123
|
+
code_challenge: codeChallenge,
|
|
124
|
+
code_challenge_method: "S256",
|
|
125
|
+
state,
|
|
126
|
+
scope: SCOPE,
|
|
127
|
+
id_token_add_organizations: "true",
|
|
128
|
+
codex_cli_simplified_flow: "true",
|
|
129
|
+
originator: "adf_studio"
|
|
130
|
+
}), authUrl = `${AUTH_URL}?${params.toString()}`;
|
|
131
|
+
await openExternal(authUrl);
|
|
132
|
+
let completion = (async () => {
|
|
133
|
+
try {
|
|
134
|
+
let result = await server.waitForCallback();
|
|
135
|
+
if (result.state !== state)
|
|
136
|
+
throw new Error("OAuth state mismatch \u2014 possible CSRF attack");
|
|
137
|
+
await this.exchangeCode(result.code, codeVerifier, redirectUri);
|
|
138
|
+
} finally {
|
|
139
|
+
server.close(), this.activeAuthFlow = null;
|
|
140
|
+
}
|
|
141
|
+
})();
|
|
142
|
+
return this.activeAuthFlow = { authUrl, callbackPort: server.port, completion }, this.activeAuthFlow;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Begin a sign-in whose OAuth callback lands on the *caller's* machine rather
|
|
146
|
+
* than on this process.
|
|
147
|
+
*
|
|
148
|
+
* The loopback flow assumes the browser and the token store share a host.
|
|
149
|
+
* That breaks for a daemon on a remote box: `http://localhost:1455` in the
|
|
150
|
+
* user's browser reaches their laptop, not the daemon. Here the daemon keeps
|
|
151
|
+
* the PKCE verifier, the caller runs its own callback server, and the caller
|
|
152
|
+
* posts the code back via `completeRelayAuthFlow`.
|
|
153
|
+
*/
|
|
154
|
+
startRelayAuthFlow(redirectUri) {
|
|
155
|
+
assertLoopbackRedirect(redirectUri), this.pruneRelayFlows();
|
|
156
|
+
let codeVerifier = generateCodeVerifier(), state = generateState(), flowId = base64url(Buffer.from(crypto.getRandomValues(new Uint8Array(24)))), expiresAt = Date.now() + RELAY_FLOW_TTL_MS, params = new URLSearchParams({
|
|
157
|
+
client_id: CLIENT_ID,
|
|
158
|
+
redirect_uri: redirectUri,
|
|
159
|
+
response_type: "code",
|
|
160
|
+
code_challenge: generateCodeChallenge(codeVerifier),
|
|
161
|
+
code_challenge_method: "S256",
|
|
162
|
+
state,
|
|
163
|
+
scope: SCOPE,
|
|
164
|
+
id_token_add_organizations: "true",
|
|
165
|
+
codex_cli_simplified_flow: "true",
|
|
166
|
+
originator: "adf_studio"
|
|
167
|
+
});
|
|
168
|
+
return this.relayFlows.set(flowId, { codeVerifier, state, redirectUri, expiresAt }), { flowId, authUrl: `${AUTH_URL}?${params.toString()}`, state, expiresAt };
|
|
169
|
+
}
|
|
170
|
+
/** Finish a relay flow with the code the caller's callback server received. */
|
|
171
|
+
async completeRelayAuthFlow(flowId, code, state) {
|
|
172
|
+
this.pruneRelayFlows();
|
|
173
|
+
let flow = this.relayFlows.get(flowId);
|
|
174
|
+
if (!flow)
|
|
175
|
+
throw new Error("Unknown or expired auth flow \u2014 start sign-in again");
|
|
176
|
+
if (this.relayFlows.delete(flowId), state !== flow.state)
|
|
177
|
+
throw new Error("OAuth state mismatch \u2014 possible CSRF attack");
|
|
178
|
+
await this.exchangeCode(code, flow.codeVerifier, flow.redirectUri);
|
|
179
|
+
}
|
|
180
|
+
pruneRelayFlows() {
|
|
181
|
+
let now = Date.now();
|
|
182
|
+
for (let [id, flow] of this.relayFlows)
|
|
183
|
+
flow.expiresAt <= now && this.relayFlows.delete(id);
|
|
184
|
+
}
|
|
185
|
+
/** Trade an authorization code for tokens and persist them. */
|
|
186
|
+
async exchangeCode(code, codeVerifier, redirectUri) {
|
|
187
|
+
let tokenResponse = await fetch(TOKEN_URL, {
|
|
188
|
+
method: "POST",
|
|
189
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
190
|
+
body: new URLSearchParams({
|
|
191
|
+
grant_type: "authorization_code",
|
|
192
|
+
client_id: CLIENT_ID,
|
|
193
|
+
code,
|
|
194
|
+
redirect_uri: redirectUri,
|
|
195
|
+
code_verifier: codeVerifier
|
|
196
|
+
}).toString()
|
|
197
|
+
});
|
|
198
|
+
if (!tokenResponse.ok) {
|
|
199
|
+
let body = await tokenResponse.text();
|
|
200
|
+
throw new Error(`Token exchange failed (${tokenResponse.status}): ${body}`);
|
|
201
|
+
}
|
|
202
|
+
let tokenData = await tokenResponse.json();
|
|
203
|
+
tokenData.id_token && (this.email = decodeJwtPayload(tokenData.id_token).email);
|
|
204
|
+
let accountId = chatgptAccountIdFromJwt(tokenData.access_token) || chatgptAccountIdFromJwt(tokenData.id_token);
|
|
205
|
+
console.log(`[ChatGPT Auth] signed in: email=${this.email}, chatgpt_account_id=${accountId || "(missing)"}`), this.persist({
|
|
206
|
+
access_token: tokenData.access_token,
|
|
207
|
+
refresh_token: tokenData.refresh_token,
|
|
208
|
+
expires_at: Date.now() + tokenData.expires_in * 1e3,
|
|
209
|
+
account_id: accountId
|
|
210
|
+
}), noteSignIn(accountId);
|
|
211
|
+
}
|
|
212
|
+
async getValidAccessToken() {
|
|
213
|
+
let tokens = this.syncFromDisk();
|
|
214
|
+
if (!tokens)
|
|
215
|
+
throw new Error("Not authenticated \u2014 sign in first");
|
|
216
|
+
return Date.now() + REFRESH_BUFFER_MS < tokens.expires_at ? tokens.access_token : this.refreshPromise ? this.refreshPromise : (this.refreshPromise = this.refreshIfStillNeeded(tokens).finally(() => {
|
|
217
|
+
this.refreshPromise = null;
|
|
218
|
+
}), this.refreshPromise);
|
|
219
|
+
}
|
|
220
|
+
getAccountId() {
|
|
221
|
+
let tokens = this.syncFromDisk();
|
|
222
|
+
return chatgptAccountIdFromJwt(tokens?.access_token) || tokens?.account_id || void 0;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Re-check the file after winning the in-process refresh lock.
|
|
226
|
+
*
|
|
227
|
+
* OpenAI rotates the refresh token on every refresh, so if Studio refreshed
|
|
228
|
+
* while this call queued, our copy is already dead and spending it would both
|
|
229
|
+
* fail here and be pointless. Adopt the newer set instead.
|
|
230
|
+
*/
|
|
231
|
+
async refreshIfStillNeeded(tokens) {
|
|
232
|
+
let fresh = this.syncFromDisk();
|
|
233
|
+
return fresh && Date.now() + REFRESH_BUFFER_MS < fresh.expires_at ? fresh.access_token : this.refreshTokens(fresh ?? tokens);
|
|
234
|
+
}
|
|
235
|
+
async refreshTokens(tokens) {
|
|
236
|
+
let data, rejected = !1;
|
|
237
|
+
try {
|
|
238
|
+
let response = await fetch(TOKEN_URL, {
|
|
239
|
+
method: "POST",
|
|
240
|
+
headers: { "Content-Type": "application/json" },
|
|
241
|
+
body: JSON.stringify({
|
|
242
|
+
client_id: CLIENT_ID,
|
|
243
|
+
grant_type: "refresh_token",
|
|
244
|
+
refresh_token: tokens.refresh_token
|
|
245
|
+
})
|
|
246
|
+
});
|
|
247
|
+
if (!response.ok)
|
|
248
|
+
throw rejected = response.status === 400 || response.status === 401, new Error(`Token refresh failed (${response.status})`);
|
|
249
|
+
data = await response.json();
|
|
250
|
+
} catch (err) {
|
|
251
|
+
let fresh = this.syncFromDisk();
|
|
252
|
+
if (fresh && fresh.refresh_token !== tokens.refresh_token && Date.now() + REFRESH_BUFFER_MS < fresh.expires_at)
|
|
253
|
+
return fresh.access_token;
|
|
254
|
+
throw rejected ? (clearTokens(), this.cachedTokens = null, this.email = void 0, new Error("Session expired \u2014 please sign in again")) : new Error(`Could not refresh the session (${err instanceof Error ? err.message : String(err)}) \u2014 still signed in, try again`);
|
|
255
|
+
}
|
|
256
|
+
if (data.id_token) {
|
|
257
|
+
let claims = decodeJwtPayload(data.id_token);
|
|
258
|
+
this.email = claims.email;
|
|
259
|
+
}
|
|
260
|
+
return this.persist({
|
|
261
|
+
access_token: data.access_token,
|
|
262
|
+
refresh_token: data.refresh_token,
|
|
263
|
+
expires_at: Date.now() + data.expires_in * 1e3,
|
|
264
|
+
account_id: chatgptAccountIdFromJwt(data.access_token) || chatgptAccountIdFromJwt(data.id_token) || tokens.account_id
|
|
265
|
+
}), data.access_token;
|
|
266
|
+
}
|
|
267
|
+
getAuthStatus() {
|
|
268
|
+
let tokens = this.syncFromDisk();
|
|
269
|
+
return tokens ? {
|
|
270
|
+
authenticated: !0,
|
|
271
|
+
email: this.email,
|
|
272
|
+
expiresAt: tokens.expires_at
|
|
273
|
+
} : { authenticated: !1 };
|
|
274
|
+
}
|
|
275
|
+
isAuthenticated() {
|
|
276
|
+
return this.syncFromDisk() !== null;
|
|
277
|
+
}
|
|
278
|
+
logout() {
|
|
279
|
+
clearTokens(), this.cachedTokens = null, this.email = void 0, this.refreshPromise = null, this.relayFlows.clear();
|
|
280
|
+
}
|
|
281
|
+
}, instance = null;
|
|
282
|
+
function getChatGptAuthManager() {
|
|
283
|
+
return instance || (instance = new ChatGptAuthManager()), instance;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export {
|
|
287
|
+
readTokens,
|
|
288
|
+
chatgptAccountIdFromJwt,
|
|
289
|
+
getChatGptAuthManager
|
|
290
|
+
};
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { createRequire as __adfCreateRequire } from 'node:module';
|
|
2
|
+
import { fileURLToPath as __adfFileURLToPath } from 'node:url';
|
|
3
|
+
import { dirname as __adfDirname } from 'node:path';
|
|
4
|
+
const require = __adfCreateRequire(import.meta.url);
|
|
5
|
+
const __filename = __adfFileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = __adfDirname(__filename);
|
|
7
|
+
import {
|
|
8
|
+
__export
|
|
9
|
+
} from "./chunk-M2RX3S2T.mjs";
|
|
10
|
+
|
|
11
|
+
// src/shared/utils/file-ref.ts
|
|
12
|
+
var file_ref_exports = {};
|
|
13
|
+
__export(file_ref_exports, {
|
|
14
|
+
adfFileUrl: () => adfFileUrl,
|
|
15
|
+
applyFileRefChanges: () => applyFileRefChanges,
|
|
16
|
+
attachmentMetadata: () => attachmentMetadata,
|
|
17
|
+
attachmentText: () => attachmentText,
|
|
18
|
+
attachmentsOf: () => attachmentsOf,
|
|
19
|
+
deletedFilePlaceholder: () => deletedFilePlaceholder,
|
|
20
|
+
displayAttachment: () => displayAttachment,
|
|
21
|
+
fileRefKind: () => fileRefKind,
|
|
22
|
+
fileRefName: () => fileRefName,
|
|
23
|
+
fileRefText: () => fileRefText,
|
|
24
|
+
isAudioInputMime: () => isAudioInputMime,
|
|
25
|
+
isFileRefBlock: () => isFileRefBlock,
|
|
26
|
+
isVideoInputMime: () => isVideoInputMime,
|
|
27
|
+
isVisionMime: () => isVisionMime,
|
|
28
|
+
mediaKindOfMime: () => mediaKindOfMime,
|
|
29
|
+
splitLegacyUploads: () => splitLegacyUploads
|
|
30
|
+
});
|
|
31
|
+
var VISION_MIMES = /* @__PURE__ */ new Set(["image/png", "image/jpeg", "image/gif", "image/webp"]), AUDIO_INPUT_MIMES = /* @__PURE__ */ new Set([
|
|
32
|
+
"audio/wav",
|
|
33
|
+
"audio/mpeg",
|
|
34
|
+
"audio/mp3",
|
|
35
|
+
"audio/aiff",
|
|
36
|
+
"audio/aac",
|
|
37
|
+
"audio/ogg",
|
|
38
|
+
"audio/flac",
|
|
39
|
+
"audio/x-m4a",
|
|
40
|
+
"audio/webm"
|
|
41
|
+
]), VIDEO_INPUT_MIMES = /* @__PURE__ */ new Set(["video/mp4", "video/mpeg", "video/quicktime", "video/webm"]);
|
|
42
|
+
function isVisionMime(mime) {
|
|
43
|
+
return !!mime && VISION_MIMES.has(mime);
|
|
44
|
+
}
|
|
45
|
+
function isAudioInputMime(mime) {
|
|
46
|
+
return !!mime && AUDIO_INPUT_MIMES.has(mime);
|
|
47
|
+
}
|
|
48
|
+
function isVideoInputMime(mime) {
|
|
49
|
+
return !!mime && VIDEO_INPUT_MIMES.has(mime);
|
|
50
|
+
}
|
|
51
|
+
function mediaKindOfMime(mime) {
|
|
52
|
+
if (isVisionMime(mime)) return "image";
|
|
53
|
+
if (isAudioInputMime(mime)) return "audio";
|
|
54
|
+
if (isVideoInputMime(mime)) return "video";
|
|
55
|
+
}
|
|
56
|
+
function isFileRefBlock(block) {
|
|
57
|
+
return block.type === "file_ref" && !!block.file_ref && typeof block.file_ref.path == "string";
|
|
58
|
+
}
|
|
59
|
+
function fileRefKind(ref) {
|
|
60
|
+
return mediaKindOfMime(ref.mime_type);
|
|
61
|
+
}
|
|
62
|
+
function fileRefName(ref) {
|
|
63
|
+
let segments = ref.path.split("/");
|
|
64
|
+
return segments[segments.length - 1] || ref.path;
|
|
65
|
+
}
|
|
66
|
+
function deletedFilePlaceholder(ref) {
|
|
67
|
+
return `[deleted: ${fileRefName(ref)}]`;
|
|
68
|
+
}
|
|
69
|
+
function adfFileUrl(path) {
|
|
70
|
+
return `adf-file://${path.split("/").map(encodeURIComponent).join("/")}`;
|
|
71
|
+
}
|
|
72
|
+
function displayAttachment(ref) {
|
|
73
|
+
let kind = fileRefKind(ref);
|
|
74
|
+
return {
|
|
75
|
+
path: ref.path,
|
|
76
|
+
name: fileRefName(ref),
|
|
77
|
+
mime_type: ref.mime_type,
|
|
78
|
+
...kind ? { kind } : {},
|
|
79
|
+
...ref.deleted ? { deleted: !0 } : {}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function attachmentsOf(blocks) {
|
|
83
|
+
let out = [];
|
|
84
|
+
for (let block of blocks) isFileRefBlock(block) && out.push(displayAttachment(block.file_ref));
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
87
|
+
function attachmentMetadata(content, previews = []) {
|
|
88
|
+
let attachments = attachmentsOf(content);
|
|
89
|
+
if (!(attachments.length === 0 && previews.length === 0))
|
|
90
|
+
return { ...previews.length > 0 ? { imagePreviewUrls: previews } : {}, ...attachments.length > 0 ? { attachments } : {} };
|
|
91
|
+
}
|
|
92
|
+
function attachmentText(a) {
|
|
93
|
+
return a.deleted ? deletedFilePlaceholder(a) : `[${a.kind ?? "file"}: ${a.name}]`;
|
|
94
|
+
}
|
|
95
|
+
var LEGACY_UPLOAD_LINE = /^\[Uploaded file: .+ \(([^,()]+), [^()]+\)\. Use fs_read with path "(.+)" to inspect it\.\]$/;
|
|
96
|
+
function splitLegacyUploads(text) {
|
|
97
|
+
if (!text.includes("[Uploaded file: ")) return { text, attachments: [] };
|
|
98
|
+
let attachments = [], kept = [];
|
|
99
|
+
for (let line of text.split(`
|
|
100
|
+
`)) {
|
|
101
|
+
let match = LEGACY_UPLOAD_LINE.exec(line.trim());
|
|
102
|
+
if (!match) {
|
|
103
|
+
kept.push(line);
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
let kind = mediaKindOfMime(match[1]);
|
|
107
|
+
attachments.push({ path: match[2], name: fileRefName({ path: match[2] }), mime_type: match[1], ...kind ? { kind } : {} });
|
|
108
|
+
}
|
|
109
|
+
return { text: kept.join(`
|
|
110
|
+
`).trim(), attachments };
|
|
111
|
+
}
|
|
112
|
+
function fileRefText(ref) {
|
|
113
|
+
return ref.deleted ? deletedFilePlaceholder(ref) : `[${fileRefKind(ref) ?? "file"}: ${ref.path}]`;
|
|
114
|
+
}
|
|
115
|
+
function applyFileRefChanges(blocks, changes) {
|
|
116
|
+
let out = null;
|
|
117
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
118
|
+
let block = blocks[i];
|
|
119
|
+
if (!isFileRefBlock(block) || block.file_ref.deleted) continue;
|
|
120
|
+
let ref = block.file_ref;
|
|
121
|
+
for (let change of changes) {
|
|
122
|
+
if (ref.deleted) break;
|
|
123
|
+
change.op === "rename" && ref.path === change.from ? ref = { ...ref, path: change.to } : change.op === "delete" && ref.path === change.path && (ref = { ...ref, deleted: !0 });
|
|
124
|
+
}
|
|
125
|
+
ref !== block.file_ref && (out ??= blocks.slice(), out[i] = { ...block, file_ref: ref });
|
|
126
|
+
}
|
|
127
|
+
return out ?? blocks;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export {
|
|
131
|
+
isVisionMime,
|
|
132
|
+
isAudioInputMime,
|
|
133
|
+
isVideoInputMime,
|
|
134
|
+
mediaKindOfMime,
|
|
135
|
+
isFileRefBlock,
|
|
136
|
+
fileRefKind,
|
|
137
|
+
fileRefName,
|
|
138
|
+
deletedFilePlaceholder,
|
|
139
|
+
displayAttachment,
|
|
140
|
+
attachmentsOf,
|
|
141
|
+
splitLegacyUploads,
|
|
142
|
+
fileRefText,
|
|
143
|
+
applyFileRefChanges,
|
|
144
|
+
file_ref_exports
|
|
145
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { createRequire as __adfCreateRequire } from 'node:module';
|
|
2
|
+
import { fileURLToPath as __adfFileURLToPath } from 'node:url';
|
|
3
|
+
import { dirname as __adfDirname } from 'node:path';
|
|
4
|
+
const require = __adfCreateRequire(import.meta.url);
|
|
5
|
+
const __filename = __adfFileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = __adfDirname(__filename);
|
|
7
|
+
|
|
8
|
+
// src/main/utils/secret-file.ts
|
|
9
|
+
import { execFileSync } from "node:child_process";
|
|
10
|
+
import { chmodSync } from "node:fs";
|
|
11
|
+
import { userInfo } from "node:os";
|
|
12
|
+
function restrictToCurrentUserWindows(path, run = (file, args) => {
|
|
13
|
+
execFileSync(file, args, { windowsHide: !0, stdio: ["ignore", "ignore", "pipe"] });
|
|
14
|
+
}) {
|
|
15
|
+
let user = process.env.USERDOMAIN && process.env.USERNAME ? `${process.env.USERDOMAIN}\\${process.env.USERNAME}` : userInfo().username;
|
|
16
|
+
run("icacls", [path, "/inheritance:r", "/grant:r", `${user}:F`]);
|
|
17
|
+
}
|
|
18
|
+
function protectSecretFile(path, opts = {}) {
|
|
19
|
+
try {
|
|
20
|
+
return (opts.platform ?? process.platform) === "win32" ? restrictToCurrentUserWindows(path, opts.run) : chmodSync(path, 384), !0;
|
|
21
|
+
} catch (err) {
|
|
22
|
+
return console.warn(`[SecretFile] Could not restrict ${path} to the current user: ${err instanceof Error ? err.message : String(err)}`), !1;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export {
|
|
27
|
+
restrictToCurrentUserWindows,
|
|
28
|
+
protectSecretFile
|
|
29
|
+
};
|