codex-multi-auth 0.1.0

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.
Files changed (327) hide show
  1. package/LICENSE +1 -0
  2. package/README.md +162 -0
  3. package/assets/opencode-logo-ornate-dark.svg +18 -0
  4. package/assets/readme-hero.svg +31 -0
  5. package/config/README.md +87 -0
  6. package/config/minimal-opencode.json +13 -0
  7. package/config/opencode-legacy.json +571 -0
  8. package/config/opencode-modern.json +239 -0
  9. package/dist/index.d.ts +45 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +3160 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/lib/accounts/rate-limits.d.ts +22 -0
  14. package/dist/lib/accounts/rate-limits.d.ts.map +1 -0
  15. package/dist/lib/accounts/rate-limits.js +63 -0
  16. package/dist/lib/accounts/rate-limits.js.map +1 -0
  17. package/dist/lib/accounts.d.ts +95 -0
  18. package/dist/lib/accounts.d.ts.map +1 -0
  19. package/dist/lib/accounts.js +668 -0
  20. package/dist/lib/accounts.js.map +1 -0
  21. package/dist/lib/audit.d.ts +45 -0
  22. package/dist/lib/audit.d.ts.map +1 -0
  23. package/dist/lib/audit.js +131 -0
  24. package/dist/lib/audit.js.map +1 -0
  25. package/dist/lib/auth/auth.d.ts +56 -0
  26. package/dist/lib/auth/auth.d.ts.map +1 -0
  27. package/dist/lib/auth/auth.js +214 -0
  28. package/dist/lib/auth/auth.js.map +1 -0
  29. package/dist/lib/auth/browser.d.ts +34 -0
  30. package/dist/lib/auth/browser.d.ts.map +1 -0
  31. package/dist/lib/auth/browser.js +185 -0
  32. package/dist/lib/auth/browser.js.map +1 -0
  33. package/dist/lib/auth/server.d.ts +24 -0
  34. package/dist/lib/auth/server.d.ts.map +1 -0
  35. package/dist/lib/auth/server.js +116 -0
  36. package/dist/lib/auth/server.js.map +1 -0
  37. package/dist/lib/auth/token-utils.d.ts +59 -0
  38. package/dist/lib/auth/token-utils.d.ts.map +1 -0
  39. package/dist/lib/auth/token-utils.js +331 -0
  40. package/dist/lib/auth/token-utils.js.map +1 -0
  41. package/dist/lib/auth-rate-limit.d.ts +20 -0
  42. package/dist/lib/auth-rate-limit.d.ts.map +1 -0
  43. package/dist/lib/auth-rate-limit.js +91 -0
  44. package/dist/lib/auth-rate-limit.js.map +1 -0
  45. package/dist/lib/auto-update-checker.d.ts +10 -0
  46. package/dist/lib/auto-update-checker.d.ts.map +1 -0
  47. package/dist/lib/auto-update-checker.js +216 -0
  48. package/dist/lib/auto-update-checker.js.map +1 -0
  49. package/dist/lib/capability-policy.d.ts +18 -0
  50. package/dist/lib/capability-policy.d.ts.map +1 -0
  51. package/dist/lib/capability-policy.js +150 -0
  52. package/dist/lib/capability-policy.js.map +1 -0
  53. package/dist/lib/circuit-breaker.d.ts +34 -0
  54. package/dist/lib/circuit-breaker.d.ts.map +1 -0
  55. package/dist/lib/circuit-breaker.js +124 -0
  56. package/dist/lib/circuit-breaker.js.map +1 -0
  57. package/dist/lib/cli.d.ts +64 -0
  58. package/dist/lib/cli.d.ts.map +1 -0
  59. package/dist/lib/cli.js +274 -0
  60. package/dist/lib/cli.js.map +1 -0
  61. package/dist/lib/codex-cli/observability.d.ts +22 -0
  62. package/dist/lib/codex-cli/observability.d.ts.map +1 -0
  63. package/dist/lib/codex-cli/observability.js +36 -0
  64. package/dist/lib/codex-cli/observability.js.map +1 -0
  65. package/dist/lib/codex-cli/state.d.ts +86 -0
  66. package/dist/lib/codex-cli/state.d.ts.map +1 -0
  67. package/dist/lib/codex-cli/state.js +470 -0
  68. package/dist/lib/codex-cli/state.js.map +1 -0
  69. package/dist/lib/codex-cli/sync.d.ts +27 -0
  70. package/dist/lib/codex-cli/sync.d.ts.map +1 -0
  71. package/dist/lib/codex-cli/sync.js +325 -0
  72. package/dist/lib/codex-cli/sync.js.map +1 -0
  73. package/dist/lib/codex-cli/writer.d.ts +12 -0
  74. package/dist/lib/codex-cli/writer.d.ts.map +1 -0
  75. package/dist/lib/codex-cli/writer.js +388 -0
  76. package/dist/lib/codex-cli/writer.js.map +1 -0
  77. package/dist/lib/codex-manager.d.ts +2 -0
  78. package/dist/lib/codex-manager.d.ts.map +1 -0
  79. package/dist/lib/codex-manager.js +4841 -0
  80. package/dist/lib/codex-manager.js.map +1 -0
  81. package/dist/lib/config.d.ts +269 -0
  82. package/dist/lib/config.d.ts.map +1 -0
  83. package/dist/lib/config.js +789 -0
  84. package/dist/lib/config.js.map +1 -0
  85. package/dist/lib/constants.d.ts +78 -0
  86. package/dist/lib/constants.d.ts.map +1 -0
  87. package/dist/lib/constants.js +78 -0
  88. package/dist/lib/constants.js.map +1 -0
  89. package/dist/lib/context-overflow.d.ts +27 -0
  90. package/dist/lib/context-overflow.d.ts.map +1 -0
  91. package/dist/lib/context-overflow.js +124 -0
  92. package/dist/lib/context-overflow.js.map +1 -0
  93. package/dist/lib/dashboard-settings.d.ts +90 -0
  94. package/dist/lib/dashboard-settings.d.ts.map +1 -0
  95. package/dist/lib/dashboard-settings.js +327 -0
  96. package/dist/lib/dashboard-settings.js.map +1 -0
  97. package/dist/lib/entitlement-cache.d.ts +41 -0
  98. package/dist/lib/entitlement-cache.d.ts.map +1 -0
  99. package/dist/lib/entitlement-cache.js +137 -0
  100. package/dist/lib/entitlement-cache.js.map +1 -0
  101. package/dist/lib/errors.d.ts +113 -0
  102. package/dist/lib/errors.d.ts.map +1 -0
  103. package/dist/lib/errors.js +103 -0
  104. package/dist/lib/errors.js.map +1 -0
  105. package/dist/lib/forecast.d.ts +42 -0
  106. package/dist/lib/forecast.d.ts.map +1 -0
  107. package/dist/lib/forecast.js +256 -0
  108. package/dist/lib/forecast.js.map +1 -0
  109. package/dist/lib/health.d.ts +33 -0
  110. package/dist/lib/health.d.ts.map +1 -0
  111. package/dist/lib/health.js +70 -0
  112. package/dist/lib/health.js.map +1 -0
  113. package/dist/lib/index.d.ts +32 -0
  114. package/dist/lib/index.d.ts.map +1 -0
  115. package/dist/lib/index.js +32 -0
  116. package/dist/lib/index.js.map +1 -0
  117. package/dist/lib/live-account-sync.d.ts +39 -0
  118. package/dist/lib/live-account-sync.d.ts.map +1 -0
  119. package/dist/lib/live-account-sync.js +196 -0
  120. package/dist/lib/live-account-sync.js.map +1 -0
  121. package/dist/lib/logger.d.ts +40 -0
  122. package/dist/lib/logger.d.ts.map +1 -0
  123. package/dist/lib/logger.js +364 -0
  124. package/dist/lib/logger.js.map +1 -0
  125. package/dist/lib/oauth-success.html +338 -0
  126. package/dist/lib/parallel-probe.d.ts +28 -0
  127. package/dist/lib/parallel-probe.d.ts.map +1 -0
  128. package/dist/lib/parallel-probe.js +97 -0
  129. package/dist/lib/parallel-probe.js.map +1 -0
  130. package/dist/lib/preemptive-quota-scheduler.d.ts +53 -0
  131. package/dist/lib/preemptive-quota-scheduler.d.ts.map +1 -0
  132. package/dist/lib/preemptive-quota-scheduler.js +220 -0
  133. package/dist/lib/preemptive-quota-scheduler.js.map +1 -0
  134. package/dist/lib/proactive-refresh.d.ts +66 -0
  135. package/dist/lib/proactive-refresh.d.ts.map +1 -0
  136. package/dist/lib/proactive-refresh.js +143 -0
  137. package/dist/lib/proactive-refresh.js.map +1 -0
  138. package/dist/lib/prompts/codex-opencode-bridge.d.ts +19 -0
  139. package/dist/lib/prompts/codex-opencode-bridge.d.ts.map +1 -0
  140. package/dist/lib/prompts/codex-opencode-bridge.js +169 -0
  141. package/dist/lib/prompts/codex-opencode-bridge.js.map +1 -0
  142. package/dist/lib/prompts/codex.d.ts +41 -0
  143. package/dist/lib/prompts/codex.d.ts.map +1 -0
  144. package/dist/lib/prompts/codex.js +383 -0
  145. package/dist/lib/prompts/codex.js.map +1 -0
  146. package/dist/lib/prompts/opencode-codex.d.ts +25 -0
  147. package/dist/lib/prompts/opencode-codex.d.ts.map +1 -0
  148. package/dist/lib/prompts/opencode-codex.js +270 -0
  149. package/dist/lib/prompts/opencode-codex.js.map +1 -0
  150. package/dist/lib/quota-cache.d.ts +68 -0
  151. package/dist/lib/quota-cache.d.ts.map +1 -0
  152. package/dist/lib/quota-cache.js +224 -0
  153. package/dist/lib/quota-cache.js.map +1 -0
  154. package/dist/lib/quota-probe.d.ts +49 -0
  155. package/dist/lib/quota-probe.d.ts.map +1 -0
  156. package/dist/lib/quota-probe.js +368 -0
  157. package/dist/lib/quota-probe.js.map +1 -0
  158. package/dist/lib/recovery/constants.d.ts +12 -0
  159. package/dist/lib/recovery/constants.d.ts.map +1 -0
  160. package/dist/lib/recovery/constants.js +31 -0
  161. package/dist/lib/recovery/constants.js.map +1 -0
  162. package/dist/lib/recovery/index.d.ts +12 -0
  163. package/dist/lib/recovery/index.d.ts.map +1 -0
  164. package/dist/lib/recovery/index.js +12 -0
  165. package/dist/lib/recovery/index.js.map +1 -0
  166. package/dist/lib/recovery/storage.d.ts +24 -0
  167. package/dist/lib/recovery/storage.d.ts.map +1 -0
  168. package/dist/lib/recovery/storage.js +362 -0
  169. package/dist/lib/recovery/storage.js.map +1 -0
  170. package/dist/lib/recovery/types.d.ts +116 -0
  171. package/dist/lib/recovery/types.d.ts.map +1 -0
  172. package/dist/lib/recovery/types.js +7 -0
  173. package/dist/lib/recovery/types.js.map +1 -0
  174. package/dist/lib/recovery.d.ts +31 -0
  175. package/dist/lib/recovery.d.ts.map +1 -0
  176. package/dist/lib/recovery.js +313 -0
  177. package/dist/lib/recovery.js.map +1 -0
  178. package/dist/lib/refresh-guardian.d.ts +31 -0
  179. package/dist/lib/refresh-guardian.d.ts.map +1 -0
  180. package/dist/lib/refresh-guardian.js +151 -0
  181. package/dist/lib/refresh-guardian.js.map +1 -0
  182. package/dist/lib/refresh-lease.d.ts +37 -0
  183. package/dist/lib/refresh-lease.d.ts.map +1 -0
  184. package/dist/lib/refresh-lease.js +335 -0
  185. package/dist/lib/refresh-lease.js.map +1 -0
  186. package/dist/lib/refresh-queue.d.ts +117 -0
  187. package/dist/lib/refresh-queue.d.ts.map +1 -0
  188. package/dist/lib/refresh-queue.js +297 -0
  189. package/dist/lib/refresh-queue.js.map +1 -0
  190. package/dist/lib/request/failure-policy.d.ts +42 -0
  191. package/dist/lib/request/failure-policy.d.ts.map +1 -0
  192. package/dist/lib/request/failure-policy.js +133 -0
  193. package/dist/lib/request/failure-policy.js.map +1 -0
  194. package/dist/lib/request/fetch-helpers.d.ts +152 -0
  195. package/dist/lib/request/fetch-helpers.d.ts.map +1 -0
  196. package/dist/lib/request/fetch-helpers.js +704 -0
  197. package/dist/lib/request/fetch-helpers.js.map +1 -0
  198. package/dist/lib/request/helpers/input-utils.d.ts +7 -0
  199. package/dist/lib/request/helpers/input-utils.d.ts.map +1 -0
  200. package/dist/lib/request/helpers/input-utils.js +214 -0
  201. package/dist/lib/request/helpers/input-utils.js.map +1 -0
  202. package/dist/lib/request/helpers/model-map.d.ts +28 -0
  203. package/dist/lib/request/helpers/model-map.d.ts.map +1 -0
  204. package/dist/lib/request/helpers/model-map.js +133 -0
  205. package/dist/lib/request/helpers/model-map.js.map +1 -0
  206. package/dist/lib/request/helpers/tool-utils.d.ts +29 -0
  207. package/dist/lib/request/helpers/tool-utils.d.ts.map +1 -0
  208. package/dist/lib/request/helpers/tool-utils.js +117 -0
  209. package/dist/lib/request/helpers/tool-utils.js.map +1 -0
  210. package/dist/lib/request/rate-limit-backoff.d.ts +17 -0
  211. package/dist/lib/request/rate-limit-backoff.d.ts.map +1 -0
  212. package/dist/lib/request/rate-limit-backoff.js +83 -0
  213. package/dist/lib/request/rate-limit-backoff.js.map +1 -0
  214. package/dist/lib/request/request-transformer.d.ts +107 -0
  215. package/dist/lib/request/request-transformer.d.ts.map +1 -0
  216. package/dist/lib/request/request-transformer.js +814 -0
  217. package/dist/lib/request/request-transformer.js.map +1 -0
  218. package/dist/lib/request/response-handler.d.ts +23 -0
  219. package/dist/lib/request/response-handler.d.ts.map +1 -0
  220. package/dist/lib/request/response-handler.js +155 -0
  221. package/dist/lib/request/response-handler.js.map +1 -0
  222. package/dist/lib/request/stream-failover.d.ts +21 -0
  223. package/dist/lib/request/stream-failover.d.ts.map +1 -0
  224. package/dist/lib/request/stream-failover.js +204 -0
  225. package/dist/lib/request/stream-failover.js.map +1 -0
  226. package/dist/lib/rotation.d.ts +146 -0
  227. package/dist/lib/rotation.d.ts.map +1 -0
  228. package/dist/lib/rotation.js +321 -0
  229. package/dist/lib/rotation.js.map +1 -0
  230. package/dist/lib/runtime-paths.d.ts +58 -0
  231. package/dist/lib/runtime-paths.d.ts.map +1 -0
  232. package/dist/lib/runtime-paths.js +164 -0
  233. package/dist/lib/runtime-paths.js.map +1 -0
  234. package/dist/lib/schemas.d.ts +435 -0
  235. package/dist/lib/schemas.d.ts.map +1 -0
  236. package/dist/lib/schemas.js +268 -0
  237. package/dist/lib/schemas.js.map +1 -0
  238. package/dist/lib/session-affinity.d.ts +23 -0
  239. package/dist/lib/session-affinity.d.ts.map +1 -0
  240. package/dist/lib/session-affinity.js +127 -0
  241. package/dist/lib/session-affinity.js.map +1 -0
  242. package/dist/lib/shutdown.d.ts +7 -0
  243. package/dist/lib/shutdown.d.ts.map +1 -0
  244. package/dist/lib/shutdown.js +43 -0
  245. package/dist/lib/shutdown.js.map +1 -0
  246. package/dist/lib/storage/migrations.d.ts +59 -0
  247. package/dist/lib/storage/migrations.d.ts.map +1 -0
  248. package/dist/lib/storage/migrations.js +41 -0
  249. package/dist/lib/storage/migrations.js.map +1 -0
  250. package/dist/lib/storage/paths.d.ts +51 -0
  251. package/dist/lib/storage/paths.d.ts.map +1 -0
  252. package/dist/lib/storage/paths.js +152 -0
  253. package/dist/lib/storage/paths.js.map +1 -0
  254. package/dist/lib/storage.d.ts +106 -0
  255. package/dist/lib/storage.d.ts.map +1 -0
  256. package/dist/lib/storage.js +896 -0
  257. package/dist/lib/storage.js.map +1 -0
  258. package/dist/lib/table-formatter.d.ts +32 -0
  259. package/dist/lib/table-formatter.d.ts.map +1 -0
  260. package/dist/lib/table-formatter.js +44 -0
  261. package/dist/lib/table-formatter.js.map +1 -0
  262. package/dist/lib/tools/hashline-tools.d.ts +51 -0
  263. package/dist/lib/tools/hashline-tools.d.ts.map +1 -0
  264. package/dist/lib/tools/hashline-tools.js +456 -0
  265. package/dist/lib/tools/hashline-tools.js.map +1 -0
  266. package/dist/lib/types.d.ts +130 -0
  267. package/dist/lib/types.d.ts.map +1 -0
  268. package/dist/lib/types.js +2 -0
  269. package/dist/lib/types.js.map +1 -0
  270. package/dist/lib/ui/ansi.d.ts +40 -0
  271. package/dist/lib/ui/ansi.d.ts.map +1 -0
  272. package/dist/lib/ui/ansi.js +68 -0
  273. package/dist/lib/ui/ansi.js.map +1 -0
  274. package/dist/lib/ui/auth-menu.d.ts +76 -0
  275. package/dist/lib/ui/auth-menu.d.ts.map +1 -0
  276. package/dist/lib/ui/auth-menu.js +590 -0
  277. package/dist/lib/ui/auth-menu.js.map +1 -0
  278. package/dist/lib/ui/confirm.d.ts +11 -0
  279. package/dist/lib/ui/confirm.d.ts.map +1 -0
  280. package/dist/lib/ui/confirm.js +29 -0
  281. package/dist/lib/ui/confirm.js.map +1 -0
  282. package/dist/lib/ui/copy.d.ts +123 -0
  283. package/dist/lib/ui/copy.d.ts.map +1 -0
  284. package/dist/lib/ui/copy.js +127 -0
  285. package/dist/lib/ui/copy.js.map +1 -0
  286. package/dist/lib/ui/format.d.ts +62 -0
  287. package/dist/lib/ui/format.d.ts.map +1 -0
  288. package/dist/lib/ui/format.js +205 -0
  289. package/dist/lib/ui/format.js.map +1 -0
  290. package/dist/lib/ui/runtime.d.ts +43 -0
  291. package/dist/lib/ui/runtime.d.ts.map +1 -0
  292. package/dist/lib/ui/runtime.js +69 -0
  293. package/dist/lib/ui/runtime.js.map +1 -0
  294. package/dist/lib/ui/select.d.ts +60 -0
  295. package/dist/lib/ui/select.d.ts.map +1 -0
  296. package/dist/lib/ui/select.js +467 -0
  297. package/dist/lib/ui/select.js.map +1 -0
  298. package/dist/lib/ui/theme.d.ts +56 -0
  299. package/dist/lib/ui/theme.d.ts.map +1 -0
  300. package/dist/lib/ui/theme.js +186 -0
  301. package/dist/lib/ui/theme.js.map +1 -0
  302. package/dist/lib/unified-settings.d.ts +71 -0
  303. package/dist/lib/unified-settings.d.ts.map +1 -0
  304. package/dist/lib/unified-settings.js +299 -0
  305. package/dist/lib/unified-settings.js.map +1 -0
  306. package/dist/lib/utils.d.ts +29 -0
  307. package/dist/lib/utils.d.ts.map +1 -0
  308. package/dist/lib/utils.js +54 -0
  309. package/dist/lib/utils.js.map +1 -0
  310. package/package.json +115 -0
  311. package/scripts/audit-dev-allowlist.js +128 -0
  312. package/scripts/bench-format/hashline-v2.mjs +642 -0
  313. package/scripts/bench-format/models.mjs +105 -0
  314. package/scripts/bench-format/opencode.mjs +205 -0
  315. package/scripts/bench-format/render.mjs +496 -0
  316. package/scripts/bench-format/stats.mjs +54 -0
  317. package/scripts/bench-format/tasks.mjs +151 -0
  318. package/scripts/benchmark-edit-formats.mjs +1161 -0
  319. package/scripts/benchmark-render-dashboard.mjs +49 -0
  320. package/scripts/codex-multi-auth.js +6 -0
  321. package/scripts/codex-routing.js +34 -0
  322. package/scripts/codex.js +122 -0
  323. package/scripts/copy-oauth-success.js +37 -0
  324. package/scripts/install-opencode-codex-auth.js +193 -0
  325. package/scripts/test-all-models.sh +7 -0
  326. package/scripts/test-model-matrix.js +424 -0
  327. package/scripts/validate-model-map.sh +7 -0
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Browser utilities for OAuth flow
3
+ * Handles platform-specific browser opening
4
+ */
5
+ import { spawn } from "node:child_process";
6
+ import fs from "node:fs";
7
+ import path from "node:path";
8
+ import { PLATFORM_OPENERS } from "../constants.js";
9
+ /**
10
+ * Gets the platform-specific command to open a URL in the default browser
11
+ * @returns Browser opener command for the current platform
12
+ */
13
+ export function getBrowserOpener() {
14
+ const platform = process.platform;
15
+ if (platform === "darwin")
16
+ return PLATFORM_OPENERS.darwin;
17
+ if (platform === "win32")
18
+ return PLATFORM_OPENERS.win32;
19
+ return PLATFORM_OPENERS.linux;
20
+ }
21
+ /**
22
+ * Determines whether a given command name exists on the system PATH.
23
+ *
24
+ * @param command - The command name to check.
25
+ * @returns `true` if a matching executable is found on PATH (on Windows this includes PATHEXT extensions or the literal `"start"`), `false` otherwise.
26
+ *
27
+ * Concurrency: result reflects the current filesystem state and may change after return; no atomicity guarantees.
28
+ * Windows filesystem behavior: resolves executable candidates using PATHEXT extensions.
29
+ * Token handling: the `command` string is used verbatim for lookup and is not redacted or modified.
30
+ */
31
+ function commandExists(command) {
32
+ if (!command)
33
+ return false;
34
+ /* v8 ignore start -- unreachable: openBrowserUrl uses PowerShell on win32 */
35
+ if (process.platform === "win32" && command.toLowerCase() === "start") {
36
+ return true;
37
+ }
38
+ /* v8 ignore stop */
39
+ const pathValue = process.env.PATH || "";
40
+ const entries = pathValue.split(path.delimiter).filter(Boolean);
41
+ if (entries.length === 0)
42
+ return false;
43
+ /* v8 ignore start -- unreachable: openBrowserUrl uses PowerShell on win32 */
44
+ if (process.platform === "win32") {
45
+ const pathext = (process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM")
46
+ .split(";")
47
+ .filter(Boolean);
48
+ const hasExtension = /\.[^\\/]+$/.test(command);
49
+ for (const entry of entries) {
50
+ if (hasExtension) {
51
+ const directCandidate = path.join(entry, command);
52
+ if (fs.existsSync(directCandidate))
53
+ return true;
54
+ continue;
55
+ }
56
+ for (const ext of pathext) {
57
+ const candidate = path.join(entry, `${command}${ext}`);
58
+ if (fs.existsSync(candidate))
59
+ return true;
60
+ }
61
+ }
62
+ return false;
63
+ }
64
+ /* v8 ignore stop */
65
+ for (const entry of entries) {
66
+ const candidate = path.join(entry, command);
67
+ try {
68
+ const stats = fs.statSync(candidate);
69
+ if (!stats.isFile())
70
+ continue;
71
+ // On POSIX, ensure at least one executable bit is set.
72
+ if ((stats.mode & 0o111) === 0)
73
+ continue;
74
+ return true;
75
+ }
76
+ catch {
77
+ continue;
78
+ }
79
+ }
80
+ return false;
81
+ }
82
+ /**
83
+ * Launches the user's default browser to open the provided URL using a platform-appropriate command.
84
+ *
85
+ * This is a best-effort, fire-and-forget launcher: it attempts a platform-specific spawn and ignores
86
+ * child-process errors. On Windows it uses PowerShell `Start-Process` with PowerShell meta-character
87
+ * escaping to reduce shell/filesystem quirks. Callers must redact any sensitive tokens (for example,
88
+ * OAuth codes) from `url` before calling. Invocations are not atomic—concurrent calls may race but are
89
+ * safe to perform.
90
+ *
91
+ * @param url - The URL to open; redact sensitive tokens (e.g., OAuth codes) before passing.
92
+ * @returns `true` if a browser launch was attempted, `false` if no suitable opener was available or an exception occurred.
93
+ */
94
+ export function openBrowserUrl(url) {
95
+ try {
96
+ // Windows: use PowerShell Start-Process to avoid cmd/start quirks with URLs containing '&' or ':'
97
+ if (process.platform === "win32") {
98
+ if (!commandExists("powershell.exe")) {
99
+ return false;
100
+ }
101
+ // Escape PowerShell special characters: backticks, double quotes, and $ (sub-expression injection)
102
+ const psUrl = url
103
+ .replace(/`/g, "``")
104
+ .replace(/\$/g, "`$")
105
+ .replace(/"/g, '""');
106
+ const child = spawn("powershell.exe", ["-NoLogo", "-NoProfile", "-Command", `Start-Process "${psUrl}"`], { stdio: "ignore" });
107
+ child.on("error", () => { });
108
+ return true;
109
+ }
110
+ const opener = getBrowserOpener();
111
+ if (!commandExists(opener)) {
112
+ return false;
113
+ }
114
+ const child = spawn(opener, [url], {
115
+ stdio: "ignore",
116
+ shell: false,
117
+ });
118
+ child.on("error", () => { });
119
+ return true;
120
+ }
121
+ catch {
122
+ // Silently fail - user can manually open the URL from instructions
123
+ return false;
124
+ }
125
+ }
126
+ /**
127
+ * Copy text into the system clipboard using a best-effort, platform-specific command.
128
+ *
129
+ * On Windows the text is escaped for PowerShell to avoid interpretation of special characters.
130
+ * This function makes no guarantees of atomicity across processes; concurrent invocations may interleave.
131
+ * Clipboard contents are not redacted or logged — callers must mask or remove sensitive tokens before calling.
132
+ *
133
+ * @param text - The text to copy; falsy or empty values produce no action
134
+ * @returns `true` if a clipboard command was launched, `false` otherwise
135
+ */
136
+ export function copyTextToClipboard(text) {
137
+ try {
138
+ if (!text)
139
+ return false;
140
+ if (process.platform === "win32") {
141
+ if (!commandExists("powershell.exe")) {
142
+ return false;
143
+ }
144
+ const psText = text
145
+ .replace(/`/g, "``")
146
+ .replace(/\$/g, "`$")
147
+ .replace(/"/g, '""');
148
+ const child = spawn("powershell.exe", ["-NoLogo", "-NoProfile", "-Command", `Set-Clipboard -Value "${psText}"`], { stdio: "ignore" });
149
+ child.on("error", () => { });
150
+ return true;
151
+ }
152
+ if (process.platform === "darwin") {
153
+ if (!commandExists("pbcopy"))
154
+ return false;
155
+ const child = spawn("pbcopy", [], {
156
+ stdio: ["pipe", "ignore", "ignore"],
157
+ shell: false,
158
+ });
159
+ child.on("error", () => { });
160
+ child.stdin?.end(text);
161
+ return true;
162
+ }
163
+ const linuxClipboardCommands = [
164
+ { command: "wl-copy", args: [] },
165
+ { command: "xclip", args: ["-selection", "clipboard"] },
166
+ { command: "xsel", args: ["--clipboard", "--input"] },
167
+ ];
168
+ for (const { command, args } of linuxClipboardCommands) {
169
+ if (!commandExists(command))
170
+ continue;
171
+ const child = spawn(command, args, {
172
+ stdio: ["pipe", "ignore", "ignore"],
173
+ shell: false,
174
+ });
175
+ child.on("error", () => { });
176
+ child.stdin?.end(text);
177
+ return true;
178
+ }
179
+ return false;
180
+ }
181
+ catch {
182
+ return false;
183
+ }
184
+ }
185
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../../../lib/auth/browser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { OAuthServerInfo } from "../types.js";
2
+ /**
3
+ * Start a local HTTP server that captures an OAuth authorization code sent to /auth/callback.
4
+ *
5
+ * The server validates the `state` query parameter, serves a static success page for valid callbacks,
6
+ * and retains a single authorization code on the server instance until consumed via `waitForCode`.
7
+ * Only one code is stored at a time; call `close` to abort polling and shut down the server.
8
+ *
9
+ * On platforms such as Windows, binding to 127.0.0.1:1455 may fail if another process holds the port
10
+ * or if firewall/antivirus restrictions prevent local binding; in that case the returned `ready`
11
+ * flag is `false` to allow a manual paste fallback.
12
+ *
13
+ * Captured authorization codes are secrets and must be treated accordingly; callers should redact
14
+ * them from logs and error messages.
15
+ *
16
+ * @param options - Object with a `state` string used to validate the OAuth redirect
17
+ * @returns An OAuthServerInfo describing the server: `port` (1455), `ready` (boolean), a `close`
18
+ * function to abort polling and close the server, and `waitForCode` which returns
19
+ * `{ code: string }` when a code becomes available or `null` on timeout/abort.
20
+ */
21
+ export declare function startLocalOAuthServer({ state }: {
22
+ state: string;
23
+ }): Promise<OAuthServerInfo>;
24
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../lib/auth/server.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAOnD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,eAAe,CAAC,CA4F5F"}
@@ -0,0 +1,116 @@
1
+ import http from "node:http";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { logError, logWarn } from "../logger.js";
6
+ // Resolve path to oauth-success.html (one level up from auth/ subfolder)
7
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
+ const successHtml = fs.readFileSync(path.join(__dirname, "..", "oauth-success.html"), "utf-8");
9
+ /**
10
+ * Start a local HTTP server that captures an OAuth authorization code sent to /auth/callback.
11
+ *
12
+ * The server validates the `state` query parameter, serves a static success page for valid callbacks,
13
+ * and retains a single authorization code on the server instance until consumed via `waitForCode`.
14
+ * Only one code is stored at a time; call `close` to abort polling and shut down the server.
15
+ *
16
+ * On platforms such as Windows, binding to 127.0.0.1:1455 may fail if another process holds the port
17
+ * or if firewall/antivirus restrictions prevent local binding; in that case the returned `ready`
18
+ * flag is `false` to allow a manual paste fallback.
19
+ *
20
+ * Captured authorization codes are secrets and must be treated accordingly; callers should redact
21
+ * them from logs and error messages.
22
+ *
23
+ * @param options - Object with a `state` string used to validate the OAuth redirect
24
+ * @returns An OAuthServerInfo describing the server: `port` (1455), `ready` (boolean), a `close`
25
+ * function to abort polling and close the server, and `waitForCode` which returns
26
+ * `{ code: string }` when a code becomes available or `null` on timeout/abort.
27
+ */
28
+ export function startLocalOAuthServer({ state }) {
29
+ let pollAborted = false;
30
+ const server = http.createServer((req, res) => {
31
+ try {
32
+ const url = new URL(req.url || "", "http://localhost");
33
+ if (url.pathname !== "/auth/callback") {
34
+ res.statusCode = 404;
35
+ res.end("Not found");
36
+ return;
37
+ }
38
+ if (url.searchParams.get("state") !== state) {
39
+ res.statusCode = 400;
40
+ res.end("State mismatch");
41
+ return;
42
+ }
43
+ const code = url.searchParams.get("code");
44
+ if (!code) {
45
+ res.statusCode = 400;
46
+ res.end("Missing authorization code");
47
+ return;
48
+ }
49
+ res.statusCode = 200;
50
+ res.setHeader("Content-Type", "text/html; charset=utf-8");
51
+ res.setHeader("X-Frame-Options", "DENY");
52
+ res.setHeader("X-Content-Type-Options", "nosniff");
53
+ res.setHeader("Content-Security-Policy", "default-src 'none'; style-src 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; script-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'");
54
+ res.end(successHtml);
55
+ const trackedServer = server;
56
+ if (trackedServer._lastCode) {
57
+ logWarn("Duplicate OAuth callback received; preserving first authorization code");
58
+ return;
59
+ }
60
+ trackedServer._lastCode = code;
61
+ }
62
+ catch (err) {
63
+ logError(`Request handler error: ${err?.message ?? String(err)}`);
64
+ res.statusCode = 500;
65
+ res.end("Internal error");
66
+ }
67
+ });
68
+ server.unref();
69
+ return new Promise((resolve) => {
70
+ server
71
+ .listen(1455, "127.0.0.1", () => {
72
+ resolve({
73
+ port: 1455,
74
+ ready: true,
75
+ close: () => {
76
+ pollAborted = true;
77
+ server.close();
78
+ },
79
+ waitForCode: async () => {
80
+ const POLL_INTERVAL_MS = 100;
81
+ const TIMEOUT_MS = 5 * 60 * 1000;
82
+ const maxIterations = Math.floor(TIMEOUT_MS / POLL_INTERVAL_MS);
83
+ const poll = () => new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
84
+ for (let i = 0; i < maxIterations; i++) {
85
+ if (pollAborted)
86
+ return null;
87
+ const lastCode = server._lastCode;
88
+ if (lastCode)
89
+ return { code: lastCode };
90
+ await poll();
91
+ }
92
+ logWarn("OAuth poll timeout after 5 minutes");
93
+ return null;
94
+ },
95
+ });
96
+ })
97
+ .on("error", (err) => {
98
+ logError(`Failed to bind http://127.0.0.1:1455 (${err?.code}). Falling back to manual paste.`);
99
+ resolve({
100
+ port: 1455,
101
+ ready: false,
102
+ close: () => {
103
+ pollAborted = true;
104
+ try {
105
+ server.close();
106
+ }
107
+ catch (closeErr) {
108
+ logError(`Failed to close OAuth server: ${closeErr?.message ?? String(closeErr)}`);
109
+ }
110
+ },
111
+ waitForCode: () => Promise.resolve(null),
112
+ });
113
+ });
114
+ });
115
+ }
116
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../lib/auth/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Token utility functions for JWT parsing and account ID extraction.
3
+ * Extracted from accounts.ts to reduce module size and improve cohesion.
4
+ */
5
+ import type { AccountIdSource } from "../types.js";
6
+ /**
7
+ * Account ID candidate from token or organization data.
8
+ */
9
+ export interface AccountIdCandidate {
10
+ accountId: string;
11
+ label: string;
12
+ source: AccountIdSource;
13
+ isDefault?: boolean;
14
+ isPersonal?: boolean;
15
+ }
16
+ /**
17
+ * Select the best workspace candidate for OAuth account binding.
18
+ * Preference order:
19
+ * 1) org default that is not personal
20
+ * 2) org default (any)
21
+ * 3) id_token candidate
22
+ * 4) non-personal org candidate
23
+ * 5) token candidate
24
+ * 6) first candidate
25
+ */
26
+ export declare function selectBestAccountCandidate(candidates: AccountIdCandidate[]): AccountIdCandidate | undefined;
27
+ /**
28
+ * Extracts the ChatGPT account ID from a JWT access token.
29
+ * @param accessToken - JWT access token from OAuth flow
30
+ * @returns Account ID string or undefined if not found
31
+ */
32
+ export declare function extractAccountId(accessToken?: string): string | undefined;
33
+ /**
34
+ * Extracts the email address from OAuth tokens.
35
+ * Checks id_token first (where OpenAI puts email), then falls back to access_token.
36
+ */
37
+ export declare function extractAccountEmail(accessToken?: string, idToken?: string): string | undefined;
38
+ /**
39
+ * Extracts all accountId candidates from access/id tokens.
40
+ * Used to support business workspaces/organizations that are not the token default.
41
+ */
42
+ export declare function getAccountIdCandidates(accessToken?: string, idToken?: string): AccountIdCandidate[];
43
+ /**
44
+ * Determines if accountId should be updated from a token-derived value.
45
+ * We keep org/manual selections stable across refreshes.
46
+ */
47
+ export declare function shouldUpdateAccountIdFromToken(source: AccountIdSource | undefined, currentAccountId?: string): boolean;
48
+ /**
49
+ * Resolve which accountId to use for runtime API calls.
50
+ * Preserves explicit org/manual selections; only token/id_token sources auto-follow token changes.
51
+ */
52
+ export declare function resolveRequestAccountId(storedAccountId: string | undefined, source: AccountIdSource | undefined, tokenAccountId: string | undefined): string | undefined;
53
+ /**
54
+ * Sanitizes an email address by trimming whitespace and lowercasing.
55
+ * @param email - Email string to sanitize
56
+ * @returns Sanitized email or undefined if invalid
57
+ */
58
+ export declare function sanitizeEmail(email: string | undefined): string | undefined;
59
+ //# sourceMappingURL=token-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-utils.d.ts","sourceRoot":"","sources":["../../../lib/auth/token-utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAc,MAAM,aAAa,CAAC;AAE/D;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,eAAe,CAAC;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAoND;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CACzC,UAAU,EAAE,kBAAkB,EAAE,GAC9B,kBAAkB,GAAG,SAAS,CA8BhC;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKzE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAuB9F;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACrC,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,MAAM,GACd,kBAAkB,EAAE,CA+BtB;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAC7C,MAAM,EAAE,eAAe,GAAG,SAAS,EACnC,gBAAgB,CAAC,EAAE,MAAM,GACvB,OAAO,CAIT;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACtC,eAAe,EAAE,MAAM,GAAG,SAAS,EACnC,MAAM,EAAE,eAAe,GAAG,SAAS,EACnC,cAAc,EAAE,MAAM,GAAG,SAAS,GAChC,MAAM,GAAG,SAAS,CAMpB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAK3E"}