@xiaoso/dsh-tool-plus 0.1.0-beta.2 → 0.1.0-beta.4

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 (235) hide show
  1. package/README.en.md +122 -0
  2. package/README.md +3 -2
  3. package/THIRD_PARTY_NOTICES.md +4 -35
  4. package/lib/abort-B7izMMna.mjs +51 -0
  5. package/lib/abort-D1_Z5Ut5.mjs +51 -0
  6. package/lib/abort-dIkZBV7Q.mjs +51 -0
  7. package/lib/amazon-bedrock-B0nxT06F.mjs +917 -0
  8. package/lib/amazon-bedrock-D-shAr1X.mjs +917 -0
  9. package/lib/amazon-bedrock-WQhvjHYu.mjs +917 -0
  10. package/lib/anthropic-BWsZFzU8.mjs +262 -0
  11. package/lib/anthropic-CJCauvYz.mjs +3115 -0
  12. package/lib/anthropic-CMT1Qj1t.mjs +3115 -0
  13. package/lib/anthropic-CZghe_9U.mjs +3115 -0
  14. package/lib/anthropic-sCMH7JID.mjs +262 -0
  15. package/lib/anthropic-tTntD8BD.mjs +262 -0
  16. package/lib/api-key-login-BzqNdM2y.mjs +157 -0
  17. package/lib/api-key-login-CWVwvHT1.mjs +157 -0
  18. package/lib/api-key-login-CpzSezsi.mjs +157 -0
  19. package/lib/aws-credentials-8Mgn5MAy.mjs +867 -0
  20. package/lib/aws-credentials-CXryMobh.mjs +867 -0
  21. package/lib/aws-credentials-ChG79ey-.mjs +867 -0
  22. package/lib/azure-openai-responses-CNkHiLUh.mjs +274 -0
  23. package/lib/azure-openai-responses-Cgmc-rbL.mjs +274 -0
  24. package/lib/azure-openai-responses-DuukbD0F.mjs +274 -0
  25. package/lib/bun-shim.mjs +252 -12
  26. package/lib/bundled-references-CSuBco5p.mjs +55 -0
  27. package/lib/bundled-references-Cavaffah.mjs +55 -0
  28. package/lib/bundled-references-sLN0YdXU.mjs +55 -0
  29. package/lib/callback-server-BEFNf-jf.mjs +398 -0
  30. package/lib/callback-server-CQ5Jo8F-.mjs +398 -0
  31. package/lib/callback-server-DDSrZ6l_.mjs +398 -0
  32. package/lib/client.js +111 -41
  33. package/lib/cursor-B3zg7EHj.mjs +273 -0
  34. package/lib/cursor-B6TUEmgP.mjs +135 -0
  35. package/lib/cursor-BIQfBC6V.mjs +135 -0
  36. package/lib/cursor-D8gvtTL3.mjs +135 -0
  37. package/lib/cursor-DNk6eXDd.mjs +5470 -0
  38. package/lib/cursor-DkSX2h3H.mjs +5441 -0
  39. package/lib/cursor-MjSm74IJ.mjs +273 -0
  40. package/lib/cursor-aJrXeYCb.mjs +273 -0
  41. package/lib/cursor-mJQwUKXK.mjs +5441 -0
  42. package/lib/device-code-DBo3B5nh.mjs +51 -0
  43. package/lib/device-code-DIb0FU-H.mjs +51 -0
  44. package/lib/device-code-OI_tQcmc.mjs +51 -0
  45. package/lib/devin-BHZZyMhO.mjs +95 -0
  46. package/lib/devin-BK7DHeca.mjs +114 -0
  47. package/lib/devin-CfMp3cXS.mjs +95 -0
  48. package/lib/devin-CldyPD8K.mjs +95 -0
  49. package/lib/devin-CzRpTUOA.mjs +114 -0
  50. package/lib/devin-D9zR5B_R.mjs +542 -0
  51. package/lib/devin-DXOeNyU7.mjs +542 -0
  52. package/lib/devin-Q1yem3lp.mjs +114 -0
  53. package/lib/devin-vNZTNUON.mjs +542 -0
  54. package/lib/error-B3bevhrs.mjs +1449 -0
  55. package/lib/error-Dd8DIqs-.mjs +1449 -0
  56. package/lib/error-yCSG0mGC.mjs +1449 -0
  57. package/lib/event-stream-BDPi64mK.mjs +151 -0
  58. package/lib/event-stream-BbFZJy-z.mjs +151 -0
  59. package/lib/event-stream-loUa0s1T.mjs +151 -0
  60. package/lib/fs-promises-shim-Bx0fpxuk.mjs +57 -0
  61. package/lib/github-copilot-4GaMtQmg.mjs +208 -0
  62. package/lib/github-copilot-B1yiyVRh.mjs +104 -0
  63. package/lib/github-copilot-B2HGSIJK.mjs +104 -0
  64. package/lib/github-copilot-BWT3eAOF.mjs +208 -0
  65. package/lib/github-copilot-CYkjeTi3.mjs +208 -0
  66. package/lib/github-copilot-jscUZ8Hf.mjs +104 -0
  67. package/lib/gitlab-duo-CM7Ref1H.mjs +155 -0
  68. package/lib/gitlab-duo-akICyfeD.mjs +155 -0
  69. package/lib/gitlab-duo-gubO4FNw.mjs +155 -0
  70. package/lib/gitlab-duo-workflow-BGAF6JDw.mjs +91 -0
  71. package/lib/gitlab-duo-workflow-CSEgYk3N.mjs +91 -0
  72. package/lib/gitlab-duo-workflow-D78tdn8E.mjs +91 -0
  73. package/lib/google-BS4T25Pn.mjs +30 -0
  74. package/lib/google-TFe-7-of.mjs +30 -0
  75. package/lib/google-antigravity-DGmwC2KV.mjs +198 -0
  76. package/lib/google-antigravity-DNYhgTpA.mjs +198 -0
  77. package/lib/google-antigravity-Dlkdhahq.mjs +198 -0
  78. package/lib/google-auth-B6gjsZvg.mjs +232 -0
  79. package/lib/google-auth-De7_s3eo.mjs +232 -0
  80. package/lib/google-auth-DhqpOYrX.mjs +232 -0
  81. package/lib/google-gemini-cli-BG_LRdIV.mjs +850 -0
  82. package/lib/google-gemini-cli-CWu8HvXW.mjs +211 -0
  83. package/lib/google-gemini-cli-Cb97bzQc.mjs +850 -0
  84. package/lib/google-gemini-cli-Cqds_Q5T.mjs +850 -0
  85. package/lib/google-gemini-cli-Dsztq0N5.mjs +211 -0
  86. package/lib/google-gemini-cli-zJhiOcND.mjs +211 -0
  87. package/lib/google-oauth-shared-CuEHaDDj.mjs +147 -0
  88. package/lib/google-oauth-shared-CwNWYdmR.mjs +147 -0
  89. package/lib/google-oauth-shared-yqlyqPPC.mjs +147 -0
  90. package/lib/google-shared-CgKmmdO3.mjs +760 -0
  91. package/lib/google-shared-Dr-VG-ap.mjs +760 -0
  92. package/lib/google-shared-DzhCb9b0.mjs +760 -0
  93. package/lib/google-vertex-BDN2tLaD.mjs +99 -0
  94. package/lib/google-vertex-DopVOQOG.mjs +99 -0
  95. package/lib/google-vertex-kscbkyRb.mjs +99 -0
  96. package/lib/google-zyDOG9x7.mjs +30 -0
  97. package/lib/identity-Da1GPU9a.mjs +219 -0
  98. package/lib/identity-DnB63pS7.mjs +219 -0
  99. package/lib/identity-xRP7_eSR.mjs +219 -0
  100. package/lib/idle-iterator-Baoyn3Hp.mjs +366 -0
  101. package/lib/idle-iterator-C6XbWcuB.mjs +366 -0
  102. package/lib/idle-iterator-DUjKQEGT.mjs +366 -0
  103. package/lib/index.mjs +4608 -3935
  104. package/lib/kimi--wUOWER5.mjs +236 -0
  105. package/lib/kimi-DMVI-zrZ.mjs +236 -0
  106. package/lib/kimi-Dh0pv3WZ.mjs +236 -0
  107. package/lib/markit-BL3cH47U.mjs +1417 -0
  108. package/lib/markit-BNiNY6SE.mjs +1417 -0
  109. package/lib/markit-M0jhziqU.mjs +1417 -0
  110. package/lib/minimax-code-BK-3eBbz.mjs +53 -0
  111. package/lib/minimax-code-DCbuA6Yk.mjs +53 -0
  112. package/lib/minimax-code-Uq8Qu9LW.mjs +53 -0
  113. package/lib/models-CfT4coYT.mjs +104660 -0
  114. package/lib/models-D_XnT6ay.mjs +104660 -0
  115. package/lib/models-SGASygJ3.mjs +104660 -0
  116. package/lib/ollama-BQMGPxtV.mjs +589 -0
  117. package/lib/ollama-DPzBmq89.mjs +589 -0
  118. package/lib/ollama-DoBz5SFm.mjs +589 -0
  119. package/lib/openai-codex-Bi-4S4PX.mjs +255 -0
  120. package/lib/openai-codex-CQL_kvYL.mjs +255 -0
  121. package/lib/openai-codex-Ch8CkT3p.mjs +255 -0
  122. package/lib/openai-codex-responses-CvxL_FMF.mjs +3144 -0
  123. package/lib/openai-codex-responses-Cz-2qpC7.mjs +3144 -0
  124. package/lib/openai-codex-responses-pejZgdZo.mjs +3144 -0
  125. package/lib/openai-completions-CF8IyNtP.mjs +1360 -0
  126. package/lib/openai-completions-DIf361kF.mjs +1360 -0
  127. package/lib/openai-completions-i8doczAk.mjs +1360 -0
  128. package/lib/openai-reasoning-fallback-DGVVLgd1.mjs +286 -0
  129. package/lib/openai-reasoning-fallback-Nj6yB2rY.mjs +286 -0
  130. package/lib/openai-reasoning-fallback-OdJREP1o.mjs +286 -0
  131. package/lib/openai-responses-BqXJInHX.mjs +867 -0
  132. package/lib/openai-responses-DTkBiiy-.mjs +867 -0
  133. package/lib/openai-responses-Db_a-U4-.mjs +867 -0
  134. package/lib/opencode-DaJjcUbf.mjs +38 -0
  135. package/lib/opencode-DhMolSoB.mjs +38 -0
  136. package/lib/opencode-Rq_Q2vAO.mjs +38 -0
  137. package/lib/perplexity-9b-RQ0mV.mjs +194 -0
  138. package/lib/perplexity-C4iLVMUj.mjs +194 -0
  139. package/lib/perplexity-Uu7Jzg5b.mjs +194 -0
  140. package/lib/proxy-DDqrmjjC.mjs +190 -0
  141. package/lib/proxy-ZtUcl6r5.mjs +190 -0
  142. package/lib/proxy-pM_NIv-H.mjs +190 -0
  143. package/lib/request-debug-HJMoJncL.mjs +183 -0
  144. package/lib/sanitize-text-CfcXzw5X.mjs +33 -0
  145. package/lib/scrapers-BkFfcPHj.mjs +9198 -0
  146. package/lib/scrapers-CL-WgdU1.mjs +9198 -0
  147. package/lib/scrapers-CVptboMs.mjs +9198 -0
  148. package/lib/scrapers-CipyKyCH.mjs +9198 -0
  149. package/lib/scrapers-DGfrYhtw.mjs +9198 -0
  150. package/lib/scrapers-DSUPYoUF.mjs +9198 -0
  151. package/lib/scrapers-DZ2GXmp7.mjs +9198 -0
  152. package/lib/scrapers-nhQAvc8d.mjs +9198 -0
  153. package/lib/shell-snapshot-fn-env.sh +67 -43
  154. package/lib/src-BgpusnsB.mjs +5076 -0
  155. package/lib/src-DTid0g4K.mjs +5001 -0
  156. package/lib/src-lDmkSRbm.mjs +5006 -0
  157. package/lib/stream-BlldLkVq.mjs +10236 -0
  158. package/lib/stream-CRtexYLe.mjs +10236 -0
  159. package/lib/stream-C_RAoxJC.mjs +10236 -0
  160. package/lib/stream-markup-healing-2toHXWXM.mjs +491 -0
  161. package/lib/stream-markup-healing-DMsxBx1L.mjs +491 -0
  162. package/lib/stream-markup-healing-KMkiAA00.mjs +491 -0
  163. package/lib/turndown-DN7ByzEI.mjs +667 -0
  164. package/lib/types/client/locales.d.ts +1 -1
  165. package/lib/types/config/fields.d.ts +1 -1
  166. package/lib/types/config/settings.d.ts +25 -3
  167. package/lib/types/config/truncate.d.ts +9 -5
  168. package/lib/types/tools/bash/background.d.ts +1 -1
  169. package/lib/types/tools/bash/bash-executor.d.ts +4 -0
  170. package/lib/types/tools/bash/bash-interceptor.d.ts +10 -8
  171. package/lib/types/tools/bash/cd-workdir.d.ts +35 -0
  172. package/lib/types/tools/bash/non-interactive-env.d.ts +2 -0
  173. package/lib/types/tools/bash/render.d.ts +4 -3
  174. package/lib/types/tools/bash/sanitize-text.d.ts +5 -0
  175. package/lib/types/tools/bash/shell-snapshot.d.ts +4 -1
  176. package/lib/types/tools/bash/shell-tokenize.d.ts +60 -0
  177. package/lib/types/tools/bash/streaming-output.d.ts +12 -212
  178. package/lib/types/tools/bash/which.d.ts +20 -0
  179. package/lib/types/tools/bash/windows-shell.d.ts +31 -0
  180. package/lib/types/tools/edit/adapter/index.d.ts +25 -3
  181. package/lib/types/tools/edit/adapter/tools/auto-generated-guard.d.ts +7 -17
  182. package/lib/types/tools/glob/adapter/index.d.ts +27 -1
  183. package/lib/types/tools/grep/adapter/index.d.ts +29 -1
  184. package/lib/types/tools/omp/edit/dispatch.d.ts +43 -0
  185. package/lib/types/tools/omp/edit/hashline/noop-loop-guard.d.ts +3 -1
  186. package/lib/types/tools/omp/sdk.d.ts +6 -0
  187. package/lib/types/tools/omp/tools/auto-generated-guard.d.ts +20 -0
  188. package/lib/types/tools/omp/tools/fetch.d.ts +2 -0
  189. package/lib/types/tools/omp/tools/read.d.ts +2 -8
  190. package/lib/types/tools/omp/tools/write.d.ts +4 -4
  191. package/lib/types/tools/omp/utils/image-loading.d.ts +10 -36
  192. package/lib/types/tools/read/adapter/index.d.ts +4 -1
  193. package/lib/types/tools/read-image/index.d.ts +4 -0
  194. package/lib/types/tools/shared/auto-generated-guard.dsh.d.ts +16 -4
  195. package/lib/types/tools/shared/bun-shim.d.ts +39 -3
  196. package/lib/types/tools/shared/fs-promises-shim.d.ts +3 -1
  197. package/lib/types/tools/shared/image-bridge.d.ts +98 -0
  198. package/lib/types/tools/shared/omp-prompt.d.ts +17 -9
  199. package/lib/types/tools/shared/session-state.d.ts +9 -3
  200. package/lib/utils-2Wq2eATG.mjs +8119 -0
  201. package/lib/utils-BnX8O3vi.mjs +12303 -0
  202. package/lib/utils-Bw139LTz.mjs +8119 -0
  203. package/lib/utils-CE8N8P4Q.mjs +12315 -0
  204. package/lib/utils-CZw4tVZQ.mjs +12315 -0
  205. package/lib/utils-C_MrQ_0z.mjs +12301 -0
  206. package/lib/utils-CiGN7OHR.mjs +12315 -0
  207. package/lib/utils-Cp76gCyk.mjs +8119 -0
  208. package/lib/utils-D0GRDgAr.mjs +12315 -0
  209. package/lib/utils-D0Z1fyoO.mjs +12299 -0
  210. package/lib/utils-D2YknRk4.mjs +51 -0
  211. package/lib/utils-DppGHXQB.mjs +51 -0
  212. package/lib/utils-DzXZDfYc.mjs +51 -0
  213. package/lib/utils-W8WdSBpX.mjs +12315 -0
  214. package/lib/vision-guard-01qSwFpf.mjs +92 -0
  215. package/lib/vision-guard-BDD4OrKo.mjs +92 -0
  216. package/lib/vision-guard-DzZGaOga.mjs +92 -0
  217. package/lib/wafer-CgtPHerf.mjs +17 -0
  218. package/lib/wafer-DRU0EjZX.mjs +17 -0
  219. package/lib/wafer-cBtrn6q9.mjs +17 -0
  220. package/lib/xai-oauth-Buk8XVvM.mjs +446 -0
  221. package/lib/xai-oauth-CMal8l1O.mjs +446 -0
  222. package/lib/xai-oauth-DPHDXKD7.mjs +446 -0
  223. package/lib/xiaomi-CZgwvX2G.mjs +157 -0
  224. package/lib/xiaomi-D2qT5cAC.mjs +157 -0
  225. package/lib/xiaomi-Dd87KSg5.mjs +157 -0
  226. package/lib/zai-7DWMkEqM.mjs +203 -0
  227. package/lib/zai-C59YnomG.mjs +203 -0
  228. package/lib/zai-CFeOt-53.mjs +203 -0
  229. package/lib/zip-Cg9ANN_U.mjs +1316 -0
  230. package/lib/zip-D36ZKsP8.mjs +1316 -0
  231. package/lib/zip-D6QXpvaJ.mjs +1316 -0
  232. package/package.json +14 -10
  233. package/presets/package.json +1 -1
  234. package/presets/tool-plus-ptc/preset.yml +1 -1
  235. package/presets/tool-plus-standard/preset.yml +1 -1
@@ -0,0 +1,208 @@
1
+ import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
+ __installBunShim();
3
+ import { V as ProviderHttpError, c as OAuthError, h as LoginCancelledError } from "./error-B3bevhrs.mjs";
4
+ import { r as getBundledModels } from "./models-CfT4coYT.mjs";
5
+ import { a as getGitHubCopilotBaseUrl, c as normalizeDomain, i as discoverGitHubCopilotApiEndpoint, l as normalizeGitHubCopilotEnterpriseDomain, n as OPENCODE_HEADERS, s as isPublicGitHubHost, t as COPILOT_API_HEADERS } from "./github-copilot-B2HGSIJK.mjs";
6
+ import { scheduler } from "node:timers/promises";
7
+ //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/registry/oauth/github-copilot.ts
8
+ /**
9
+ * GitHub Copilot OAuth flow (opencode OAuth app)
10
+ */
11
+ const CLIENT_ID = "Ov23li8tweQw6odWQebz";
12
+ const INITIAL_POLL_INTERVAL_MULTIPLIER = 1.2;
13
+ const SLOW_DOWN_POLL_INTERVAL_MULTIPLIER = 1.4;
14
+ function getUrls(domain) {
15
+ return {
16
+ deviceCodeUrl: `https://${domain}/login/device/code`,
17
+ accessTokenUrl: `https://${domain}/login/oauth/access_token`
18
+ };
19
+ }
20
+ async function fetchJson(url, init, fetchImpl) {
21
+ const response = await fetchImpl(url, init);
22
+ if (!response.ok) {
23
+ const text = await response.text();
24
+ throw new ProviderHttpError(`${response.status} ${response.statusText}: ${text}`, response.status);
25
+ }
26
+ return response.json();
27
+ }
28
+ async function startDeviceFlow(domain, fetchImpl) {
29
+ const data = await fetchJson(getUrls(domain).deviceCodeUrl, {
30
+ method: "POST",
31
+ headers: {
32
+ Accept: "application/json",
33
+ "Content-Type": "application/json",
34
+ ...OPENCODE_HEADERS
35
+ },
36
+ body: JSON.stringify({
37
+ client_id: CLIENT_ID,
38
+ scope: "read:user"
39
+ })
40
+ }, fetchImpl);
41
+ if (!data || typeof data !== "object") throw new OAuthError("Invalid device code response", {
42
+ kind: "validation",
43
+ provider: "github-copilot"
44
+ });
45
+ const deviceCode = data.device_code;
46
+ const userCode = data.user_code;
47
+ const verificationUri = data.verification_uri;
48
+ const interval = data.interval;
49
+ const expiresIn = data.expires_in;
50
+ if (typeof deviceCode !== "string" || typeof userCode !== "string" || typeof verificationUri !== "string" || typeof interval !== "number" || typeof expiresIn !== "number") throw new OAuthError("Invalid device code response fields", {
51
+ kind: "validation",
52
+ provider: "github-copilot"
53
+ });
54
+ return {
55
+ device_code: deviceCode,
56
+ user_code: userCode,
57
+ verification_uri: verificationUri,
58
+ interval,
59
+ expires_in: expiresIn
60
+ };
61
+ }
62
+ async function pollForGitHubAccessToken(domain, deviceCode, intervalSeconds, expiresIn, signal, fetchImpl, pollIntervalFloorMs = 1e3, pollIntervalScaleMs = 1e3) {
63
+ const urls = getUrls(domain);
64
+ const deadline = Date.now() + expiresIn * 1e3;
65
+ let intervalMs = Math.max(pollIntervalFloorMs, Math.floor(intervalSeconds * pollIntervalScaleMs));
66
+ let intervalMultiplier = INITIAL_POLL_INTERVAL_MULTIPLIER;
67
+ let slowDownResponses = 0;
68
+ while (Date.now() < deadline) {
69
+ if (signal?.aborted) throw new LoginCancelledError();
70
+ const remainingMs = deadline - Date.now();
71
+ const waitMs = Math.min(Math.ceil(intervalMs * intervalMultiplier), remainingMs);
72
+ try {
73
+ await scheduler.wait(waitMs, { signal });
74
+ } catch {
75
+ throw new LoginCancelledError();
76
+ }
77
+ const raw = await fetchJson(urls.accessTokenUrl, {
78
+ method: "POST",
79
+ headers: {
80
+ Accept: "application/json",
81
+ "Content-Type": "application/json",
82
+ ...OPENCODE_HEADERS
83
+ },
84
+ body: JSON.stringify({
85
+ client_id: CLIENT_ID,
86
+ device_code: deviceCode,
87
+ grant_type: "urn:ietf:params:oauth:grant-type:device_code"
88
+ })
89
+ }, fetchImpl);
90
+ if (raw && typeof raw === "object" && typeof raw.access_token === "string") return raw.access_token;
91
+ if (raw && typeof raw === "object" && typeof raw.error === "string") {
92
+ const { error, error_description: description, interval } = raw;
93
+ if (error === "authorization_pending") continue;
94
+ if (error === "slow_down") {
95
+ slowDownResponses += 1;
96
+ intervalMs = typeof interval === "number" && interval > 0 ? Math.max(pollIntervalFloorMs, interval * pollIntervalScaleMs) : Math.max(pollIntervalFloorMs, intervalMs + 5 * pollIntervalScaleMs);
97
+ intervalMultiplier = SLOW_DOWN_POLL_INTERVAL_MULTIPLIER;
98
+ continue;
99
+ }
100
+ const descriptionSuffix = description ? `: ${description}` : "";
101
+ throw new OAuthError(`Device flow failed: ${error}${descriptionSuffix}`, {
102
+ kind: "polling",
103
+ provider: "github-copilot"
104
+ });
105
+ }
106
+ }
107
+ if (slowDownResponses > 0) throw new OAuthError("Device flow timed out after one or more slow_down responses. This is often caused by clock drift in WSL or VM environments. Please sync or restart the VM clock and try again.", {
108
+ kind: "timeout",
109
+ provider: "github-copilot"
110
+ });
111
+ throw new OAuthError("Device flow timed out", {
112
+ kind: "timeout",
113
+ provider: "github-copilot"
114
+ });
115
+ }
116
+ /** Far-future expiry (10 years). GitHub OAuth tokens are long-lived; no JWT exchange needed. */
117
+ const FAR_FUTURE_MS = Date.now() + 315576e6;
118
+ /**
119
+ * Refresh GitHub Copilot token.
120
+ * With the opencode OAuth flow, the GitHub token is used directly — no JWT exchange needed.
121
+ */
122
+ function refreshGitHubCopilotToken(refreshToken, enterpriseDomain, apiEndpoint) {
123
+ return {
124
+ refresh: refreshToken,
125
+ access: refreshToken,
126
+ expires: FAR_FUTURE_MS,
127
+ enterpriseUrl: enterpriseDomain,
128
+ apiEndpoint
129
+ };
130
+ }
131
+ /**
132
+ * Enable a model for the user's GitHub Copilot account.
133
+ * This is required for some models (like Claude, Grok) before they can be used.
134
+ */
135
+ async function enableGitHubCopilotModel(token, modelId, fetchImpl, enterpriseDomain, apiEndpoint) {
136
+ const url = `${apiEndpoint ?? getGitHubCopilotBaseUrl(enterpriseDomain)}/models/${modelId}/policy`;
137
+ try {
138
+ return (await fetchImpl(url, {
139
+ method: "POST",
140
+ headers: {
141
+ "Content-Type": "application/json",
142
+ Authorization: `Bearer ${token}`,
143
+ ...COPILOT_API_HEADERS,
144
+ "openai-intent": "chat-policy",
145
+ "x-interaction-type": "chat-policy"
146
+ },
147
+ body: JSON.stringify({ state: "enabled" })
148
+ })).ok;
149
+ } catch {
150
+ return false;
151
+ }
152
+ }
153
+ /**
154
+ * Enable all known GitHub Copilot models that may require policy acceptance.
155
+ * Called after successful login to ensure all models are available.
156
+ */
157
+ async function enableAllGitHubCopilotModels(token, enterpriseDomain, apiEndpoint, fetchImpl, onProgress) {
158
+ const wireModelIds = [...new Set(getBundledModels("github-copilot").map((model) => model.requestModelId ?? model.id))];
159
+ const BATCH_SIZE = 5;
160
+ for (let i = 0; i < wireModelIds.length; i += BATCH_SIZE) {
161
+ const batch = wireModelIds.slice(i, i + BATCH_SIZE);
162
+ await Promise.all(batch.map(async (modelId) => {
163
+ const success = await enableGitHubCopilotModel(token, modelId, fetchImpl, enterpriseDomain, apiEndpoint);
164
+ onProgress?.(modelId, success);
165
+ }));
166
+ }
167
+ }
168
+ /**
169
+ * Login with GitHub Copilot OAuth (device code flow)
170
+ *
171
+ * @param options.onAuth - Callback with URL and optional instructions (user code)
172
+ * @param options.onPrompt - Callback to prompt user for input
173
+ * @param options.onProgress - Optional progress callback
174
+ * @param options.signal - Optional AbortSignal for cancellation
175
+ */
176
+ async function loginGitHubCopilot(options) {
177
+ const fetchImpl = options.fetch ?? fetch;
178
+ const input = await options.onPrompt({
179
+ message: "GitHub Enterprise URL/domain (blank for github.com)",
180
+ placeholder: "company.ghe.com",
181
+ allowEmpty: true
182
+ });
183
+ if (options.signal?.aborted) throw new LoginCancelledError();
184
+ const trimmed = input.trim();
185
+ const normalizedDomain = normalizeDomain(input);
186
+ if (trimmed && !normalizedDomain) throw new OAuthError("Invalid GitHub Enterprise URL/domain", {
187
+ kind: "validation",
188
+ provider: "github-copilot"
189
+ });
190
+ const enterpriseDomain = normalizeGitHubCopilotEnterpriseDomain(normalizedDomain ?? void 0);
191
+ const domain = normalizedDomain && isPublicGitHubHost(normalizedDomain) ? "github.com" : normalizedDomain ?? "github.com";
192
+ const device = await startDeviceFlow(domain, fetchImpl);
193
+ options.onAuth(device.verification_uri, `Enter code: ${device.user_code}`);
194
+ const githubAccessToken = await pollForGitHubAccessToken(domain, device.device_code, device.interval, device.expires_in, options.signal, fetchImpl, options.pollIntervalFloorMs, options.pollIntervalScaleMs);
195
+ const apiEndpoint = await discoverGitHubCopilotApiEndpoint(githubAccessToken, fetchImpl);
196
+ const credentials = {
197
+ refresh: githubAccessToken,
198
+ access: githubAccessToken,
199
+ expires: FAR_FUTURE_MS,
200
+ enterpriseUrl: enterpriseDomain ?? void 0,
201
+ apiEndpoint
202
+ };
203
+ options.onProgress?.("Enabling models...");
204
+ await enableAllGitHubCopilotModels(githubAccessToken, enterpriseDomain ?? void 0, apiEndpoint, fetchImpl);
205
+ return credentials;
206
+ }
207
+ //#endregion
208
+ export { loginGitHubCopilot, refreshGitHubCopilotToken };
@@ -0,0 +1,104 @@
1
+ import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
+ __installBunShim();
3
+ import { n as isRecord } from "./type-guards-B9VVjRDK.mjs";
4
+ import "./utils-D2YknRk4.mjs";
5
+ const OPENCODE_HEADERS = { "User-Agent": "opencode/1.3.15" };
6
+ /**
7
+ * Copilot API version sent on `api.githubcopilot.com` requests (`/models`,
8
+ * chat endpoints). Newer versions unlock tiered context metadata: `/models`
9
+ * reports the full long-context window in `capabilities.limits` plus per-tier
10
+ * boundaries/prices under `billing.token_prices.{default,long_context}`.
11
+ * Without it the endpoint serves default-tier limits only (e.g. 264k instead
12
+ * of 1M for Claude Opus). Never send this to `api.github.com` REST endpoints —
13
+ * they validate `X-GitHub-Api-Version` against the REST version vocabulary.
14
+ */
15
+ const COPILOT_API_VERSION = "2026-06-01";
16
+ /** Headers for `api.githubcopilot.com` (capi) requests: discovery, chat, policy. */
17
+ const COPILOT_API_HEADERS = {
18
+ ...OPENCODE_HEADERS,
19
+ "X-GitHub-Api-Version": COPILOT_API_VERSION
20
+ };
21
+ const PUBLIC_GITHUB_HOSTS = /* @__PURE__ */ new Set([
22
+ "api.github.com",
23
+ "github.com",
24
+ "www.github.com"
25
+ ]);
26
+ function isPublicGitHubHost(host) {
27
+ return PUBLIC_GITHUB_HOSTS.has(host.trim().toLowerCase());
28
+ }
29
+ /** Canonical personal-Copilot API host. */
30
+ const PERSONAL_GITHUB_COPILOT_BASE_URL = "https://api.githubcopilot.com";
31
+ /** `true` when the resolved base URL is the canonical personal-Copilot host. */
32
+ function isPersonalGitHubCopilotBaseUrl(baseUrl) {
33
+ return baseUrl === PERSONAL_GITHUB_COPILOT_BASE_URL;
34
+ }
35
+ function normalizeGitHubCopilotEnterpriseDomain(input) {
36
+ const trimmed = input?.trim();
37
+ if (!trimmed) return void 0;
38
+ const normalized = normalizeDomain(trimmed) ?? trimmed.toLowerCase();
39
+ if (!normalized || isPublicGitHubHost(normalized)) return void 0;
40
+ return normalized;
41
+ }
42
+ function normalizeGitHubCopilotApiEndpoint(input) {
43
+ const trimmed = input?.trim();
44
+ if (!trimmed?.startsWith("https://")) return void 0;
45
+ try {
46
+ const url = new URL(trimmed);
47
+ if (url.protocol !== "https:" || !url.hostname) return void 0;
48
+ return trimmed.replace(/\/+$/, "");
49
+ } catch {
50
+ return;
51
+ }
52
+ }
53
+ /**
54
+ * Resolve the plan-specific Copilot API endpoint advertised for a GitHub token.
55
+ * Login and raw environment-token discovery share this best-effort probe. Pass
56
+ * a `signal` to bound it against the same discovery deadline as `/models`; a
57
+ * stalled probe otherwise blocks discovery indefinitely.
58
+ */
59
+ async function discoverGitHubCopilotApiEndpoint(token, fetchImpl, signal) {
60
+ try {
61
+ const response = await fetchImpl("https://api.github.com/copilot_internal/user", {
62
+ headers: {
63
+ Accept: "application/json",
64
+ Authorization: `token ${token}`,
65
+ ...OPENCODE_HEADERS
66
+ },
67
+ signal
68
+ });
69
+ if (!response.ok) return void 0;
70
+ const data = await response.json();
71
+ if (!isRecord(data) || !isRecord(data.endpoints)) return void 0;
72
+ const endpoint = data.endpoints.api;
73
+ return typeof endpoint === "string" ? normalizeGitHubCopilotApiEndpoint(endpoint) : void 0;
74
+ } catch {
75
+ return;
76
+ }
77
+ }
78
+ function parseGitHubCopilotApiKey(apiKeyRaw) {
79
+ try {
80
+ const parsed = JSON.parse(apiKeyRaw);
81
+ if (typeof parsed.token === "string") return {
82
+ accessToken: parsed.token,
83
+ enterpriseUrl: typeof parsed.enterpriseUrl === "string" ? normalizeGitHubCopilotEnterpriseDomain(parsed.enterpriseUrl) : void 0,
84
+ apiEndpoint: typeof parsed.apiEndpoint === "string" ? normalizeGitHubCopilotApiEndpoint(parsed.apiEndpoint) : void 0
85
+ };
86
+ } catch {}
87
+ return { accessToken: apiKeyRaw };
88
+ }
89
+ function normalizeDomain(input) {
90
+ const trimmed = input.trim();
91
+ if (!trimmed) return null;
92
+ try {
93
+ return (trimmed.includes("://") ? new URL(trimmed) : new URL(`https://${trimmed}`)).hostname;
94
+ } catch {
95
+ return null;
96
+ }
97
+ }
98
+ function getGitHubCopilotBaseUrl(enterpriseDomain) {
99
+ const normalizedEnterpriseDomain = normalizeGitHubCopilotEnterpriseDomain(enterpriseDomain);
100
+ if (!normalizedEnterpriseDomain) return "https://api.githubcopilot.com";
101
+ return `https://${normalizedEnterpriseDomain.startsWith("copilot-api.") ? normalizedEnterpriseDomain : `copilot-api.${normalizedEnterpriseDomain}`}`;
102
+ }
103
+ //#endregion
104
+ export { getGitHubCopilotBaseUrl as a, normalizeDomain as c, discoverGitHubCopilotApiEndpoint as i, normalizeGitHubCopilotEnterpriseDomain as l, OPENCODE_HEADERS as n, isPersonalGitHubCopilotBaseUrl as o, PERSONAL_GITHUB_COPILOT_BASE_URL as r, isPublicGitHubHost as s, COPILOT_API_HEADERS as t, parseGitHubCopilotApiKey as u };
@@ -0,0 +1,104 @@
1
+ import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
+ __installBunShim();
3
+ import { n as isRecord } from "./type-guards-B9VVjRDK.mjs";
4
+ import "./utils-DppGHXQB.mjs";
5
+ const OPENCODE_HEADERS = { "User-Agent": "opencode/1.3.15" };
6
+ /**
7
+ * Copilot API version sent on `api.githubcopilot.com` requests (`/models`,
8
+ * chat endpoints). Newer versions unlock tiered context metadata: `/models`
9
+ * reports the full long-context window in `capabilities.limits` plus per-tier
10
+ * boundaries/prices under `billing.token_prices.{default,long_context}`.
11
+ * Without it the endpoint serves default-tier limits only (e.g. 264k instead
12
+ * of 1M for Claude Opus). Never send this to `api.github.com` REST endpoints —
13
+ * they validate `X-GitHub-Api-Version` against the REST version vocabulary.
14
+ */
15
+ const COPILOT_API_VERSION = "2026-06-01";
16
+ /** Headers for `api.githubcopilot.com` (capi) requests: discovery, chat, policy. */
17
+ const COPILOT_API_HEADERS = {
18
+ ...OPENCODE_HEADERS,
19
+ "X-GitHub-Api-Version": COPILOT_API_VERSION
20
+ };
21
+ const PUBLIC_GITHUB_HOSTS = /* @__PURE__ */ new Set([
22
+ "api.github.com",
23
+ "github.com",
24
+ "www.github.com"
25
+ ]);
26
+ function isPublicGitHubHost(host) {
27
+ return PUBLIC_GITHUB_HOSTS.has(host.trim().toLowerCase());
28
+ }
29
+ /** Canonical personal-Copilot API host. */
30
+ const PERSONAL_GITHUB_COPILOT_BASE_URL = "https://api.githubcopilot.com";
31
+ /** `true` when the resolved base URL is the canonical personal-Copilot host. */
32
+ function isPersonalGitHubCopilotBaseUrl(baseUrl) {
33
+ return baseUrl === PERSONAL_GITHUB_COPILOT_BASE_URL;
34
+ }
35
+ function normalizeGitHubCopilotEnterpriseDomain(input) {
36
+ const trimmed = input?.trim();
37
+ if (!trimmed) return void 0;
38
+ const normalized = normalizeDomain(trimmed) ?? trimmed.toLowerCase();
39
+ if (!normalized || isPublicGitHubHost(normalized)) return void 0;
40
+ return normalized;
41
+ }
42
+ function normalizeGitHubCopilotApiEndpoint(input) {
43
+ const trimmed = input?.trim();
44
+ if (!trimmed?.startsWith("https://")) return void 0;
45
+ try {
46
+ const url = new URL(trimmed);
47
+ if (url.protocol !== "https:" || !url.hostname) return void 0;
48
+ return trimmed.replace(/\/+$/, "");
49
+ } catch {
50
+ return;
51
+ }
52
+ }
53
+ /**
54
+ * Resolve the plan-specific Copilot API endpoint advertised for a GitHub token.
55
+ * Login and raw environment-token discovery share this best-effort probe. Pass
56
+ * a `signal` to bound it against the same discovery deadline as `/models`; a
57
+ * stalled probe otherwise blocks discovery indefinitely.
58
+ */
59
+ async function discoverGitHubCopilotApiEndpoint(token, fetchImpl, signal) {
60
+ try {
61
+ const response = await fetchImpl("https://api.github.com/copilot_internal/user", {
62
+ headers: {
63
+ Accept: "application/json",
64
+ Authorization: `token ${token}`,
65
+ ...OPENCODE_HEADERS
66
+ },
67
+ signal
68
+ });
69
+ if (!response.ok) return void 0;
70
+ const data = await response.json();
71
+ if (!isRecord(data) || !isRecord(data.endpoints)) return void 0;
72
+ const endpoint = data.endpoints.api;
73
+ return typeof endpoint === "string" ? normalizeGitHubCopilotApiEndpoint(endpoint) : void 0;
74
+ } catch {
75
+ return;
76
+ }
77
+ }
78
+ function parseGitHubCopilotApiKey(apiKeyRaw) {
79
+ try {
80
+ const parsed = JSON.parse(apiKeyRaw);
81
+ if (typeof parsed.token === "string") return {
82
+ accessToken: parsed.token,
83
+ enterpriseUrl: typeof parsed.enterpriseUrl === "string" ? normalizeGitHubCopilotEnterpriseDomain(parsed.enterpriseUrl) : void 0,
84
+ apiEndpoint: typeof parsed.apiEndpoint === "string" ? normalizeGitHubCopilotApiEndpoint(parsed.apiEndpoint) : void 0
85
+ };
86
+ } catch {}
87
+ return { accessToken: apiKeyRaw };
88
+ }
89
+ function normalizeDomain(input) {
90
+ const trimmed = input.trim();
91
+ if (!trimmed) return null;
92
+ try {
93
+ return (trimmed.includes("://") ? new URL(trimmed) : new URL(`https://${trimmed}`)).hostname;
94
+ } catch {
95
+ return null;
96
+ }
97
+ }
98
+ function getGitHubCopilotBaseUrl(enterpriseDomain) {
99
+ const normalizedEnterpriseDomain = normalizeGitHubCopilotEnterpriseDomain(enterpriseDomain);
100
+ if (!normalizedEnterpriseDomain) return "https://api.githubcopilot.com";
101
+ return `https://${normalizedEnterpriseDomain.startsWith("copilot-api.") ? normalizedEnterpriseDomain : `copilot-api.${normalizedEnterpriseDomain}`}`;
102
+ }
103
+ //#endregion
104
+ export { getGitHubCopilotBaseUrl as a, normalizeDomain as c, discoverGitHubCopilotApiEndpoint as i, normalizeGitHubCopilotEnterpriseDomain as l, OPENCODE_HEADERS as n, isPersonalGitHubCopilotBaseUrl as o, PERSONAL_GITHUB_COPILOT_BASE_URL as r, isPublicGitHubHost as s, COPILOT_API_HEADERS as t, parseGitHubCopilotApiKey as u };
@@ -0,0 +1,208 @@
1
+ import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
+ __installBunShim();
3
+ import { V as ProviderHttpError, c as OAuthError, h as LoginCancelledError } from "./error-yCSG0mGC.mjs";
4
+ import { r as getBundledModels } from "./models-D_XnT6ay.mjs";
5
+ import { a as getGitHubCopilotBaseUrl, c as normalizeDomain, i as discoverGitHubCopilotApiEndpoint, l as normalizeGitHubCopilotEnterpriseDomain, n as OPENCODE_HEADERS, s as isPublicGitHubHost, t as COPILOT_API_HEADERS } from "./github-copilot-jscUZ8Hf.mjs";
6
+ import { scheduler } from "node:timers/promises";
7
+ //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/registry/oauth/github-copilot.ts
8
+ /**
9
+ * GitHub Copilot OAuth flow (opencode OAuth app)
10
+ */
11
+ const CLIENT_ID = "Ov23li8tweQw6odWQebz";
12
+ const INITIAL_POLL_INTERVAL_MULTIPLIER = 1.2;
13
+ const SLOW_DOWN_POLL_INTERVAL_MULTIPLIER = 1.4;
14
+ function getUrls(domain) {
15
+ return {
16
+ deviceCodeUrl: `https://${domain}/login/device/code`,
17
+ accessTokenUrl: `https://${domain}/login/oauth/access_token`
18
+ };
19
+ }
20
+ async function fetchJson(url, init, fetchImpl) {
21
+ const response = await fetchImpl(url, init);
22
+ if (!response.ok) {
23
+ const text = await response.text();
24
+ throw new ProviderHttpError(`${response.status} ${response.statusText}: ${text}`, response.status);
25
+ }
26
+ return response.json();
27
+ }
28
+ async function startDeviceFlow(domain, fetchImpl) {
29
+ const data = await fetchJson(getUrls(domain).deviceCodeUrl, {
30
+ method: "POST",
31
+ headers: {
32
+ Accept: "application/json",
33
+ "Content-Type": "application/json",
34
+ ...OPENCODE_HEADERS
35
+ },
36
+ body: JSON.stringify({
37
+ client_id: CLIENT_ID,
38
+ scope: "read:user"
39
+ })
40
+ }, fetchImpl);
41
+ if (!data || typeof data !== "object") throw new OAuthError("Invalid device code response", {
42
+ kind: "validation",
43
+ provider: "github-copilot"
44
+ });
45
+ const deviceCode = data.device_code;
46
+ const userCode = data.user_code;
47
+ const verificationUri = data.verification_uri;
48
+ const interval = data.interval;
49
+ const expiresIn = data.expires_in;
50
+ if (typeof deviceCode !== "string" || typeof userCode !== "string" || typeof verificationUri !== "string" || typeof interval !== "number" || typeof expiresIn !== "number") throw new OAuthError("Invalid device code response fields", {
51
+ kind: "validation",
52
+ provider: "github-copilot"
53
+ });
54
+ return {
55
+ device_code: deviceCode,
56
+ user_code: userCode,
57
+ verification_uri: verificationUri,
58
+ interval,
59
+ expires_in: expiresIn
60
+ };
61
+ }
62
+ async function pollForGitHubAccessToken(domain, deviceCode, intervalSeconds, expiresIn, signal, fetchImpl, pollIntervalFloorMs = 1e3, pollIntervalScaleMs = 1e3) {
63
+ const urls = getUrls(domain);
64
+ const deadline = Date.now() + expiresIn * 1e3;
65
+ let intervalMs = Math.max(pollIntervalFloorMs, Math.floor(intervalSeconds * pollIntervalScaleMs));
66
+ let intervalMultiplier = INITIAL_POLL_INTERVAL_MULTIPLIER;
67
+ let slowDownResponses = 0;
68
+ while (Date.now() < deadline) {
69
+ if (signal?.aborted) throw new LoginCancelledError();
70
+ const remainingMs = deadline - Date.now();
71
+ const waitMs = Math.min(Math.ceil(intervalMs * intervalMultiplier), remainingMs);
72
+ try {
73
+ await scheduler.wait(waitMs, { signal });
74
+ } catch {
75
+ throw new LoginCancelledError();
76
+ }
77
+ const raw = await fetchJson(urls.accessTokenUrl, {
78
+ method: "POST",
79
+ headers: {
80
+ Accept: "application/json",
81
+ "Content-Type": "application/json",
82
+ ...OPENCODE_HEADERS
83
+ },
84
+ body: JSON.stringify({
85
+ client_id: CLIENT_ID,
86
+ device_code: deviceCode,
87
+ grant_type: "urn:ietf:params:oauth:grant-type:device_code"
88
+ })
89
+ }, fetchImpl);
90
+ if (raw && typeof raw === "object" && typeof raw.access_token === "string") return raw.access_token;
91
+ if (raw && typeof raw === "object" && typeof raw.error === "string") {
92
+ const { error, error_description: description, interval } = raw;
93
+ if (error === "authorization_pending") continue;
94
+ if (error === "slow_down") {
95
+ slowDownResponses += 1;
96
+ intervalMs = typeof interval === "number" && interval > 0 ? Math.max(pollIntervalFloorMs, interval * pollIntervalScaleMs) : Math.max(pollIntervalFloorMs, intervalMs + 5 * pollIntervalScaleMs);
97
+ intervalMultiplier = SLOW_DOWN_POLL_INTERVAL_MULTIPLIER;
98
+ continue;
99
+ }
100
+ const descriptionSuffix = description ? `: ${description}` : "";
101
+ throw new OAuthError(`Device flow failed: ${error}${descriptionSuffix}`, {
102
+ kind: "polling",
103
+ provider: "github-copilot"
104
+ });
105
+ }
106
+ }
107
+ if (slowDownResponses > 0) throw new OAuthError("Device flow timed out after one or more slow_down responses. This is often caused by clock drift in WSL or VM environments. Please sync or restart the VM clock and try again.", {
108
+ kind: "timeout",
109
+ provider: "github-copilot"
110
+ });
111
+ throw new OAuthError("Device flow timed out", {
112
+ kind: "timeout",
113
+ provider: "github-copilot"
114
+ });
115
+ }
116
+ /** Far-future expiry (10 years). GitHub OAuth tokens are long-lived; no JWT exchange needed. */
117
+ const FAR_FUTURE_MS = Date.now() + 315576e6;
118
+ /**
119
+ * Refresh GitHub Copilot token.
120
+ * With the opencode OAuth flow, the GitHub token is used directly — no JWT exchange needed.
121
+ */
122
+ function refreshGitHubCopilotToken(refreshToken, enterpriseDomain, apiEndpoint) {
123
+ return {
124
+ refresh: refreshToken,
125
+ access: refreshToken,
126
+ expires: FAR_FUTURE_MS,
127
+ enterpriseUrl: enterpriseDomain,
128
+ apiEndpoint
129
+ };
130
+ }
131
+ /**
132
+ * Enable a model for the user's GitHub Copilot account.
133
+ * This is required for some models (like Claude, Grok) before they can be used.
134
+ */
135
+ async function enableGitHubCopilotModel(token, modelId, fetchImpl, enterpriseDomain, apiEndpoint) {
136
+ const url = `${apiEndpoint ?? getGitHubCopilotBaseUrl(enterpriseDomain)}/models/${modelId}/policy`;
137
+ try {
138
+ return (await fetchImpl(url, {
139
+ method: "POST",
140
+ headers: {
141
+ "Content-Type": "application/json",
142
+ Authorization: `Bearer ${token}`,
143
+ ...COPILOT_API_HEADERS,
144
+ "openai-intent": "chat-policy",
145
+ "x-interaction-type": "chat-policy"
146
+ },
147
+ body: JSON.stringify({ state: "enabled" })
148
+ })).ok;
149
+ } catch {
150
+ return false;
151
+ }
152
+ }
153
+ /**
154
+ * Enable all known GitHub Copilot models that may require policy acceptance.
155
+ * Called after successful login to ensure all models are available.
156
+ */
157
+ async function enableAllGitHubCopilotModels(token, enterpriseDomain, apiEndpoint, fetchImpl, onProgress) {
158
+ const wireModelIds = [...new Set(getBundledModels("github-copilot").map((model) => model.requestModelId ?? model.id))];
159
+ const BATCH_SIZE = 5;
160
+ for (let i = 0; i < wireModelIds.length; i += BATCH_SIZE) {
161
+ const batch = wireModelIds.slice(i, i + BATCH_SIZE);
162
+ await Promise.all(batch.map(async (modelId) => {
163
+ const success = await enableGitHubCopilotModel(token, modelId, fetchImpl, enterpriseDomain, apiEndpoint);
164
+ onProgress?.(modelId, success);
165
+ }));
166
+ }
167
+ }
168
+ /**
169
+ * Login with GitHub Copilot OAuth (device code flow)
170
+ *
171
+ * @param options.onAuth - Callback with URL and optional instructions (user code)
172
+ * @param options.onPrompt - Callback to prompt user for input
173
+ * @param options.onProgress - Optional progress callback
174
+ * @param options.signal - Optional AbortSignal for cancellation
175
+ */
176
+ async function loginGitHubCopilot(options) {
177
+ const fetchImpl = options.fetch ?? fetch;
178
+ const input = await options.onPrompt({
179
+ message: "GitHub Enterprise URL/domain (blank for github.com)",
180
+ placeholder: "company.ghe.com",
181
+ allowEmpty: true
182
+ });
183
+ if (options.signal?.aborted) throw new LoginCancelledError();
184
+ const trimmed = input.trim();
185
+ const normalizedDomain = normalizeDomain(input);
186
+ if (trimmed && !normalizedDomain) throw new OAuthError("Invalid GitHub Enterprise URL/domain", {
187
+ kind: "validation",
188
+ provider: "github-copilot"
189
+ });
190
+ const enterpriseDomain = normalizeGitHubCopilotEnterpriseDomain(normalizedDomain ?? void 0);
191
+ const domain = normalizedDomain && isPublicGitHubHost(normalizedDomain) ? "github.com" : normalizedDomain ?? "github.com";
192
+ const device = await startDeviceFlow(domain, fetchImpl);
193
+ options.onAuth(device.verification_uri, `Enter code: ${device.user_code}`);
194
+ const githubAccessToken = await pollForGitHubAccessToken(domain, device.device_code, device.interval, device.expires_in, options.signal, fetchImpl, options.pollIntervalFloorMs, options.pollIntervalScaleMs);
195
+ const apiEndpoint = await discoverGitHubCopilotApiEndpoint(githubAccessToken, fetchImpl);
196
+ const credentials = {
197
+ refresh: githubAccessToken,
198
+ access: githubAccessToken,
199
+ expires: FAR_FUTURE_MS,
200
+ enterpriseUrl: enterpriseDomain ?? void 0,
201
+ apiEndpoint
202
+ };
203
+ options.onProgress?.("Enabling models...");
204
+ await enableAllGitHubCopilotModels(githubAccessToken, enterpriseDomain ?? void 0, apiEndpoint, fetchImpl);
205
+ return credentials;
206
+ }
207
+ //#endregion
208
+ export { loginGitHubCopilot, refreshGitHubCopilotToken };