openai-oauth 2.0.0-beta.2 → 2.0.0-beta.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 +22 -1
- package/dist/{chunk-UZ3AHAWX.js → chunk-KROVQ42X.js} +594 -554
- package/dist/cli.js +962 -38
- package/dist/index.js +1 -1
- package/package.json +4 -4
|
@@ -1,474 +1,34 @@
|
|
|
1
|
-
// src/
|
|
2
|
-
import { spawn } from "child_process";
|
|
1
|
+
// src/server.ts
|
|
3
2
|
import { createServer } from "http";
|
|
4
|
-
import { createConnection } from "net";
|
|
5
3
|
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} from "@openai-oauth/
|
|
10
|
-
|
|
11
|
-
// src/callback-success.html?raw
|
|
12
|
-
var callback_success_default = `<!doctype html>
|
|
13
|
-
<html lang="en">
|
|
14
|
-
<head>
|
|
15
|
-
<meta charset="utf-8" />
|
|
16
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
17
|
-
<title>OpenAI OAuth Sign-In</title>
|
|
18
|
-
<link
|
|
19
|
-
rel="icon"
|
|
20
|
-
type="image/svg+xml"
|
|
21
|
-
href='data:image/svg+xml,%3Csvg width="1412" height="1412" viewBox="0 0 1412 1412" fill="none" xmlns="http://www.w3.org/2000/svg"%3E%3Cstyle%3E.mark%7Bfill:%23111111%7D@media(prefers-color-scheme:dark)%7B.mark%7Bfill:%23ffffff%7D%7D%3C/style%3E%3Cpath class="mark" d="M597.462 0.857699C673.717 -4.5771 755.535 16.0618 820.557 55.7878C839.621 67.4347 853.532 77.8804 870.903 91.7881C915.947 83.6597 962.083 83.5966 1007.15 91.601C1108.64 109.677 1198.75 167.436 1257.54 252.101C1315.95 336.355 1338.56 440.326 1320.41 541.218C1348.4 575.095 1369.47 609.408 1385.5 650.519C1422.8 746.143 1420.65 852.641 1379.53 946.681C1345.7 1023.88 1287.62 1087.95 1214.08 1129.17C1193.85 1140.47 1177.72 1147.33 1156.35 1155.65C1150.8 1167.38 1146.43 1180.08 1140.53 1192.52C1124.33 1226.23 1103.33 1257.42 1078.21 1285.12C1009.53 1360.77 913.675 1406.14 811.622 1411.3C797.103 1412.74 770.195 1411.71 755.535 1410.39C669.671 1402.64 607.216 1373.41 541.228 1320.14C498.371 1327.97 454.491 1328.42 411.479 1321.49C309.519 1305.16 218.308 1248.8 158.127 1164.91C95.5192 1077.93 74.597 975.652 91.7694 870.624C63.5815 837.852 41.1539 800.536 25.4414 760.272C-11.0983 663.999 -8.18036 557.204 33.5617 463.069C77.8418 363.472 155.004 295.015 255.809 256.181C260.004 248.164 265.705 231.947 270.502 221.837C286.044 188.764 306.234 158.081 330.46 130.717C398.638 53.6473 494.725 6.91416 597.462 0.857699ZM803.624 1297.49C879.882 1292.64 946.234 1261.95 997.071 1204.28C1015.09 1183.82 1029.9 1160.75 1041.02 1135.85C1047.58 1121.23 1051.8 1106.22 1056.86 1091.08C1067.19 1060.2 1088.78 1058.15 1115.61 1048.88C1125.47 1045.52 1135.09 1041.52 1144.43 1036.9C1243.91 988.43 1304.38 884.819 1297.64 774.394C1294 716.163 1271.8 660.631 1234.27 615.946C1223.26 602.711 1208.28 591.435 1203.34 574.896C1197.16 554.244 1207.83 529.807 1210.67 506.759C1221.87 416.705 1187.69 326.959 1119.41 267.154C1064.95 219.454 993.758 195.357 921.517 200.173C909.062 200.932 896.689 202.63 884.487 205.252C858.307 210.809 839.711 217.803 816.524 196.759C802.123 183.693 793.783 175.007 777.726 163.451C738.141 135.075 691.432 118.286 642.835 114.967C634.456 114.329 619.975 113.369 611.816 114.357C536.156 118.188 468.827 147.965 417.756 204.614C399.016 225.371 383.578 248.884 371.981 274.328C368.409 282.286 365.23 290.414 362.455 298.682C357.28 314.179 354.556 330.003 342.859 342.026C330.473 354.758 314.132 357.158 297.998 362.604C288.467 365.803 279.144 369.592 270.084 373.948C170.322 421.514 108.992 524.42 114.64 634.77C117.764 693.592 139.719 749.855 177.266 795.249C188.357 808.68 203.749 820.374 208.712 836.975C214.929 857.779 204.623 882.481 201.669 905.586C190.625 994.243 223.634 1082.71 290.065 1142.47C341.827 1188.92 413.829 1216.16 483.523 1212.31C496.702 1211.71 509.821 1210.17 522.783 1207.71C549.917 1202.44 573.428 1193.61 595.85 1215.61C654.397 1273.04 720.807 1298.82 803.624 1297.49Z"/%3E%3C/svg%3E'
|
|
22
|
-
/>
|
|
23
|
-
<style>
|
|
24
|
-
:root {
|
|
25
|
-
color-scheme: light;
|
|
26
|
-
background: #ffffff;
|
|
27
|
-
color: #111111;
|
|
28
|
-
font-family:
|
|
29
|
-
ui-sans-serif,
|
|
30
|
-
system-ui,
|
|
31
|
-
-apple-system,
|
|
32
|
-
BlinkMacSystemFont,
|
|
33
|
-
"Segoe UI",
|
|
34
|
-
sans-serif;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
body {
|
|
38
|
-
display: grid;
|
|
39
|
-
margin: 0;
|
|
40
|
-
min-height: 100vh;
|
|
41
|
-
place-items: center;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
main {
|
|
45
|
-
text-align: center;
|
|
46
|
-
width: min(430px, calc(100vw - 48px));
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
.brand {
|
|
50
|
-
align-items: center;
|
|
51
|
-
display: inline-flex;
|
|
52
|
-
gap: 7px;
|
|
53
|
-
margin-bottom: 28px;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
.logo {
|
|
57
|
-
display: block;
|
|
58
|
-
height: 16px;
|
|
59
|
-
transform: translateY(-1px);
|
|
60
|
-
width: 16px;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
.wordmark {
|
|
64
|
-
display: block;
|
|
65
|
-
height: 15px;
|
|
66
|
-
width: auto;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
h1 {
|
|
70
|
-
font-size: clamp(25px, 3.1vw, 31px);
|
|
71
|
-
font-weight: 540;
|
|
72
|
-
letter-spacing: 0;
|
|
73
|
-
line-height: 1.1;
|
|
74
|
-
margin: 0;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
p {
|
|
78
|
-
color: #111111;
|
|
79
|
-
font-size: 18px;
|
|
80
|
-
line-height: 1.45;
|
|
81
|
-
margin: 18px auto 0;
|
|
82
|
-
max-width: 340px;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
footer {
|
|
86
|
-
align-items: center;
|
|
87
|
-
bottom: 34px;
|
|
88
|
-
color: #6f6f6f;
|
|
89
|
-
display: flex;
|
|
90
|
-
flex-direction: column;
|
|
91
|
-
font-size: 12px;
|
|
92
|
-
gap: 7px;
|
|
93
|
-
left: 24px;
|
|
94
|
-
line-height: 1.25;
|
|
95
|
-
position: fixed;
|
|
96
|
-
right: 24px;
|
|
97
|
-
text-align: center;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
footer a {
|
|
101
|
-
color: inherit;
|
|
102
|
-
text-decoration: none;
|
|
103
|
-
}
|
|
4
|
+
createOpenAIOAuth
|
|
5
|
+
} from "@openai-oauth/ai-sdk";
|
|
6
|
+
import { createCodexOAuthClient } from "@openai-oauth/core";
|
|
7
|
+
import { openaiCredentials } from "@openai-oauth/local";
|
|
104
8
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
9
|
+
// src/chat-completions.ts
|
|
10
|
+
import { generateText } from "ai";
|
|
108
11
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
display: flex;
|
|
112
|
-
gap: 8px;
|
|
113
|
-
justify-content: center;
|
|
114
|
-
}
|
|
115
|
-
</style>
|
|
116
|
-
</head>
|
|
117
|
-
<body>
|
|
118
|
-
<main aria-labelledby="title">
|
|
119
|
-
<div class="brand" aria-label="OpenAI OAuth">
|
|
120
|
-
<svg
|
|
121
|
-
aria-hidden="true"
|
|
122
|
-
class="logo"
|
|
123
|
-
fill="none"
|
|
124
|
-
viewBox="0 0 1412 1412"
|
|
125
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
126
|
-
>
|
|
127
|
-
<path
|
|
128
|
-
d="M597.462 0.857699C673.717 -4.5771 755.535 16.0618 820.557 55.7878C839.621 67.4347 853.532 77.8804 870.903 91.7881C915.947 83.6597 962.083 83.5966 1007.15 91.601C1108.64 109.677 1198.75 167.436 1257.54 252.101C1315.95 336.355 1338.56 440.326 1320.41 541.218C1348.4 575.095 1369.47 609.408 1385.5 650.519C1422.8 746.143 1420.65 852.641 1379.53 946.681C1345.7 1023.88 1287.62 1087.95 1214.08 1129.17C1193.85 1140.47 1177.72 1147.33 1156.35 1155.65C1150.8 1167.38 1146.43 1180.08 1140.53 1192.52C1124.33 1226.23 1103.33 1257.42 1078.21 1285.12C1009.53 1360.77 913.675 1406.14 811.622 1411.3C797.103 1412.74 770.195 1411.71 755.535 1410.39C669.671 1402.64 607.216 1373.41 541.228 1320.14C498.371 1327.97 454.491 1328.42 411.479 1321.49C309.519 1305.16 218.308 1248.8 158.127 1164.91C95.5192 1077.93 74.597 975.652 91.7694 870.624C63.5815 837.852 41.1539 800.536 25.4414 760.272C-11.0983 663.999 -8.18036 557.204 33.5617 463.069C77.8418 363.472 155.004 295.015 255.809 256.181C260.004 248.164 265.705 231.947 270.502 221.837C286.044 188.764 306.234 158.081 330.46 130.717C398.638 53.6473 494.725 6.91416 597.462 0.857699ZM803.624 1297.49C879.882 1292.64 946.234 1261.95 997.071 1204.28C1015.09 1183.82 1029.9 1160.75 1041.02 1135.85C1047.58 1121.23 1051.8 1106.22 1056.86 1091.08C1067.19 1060.2 1088.78 1058.15 1115.61 1048.88C1125.47 1045.52 1135.09 1041.52 1144.43 1036.9C1243.91 988.43 1304.38 884.819 1297.64 774.394C1294 716.163 1271.8 660.631 1234.27 615.946C1223.26 602.711 1208.28 591.435 1203.34 574.896C1197.16 554.244 1207.83 529.807 1210.67 506.759C1221.87 416.705 1187.69 326.959 1119.41 267.154C1064.95 219.454 993.758 195.357 921.517 200.173C909.062 200.932 896.689 202.63 884.487 205.252C858.307 210.809 839.711 217.803 816.524 196.759C802.123 183.693 793.783 175.007 777.726 163.451C738.141 135.075 691.432 118.286 642.835 114.967C634.456 114.329 619.975 113.369 611.816 114.357C536.156 118.188 468.827 147.965 417.756 204.614C399.016 225.371 383.578 248.884 371.981 274.328C368.409 282.286 365.23 290.414 362.455 298.682C357.28 314.179 354.556 330.003 342.859 342.026C330.473 354.758 314.132 357.158 297.998 362.604C288.467 365.803 279.144 369.592 270.084 373.948C170.322 421.514 108.992 524.42 114.64 634.77C117.764 693.592 139.719 749.855 177.266 795.249C188.357 808.68 203.749 820.374 208.712 836.975C214.929 857.779 204.623 882.481 201.669 905.586C190.625 994.243 223.634 1082.71 290.065 1142.47C341.827 1188.92 413.829 1216.16 483.523 1212.31C496.702 1211.71 509.821 1210.17 522.783 1207.71C549.917 1202.44 573.428 1193.61 595.85 1215.61C654.397 1273.04 720.807 1298.82 803.624 1297.49Z"
|
|
129
|
-
fill="currentColor"
|
|
130
|
-
/>
|
|
131
|
-
<path
|
|
132
|
-
d="M528.104 673.1C645.003 673.1 739.769 767.837 739.769 884.701C739.769 1001.56 645.003 1096.3 528.104 1096.3C411.204 1096.3 316.439 1001.56 316.439 884.701C316.439 767.837 411.204 673.1 528.104 673.1ZM526.618 785.954C472.886 785.954 429.327 829.499 429.327 883.216C429.327 936.932 472.886 980.478 526.618 980.478C580.351 980.478 623.91 936.932 623.91 883.216C623.91 829.499 580.351 785.954 526.618 785.954Z"
|
|
133
|
-
fill="currentColor"
|
|
134
|
-
fill-rule="evenodd"
|
|
135
|
-
clip-rule="evenodd"
|
|
136
|
-
/>
|
|
137
|
-
<path
|
|
138
|
-
d="M974.454 335.733L1055.33 416.583L688.769 783.031L607.895 702.182L974.454 335.733Z"
|
|
139
|
-
fill="currentColor"
|
|
140
|
-
/>
|
|
141
|
-
<path
|
|
142
|
-
d="M820.585 766.758L704.525 767.283L821.11 650.733L820.585 766.758Z"
|
|
143
|
-
fill="currentColor"
|
|
144
|
-
/>
|
|
145
|
-
<path
|
|
146
|
-
d="M937.694 649.684L821.11 650.733L938.744 533.135L937.694 649.684Z"
|
|
147
|
-
fill="currentColor"
|
|
148
|
-
/>
|
|
149
|
-
<path
|
|
150
|
-
d="M1054.8 532.611L938.744 533.135L1055.33 416.586L1054.8 532.611Z"
|
|
151
|
-
fill="currentColor"
|
|
152
|
-
/>
|
|
153
|
-
<path
|
|
154
|
-
d="M1054.8 336.259L1055.33 416.583L974.454 335.733L1054.8 336.259Z"
|
|
155
|
-
fill="currentColor"
|
|
156
|
-
/>
|
|
157
|
-
</svg>
|
|
158
|
-
<svg
|
|
159
|
-
aria-label="OpenAI OAuth"
|
|
160
|
-
class="wordmark"
|
|
161
|
-
fill="none"
|
|
162
|
-
viewBox="0 0 2769 391"
|
|
163
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
164
|
-
>
|
|
165
|
-
<path d="M2495.6 239.383L2495.6 4.36719H2442.96L2442.96 251.081C2442.96 264.073 2446.69 279.793 2455.73 289.364C2464.76 298.935 2471.68 305.315 2488.69 305.315H2549.84V263.31H2514.21C2507.02 263.31 2501.82 258.862 2499.33 254.803C2496.83 250.743 2495.6 246.21 2495.6 239.383Z" fill="black"/>
|
|
166
|
-
<rect x="2543.46" y="90.5039" width="47.854" height="146.752" transform="rotate(90 2543.46 90.5039)" fill="black"/>
|
|
167
|
-
<path d="M1734.79 0C1649.66 0 1580 69.6496 1580 154.777C1580 239.904 1649.66 309.554 1734.79 309.554C1819.93 309.554 1889.59 240.334 1889.59 154.777C1889.59 69.2197 1820.36 0 1734.79 0ZM1734.79 254.092C1681.91 254.092 1639.34 210.669 1639.34 154.777C1639.34 98.8852 1681.91 55.4617 1734.79 55.4617C1787.68 55.4617 1830.25 98.8852 1830.25 154.777C1830.25 210.669 1787.68 254.092 1734.79 254.092Z" fill="black"/>
|
|
168
|
-
<path d="M1984.56 8.62109L1862.87 309.576H1922.64L1948.44 243.796H2086.89L2112.69 309.576H2173.32L2052.49 8.62109H1984.56ZM1967.79 193.923L2017.67 67.9522L2067.11 193.923H1967.79Z" fill="black"/>
|
|
169
|
-
<path d="M2687.02 86.0449C2662.08 86.0449 2635.86 97.2232 2623.82 115.71V4.36719H2567.92V305.312H2623.82V189.659C2623.82 156.124 2641.88 134.198 2671.11 134.198C2698.2 134.198 2712.82 154.835 2712.82 183.64V305.312H2768.72V174.612C2768.72 121.3 2736.04 86.0449 2687.02 86.0449Z" fill="black"/>
|
|
170
|
-
<path d="M2255.09 309.773C2280.02 309.773 2306.25 298.595 2318.29 280.108L2318.29 305.474L2374.19 305.474L2374.19 90.5062L2318.29 90.5062L2318.29 206.159C2318.29 239.694 2300.23 261.621 2271 261.621C2243.91 261.621 2229.29 240.984 2229.29 212.178L2229.29 90.5062L2173.39 90.5062L2173.39 221.207C2173.39 274.519 2206.07 309.773 2255.09 309.773Z" fill="black"/>
|
|
171
|
-
<path d="M154.577 0C69.5595 0 0 69.6066 0 154.681C0 239.756 69.5595 309.363 154.577 309.363C239.594 309.363 309.153 240.186 309.153 154.681C309.153 69.1769 240.023 0 154.577 0ZM154.577 253.935C101.763 253.935 59.2544 210.538 59.2544 154.681C59.2544 98.8242 101.763 55.4275 154.577 55.4275C207.39 55.4275 249.899 98.8242 249.899 154.681C249.899 210.538 207.39 253.935 154.577 253.935ZM465.447 85.9341C437.533 85.9341 410.487 97.1055 396.312 116.011V90.2308H340.493V391H396.312V282.293C410.482 299.91 436.674 309.363 465.442 309.363C525.555 309.363 572.787 262.099 572.787 197.648C572.787 133.198 525.561 85.9341 465.447 85.9341ZM455.996 260.81C424.222 260.81 395.883 235.889 395.883 197.648C395.883 159.408 424.222 134.487 455.996 134.487C487.77 134.487 516.104 159.408 516.104 197.648C516.104 235.889 487.77 260.81 455.996 260.81ZM704.187 85.9341C643.216 85.9341 595.125 133.627 595.125 197.648C595.125 261.669 637.204 309.363 705.905 309.363C762.154 309.363 798.222 275.419 809.385 237.178H754.854C747.984 253.076 728.662 264.247 705.476 264.247C676.707 264.247 654.809 244.053 649.656 215.265H811.962V193.352C811.962 134.916 771.171 85.9341 704.187 85.9341ZM650.086 175.735C656.097 148.666 678.425 131.049 705.476 131.049C734.244 131.049 756.142 149.955 758.719 175.735H650.086ZM960.522 85.9341C935.618 85.9341 909.426 97.1055 897.403 115.581V90.2308H841.584V305.066H897.403V189.485C897.403 155.97 915.437 134.057 944.635 134.057C971.686 134.057 986.285 154.681 986.285 183.469V305.066H1042.1V174.446C1042.1 121.167 1009.47 85.9341 960.522 85.9341ZM1185.07 4.30681L1063.55 305.076H1123.24L1149 239.336H1287.26L1313.02 305.076H1373.56L1252.91 4.30681H1185.07ZM1168.32 189.495L1218.13 63.6013L1267.51 189.495H1168.32ZM1453 4.30681H1396.32V305.076H1453V4.30681Z" fill="black"/>
|
|
172
|
-
</svg>
|
|
173
|
-
</div>
|
|
174
|
-
<h1 id="title">Sign-in complete</h1>
|
|
175
|
-
<p>
|
|
176
|
-
Your ChatGPT credentials are saved locally. You can close this
|
|
177
|
-
window and return to your terminal.
|
|
178
|
-
</p>
|
|
179
|
-
</main>
|
|
180
|
-
<footer>
|
|
181
|
-
<a href="https://github.com/evanzhoudev/openai-oauth">
|
|
182
|
-
Learn more about OpenAI OAuth
|
|
183
|
-
</a>
|
|
184
|
-
<div class="footer-links">
|
|
185
|
-
<a href="https://github.com/evanzhoudev/openai-oauth">GitHub</a>
|
|
186
|
-
<span aria-hidden="true">\u22C5</span>
|
|
187
|
-
<a href="https://github.com/evanzhoudev/openai-oauth#legal">Legal</a>
|
|
188
|
-
</div>
|
|
189
|
-
</footer>
|
|
190
|
-
</body>
|
|
191
|
-
</html>
|
|
192
|
-
`;
|
|
12
|
+
// src/chat-messages.ts
|
|
13
|
+
import { jsonSchema, tool } from "ai";
|
|
193
14
|
|
|
194
|
-
// src/
|
|
195
|
-
|
|
196
|
-
var
|
|
197
|
-
var
|
|
198
|
-
var
|
|
199
|
-
|
|
200
|
-
var isAddressUnavailableError = (error) => error instanceof Error && "code" in error && ["EADDRNOTAVAIL", "EAFNOSUPPORT"].includes(
|
|
201
|
-
String(error.code)
|
|
202
|
-
);
|
|
203
|
-
var createLoginCancelledError = () => new Error("OpenAI OAuth login cancelled.");
|
|
204
|
-
var toCallbackHtml = (title, message) => `<!doctype html>
|
|
205
|
-
<html lang="en">
|
|
206
|
-
<head>
|
|
207
|
-
<meta charset="utf-8" />
|
|
208
|
-
<title>${title}</title>
|
|
209
|
-
<style>
|
|
210
|
-
body {
|
|
211
|
-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
212
|
-
margin: 3rem;
|
|
213
|
-
line-height: 1.5;
|
|
214
|
-
}
|
|
215
|
-
</style>
|
|
216
|
-
</head>
|
|
217
|
-
<body>
|
|
218
|
-
<h1>${title}</h1>
|
|
219
|
-
<p>${message}</p>
|
|
220
|
-
</body>
|
|
221
|
-
</html>`;
|
|
222
|
-
var htmlHeaders = {
|
|
223
|
-
"Content-Type": "text/html; charset=utf-8",
|
|
224
|
-
Connection: "close"
|
|
15
|
+
// src/shared.ts
|
|
16
|
+
import { Buffer } from "buffer";
|
|
17
|
+
var DEFAULT_HOST = "127.0.0.1";
|
|
18
|
+
var DEFAULT_PORT = 10531;
|
|
19
|
+
var jsonHeaders = {
|
|
20
|
+
"content-type": "application/json; charset=utf-8"
|
|
225
21
|
};
|
|
226
|
-
var
|
|
227
|
-
"
|
|
228
|
-
|
|
22
|
+
var sseHeaders = {
|
|
23
|
+
"content-type": "text/event-stream; charset=utf-8",
|
|
24
|
+
"cache-control": "no-cache, no-transform",
|
|
25
|
+
connection: "keep-alive",
|
|
26
|
+
"x-accel-buffering": "no"
|
|
229
27
|
};
|
|
230
|
-
var
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
const child = spawn(command, args, {
|
|
235
|
-
detached: true,
|
|
236
|
-
stdio: "ignore"
|
|
237
|
-
});
|
|
238
|
-
child.on("error", () => void 0);
|
|
239
|
-
child.unref();
|
|
240
|
-
};
|
|
241
|
-
var toCallbackPortInUseMessage = (redirectHost, port) => `OpenAI OAuth login needs http://${redirectHost}:${port}/auth/callback, but port ${port} is already in use. Stop the process using that port and try again.`;
|
|
242
|
-
var listen = (server, port, host) => new Promise((resolve, reject) => {
|
|
243
|
-
server.once("error", reject);
|
|
244
|
-
const onListening = () => {
|
|
245
|
-
server.off("error", reject);
|
|
246
|
-
resolve();
|
|
247
|
-
};
|
|
248
|
-
server.listen(port, host, onListening);
|
|
249
|
-
});
|
|
250
|
-
var closeServers = async (servers) => {
|
|
251
|
-
await Promise.all(servers.map((server) => closeServer(server)));
|
|
252
|
-
};
|
|
253
|
-
var listenOnCallbackPort = async (handler, port, host) => {
|
|
254
|
-
if (host) {
|
|
255
|
-
const server = createServer(handler);
|
|
256
|
-
await listen(server, port, host);
|
|
257
|
-
return [server];
|
|
258
|
-
}
|
|
259
|
-
const servers = [];
|
|
260
|
-
for (const loopbackHost of LOOPBACK_LISTEN_HOSTS) {
|
|
261
|
-
const server = createServer(handler);
|
|
262
|
-
try {
|
|
263
|
-
await listen(server, port, loopbackHost);
|
|
264
|
-
servers.push(server);
|
|
265
|
-
} catch (error) {
|
|
266
|
-
await closeServer(server);
|
|
267
|
-
if (isAddressUnavailableError(error)) {
|
|
268
|
-
continue;
|
|
269
|
-
}
|
|
270
|
-
await closeServers(servers);
|
|
271
|
-
throw error;
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
if (servers.length === 0) {
|
|
275
|
-
throw new Error("No loopback address is available for OpenAI OAuth login.");
|
|
276
|
-
}
|
|
277
|
-
return servers;
|
|
278
|
-
};
|
|
279
|
-
var closeServer = (server) => new Promise((resolve, reject) => {
|
|
280
|
-
if (!server.listening) {
|
|
281
|
-
resolve();
|
|
282
|
-
return;
|
|
283
|
-
}
|
|
284
|
-
server.close((error) => {
|
|
285
|
-
if (error) {
|
|
286
|
-
reject(error);
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
resolve();
|
|
290
|
-
});
|
|
291
|
-
server.closeIdleConnections?.();
|
|
292
|
-
});
|
|
293
|
-
var isCallbackHostReachable = (host, port, timeoutMs = 100) => new Promise((resolve) => {
|
|
294
|
-
let settled = false;
|
|
295
|
-
const socket = createConnection({ host, port });
|
|
296
|
-
const settle = (value) => {
|
|
297
|
-
if (settled) {
|
|
298
|
-
return;
|
|
299
|
-
}
|
|
300
|
-
settled = true;
|
|
301
|
-
socket.destroy();
|
|
302
|
-
resolve(value);
|
|
303
|
-
};
|
|
304
|
-
socket.setTimeout(timeoutMs);
|
|
305
|
-
socket.once("connect", () => settle(true));
|
|
306
|
-
socket.once("error", () => settle(false));
|
|
307
|
-
socket.once("timeout", () => settle(false));
|
|
308
|
-
});
|
|
309
|
-
var runOpenAIOAuthLogin = async (options = {}) => {
|
|
310
|
-
if (options.signal?.aborted) {
|
|
311
|
-
throw createLoginCancelledError();
|
|
312
|
-
}
|
|
313
|
-
const redirectHost = options.redirectHost ?? DEFAULT_LOGIN_REDIRECT_HOST;
|
|
314
|
-
const listenHost = options.host;
|
|
315
|
-
const callbackPort = DEFAULT_LOGIN_PORT;
|
|
316
|
-
const timeoutMs = options.timeoutMs ?? DEFAULT_LOGIN_TIMEOUT_MS;
|
|
317
|
-
const onMessage = options.onMessage ?? console.log;
|
|
318
|
-
let expectedState = "";
|
|
319
|
-
let redirectUri = "";
|
|
320
|
-
let servers = [];
|
|
321
|
-
let settleCallback;
|
|
322
|
-
let rejectCallback;
|
|
323
|
-
let rejectAbort;
|
|
324
|
-
const callbackPromise = new Promise((resolve, reject) => {
|
|
325
|
-
settleCallback = resolve;
|
|
326
|
-
rejectCallback = reject;
|
|
327
|
-
});
|
|
328
|
-
const abortPromise = new Promise((_, reject) => {
|
|
329
|
-
rejectAbort = reject;
|
|
330
|
-
});
|
|
331
|
-
const abortLogin = () => {
|
|
332
|
-
rejectAbort?.(createLoginCancelledError());
|
|
333
|
-
};
|
|
334
|
-
options.signal?.addEventListener("abort", abortLogin, { once: true });
|
|
335
|
-
const handleCallbackRequest = (req, res) => {
|
|
336
|
-
const url = new URL(req.url ?? "/", redirectUri || `http://${redirectHost}`);
|
|
337
|
-
if (url.pathname === "/cancel") {
|
|
338
|
-
res.writeHead(200, textHeaders);
|
|
339
|
-
res.end("Cancelled");
|
|
340
|
-
rejectCallback?.(new Error("OpenAI OAuth login cancelled."));
|
|
341
|
-
return;
|
|
342
|
-
}
|
|
343
|
-
if (url.pathname !== "/auth/callback") {
|
|
344
|
-
res.writeHead(404, textHeaders);
|
|
345
|
-
res.end("Not found");
|
|
346
|
-
return;
|
|
347
|
-
}
|
|
348
|
-
const error = url.searchParams.get("error");
|
|
349
|
-
if (error) {
|
|
350
|
-
res.writeHead(400, htmlHeaders);
|
|
351
|
-
res.end(
|
|
352
|
-
toCallbackHtml(
|
|
353
|
-
"OpenAI OAuth login failed",
|
|
354
|
-
"You can close this window and return to the terminal."
|
|
355
|
-
)
|
|
356
|
-
);
|
|
357
|
-
rejectCallback?.(new Error(`OpenAI OAuth login failed: ${error}`));
|
|
358
|
-
return;
|
|
359
|
-
}
|
|
360
|
-
const state = url.searchParams.get("state");
|
|
361
|
-
const code = url.searchParams.get("code");
|
|
362
|
-
if (!code || state !== expectedState) {
|
|
363
|
-
res.writeHead(400, htmlHeaders);
|
|
364
|
-
res.end(
|
|
365
|
-
toCallbackHtml(
|
|
366
|
-
"OpenAI OAuth login failed",
|
|
367
|
-
"You can close this window and return to the terminal."
|
|
368
|
-
)
|
|
369
|
-
);
|
|
370
|
-
rejectCallback?.(new Error("OpenAI OAuth callback was invalid."));
|
|
371
|
-
return;
|
|
372
|
-
}
|
|
373
|
-
res.writeHead(200, htmlHeaders);
|
|
374
|
-
res.end(callback_success_default);
|
|
375
|
-
settleCallback?.({ code });
|
|
376
|
-
};
|
|
377
|
-
if (await isCallbackHostReachable(redirectHost, callbackPort)) {
|
|
378
|
-
throw new Error(toCallbackPortInUseMessage(redirectHost, callbackPort));
|
|
379
|
-
}
|
|
380
|
-
try {
|
|
381
|
-
servers = await listenOnCallbackPort(
|
|
382
|
-
handleCallbackRequest,
|
|
383
|
-
callbackPort,
|
|
384
|
-
listenHost
|
|
385
|
-
);
|
|
386
|
-
const address = servers[0]?.address();
|
|
387
|
-
if (address?.port !== callbackPort) {
|
|
388
|
-
throw new Error("OpenAI OAuth login callback port could not be resolved.");
|
|
389
|
-
}
|
|
390
|
-
} catch (error) {
|
|
391
|
-
if (isAddressInUseError(error)) {
|
|
392
|
-
throw new Error(toCallbackPortInUseMessage(redirectHost, callbackPort));
|
|
393
|
-
}
|
|
394
|
-
throw error;
|
|
395
|
-
}
|
|
396
|
-
try {
|
|
397
|
-
redirectUri = `http://${redirectHost}:${callbackPort}/auth/callback`;
|
|
398
|
-
if (options.signal?.aborted) {
|
|
399
|
-
throw createLoginCancelledError();
|
|
400
|
-
}
|
|
401
|
-
const request = await createOpenAIOAuthRequest({
|
|
402
|
-
redirectUri,
|
|
403
|
-
clientId: options.clientId
|
|
404
|
-
});
|
|
405
|
-
expectedState = request.state;
|
|
406
|
-
onMessage(`OpenAI OAuth login URL: ${request.authorizationUrl}`);
|
|
407
|
-
if (options.openBrowser !== false) {
|
|
408
|
-
openUrl(request.authorizationUrl);
|
|
409
|
-
}
|
|
410
|
-
const timeout = new Promise((_, reject) => {
|
|
411
|
-
setTimeout(() => {
|
|
412
|
-
reject(new Error("OpenAI OAuth login timed out."));
|
|
413
|
-
}, timeoutMs).unref();
|
|
414
|
-
});
|
|
415
|
-
const callback = await Promise.race([
|
|
416
|
-
callbackPromise,
|
|
417
|
-
timeout,
|
|
418
|
-
abortPromise
|
|
419
|
-
]);
|
|
420
|
-
const token = await exchangeOpenAIOAuthCode({
|
|
421
|
-
code: callback.code,
|
|
422
|
-
codeVerifier: request.codeVerifier,
|
|
423
|
-
redirectUri,
|
|
424
|
-
clientId: options.clientId,
|
|
425
|
-
tokenUrl: options.tokenUrl,
|
|
426
|
-
fetch: options.fetch,
|
|
427
|
-
signal: options.signal
|
|
428
|
-
});
|
|
429
|
-
const saved = await saveAuthTokens({
|
|
430
|
-
token,
|
|
431
|
-
authFilePath: options.authFilePath
|
|
432
|
-
});
|
|
433
|
-
onMessage(`Credentials saved to ${saved.path}`);
|
|
434
|
-
return saved;
|
|
435
|
-
} finally {
|
|
436
|
-
options.signal?.removeEventListener("abort", abortLogin);
|
|
437
|
-
await closeServers(servers);
|
|
438
|
-
}
|
|
439
|
-
};
|
|
440
|
-
|
|
441
|
-
// src/server.ts
|
|
442
|
-
import { createServer as createServer2 } from "http";
|
|
443
|
-
import {
|
|
444
|
-
createOpenAIOAuth
|
|
445
|
-
} from "@openai-oauth/ai-sdk";
|
|
446
|
-
import { createCodexOAuthClient } from "@openai-oauth/core";
|
|
447
|
-
import { openaiCredentials } from "@openai-oauth/local";
|
|
448
|
-
|
|
449
|
-
// src/chat-completions.ts
|
|
450
|
-
import { generateText } from "ai";
|
|
451
|
-
|
|
452
|
-
// src/chat-messages.ts
|
|
453
|
-
import { jsonSchema, tool } from "ai";
|
|
454
|
-
|
|
455
|
-
// src/shared.ts
|
|
456
|
-
import { Buffer } from "buffer";
|
|
457
|
-
var DEFAULT_HOST = "127.0.0.1";
|
|
458
|
-
var DEFAULT_PORT = 10531;
|
|
459
|
-
var jsonHeaders = {
|
|
460
|
-
"content-type": "application/json; charset=utf-8"
|
|
461
|
-
};
|
|
462
|
-
var sseHeaders = {
|
|
463
|
-
"content-type": "text/event-stream; charset=utf-8",
|
|
464
|
-
"cache-control": "no-cache, no-transform",
|
|
465
|
-
connection: "keep-alive",
|
|
466
|
-
"x-accel-buffering": "no"
|
|
467
|
-
};
|
|
468
|
-
var corsHeaders = {
|
|
469
|
-
"access-control-allow-origin": "*",
|
|
470
|
-
"access-control-allow-methods": "GET,POST,OPTIONS",
|
|
471
|
-
"access-control-allow-headers": "authorization,content-type"
|
|
28
|
+
var corsHeaders = {
|
|
29
|
+
"access-control-allow-origin": "*",
|
|
30
|
+
"access-control-allow-methods": "GET,POST,OPTIONS",
|
|
31
|
+
"access-control-allow-headers": "authorization,content-type"
|
|
472
32
|
};
|
|
473
33
|
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
474
34
|
var isJsonValue = (value) => {
|
|
@@ -535,6 +95,8 @@ var summarizeChatRequest = (request) => ({
|
|
|
535
95
|
});
|
|
536
96
|
var copyUpstreamResponse = (response) => {
|
|
537
97
|
const headers = new Headers(response.headers);
|
|
98
|
+
headers.delete("content-encoding");
|
|
99
|
+
headers.delete("content-length");
|
|
538
100
|
for (const [key, value] of Object.entries(corsHeaders)) {
|
|
539
101
|
headers.set(key, value);
|
|
540
102
|
}
|
|
@@ -1126,10 +688,42 @@ var handleChatCompletionsRequest = async (request, provider, logger) => {
|
|
|
1126
688
|
}
|
|
1127
689
|
};
|
|
1128
690
|
|
|
691
|
+
// src/images.ts
|
|
692
|
+
var handleImageGenerationRequest = async (request, client) => {
|
|
693
|
+
const upstream = await client.request("/images/generations", {
|
|
694
|
+
method: "POST",
|
|
695
|
+
headers: { "Content-Type": "application/json" },
|
|
696
|
+
body: await request.text(),
|
|
697
|
+
signal: request.signal
|
|
698
|
+
});
|
|
699
|
+
return copyUpstreamResponse(upstream);
|
|
700
|
+
};
|
|
701
|
+
var handleImageEditRequest = async (request, client) => {
|
|
702
|
+
if (!request.headers.get("content-type")?.includes("multipart/form-data")) {
|
|
703
|
+
return toErrorResponse(
|
|
704
|
+
"Image editing requires a multipart/form-data request body."
|
|
705
|
+
);
|
|
706
|
+
}
|
|
707
|
+
let body;
|
|
708
|
+
try {
|
|
709
|
+
body = await request.formData();
|
|
710
|
+
} catch {
|
|
711
|
+
return toErrorResponse("Image editing request contains invalid form data.");
|
|
712
|
+
}
|
|
713
|
+
const upstream = await client.request("/images/edits", {
|
|
714
|
+
method: "POST",
|
|
715
|
+
body,
|
|
716
|
+
signal: request.signal
|
|
717
|
+
});
|
|
718
|
+
return copyUpstreamResponse(upstream);
|
|
719
|
+
};
|
|
720
|
+
|
|
1129
721
|
// src/models.ts
|
|
1130
722
|
var MODELS_CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
723
|
+
var IMAGE_MODEL_ID = "gpt-image-2";
|
|
1131
724
|
var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1132
725
|
var uniqueStrings = (values) => [...new Set(values)];
|
|
726
|
+
var withImageModel = (models) => uniqueStrings([...models, IMAGE_MODEL_ID]);
|
|
1133
727
|
var modelListError = (bodyText) => {
|
|
1134
728
|
try {
|
|
1135
729
|
const parsed = JSON.parse(bodyText);
|
|
@@ -1161,7 +755,7 @@ var readModelList = async (client) => {
|
|
|
1161
755
|
if (models.length === 0) {
|
|
1162
756
|
throw new Error("Codex returned an empty models list.");
|
|
1163
757
|
}
|
|
1164
|
-
return models;
|
|
758
|
+
return withImageModel(models);
|
|
1165
759
|
};
|
|
1166
760
|
var resolveOpenAIOAuthModels = async (client, configuredModels) => Array.isArray(configuredModels) && configuredModels.length > 0 ? uniqueStrings(configuredModels) : readModelList(client);
|
|
1167
761
|
var createModelResolver = (client, configuredModels) => {
|
|
@@ -1251,111 +845,557 @@ var handleRoutes = async (request, settings, provider, client, resolveModels, re
|
|
|
1251
845
|
replay_state: "stateless"
|
|
1252
846
|
});
|
|
1253
847
|
}
|
|
1254
|
-
if (request.method === "GET" && url.pathname === "/v1/models") {
|
|
848
|
+
if (request.method === "GET" && url.pathname === "/v1/models") {
|
|
849
|
+
try {
|
|
850
|
+
const models = await resolveModels();
|
|
851
|
+
return toJsonResponse({
|
|
852
|
+
object: "list",
|
|
853
|
+
data: models.map((id) => ({
|
|
854
|
+
id,
|
|
855
|
+
object: "model",
|
|
856
|
+
created: 0,
|
|
857
|
+
owned_by: "codex-oauth"
|
|
858
|
+
}))
|
|
859
|
+
});
|
|
860
|
+
} catch (error) {
|
|
861
|
+
return toErrorResponse(
|
|
862
|
+
error instanceof Error ? error.message : "Failed to load models.",
|
|
863
|
+
502,
|
|
864
|
+
"upstream_error"
|
|
865
|
+
);
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
if (request.method === "POST" && url.pathname === "/v1/responses") {
|
|
869
|
+
return handleResponsesRequest(request, settings, client);
|
|
870
|
+
}
|
|
871
|
+
if (request.method === "POST" && url.pathname === "/v1/chat/completions") {
|
|
872
|
+
return handleChatCompletionsRequest(request, provider, requestLogger);
|
|
873
|
+
}
|
|
874
|
+
if (request.method === "POST" && url.pathname === "/v1/images/generations") {
|
|
875
|
+
return handleImageGenerationRequest(request, client);
|
|
876
|
+
}
|
|
877
|
+
if (request.method === "POST" && url.pathname === "/v1/images/edits") {
|
|
878
|
+
return handleImageEditRequest(request, client);
|
|
879
|
+
}
|
|
880
|
+
return toErrorResponse("Route not found.", 404, "not_found_error");
|
|
881
|
+
};
|
|
882
|
+
var createOpenAIOAuthFetchHandler = (settings = {}) => {
|
|
883
|
+
const auth = openaiCredentials(settings);
|
|
884
|
+
const sharedSettings = {
|
|
885
|
+
...settings,
|
|
886
|
+
auth: () => auth.getSession(),
|
|
887
|
+
responsesState: false
|
|
888
|
+
};
|
|
889
|
+
const client = createCodexOAuthClient(sharedSettings);
|
|
890
|
+
const provider = createOpenAIOAuth(auth);
|
|
891
|
+
const resolveModels = createModelResolver(client, settings.models);
|
|
892
|
+
const requestLogger = createRequestLogger(settings);
|
|
893
|
+
return async (request) => {
|
|
894
|
+
try {
|
|
895
|
+
return await handleRoutes(
|
|
896
|
+
request,
|
|
897
|
+
settings,
|
|
898
|
+
provider,
|
|
899
|
+
client,
|
|
900
|
+
resolveModels,
|
|
901
|
+
requestLogger
|
|
902
|
+
);
|
|
903
|
+
} catch (error) {
|
|
904
|
+
return toErrorResponse(
|
|
905
|
+
error instanceof Error ? error.message : "Unexpected server error.",
|
|
906
|
+
500,
|
|
907
|
+
"server_error"
|
|
908
|
+
);
|
|
909
|
+
}
|
|
910
|
+
};
|
|
911
|
+
};
|
|
912
|
+
var startOpenAIOAuthServer = async (settings = {}) => {
|
|
913
|
+
const host = settings.host ?? DEFAULT_HOST;
|
|
914
|
+
const port = settings.port ?? DEFAULT_PORT;
|
|
915
|
+
const handler = createOpenAIOAuthFetchHandler(settings);
|
|
916
|
+
const server = createServer(async (req, res) => {
|
|
917
|
+
try {
|
|
918
|
+
const request = await toWebRequest(req, { host, port });
|
|
919
|
+
const response = await handler(request);
|
|
920
|
+
await writeWebResponse(res, response);
|
|
921
|
+
} catch (error) {
|
|
922
|
+
if (res.headersSent || res.writableEnded) {
|
|
923
|
+
res.destroy(error instanceof Error ? error : void 0);
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
const message = error instanceof Error ? error.message : "Unexpected server error.";
|
|
927
|
+
await writeWebResponse(res, toErrorResponse(message, 500, "server_error"));
|
|
928
|
+
}
|
|
929
|
+
});
|
|
930
|
+
await new Promise((resolve, reject) => {
|
|
931
|
+
server.once("error", reject);
|
|
932
|
+
server.listen(port, host, () => {
|
|
933
|
+
server.off("error", reject);
|
|
934
|
+
resolve();
|
|
935
|
+
});
|
|
936
|
+
});
|
|
937
|
+
const address = resolveAddress(server.address(), host);
|
|
938
|
+
return {
|
|
939
|
+
server,
|
|
940
|
+
host: address.host,
|
|
941
|
+
port: address.port,
|
|
942
|
+
url: `http://${address.host}:${address.port}/v1`,
|
|
943
|
+
close: () => new Promise((resolve, reject) => {
|
|
944
|
+
server.close((error) => {
|
|
945
|
+
if (error) {
|
|
946
|
+
reject(error);
|
|
947
|
+
return;
|
|
948
|
+
}
|
|
949
|
+
resolve();
|
|
950
|
+
});
|
|
951
|
+
})
|
|
952
|
+
};
|
|
953
|
+
};
|
|
954
|
+
|
|
955
|
+
// src/login.ts
|
|
956
|
+
import { spawn } from "child_process";
|
|
957
|
+
import { createServer as createServer2 } from "http";
|
|
958
|
+
import { createConnection } from "net";
|
|
959
|
+
import {
|
|
960
|
+
createOpenAIOAuthRequest,
|
|
961
|
+
exchangeOpenAIOAuthCode,
|
|
962
|
+
saveAuthTokens
|
|
963
|
+
} from "@openai-oauth/core";
|
|
964
|
+
|
|
965
|
+
// src/callback-success.html?raw
|
|
966
|
+
var callback_success_default = `<!doctype html>
|
|
967
|
+
<html lang="en">
|
|
968
|
+
<head>
|
|
969
|
+
<meta charset="utf-8" />
|
|
970
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
971
|
+
<title>OpenAI OAuth Sign-In</title>
|
|
972
|
+
<link
|
|
973
|
+
rel="icon"
|
|
974
|
+
type="image/svg+xml"
|
|
975
|
+
href='data:image/svg+xml,%3Csvg width="1412" height="1412" viewBox="0 0 1412 1412" fill="none" xmlns="http://www.w3.org/2000/svg"%3E%3Cstyle%3E.mark%7Bfill:%23111111%7D@media(prefers-color-scheme:dark)%7B.mark%7Bfill:%23ffffff%7D%7D%3C/style%3E%3Cpath class="mark" d="M597.462 0.857699C673.717 -4.5771 755.535 16.0618 820.557 55.7878C839.621 67.4347 853.532 77.8804 870.903 91.7881C915.947 83.6597 962.083 83.5966 1007.15 91.601C1108.64 109.677 1198.75 167.436 1257.54 252.101C1315.95 336.355 1338.56 440.326 1320.41 541.218C1348.4 575.095 1369.47 609.408 1385.5 650.519C1422.8 746.143 1420.65 852.641 1379.53 946.681C1345.7 1023.88 1287.62 1087.95 1214.08 1129.17C1193.85 1140.47 1177.72 1147.33 1156.35 1155.65C1150.8 1167.38 1146.43 1180.08 1140.53 1192.52C1124.33 1226.23 1103.33 1257.42 1078.21 1285.12C1009.53 1360.77 913.675 1406.14 811.622 1411.3C797.103 1412.74 770.195 1411.71 755.535 1410.39C669.671 1402.64 607.216 1373.41 541.228 1320.14C498.371 1327.97 454.491 1328.42 411.479 1321.49C309.519 1305.16 218.308 1248.8 158.127 1164.91C95.5192 1077.93 74.597 975.652 91.7694 870.624C63.5815 837.852 41.1539 800.536 25.4414 760.272C-11.0983 663.999 -8.18036 557.204 33.5617 463.069C77.8418 363.472 155.004 295.015 255.809 256.181C260.004 248.164 265.705 231.947 270.502 221.837C286.044 188.764 306.234 158.081 330.46 130.717C398.638 53.6473 494.725 6.91416 597.462 0.857699ZM803.624 1297.49C879.882 1292.64 946.234 1261.95 997.071 1204.28C1015.09 1183.82 1029.9 1160.75 1041.02 1135.85C1047.58 1121.23 1051.8 1106.22 1056.86 1091.08C1067.19 1060.2 1088.78 1058.15 1115.61 1048.88C1125.47 1045.52 1135.09 1041.52 1144.43 1036.9C1243.91 988.43 1304.38 884.819 1297.64 774.394C1294 716.163 1271.8 660.631 1234.27 615.946C1223.26 602.711 1208.28 591.435 1203.34 574.896C1197.16 554.244 1207.83 529.807 1210.67 506.759C1221.87 416.705 1187.69 326.959 1119.41 267.154C1064.95 219.454 993.758 195.357 921.517 200.173C909.062 200.932 896.689 202.63 884.487 205.252C858.307 210.809 839.711 217.803 816.524 196.759C802.123 183.693 793.783 175.007 777.726 163.451C738.141 135.075 691.432 118.286 642.835 114.967C634.456 114.329 619.975 113.369 611.816 114.357C536.156 118.188 468.827 147.965 417.756 204.614C399.016 225.371 383.578 248.884 371.981 274.328C368.409 282.286 365.23 290.414 362.455 298.682C357.28 314.179 354.556 330.003 342.859 342.026C330.473 354.758 314.132 357.158 297.998 362.604C288.467 365.803 279.144 369.592 270.084 373.948C170.322 421.514 108.992 524.42 114.64 634.77C117.764 693.592 139.719 749.855 177.266 795.249C188.357 808.68 203.749 820.374 208.712 836.975C214.929 857.779 204.623 882.481 201.669 905.586C190.625 994.243 223.634 1082.71 290.065 1142.47C341.827 1188.92 413.829 1216.16 483.523 1212.31C496.702 1211.71 509.821 1210.17 522.783 1207.71C549.917 1202.44 573.428 1193.61 595.85 1215.61C654.397 1273.04 720.807 1298.82 803.624 1297.49Z"/%3E%3C/svg%3E'
|
|
976
|
+
/>
|
|
977
|
+
<style>
|
|
978
|
+
:root {
|
|
979
|
+
color-scheme: light;
|
|
980
|
+
background: #ffffff;
|
|
981
|
+
color: #111111;
|
|
982
|
+
font-family:
|
|
983
|
+
ui-sans-serif,
|
|
984
|
+
system-ui,
|
|
985
|
+
-apple-system,
|
|
986
|
+
BlinkMacSystemFont,
|
|
987
|
+
"Segoe UI",
|
|
988
|
+
sans-serif;
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
body {
|
|
992
|
+
display: grid;
|
|
993
|
+
margin: 0;
|
|
994
|
+
min-height: 100vh;
|
|
995
|
+
place-items: center;
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
main {
|
|
999
|
+
text-align: center;
|
|
1000
|
+
width: min(430px, calc(100vw - 48px));
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
.brand {
|
|
1004
|
+
align-items: center;
|
|
1005
|
+
display: inline-flex;
|
|
1006
|
+
gap: 7px;
|
|
1007
|
+
margin-bottom: 28px;
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
.logo {
|
|
1011
|
+
display: block;
|
|
1012
|
+
height: 16px;
|
|
1013
|
+
transform: translateY(-1px);
|
|
1014
|
+
width: 16px;
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
.wordmark {
|
|
1018
|
+
display: block;
|
|
1019
|
+
height: 15px;
|
|
1020
|
+
width: auto;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
h1 {
|
|
1024
|
+
font-size: clamp(25px, 3.1vw, 31px);
|
|
1025
|
+
font-weight: 540;
|
|
1026
|
+
letter-spacing: 0;
|
|
1027
|
+
line-height: 1.1;
|
|
1028
|
+
margin: 0;
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
p {
|
|
1032
|
+
color: #111111;
|
|
1033
|
+
font-size: 18px;
|
|
1034
|
+
line-height: 1.45;
|
|
1035
|
+
margin: 18px auto 0;
|
|
1036
|
+
max-width: 340px;
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
footer {
|
|
1040
|
+
align-items: center;
|
|
1041
|
+
bottom: 34px;
|
|
1042
|
+
color: #6f6f6f;
|
|
1043
|
+
display: flex;
|
|
1044
|
+
flex-direction: column;
|
|
1045
|
+
font-size: 12px;
|
|
1046
|
+
gap: 7px;
|
|
1047
|
+
left: 24px;
|
|
1048
|
+
line-height: 1.25;
|
|
1049
|
+
position: fixed;
|
|
1050
|
+
right: 24px;
|
|
1051
|
+
text-align: center;
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
footer a {
|
|
1055
|
+
color: inherit;
|
|
1056
|
+
text-decoration: none;
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
footer a:hover {
|
|
1060
|
+
color: #111111;
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
.footer-links {
|
|
1064
|
+
align-items: center;
|
|
1065
|
+
display: flex;
|
|
1066
|
+
gap: 8px;
|
|
1067
|
+
justify-content: center;
|
|
1068
|
+
}
|
|
1069
|
+
</style>
|
|
1070
|
+
</head>
|
|
1071
|
+
<body>
|
|
1072
|
+
<main aria-labelledby="title">
|
|
1073
|
+
<div class="brand" aria-label="OpenAI OAuth">
|
|
1074
|
+
<svg
|
|
1075
|
+
aria-hidden="true"
|
|
1076
|
+
class="logo"
|
|
1077
|
+
fill="none"
|
|
1078
|
+
viewBox="0 0 1412 1412"
|
|
1079
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
1080
|
+
>
|
|
1081
|
+
<path
|
|
1082
|
+
d="M597.462 0.857699C673.717 -4.5771 755.535 16.0618 820.557 55.7878C839.621 67.4347 853.532 77.8804 870.903 91.7881C915.947 83.6597 962.083 83.5966 1007.15 91.601C1108.64 109.677 1198.75 167.436 1257.54 252.101C1315.95 336.355 1338.56 440.326 1320.41 541.218C1348.4 575.095 1369.47 609.408 1385.5 650.519C1422.8 746.143 1420.65 852.641 1379.53 946.681C1345.7 1023.88 1287.62 1087.95 1214.08 1129.17C1193.85 1140.47 1177.72 1147.33 1156.35 1155.65C1150.8 1167.38 1146.43 1180.08 1140.53 1192.52C1124.33 1226.23 1103.33 1257.42 1078.21 1285.12C1009.53 1360.77 913.675 1406.14 811.622 1411.3C797.103 1412.74 770.195 1411.71 755.535 1410.39C669.671 1402.64 607.216 1373.41 541.228 1320.14C498.371 1327.97 454.491 1328.42 411.479 1321.49C309.519 1305.16 218.308 1248.8 158.127 1164.91C95.5192 1077.93 74.597 975.652 91.7694 870.624C63.5815 837.852 41.1539 800.536 25.4414 760.272C-11.0983 663.999 -8.18036 557.204 33.5617 463.069C77.8418 363.472 155.004 295.015 255.809 256.181C260.004 248.164 265.705 231.947 270.502 221.837C286.044 188.764 306.234 158.081 330.46 130.717C398.638 53.6473 494.725 6.91416 597.462 0.857699ZM803.624 1297.49C879.882 1292.64 946.234 1261.95 997.071 1204.28C1015.09 1183.82 1029.9 1160.75 1041.02 1135.85C1047.58 1121.23 1051.8 1106.22 1056.86 1091.08C1067.19 1060.2 1088.78 1058.15 1115.61 1048.88C1125.47 1045.52 1135.09 1041.52 1144.43 1036.9C1243.91 988.43 1304.38 884.819 1297.64 774.394C1294 716.163 1271.8 660.631 1234.27 615.946C1223.26 602.711 1208.28 591.435 1203.34 574.896C1197.16 554.244 1207.83 529.807 1210.67 506.759C1221.87 416.705 1187.69 326.959 1119.41 267.154C1064.95 219.454 993.758 195.357 921.517 200.173C909.062 200.932 896.689 202.63 884.487 205.252C858.307 210.809 839.711 217.803 816.524 196.759C802.123 183.693 793.783 175.007 777.726 163.451C738.141 135.075 691.432 118.286 642.835 114.967C634.456 114.329 619.975 113.369 611.816 114.357C536.156 118.188 468.827 147.965 417.756 204.614C399.016 225.371 383.578 248.884 371.981 274.328C368.409 282.286 365.23 290.414 362.455 298.682C357.28 314.179 354.556 330.003 342.859 342.026C330.473 354.758 314.132 357.158 297.998 362.604C288.467 365.803 279.144 369.592 270.084 373.948C170.322 421.514 108.992 524.42 114.64 634.77C117.764 693.592 139.719 749.855 177.266 795.249C188.357 808.68 203.749 820.374 208.712 836.975C214.929 857.779 204.623 882.481 201.669 905.586C190.625 994.243 223.634 1082.71 290.065 1142.47C341.827 1188.92 413.829 1216.16 483.523 1212.31C496.702 1211.71 509.821 1210.17 522.783 1207.71C549.917 1202.44 573.428 1193.61 595.85 1215.61C654.397 1273.04 720.807 1298.82 803.624 1297.49Z"
|
|
1083
|
+
fill="currentColor"
|
|
1084
|
+
/>
|
|
1085
|
+
<path
|
|
1086
|
+
d="M528.104 673.1C645.003 673.1 739.769 767.837 739.769 884.701C739.769 1001.56 645.003 1096.3 528.104 1096.3C411.204 1096.3 316.439 1001.56 316.439 884.701C316.439 767.837 411.204 673.1 528.104 673.1ZM526.618 785.954C472.886 785.954 429.327 829.499 429.327 883.216C429.327 936.932 472.886 980.478 526.618 980.478C580.351 980.478 623.91 936.932 623.91 883.216C623.91 829.499 580.351 785.954 526.618 785.954Z"
|
|
1087
|
+
fill="currentColor"
|
|
1088
|
+
fill-rule="evenodd"
|
|
1089
|
+
clip-rule="evenodd"
|
|
1090
|
+
/>
|
|
1091
|
+
<path
|
|
1092
|
+
d="M974.454 335.733L1055.33 416.583L688.769 783.031L607.895 702.182L974.454 335.733Z"
|
|
1093
|
+
fill="currentColor"
|
|
1094
|
+
/>
|
|
1095
|
+
<path
|
|
1096
|
+
d="M820.585 766.758L704.525 767.283L821.11 650.733L820.585 766.758Z"
|
|
1097
|
+
fill="currentColor"
|
|
1098
|
+
/>
|
|
1099
|
+
<path
|
|
1100
|
+
d="M937.694 649.684L821.11 650.733L938.744 533.135L937.694 649.684Z"
|
|
1101
|
+
fill="currentColor"
|
|
1102
|
+
/>
|
|
1103
|
+
<path
|
|
1104
|
+
d="M1054.8 532.611L938.744 533.135L1055.33 416.586L1054.8 532.611Z"
|
|
1105
|
+
fill="currentColor"
|
|
1106
|
+
/>
|
|
1107
|
+
<path
|
|
1108
|
+
d="M1054.8 336.259L1055.33 416.583L974.454 335.733L1054.8 336.259Z"
|
|
1109
|
+
fill="currentColor"
|
|
1110
|
+
/>
|
|
1111
|
+
</svg>
|
|
1112
|
+
<svg
|
|
1113
|
+
aria-label="OpenAI OAuth"
|
|
1114
|
+
class="wordmark"
|
|
1115
|
+
fill="none"
|
|
1116
|
+
viewBox="0 0 2769 391"
|
|
1117
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
1118
|
+
>
|
|
1119
|
+
<path d="M2495.6 239.383L2495.6 4.36719H2442.96L2442.96 251.081C2442.96 264.073 2446.69 279.793 2455.73 289.364C2464.76 298.935 2471.68 305.315 2488.69 305.315H2549.84V263.31H2514.21C2507.02 263.31 2501.82 258.862 2499.33 254.803C2496.83 250.743 2495.6 246.21 2495.6 239.383Z" fill="black"/>
|
|
1120
|
+
<rect x="2543.46" y="90.5039" width="47.854" height="146.752" transform="rotate(90 2543.46 90.5039)" fill="black"/>
|
|
1121
|
+
<path d="M1734.79 0C1649.66 0 1580 69.6496 1580 154.777C1580 239.904 1649.66 309.554 1734.79 309.554C1819.93 309.554 1889.59 240.334 1889.59 154.777C1889.59 69.2197 1820.36 0 1734.79 0ZM1734.79 254.092C1681.91 254.092 1639.34 210.669 1639.34 154.777C1639.34 98.8852 1681.91 55.4617 1734.79 55.4617C1787.68 55.4617 1830.25 98.8852 1830.25 154.777C1830.25 210.669 1787.68 254.092 1734.79 254.092Z" fill="black"/>
|
|
1122
|
+
<path d="M1984.56 8.62109L1862.87 309.576H1922.64L1948.44 243.796H2086.89L2112.69 309.576H2173.32L2052.49 8.62109H1984.56ZM1967.79 193.923L2017.67 67.9522L2067.11 193.923H1967.79Z" fill="black"/>
|
|
1123
|
+
<path d="M2687.02 86.0449C2662.08 86.0449 2635.86 97.2232 2623.82 115.71V4.36719H2567.92V305.312H2623.82V189.659C2623.82 156.124 2641.88 134.198 2671.11 134.198C2698.2 134.198 2712.82 154.835 2712.82 183.64V305.312H2768.72V174.612C2768.72 121.3 2736.04 86.0449 2687.02 86.0449Z" fill="black"/>
|
|
1124
|
+
<path d="M2255.09 309.773C2280.02 309.773 2306.25 298.595 2318.29 280.108L2318.29 305.474L2374.19 305.474L2374.19 90.5062L2318.29 90.5062L2318.29 206.159C2318.29 239.694 2300.23 261.621 2271 261.621C2243.91 261.621 2229.29 240.984 2229.29 212.178L2229.29 90.5062L2173.39 90.5062L2173.39 221.207C2173.39 274.519 2206.07 309.773 2255.09 309.773Z" fill="black"/>
|
|
1125
|
+
<path d="M154.577 0C69.5595 0 0 69.6066 0 154.681C0 239.756 69.5595 309.363 154.577 309.363C239.594 309.363 309.153 240.186 309.153 154.681C309.153 69.1769 240.023 0 154.577 0ZM154.577 253.935C101.763 253.935 59.2544 210.538 59.2544 154.681C59.2544 98.8242 101.763 55.4275 154.577 55.4275C207.39 55.4275 249.899 98.8242 249.899 154.681C249.899 210.538 207.39 253.935 154.577 253.935ZM465.447 85.9341C437.533 85.9341 410.487 97.1055 396.312 116.011V90.2308H340.493V391H396.312V282.293C410.482 299.91 436.674 309.363 465.442 309.363C525.555 309.363 572.787 262.099 572.787 197.648C572.787 133.198 525.561 85.9341 465.447 85.9341ZM455.996 260.81C424.222 260.81 395.883 235.889 395.883 197.648C395.883 159.408 424.222 134.487 455.996 134.487C487.77 134.487 516.104 159.408 516.104 197.648C516.104 235.889 487.77 260.81 455.996 260.81ZM704.187 85.9341C643.216 85.9341 595.125 133.627 595.125 197.648C595.125 261.669 637.204 309.363 705.905 309.363C762.154 309.363 798.222 275.419 809.385 237.178H754.854C747.984 253.076 728.662 264.247 705.476 264.247C676.707 264.247 654.809 244.053 649.656 215.265H811.962V193.352C811.962 134.916 771.171 85.9341 704.187 85.9341ZM650.086 175.735C656.097 148.666 678.425 131.049 705.476 131.049C734.244 131.049 756.142 149.955 758.719 175.735H650.086ZM960.522 85.9341C935.618 85.9341 909.426 97.1055 897.403 115.581V90.2308H841.584V305.066H897.403V189.485C897.403 155.97 915.437 134.057 944.635 134.057C971.686 134.057 986.285 154.681 986.285 183.469V305.066H1042.1V174.446C1042.1 121.167 1009.47 85.9341 960.522 85.9341ZM1185.07 4.30681L1063.55 305.076H1123.24L1149 239.336H1287.26L1313.02 305.076H1373.56L1252.91 4.30681H1185.07ZM1168.32 189.495L1218.13 63.6013L1267.51 189.495H1168.32ZM1453 4.30681H1396.32V305.076H1453V4.30681Z" fill="black"/>
|
|
1126
|
+
</svg>
|
|
1127
|
+
</div>
|
|
1128
|
+
<h1 id="title">Sign-in complete</h1>
|
|
1129
|
+
<p>
|
|
1130
|
+
Your ChatGPT credentials are saved locally. You can close this
|
|
1131
|
+
window and return to your terminal.
|
|
1132
|
+
</p>
|
|
1133
|
+
</main>
|
|
1134
|
+
<footer>
|
|
1135
|
+
<a href="https://github.com/evanzhoudev/openai-oauth">
|
|
1136
|
+
Learn more about OpenAI OAuth
|
|
1137
|
+
</a>
|
|
1138
|
+
<div class="footer-links">
|
|
1139
|
+
<a href="https://github.com/evanzhoudev/openai-oauth">GitHub</a>
|
|
1140
|
+
<span aria-hidden="true">\u22C5</span>
|
|
1141
|
+
<a href="https://github.com/evanzhoudev/openai-oauth#legal">Legal</a>
|
|
1142
|
+
</div>
|
|
1143
|
+
</footer>
|
|
1144
|
+
</body>
|
|
1145
|
+
</html>
|
|
1146
|
+
`;
|
|
1147
|
+
|
|
1148
|
+
// src/login.ts
|
|
1149
|
+
var DEFAULT_LOGIN_REDIRECT_HOST = "localhost";
|
|
1150
|
+
var DEFAULT_LOGIN_PORT = 1455;
|
|
1151
|
+
var DEFAULT_LOGIN_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
1152
|
+
var LOOPBACK_LISTEN_HOSTS = ["::1", "127.0.0.1"];
|
|
1153
|
+
var isAddressInUseError = (error) => error instanceof Error && "code" in error && error.code === "EADDRINUSE";
|
|
1154
|
+
var isAddressUnavailableError = (error) => error instanceof Error && "code" in error && ["EADDRNOTAVAIL", "EAFNOSUPPORT"].includes(
|
|
1155
|
+
String(error.code)
|
|
1156
|
+
);
|
|
1157
|
+
var createLoginCancelledError = () => new Error("OpenAI OAuth login cancelled.");
|
|
1158
|
+
var toCallbackHtml = (title, message) => `<!doctype html>
|
|
1159
|
+
<html lang="en">
|
|
1160
|
+
<head>
|
|
1161
|
+
<meta charset="utf-8" />
|
|
1162
|
+
<title>${title}</title>
|
|
1163
|
+
<style>
|
|
1164
|
+
body {
|
|
1165
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
1166
|
+
margin: 3rem;
|
|
1167
|
+
line-height: 1.5;
|
|
1168
|
+
}
|
|
1169
|
+
</style>
|
|
1170
|
+
</head>
|
|
1171
|
+
<body>
|
|
1172
|
+
<h1>${title}</h1>
|
|
1173
|
+
<p>${message}</p>
|
|
1174
|
+
</body>
|
|
1175
|
+
</html>`;
|
|
1176
|
+
var htmlHeaders = {
|
|
1177
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
1178
|
+
Connection: "close"
|
|
1179
|
+
};
|
|
1180
|
+
var textHeaders = {
|
|
1181
|
+
"Content-Type": "text/plain; charset=utf-8",
|
|
1182
|
+
Connection: "close"
|
|
1183
|
+
};
|
|
1184
|
+
var openUrl = (url) => {
|
|
1185
|
+
const platform = process.platform;
|
|
1186
|
+
const command = platform === "darwin" ? "open" : platform === "win32" ? "cmd" : "xdg-open";
|
|
1187
|
+
const args = platform === "win32" ? ["/c", "start", '""', url] : [url];
|
|
1188
|
+
const child = spawn(command, args, {
|
|
1189
|
+
detached: true,
|
|
1190
|
+
stdio: "ignore"
|
|
1191
|
+
});
|
|
1192
|
+
child.on("error", () => void 0);
|
|
1193
|
+
child.unref();
|
|
1194
|
+
};
|
|
1195
|
+
var toCallbackPortInUseMessage = (redirectHost, port) => `OpenAI OAuth login needs http://${redirectHost}:${port}/auth/callback, but port ${port} is already in use. Stop the process using that port and try again.`;
|
|
1196
|
+
var listen = (server, port, host) => new Promise((resolve, reject) => {
|
|
1197
|
+
server.once("error", reject);
|
|
1198
|
+
const onListening = () => {
|
|
1199
|
+
server.off("error", reject);
|
|
1200
|
+
resolve();
|
|
1201
|
+
};
|
|
1202
|
+
server.listen(port, host, onListening);
|
|
1203
|
+
});
|
|
1204
|
+
var closeServers = async (servers) => {
|
|
1205
|
+
await Promise.all(servers.map((server) => closeServer(server)));
|
|
1206
|
+
};
|
|
1207
|
+
var listenOnCallbackPort = async (handler, port, host) => {
|
|
1208
|
+
if (host) {
|
|
1209
|
+
const server = createServer2(handler);
|
|
1210
|
+
await listen(server, port, host);
|
|
1211
|
+
return [server];
|
|
1212
|
+
}
|
|
1213
|
+
const servers = [];
|
|
1214
|
+
for (const loopbackHost of LOOPBACK_LISTEN_HOSTS) {
|
|
1215
|
+
const server = createServer2(handler);
|
|
1255
1216
|
try {
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
object: "list",
|
|
1259
|
-
data: models.map((id) => ({
|
|
1260
|
-
id,
|
|
1261
|
-
object: "model",
|
|
1262
|
-
created: 0,
|
|
1263
|
-
owned_by: "codex-oauth"
|
|
1264
|
-
}))
|
|
1265
|
-
});
|
|
1217
|
+
await listen(server, port, loopbackHost);
|
|
1218
|
+
servers.push(server);
|
|
1266
1219
|
} catch (error) {
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
);
|
|
1220
|
+
await closeServer(server);
|
|
1221
|
+
if (isAddressUnavailableError(error)) {
|
|
1222
|
+
continue;
|
|
1223
|
+
}
|
|
1224
|
+
await closeServers(servers);
|
|
1225
|
+
throw error;
|
|
1272
1226
|
}
|
|
1273
1227
|
}
|
|
1274
|
-
if (
|
|
1275
|
-
|
|
1276
|
-
}
|
|
1277
|
-
if (request.method === "POST" && url.pathname === "/v1/chat/completions") {
|
|
1278
|
-
return handleChatCompletionsRequest(request, provider, requestLogger);
|
|
1228
|
+
if (servers.length === 0) {
|
|
1229
|
+
throw new Error("No loopback address is available for OpenAI OAuth login.");
|
|
1279
1230
|
}
|
|
1280
|
-
return
|
|
1231
|
+
return servers;
|
|
1281
1232
|
};
|
|
1282
|
-
var
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1233
|
+
var closeServer = (server) => new Promise((resolve, reject) => {
|
|
1234
|
+
if (!server.listening) {
|
|
1235
|
+
resolve();
|
|
1236
|
+
return;
|
|
1237
|
+
}
|
|
1238
|
+
server.close((error) => {
|
|
1239
|
+
if (error) {
|
|
1240
|
+
reject(error);
|
|
1241
|
+
return;
|
|
1242
|
+
}
|
|
1243
|
+
resolve();
|
|
1244
|
+
});
|
|
1245
|
+
server.closeIdleConnections?.();
|
|
1246
|
+
});
|
|
1247
|
+
var isCallbackHostReachable = (host, port, timeoutMs = 100) => new Promise((resolve) => {
|
|
1248
|
+
let settled = false;
|
|
1249
|
+
const socket = createConnection({ host, port });
|
|
1250
|
+
const settle = (value) => {
|
|
1251
|
+
if (settled) {
|
|
1252
|
+
return;
|
|
1253
|
+
}
|
|
1254
|
+
settled = true;
|
|
1255
|
+
socket.destroy();
|
|
1256
|
+
resolve(value);
|
|
1288
1257
|
};
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1258
|
+
socket.setTimeout(timeoutMs);
|
|
1259
|
+
socket.once("connect", () => settle(true));
|
|
1260
|
+
socket.once("error", () => settle(false));
|
|
1261
|
+
socket.once("timeout", () => settle(false));
|
|
1262
|
+
});
|
|
1263
|
+
var runOpenAIOAuthLogin = async (options = {}) => {
|
|
1264
|
+
if (options.signal?.aborted) {
|
|
1265
|
+
throw createLoginCancelledError();
|
|
1266
|
+
}
|
|
1267
|
+
const redirectHost = options.redirectHost ?? DEFAULT_LOGIN_REDIRECT_HOST;
|
|
1268
|
+
const listenHost = options.host;
|
|
1269
|
+
const callbackPort = DEFAULT_LOGIN_PORT;
|
|
1270
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_LOGIN_TIMEOUT_MS;
|
|
1271
|
+
const onMessage = options.onMessage ?? console.log;
|
|
1272
|
+
let expectedState = "";
|
|
1273
|
+
let redirectUri = "";
|
|
1274
|
+
let servers = [];
|
|
1275
|
+
let settleCallback;
|
|
1276
|
+
let rejectCallback;
|
|
1277
|
+
let rejectAbort;
|
|
1278
|
+
const callbackPromise = new Promise((resolve, reject) => {
|
|
1279
|
+
settleCallback = resolve;
|
|
1280
|
+
rejectCallback = reject;
|
|
1281
|
+
});
|
|
1282
|
+
const abortPromise = new Promise((_, reject) => {
|
|
1283
|
+
rejectAbort = reject;
|
|
1284
|
+
});
|
|
1285
|
+
const abortLogin = () => {
|
|
1286
|
+
rejectAbort?.(createLoginCancelledError());
|
|
1287
|
+
};
|
|
1288
|
+
options.signal?.addEventListener("abort", abortLogin, { once: true });
|
|
1289
|
+
const handleCallbackRequest = (req, res) => {
|
|
1290
|
+
const url = new URL(req.url ?? "/", redirectUri || `http://${redirectHost}`);
|
|
1291
|
+
if (url.pathname === "/cancel") {
|
|
1292
|
+
res.writeHead(200, textHeaders);
|
|
1293
|
+
res.end("Cancelled");
|
|
1294
|
+
rejectCallback?.(new Error("OpenAI OAuth login cancelled."));
|
|
1295
|
+
return;
|
|
1296
|
+
}
|
|
1297
|
+
if (url.pathname !== "/auth/callback") {
|
|
1298
|
+
res.writeHead(404, textHeaders);
|
|
1299
|
+
res.end("Not found");
|
|
1300
|
+
return;
|
|
1301
|
+
}
|
|
1302
|
+
const error = url.searchParams.get("error");
|
|
1303
|
+
if (error) {
|
|
1304
|
+
res.writeHead(400, htmlHeaders);
|
|
1305
|
+
res.end(
|
|
1306
|
+
toCallbackHtml(
|
|
1307
|
+
"OpenAI OAuth login failed",
|
|
1308
|
+
"You can close this window and return to the terminal."
|
|
1309
|
+
)
|
|
1302
1310
|
);
|
|
1303
|
-
|
|
1304
|
-
return
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1311
|
+
rejectCallback?.(new Error(`OpenAI OAuth login failed: ${error}`));
|
|
1312
|
+
return;
|
|
1313
|
+
}
|
|
1314
|
+
const state = url.searchParams.get("state");
|
|
1315
|
+
const code = url.searchParams.get("code");
|
|
1316
|
+
if (!code || state !== expectedState) {
|
|
1317
|
+
res.writeHead(400, htmlHeaders);
|
|
1318
|
+
res.end(
|
|
1319
|
+
toCallbackHtml(
|
|
1320
|
+
"OpenAI OAuth login failed",
|
|
1321
|
+
"You can close this window and return to the terminal."
|
|
1322
|
+
)
|
|
1308
1323
|
);
|
|
1324
|
+
rejectCallback?.(new Error("OpenAI OAuth callback was invalid."));
|
|
1325
|
+
return;
|
|
1309
1326
|
}
|
|
1327
|
+
res.writeHead(200, htmlHeaders);
|
|
1328
|
+
res.end(callback_success_default);
|
|
1329
|
+
settleCallback?.({ code });
|
|
1310
1330
|
};
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
res.destroy(error instanceof Error ? error : void 0);
|
|
1324
|
-
return;
|
|
1325
|
-
}
|
|
1326
|
-
const message = error instanceof Error ? error.message : "Unexpected server error.";
|
|
1327
|
-
await writeWebResponse(res, toErrorResponse(message, 500, "server_error"));
|
|
1331
|
+
if (await isCallbackHostReachable(redirectHost, callbackPort)) {
|
|
1332
|
+
throw new Error(toCallbackPortInUseMessage(redirectHost, callbackPort));
|
|
1333
|
+
}
|
|
1334
|
+
try {
|
|
1335
|
+
servers = await listenOnCallbackPort(
|
|
1336
|
+
handleCallbackRequest,
|
|
1337
|
+
callbackPort,
|
|
1338
|
+
listenHost
|
|
1339
|
+
);
|
|
1340
|
+
const address = servers[0]?.address();
|
|
1341
|
+
if (address?.port !== callbackPort) {
|
|
1342
|
+
throw new Error("OpenAI OAuth login callback port could not be resolved.");
|
|
1328
1343
|
}
|
|
1329
|
-
})
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1344
|
+
} catch (error) {
|
|
1345
|
+
if (isAddressInUseError(error)) {
|
|
1346
|
+
throw new Error(toCallbackPortInUseMessage(redirectHost, callbackPort));
|
|
1347
|
+
}
|
|
1348
|
+
throw error;
|
|
1349
|
+
}
|
|
1350
|
+
try {
|
|
1351
|
+
redirectUri = `http://${redirectHost}:${callbackPort}/auth/callback`;
|
|
1352
|
+
if (options.signal?.aborted) {
|
|
1353
|
+
throw createLoginCancelledError();
|
|
1354
|
+
}
|
|
1355
|
+
const request = await createOpenAIOAuthRequest({
|
|
1356
|
+
redirectUri,
|
|
1357
|
+
clientId: options.clientId
|
|
1335
1358
|
});
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1359
|
+
expectedState = request.state;
|
|
1360
|
+
onMessage(`OpenAI OAuth login URL: ${request.authorizationUrl}`);
|
|
1361
|
+
if (options.openBrowser !== false) {
|
|
1362
|
+
openUrl(request.authorizationUrl);
|
|
1363
|
+
}
|
|
1364
|
+
const timeout = new Promise((_, reject) => {
|
|
1365
|
+
setTimeout(() => {
|
|
1366
|
+
reject(new Error("OpenAI OAuth login timed out."));
|
|
1367
|
+
}, timeoutMs).unref();
|
|
1368
|
+
});
|
|
1369
|
+
const callback = await Promise.race([
|
|
1370
|
+
callbackPromise,
|
|
1371
|
+
timeout,
|
|
1372
|
+
abortPromise
|
|
1373
|
+
]);
|
|
1374
|
+
const token = await exchangeOpenAIOAuthCode({
|
|
1375
|
+
code: callback.code,
|
|
1376
|
+
codeVerifier: request.codeVerifier,
|
|
1377
|
+
redirectUri,
|
|
1378
|
+
clientId: options.clientId,
|
|
1379
|
+
tokenUrl: options.tokenUrl,
|
|
1380
|
+
fetch: options.fetch,
|
|
1381
|
+
signal: options.signal
|
|
1382
|
+
});
|
|
1383
|
+
const saved = await saveAuthTokens({
|
|
1384
|
+
token,
|
|
1385
|
+
authFilePath: options.authFilePath
|
|
1386
|
+
});
|
|
1387
|
+
onMessage(`Credentials saved to ${saved.path}`);
|
|
1388
|
+
return saved;
|
|
1389
|
+
} finally {
|
|
1390
|
+
options.signal?.removeEventListener("abort", abortLogin);
|
|
1391
|
+
await closeServers(servers);
|
|
1392
|
+
}
|
|
1353
1393
|
};
|
|
1354
1394
|
|
|
1355
1395
|
export {
|
|
1356
|
-
runOpenAIOAuthLogin,
|
|
1357
|
-
DEFAULT_PORT,
|
|
1358
1396
|
resolveOpenAIOAuthModels,
|
|
1397
|
+
DEFAULT_PORT,
|
|
1359
1398
|
createOpenAIOAuthFetchHandler,
|
|
1360
|
-
startOpenAIOAuthServer
|
|
1399
|
+
startOpenAIOAuthServer,
|
|
1400
|
+
runOpenAIOAuthLogin
|
|
1361
1401
|
};
|