@xiaoso/dsh-tool-plus 0.1.6 → 0.1.7-beta.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 (119) hide show
  1. package/THIRD_PARTY_NOTICES.md +9 -3
  2. package/lib/{abort-Cwwm4Err.mjs → abort-Caqff3M6.mjs} +2 -2
  3. package/lib/alibaba-coding-plan-DTupMiAi.mjs +73 -0
  4. package/lib/alibaba-token-plan-CHGyWOfX.mjs +46 -0
  5. package/lib/alibaba-token-plan-Dj3OZhEE.mjs +82 -0
  6. package/lib/{amazon-bedrock-TVMpUTRG.mjs → amazon-bedrock-DbFSYXfJ.mjs} +117 -38
  7. package/lib/{anthropic-BL6LFDQS.mjs → anthropic-CTJ3IQVa.mjs} +675 -166
  8. package/lib/anthropic-CXfWlp-x.mjs +105 -0
  9. package/lib/{aws-credentials-B20dliS7.mjs → anthropic-wire-CKuhDwZ1.mjs} +74 -14
  10. package/lib/{api-key-login-CIDnXeYd.mjs → api-key-validation-CGCJFbFr.mjs} +27 -68
  11. package/lib/{azure-openai-responses-BkhsLmN3.mjs → azure-openai-responses-ChFbWaGj.mjs} +27 -16
  12. package/lib/{browser-render-CmgvSNte.mjs → browser-render-9o0Rknop.mjs} +4 -4
  13. package/lib/bun-shim.mjs +71 -2
  14. package/lib/{bundled-references-ChZSPDFw.mjs → bundled-references-DY3EJxZV.mjs} +6 -5
  15. package/lib/cline-pass-Bwg3esu9.mjs +44 -0
  16. package/lib/cloudflare-ai-gateway-BupNXyKK.mjs +35 -0
  17. package/lib/cloudflare-ai-gateway-EWo0VkP5.mjs +44 -0
  18. package/lib/collapse-DOR8sOGf.mjs +2304 -0
  19. package/lib/coreweave-C82HrLpb.mjs +31 -0
  20. package/lib/coreweave-Ct8cF-da.mjs +14 -0
  21. package/lib/{cursor-B6HcmplF.mjs → cursor-B95LzVWV.mjs} +11 -3
  22. package/lib/{cursor-CRpLpaZ3.mjs → cursor-DJV_dcgB.mjs} +887 -1784
  23. package/lib/{cursor-B8m6SqAH.mjs → cursor-LKGjucn2.mjs} +48 -38
  24. package/lib/cursor-proto-B8Wj8bv9.mjs +10513 -0
  25. package/lib/{deterministic-id-D-yIV_eI.mjs → deterministic-id-CUEIMSqR.mjs} +1 -1
  26. package/lib/devin-BMTdx_hx.mjs +316 -0
  27. package/lib/{devin-DUAfvBsW.mjs → devin-DSp0Rw_E.mjs} +172 -86
  28. package/lib/devin-ExGIghmx.mjs +69 -0
  29. package/lib/devin-proto-Br8fdyNl.mjs +2888 -0
  30. package/lib/{dom-CawWi8fa.mjs → dom-DG3sPESc.mjs} +8 -8
  31. package/lib/effort-BdtQMN-_.mjs +23 -0
  32. package/lib/{error-C-f_Wnw4.mjs → error-CORgGg5a.mjs} +275 -154
  33. package/lib/{event-stream-Dh2guZxS.mjs → event-stream-ulcDenZD.mjs} +20 -4
  34. package/lib/{gemini-headers-DKUShltF.mjs → gemini-headers-Co9cVvex.mjs} +2 -2
  35. package/lib/{github-copilot-suDymKrx.mjs → github-copilot-Dstq1D3s.mjs} +69 -29
  36. package/lib/github-copilot-headers-DOh1gt_w.mjs +312 -0
  37. package/lib/gitlab-duo-DSCMrU0m.mjs +11 -0
  38. package/lib/google-CtsKkOQK.mjs +38 -0
  39. package/lib/google-antigravity-z-5KsEci.mjs +252 -0
  40. package/lib/{google-auth-DYJLM792.mjs → google-auth-ieLBaneO.mjs} +4 -4
  41. package/lib/{google-gemini-cli-8BT513Ul.mjs → google-gemini-cli-C6NE5mWz.mjs} +28 -54
  42. package/lib/{google-gemini-cli-D6cSmfvB.mjs → google-gemini-cli-CAIPSl7e.mjs} +23 -29
  43. package/lib/google-oauth-shared-DhMllAkt.mjs +53 -0
  44. package/lib/{google-shared-CVbHK5vZ.mjs → google-shared-B0aNCYEH.mjs} +140 -44
  45. package/lib/{google-validation-Cgbn3tWJ.mjs → google-validation-BEkNs-Bx.mjs} +1 -1
  46. package/lib/{google-vertex-Bui-ypAe.mjs → google-vertex-Bbd1tYNc.mjs} +8 -8
  47. package/lib/hosts-00rjRzUD.mjs +203 -0
  48. package/lib/id-AL5obQzR.mjs +71 -0
  49. package/lib/{idle-iterator-CYAxUkSD.mjs → idle-iterator-DlUkEfzW.mjs} +3 -3
  50. package/lib/index.mjs +587 -5266
  51. package/lib/kilo-ChJL54wq.mjs +81 -0
  52. package/lib/kimi-C2c_Zq8A.mjs +67 -0
  53. package/lib/{launch-BmgEUycu.mjs → launch-DKDH71En.mjs} +1 -1
  54. package/lib/markit-CmRfm4E2.mjs +9885 -0
  55. package/lib/models-DnXMYGcJ.mjs +381604 -0
  56. package/lib/muse-code-Di1VZmB1.mjs +143 -0
  57. package/lib/{ollama-Df9ce-Cp.mjs → ollama-B8ic3sEp.mjs} +15 -30
  58. package/lib/{openai-codex-CAVI3Me-.mjs → openai-codex-DuJNC99x.mjs} +29 -99
  59. package/lib/{openai-codex-responses-BcnOotRB.mjs → openai-codex-responses-BL29nh9K.mjs} +204 -116
  60. package/lib/{openai-completions-Bq4WT47M.mjs → openai-completions-BK2f2dBv.mjs} +152 -82
  61. package/lib/openai-configuration-update-xMYUjaK_.mjs +150 -0
  62. package/lib/{openai-reasoning-fallback-DXsfiSXO.mjs → openai-reasoning-fallback-BdB3RCbj.mjs} +106 -12
  63. package/lib/{openai-responses-Mq_-PjvE.mjs → openai-responses-CGQPlIIy.mjs} +76 -82
  64. package/lib/{perplexity-XgLF73E7.mjs → perplexity-TBjz3VMB.mjs} +52 -9
  65. package/lib/{pkce-BlQikGPu.mjs → pkce-BYjmugmw.mjs} +1 -1
  66. package/lib/protobuf-aab1UGVn.mjs +717 -0
  67. package/lib/{provider-response-C6vcbQyO.mjs → provider-response-SqKSkkUc.mjs} +1 -1
  68. package/lib/{proxy-D9lm7ONA.mjs → proxy-5nWqRL1f.mjs} +45 -5
  69. package/lib/{readability-Cpm-ocau.mjs → readability-uGhqb4GC.mjs} +2 -2
  70. package/lib/reference-CtvM4zLU.mjs +114 -0
  71. package/lib/{request-debug-HJMoJncL.mjs → request-debug-NQN0BjHH.mjs} +1 -1
  72. package/lib/{sanitize-text-CfcXzw5X.mjs → sanitize-text-BCf5KmCf.mjs} +1 -1
  73. package/lib/{scrapers-Cg5w77td.mjs → scrapers-D8oWspgW.mjs} +12 -12
  74. package/lib/{src-BcD0_rQR.mjs → src-BwW51vA5.mjs} +979 -388
  75. package/lib/{sse-debug-CYdjOC96.mjs → sse-debug-B-tkLCPW.mjs} +1 -1
  76. package/lib/{stream-Bjq8wjfr.mjs → stream-B_7qN-bA.mjs} +3802 -2623
  77. package/lib/stream-markup-healing-DKT1lnkW.mjs +267 -0
  78. package/lib/{strict-tool-validation-imVLUcbI.mjs → strict-tool-validation-CBTz1dAA.mjs} +2 -2
  79. package/lib/taxonomy-DSIM99rS.mjs +15392 -0
  80. package/lib/{stream-markup-healing-DZ6bVDxH.mjs → thinking-CiLa2LFB.mjs} +31 -186
  81. package/lib/{turndown-DN7ByzEI.mjs → turndown-DrX1M4WG.mjs} +4 -4
  82. package/lib/{type-guards-B9VVjRDK.mjs → type-guards-CttAANEx.mjs} +1 -1
  83. package/lib/{types-DX_bvuus.mjs → types-PVueGi9S.mjs} +2 -2
  84. package/lib/{utils-C-dSORPa.mjs → utils-CCfhUQen.mjs} +2364 -2676
  85. package/lib/{utils-Cp2Mxf_U.mjs → utils-CUPhpw9A.mjs} +413 -134
  86. package/lib/{utils-CQHPEQ3W.mjs → utils-DeWqNWV8.mjs} +2 -2
  87. package/lib/{vision-guard-mBmtAHx0.mjs → vision-guard-_XwsL1DF.mjs} +14 -29
  88. package/lib/xai-oauth-CXhnz0gO.mjs +210 -0
  89. package/lib/{xiaomi-7mE345KX.mjs → xiaomi-psoUItal.mjs} +8 -37
  90. package/lib/{zai-CeNpMV3W.mjs → zai-ApJ8HBgT.mjs} +8 -71
  91. package/lib/{zip-BK7UHCwX.mjs → zip-Kd602XNe.mjs} +1 -1
  92. package/package.json +11 -11
  93. package/presets/package.json +1 -1
  94. package/presets/tool-plus-ptc/agent.cordis.yml +1 -1
  95. package/presets/tool-plus-standard/agent.cordis.yml +1 -1
  96. package/lib/agent_pb-Rizyt9Zg.mjs +0 -805
  97. package/lib/anthropic-CDmj476p.mjs +0 -262
  98. package/lib/api_server_pb-CDZgLMta.mjs +0 -252
  99. package/lib/callback-server-CFJK-jvK.mjs +0 -398
  100. package/lib/codex-P1dGpX7G.mjs +0 -54
  101. package/lib/device-code-CuXTWYwY.mjs +0 -51
  102. package/lib/devin-BcQwht1W.mjs +0 -114
  103. package/lib/devin-BvMfGevz.mjs +0 -95
  104. package/lib/github-copilot-B3kQl0g0.mjs +0 -104
  105. package/lib/gitlab-duo-BriUTP8k.mjs +0 -155
  106. package/lib/gitlab-duo-workflow-wK5Ljzmc.mjs +0 -91
  107. package/lib/google-CE5tFDod.mjs +0 -30
  108. package/lib/google-antigravity-C1jgNljz.mjs +0 -198
  109. package/lib/google-oauth-shared-BLVTvokk.mjs +0 -147
  110. package/lib/grammar-D-NqNUxQ.mjs +0 -49
  111. package/lib/identity-HNO1Oe9B.mjs +0 -219
  112. package/lib/kimi-DgcUpPtK.mjs +0 -236
  113. package/lib/markit-DtGoRE6M.mjs +0 -1417
  114. package/lib/minimax-code-Y3h5li9N.mjs +0 -53
  115. package/lib/models-DRA2c_8U.mjs +0 -104660
  116. package/lib/opencode-BsVw9rCD.mjs +0 -38
  117. package/lib/to-binary-B1BEBIPC.mjs +0 -6002
  118. package/lib/wafer-BlhWLweO.mjs +0 -17
  119. package/lib/xai-oauth-5pORHUrg.mjs +0 -446
@@ -1,398 +0,0 @@
1
- import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
- __installBunShim();
3
- import { c as OAuthError, h as LoginCancelledError, t as ConfigurationError } from "./error-C-f_Wnw4.mjs";
4
- //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/registry/oauth/oauth.html
5
- var oauth_default = "<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>oh my pi · authentication</title>\n <style>\n :root {\n /* dark, slightly purple-tinted neutrals — never #000 */\n --ink-0: oklch(0.135 0.018 295);\n --ink-1: oklch(0.172 0.022 295);\n --ink-2: oklch(0.21 0.024 295);\n --ink-4: oklch(0.36 0.024 295);\n --ink-5: oklch(0.5 0.022 290);\n --ink-6: oklch(0.66 0.018 290);\n --ink-7: oklch(0.82 0.014 285);\n --ink-9: oklch(0.97 0.008 90);\n\n /* brand: magenta lead, cyan reply */\n --magenta: oklch(0.7 0.24 340);\n --iris: oklch(0.62 0.21 295);\n --cyan: oklch(0.81 0.14 200);\n\n /* signal */\n --success: oklch(0.78 0.16 150);\n --error: oklch(0.66 0.22 25);\n\n --bg: var(--ink-0);\n --fg: var(--ink-9);\n --fg-dim: var(--ink-7);\n --fg-faint: var(--ink-5);\n --rule: oklch(1 0 0 / 0.07);\n --rule-strong: oklch(1 0 0 / 0.14);\n --accent: var(--magenta);\n --accent-2: var(--cyan);\n\n color-scheme: dark;\n }\n\n * {\n box-sizing: border-box;\n }\n\n body {\n font-family: \"Geist\", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n background:\n radial-gradient(ellipse 80vw 60vh at 18% -10%, oklch(0.7 0.24 340 / 0.13), transparent 60%),\n radial-gradient(ellipse 70vw 70vh at 110% 30%, oklch(0.81 0.14 200 / 0.09), transparent 60%),\n var(--bg);\n color: var(--fg);\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n margin: 0;\n padding: 1.5rem;\n -webkit-font-smoothing: antialiased;\n text-rendering: optimizeLegibility;\n overflow-x: clip;\n }\n\n /* ascii grid backdrop */\n .grid-bg {\n position: fixed;\n inset: 0;\n background-image:\n linear-gradient(to right, oklch(1 0 0 / 0.025) 1px, transparent 1px),\n linear-gradient(to bottom, oklch(1 0 0 / 0.025) 1px, transparent 1px);\n background-size: 56px 56px;\n background-position: -1px -1px;\n mask-image: radial-gradient(ellipse at 50% 30%, #000 30%, transparent 75%);\n pointer-events: none;\n z-index: 0;\n }\n\n .container {\n position: relative;\n z-index: 1;\n background: oklch(0.172 0.022 295 / 0.72);\n backdrop-filter: blur(16px);\n -webkit-backdrop-filter: blur(16px);\n border: 1px solid var(--rule);\n border-radius: 16px;\n padding: 2.5rem 2.5rem 2rem;\n width: 100%;\n max-width: 420px;\n text-align: center;\n box-shadow:\n 0 24px 48px -12px oklch(0 0 0 / 0.55),\n 0 0 0 1px oklch(1 0 0 / 0.03) inset;\n opacity: 0;\n transform: translateY(10px);\n animation: rise 0.6s cubic-bezier(0.16, 1, 0.3, 1) forwards;\n }\n @keyframes rise {\n to {\n opacity: 1;\n transform: none;\n }\n }\n\n /* brand header */\n .brand {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n margin-bottom: 2rem;\n }\n .brand svg {\n width: 22px;\n height: 22px;\n }\n .brand .wordmark {\n font-size: 13px;\n font-weight: 500;\n letter-spacing: -0.01em;\n color: var(--fg);\n }\n\n /* status mark */\n .mark-wrap {\n position: relative;\n width: 72px;\n height: 72px;\n margin: 0 auto 1.5rem;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n .mark-wrap::before {\n content: \"\";\n position: absolute;\n inset: 0;\n border-radius: 50%;\n background: oklch(1 0 0 / 0.05);\n z-index: 0;\n }\n .mark {\n width: 40px;\n height: 40px;\n z-index: 2;\n }\n .timer-svg {\n position: absolute;\n top: -2px;\n left: -2px;\n width: 76px;\n height: 76px;\n transform: rotate(-90deg);\n z-index: 1;\n pointer-events: none;\n }\n .timer-circle {\n fill: none;\n stroke-width: 2;\n stroke-linecap: round;\n stroke-dasharray: 226;\n stroke-dashoffset: 0;\n }\n .countdown .timer-circle {\n animation: countdown 3s linear forwards;\n }\n @keyframes countdown {\n to {\n stroke-dashoffset: 226;\n }\n }\n\n h1 {\n font-family: \"Fraunces\", \"Iowan Old Style\", Georgia, serif;\n font-size: 1.6rem;\n font-weight: 500;\n letter-spacing: -0.022em;\n line-height: 1.15;\n margin: 0 0 0.75rem;\n text-wrap: balance;\n }\n p {\n color: var(--fg-dim);\n line-height: 1.6;\n margin: 0 0 1.75rem;\n font-size: 0.95rem;\n }\n\n .btn {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n background: var(--fg);\n color: var(--bg);\n font-family: inherit;\n font-weight: 500;\n padding: 0.65rem 1.4rem;\n border-radius: 8px;\n text-decoration: none;\n font-size: 0.9rem;\n transition: opacity 0.2s, transform 0.2s;\n cursor: pointer;\n border: none;\n }\n .btn:hover {\n opacity: 0.88;\n transform: translateY(-1px);\n }\n .btn:active {\n transform: translateY(0);\n }\n\n /* State: success */\n .success .mark-wrap::before {\n background: oklch(0.78 0.16 150 / 0.12);\n }\n .success .mark {\n color: var(--success);\n }\n .success .timer-circle {\n stroke: var(--success);\n }\n .success .icon-error {\n display: none;\n }\n\n /* State: error */\n .error .mark-wrap::before {\n background: oklch(0.66 0.22 25 / 0.12);\n }\n .error .mark {\n color: var(--error);\n }\n .error .timer-circle {\n stroke: var(--error);\n }\n .error .icon-success,\n .error .timer-svg {\n display: none;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .container,\n .countdown .timer-circle {\n animation: none;\n }\n .container {\n opacity: 1;\n transform: none;\n }\n }\n </style>\n </head>\n <body>\n <span aria-hidden=\"true\" class=\"grid-bg\"></span>\n <div id=\"app\" class=\"container\">\n <div class=\"brand\">\n <svg viewBox=\"0 0 64 64\" aria-hidden=\"true\">\n <defs>\n <linearGradient id=\"pi-grad\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\">\n <stop offset=\"0\" stop-color=\"oklch(0.7 0.24 340)\" />\n <stop offset=\".5\" stop-color=\"oklch(0.62 0.21 295)\" />\n <stop offset=\"1\" stop-color=\"oklch(0.81 0.14 200)\" />\n </linearGradient>\n </defs>\n <path fill=\"url(#pi-grad)\" d=\"M10 14h44v9H43v33h-9V23h-9v22h-9V23H10z\" />\n </svg>\n <span class=\"wordmark\">oh my pi</span>\n </div>\n\n <div class=\"mark-wrap\">\n <svg class=\"timer-svg\" viewBox=\"0 0 76 76\">\n <circle class=\"timer-circle\" cx=\"38\" cy=\"38\" r=\"36\"></circle>\n </svg>\n <svg class=\"mark icon-success\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n <svg class=\"mark icon-error\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </div>\n\n <h1 id=\"title\">Authentication</h1>\n <p id=\"message\"></p>\n <button onclick=\"window.close()\" class=\"btn\">Close Window</button>\n </div>\n\n <script id=\"server-state\" type=\"application/json\">\n __OAUTH_STATE__\n <\/script>\n\n <script>\n let serverState;\n try {\n serverState = JSON.parse(document.getElementById(\"server-state\").textContent);\n } catch {\n const params = new URLSearchParams(window.location.search);\n serverState = {\n ok: params.get(\"ok\") === \"1\",\n error: params.get(\"error\") || \"Authentication failed\",\n };\n }\n\n const app = document.getElementById(\"app\");\n const title = document.getElementById(\"title\");\n const message = document.getElementById(\"message\");\n\n if (serverState.ok) {\n app.classList.add(\"success\", \"countdown\");\n title.textContent = \"Authentication Successful\";\n message.innerHTML = \"You have successfully logged in.<br>You can now close this tab.\";\n setTimeout(() => window.close(), 3000);\n } else {\n app.classList.add(\"error\");\n title.textContent = \"Authentication Failed\";\n message.textContent = serverState.error || \"An error occurred\";\n }\n <\/script>\n </body>\n</html>\n";
6
- //#endregion
7
- //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/registry/oauth/callback-server.ts
8
- /**
9
- * Abstract base class for OAuth flows with local callback servers.
10
- *
11
- * Handles:
12
- * - Port allocation (tries expected port, falls back to random)
13
- * - Callback server setup and request handling
14
- * - Common OAuth flow logic
15
- *
16
- * Providers extend this and implement:
17
- * - generateAuthUrl(): Build provider-specific authorization URL
18
- * - exchangeToken(): Exchange authorization code for tokens
19
- */
20
- const DEFAULT_TIMEOUT = 3e5;
21
- const DEFAULT_HOSTNAME = "localhost";
22
- const CALLBACK_PATH = "/callback";
23
- const IPV4_LOOPBACK = "127.0.0.1";
24
- const IPV6_LOOPBACK = "::1";
25
- /**
26
- * How many times a random-port bind may be redrawn when the ephemeral port it
27
- * landed on is already held on {@link IPV6_LOOPBACK} by that exact address.
28
- * Small on purpose: each redraw picks a fresh port, so a repeat collision is
29
- * vanishingly unlikely.
30
- */
31
- const IPV6_COMPANION_ATTEMPTS = 4;
32
- /**
33
- * Path served by {@link OAuthCallbackFlow} that 302-redirects to the pending
34
- * authorization URL. Kept out of {@link OAuthCallbackFlowOptions} because it
35
- * lives on the loopback callback server alongside {@link CALLBACK_PATH} and
36
- * must never clash with a provider-registered redirect URI (all known
37
- * providers register `/callback`-shaped paths).
38
- */
39
- const LAUNCH_PATH = "/launch";
40
- /**
41
- * Whether a failed bind means "another process already holds this port".
42
- * Bun surfaces `EADDRINUSE` on the error's `code` where the platform reports
43
- * it, and otherwise only in the message, so both are checked.
44
- */
45
- function isAddressInUse(error) {
46
- const code = error?.code;
47
- if (typeof code === "string") return code === "EADDRINUSE";
48
- return error instanceof Error && /EADDRINUSE|in use/i.test(error.message);
49
- }
50
- /**
51
- * Abstract base class for OAuth flows with local callback servers.
52
- */
53
- var OAuthCallbackFlow = class {
54
- ctrl;
55
- preferredPort;
56
- callbackPath;
57
- callbackHostname;
58
- redirectUri;
59
- allowPortFallback;
60
- #manualInputOnly;
61
- #callbackResolve;
62
- #callbackReject;
63
- /**
64
- * Authorization URL the `/launch` route currently redirects to. Set by
65
- * {@link login} after {@link generateAuthUrl} and before {@link OAuthController.onAuth}
66
- * fires, cleared when the server stops. `undefined` before the flow reaches
67
- * that point and after it finishes, so `/launch` returns 503 rather than
68
- * a stale URL.
69
- */
70
- #pendingAuthUrl;
71
- constructor(ctrl, preferredPortOrOptions, callbackPath = CALLBACK_PATH) {
72
- this.ctrl = ctrl;
73
- if (typeof preferredPortOrOptions === "number") {
74
- this.preferredPort = preferredPortOrOptions;
75
- this.callbackPath = callbackPath;
76
- this.callbackHostname = DEFAULT_HOSTNAME;
77
- this.allowPortFallback = true;
78
- this.#manualInputOnly = false;
79
- return;
80
- }
81
- this.preferredPort = preferredPortOrOptions.preferredPort;
82
- this.callbackPath = preferredPortOrOptions.callbackPath ?? CALLBACK_PATH;
83
- this.callbackHostname = preferredPortOrOptions.callbackHostname ?? DEFAULT_HOSTNAME;
84
- this.redirectUri = preferredPortOrOptions.redirectUri;
85
- this.allowPortFallback = preferredPortOrOptions.allowPortFallback ?? true;
86
- this.#manualInputOnly = preferredPortOrOptions.manualInputOnly ?? false;
87
- }
88
- /**
89
- * Generate CSRF state token. Override if provider needs custom state generation.
90
- */
91
- generateState() {
92
- const bytes = /* @__PURE__ */ new Uint8Array(16);
93
- crypto.getRandomValues(bytes);
94
- return Array.from(bytes).map((value) => value.toString(16).padStart(2, "0")).join("");
95
- }
96
- #loginCancelledError() {
97
- return new LoginCancelledError(`OAuth callback cancelled: ${this.ctrl.signal?.reason}`);
98
- }
99
- #throwIfCancelled() {
100
- if (this.ctrl.signal?.aborted) throw this.#loginCancelledError();
101
- }
102
- /**
103
- * Execute the OAuth login flow.
104
- */
105
- async login() {
106
- const state = this.generateState();
107
- this.#throwIfCancelled();
108
- const { server, redirectUri, launchUrl } = this.#manualInputOnly ? {
109
- server: void 0,
110
- redirectUri: this.#buildRedirectUri(),
111
- launchUrl: void 0
112
- } : await this.#startCallbackServer(state);
113
- try {
114
- this.#throwIfCancelled();
115
- const { url: authUrl, instructions } = await this.generateAuthUrl(state, redirectUri);
116
- this.#throwIfCancelled();
117
- this.#pendingAuthUrl = authUrl;
118
- this.ctrl.onAuth?.({
119
- url: authUrl,
120
- launchUrl,
121
- instructions
122
- });
123
- this.ctrl.onProgress?.(this.#manualInputOnly ? "Waiting for pasted authorization code..." : "Waiting for browser authentication...");
124
- const { code } = await this.#waitForCallback(state);
125
- this.#throwIfCancelled();
126
- this.ctrl.onProgress?.("Exchanging authorization code for tokens...");
127
- return await this.exchangeToken(code, state, redirectUri);
128
- } finally {
129
- this.#pendingAuthUrl = void 0;
130
- server?.stop();
131
- }
132
- }
133
- #buildRedirectUri() {
134
- return this.redirectUri ?? `http://${this.callbackHostname}:${this.preferredPort}${this.callbackPath}`;
135
- }
136
- /**
137
- * Start callback server, trying preferred port first, falling back to random.
138
- * `launchUrl` is `undefined` when the caller configured `callbackPath` to
139
- * collide with {@link LAUNCH_PATH} — the callback handler resolves the real
140
- * callback in that case, so advertising a self-redirecting URL would be
141
- * incorrect.
142
- */
143
- async #startCallbackServer(expectedState) {
144
- try {
145
- const server = this.#createServer(this.preferredPort, expectedState);
146
- const actualPort = this.#resolveServerPort(server);
147
- const launchUrl = this.#launchUrlIfSafe(actualPort);
148
- if (this.redirectUri) return {
149
- server,
150
- redirectUri: this.redirectUri,
151
- launchUrl
152
- };
153
- return {
154
- server,
155
- redirectUri: `http://${this.callbackHostname}:${actualPort}${this.callbackPath}`,
156
- launchUrl
157
- };
158
- } catch (cause) {
159
- if (this.redirectUri) throw new ConfigurationError(`OAuth callback port ${this.preferredPort} is in use, but oauth.redirectUri (${this.redirectUri}) requires this exact port. Free port ${this.preferredPort} (e.g. stop the process bound to it) and retry, or change oauth.redirectUri to point at an available port.`, { cause });
160
- if (!this.allowPortFallback) throw new ConfigurationError(`OAuth callback port ${this.preferredPort} is in use. The OAuth provider validates redirect URIs against its registered callback, so falling back to a random port would be rejected. Free port ${this.preferredPort} (e.g. stop the process bound to it) and retry, or set oauth.callbackPort/oauth.redirectUri to a port the provider has registered.`, { cause });
161
- const server = this.#createServer(0, expectedState);
162
- const actualPort = this.#resolveServerPort(server);
163
- const redirectUri = `http://${this.callbackHostname}:${actualPort}${this.callbackPath}`;
164
- const launchUrl = this.#launchUrlIfSafe(actualPort);
165
- this.ctrl.onProgress?.(`Preferred port ${this.preferredPort} unavailable, using port ${actualPort}`);
166
- return {
167
- server,
168
- redirectUri,
169
- launchUrl
170
- };
171
- }
172
- }
173
- /**
174
- * Read the numeric port a callback server bound to. `Bun.Server.port` is
175
- * declared `number | undefined` because Unix-socket servers have no port,
176
- * but every callback flow uses TCP; a missing port here indicates a
177
- * configuration error rather than a fallback case.
178
- */
179
- #resolveServerPort(server) {
180
- const port = server.port;
181
- if (typeof port !== "number") throw new ConfigurationError("OAuth callback server bound to a non-TCP endpoint; expected a numeric port. Check `oauth.callbackPort`/`oauth.redirectUri`.");
182
- return port;
183
- }
184
- /**
185
- * Build the `/launch` URL served by the callback server bound to `port`, or
186
- * `undefined` when it must not be advertised:
187
- * - the configured `callbackPath` (or a `redirectUri` whose pathname
188
- * resolves to {@link LAUNCH_PATH}) would collide with the launch route;
189
- * - the flow's `redirectUri` never returns to this loopback server: fixed
190
- * non-loopback hosts, or custom schemes like GitLab Duo's `vscode://`
191
- * URI — which `new URL` parses without complaint, so a scheme/host check
192
- * is required, not just the parse failure path. Advertising a localhost
193
- * `/launch` target for such flows misrepresents the callback endpoint
194
- * and hands remote users a URL that resolves nowhere.
195
- * Kept short (~30 chars) so UIs can advertise it as a
196
- * viewport-truncation-safe copy target for the full authorization URL.
197
- */
198
- #launchUrlIfSafe(port) {
199
- if (this.callbackPath === LAUNCH_PATH) return void 0;
200
- if (this.redirectUri) try {
201
- const parsed = new URL(this.redirectUri);
202
- if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return void 0;
203
- if (parsed.hostname !== "localhost" && parsed.hostname !== "127.0.0.1" && parsed.hostname !== "[::1]") return;
204
- if (parsed.pathname === LAUNCH_PATH) return void 0;
205
- } catch {
206
- return;
207
- }
208
- return `http://${this.callbackHostname}:${port}${LAUNCH_PATH}`;
209
- }
210
- /**
211
- * Create the HTTP listener(s) for the OAuth callback.
212
- *
213
- * `localhost` is not a single endpoint: it resolves to both
214
- * {@link IPV4_LOOPBACK} and {@link IPV6_LOOPBACK}, and clients commonly try
215
- * `::1` first. Binding only the IPv4 literal hands the authorization code to
216
- * whatever holds the IPv6 loopback on the same port — a dev server on
217
- * `*:3000` is the common case — which answers from its own routes while this
218
- * flow waits out the full {@link DEFAULT_TIMEOUT}. Nothing detects it either:
219
- * a specific-address bind coexists with another process's wildcard bind, so
220
- * `Bun.serve` reports the port as free and the random-port fallback in
221
- * {@link #startCallbackServer} never runs.
222
- *
223
- * Binding both loopback literals fixes the delivery rather than dodging it:
224
- * the kernel routes a connection to the most specific matching bind, so our
225
- * `::1` listener receives `localhost` traffic that would otherwise reach a
226
- * process bound to the `::` wildcard. Both listeners answer the same routes,
227
- * so which family the client resolves stops mattering.
228
- *
229
- * A genuine collision — another process on exactly this loopback address and
230
- * port — still raises EADDRINUSE and reaches the caller's in-use policy. A
231
- * host that cannot bind `::1` at all (IPv6 disabled, address unavailable) is
232
- * not a collision: the IPv4 listener is the only reachable endpoint there, so
233
- * it serves alone.
234
- */
235
- #createServer(port, expectedState) {
236
- if (this.callbackHostname !== DEFAULT_HOSTNAME) return this.#serve(this.callbackHostname, port, expectedState);
237
- for (let attempt = 0;; attempt++) {
238
- const primary = this.#serve(IPV4_LOOPBACK, port, expectedState);
239
- const boundPort = primary.port;
240
- if (typeof boundPort !== "number") return primary;
241
- let companion;
242
- try {
243
- companion = this.#serve(IPV6_LOOPBACK, boundPort, expectedState);
244
- } catch (cause) {
245
- if (!isAddressInUse(cause)) return primary;
246
- primary.stop(true);
247
- if (port !== 0 || attempt >= IPV6_COMPANION_ATTEMPTS) throw cause;
248
- continue;
249
- }
250
- return {
251
- get port() {
252
- return primary.port;
253
- },
254
- stop: (closeActiveConnections) => {
255
- companion.stop(closeActiveConnections);
256
- return primary.stop(closeActiveConnections);
257
- }
258
- };
259
- }
260
- }
261
- /** Bind one loopback listener serving the callback and launch routes. */
262
- #serve(hostname, port, expectedState) {
263
- return Bun.serve({
264
- hostname,
265
- port,
266
- reusePort: false,
267
- fetch: (req) => this.#handleCallback(req, expectedState)
268
- });
269
- }
270
- /**
271
- * Handle OAuth callback HTTP request. Two routes on the same loopback server:
272
- * - `callbackPath` (default `/callback`) — the provider redirect target.
273
- * - {@link LAUNCH_PATH} (`/launch`) — 302 to the pending authorization URL so
274
- * viewport-safe copy targets can survive TUI truncation.
275
- *
276
- * `callbackPath` wins any collision: an OMP config that pins the provider
277
- * redirect at `/launch` (via `oauth.callbackPath` or a loopback
278
- * `oauth.redirectUri`) must resolve the callback normally rather than
279
- * self-redirect. `#startCallbackServer` also suppresses `launchUrl` in that
280
- * case, so the launch route is never advertised when it would collide.
281
- */
282
- #handleCallback(req, expectedState) {
283
- const url = new URL(req.url);
284
- if (url.pathname !== this.callbackPath) {
285
- if (url.pathname === LAUNCH_PATH) {
286
- const pending = this.#pendingAuthUrl;
287
- if (!pending) return new Response("OAuth launch URL is no longer active", { status: 503 });
288
- return Response.redirect(pending, 302);
289
- }
290
- return new Response("Not Found", { status: 404 });
291
- }
292
- const code = url.searchParams.get("code");
293
- const state = url.searchParams.get("state") || "";
294
- const error = url.searchParams.get("error") || "";
295
- const errorDescription = url.searchParams.get("error_description") || error;
296
- let resultState;
297
- if (error) resultState = {
298
- ok: false,
299
- error: `Authorization failed: ${errorDescription}`
300
- };
301
- else if (!code) resultState = {
302
- ok: false,
303
- error: "Missing authorization code"
304
- };
305
- else if (expectedState && state !== expectedState) resultState = {
306
- ok: false,
307
- error: "State mismatch - possible CSRF attack"
308
- };
309
- else resultState = {
310
- ok: true,
311
- code,
312
- state
313
- };
314
- if (resultState.ok) {
315
- const resolve = this.#callbackResolve;
316
- queueMicrotask(() => {
317
- resolve?.({
318
- code: resultState.code,
319
- state: resultState.state
320
- });
321
- });
322
- } else if (error && (!expectedState || state === expectedState)) {
323
- const reject = this.#callbackReject;
324
- const message = resultState.error ?? `Authorization failed: ${errorDescription}`;
325
- queueMicrotask(() => {
326
- reject?.(new OAuthError(message, { kind: "device-auth" }));
327
- });
328
- }
329
- return new Response(oauth_default.replaceAll("__OAUTH_STATE__", JSON.stringify(resultState)), {
330
- status: resultState.ok ? 200 : 500,
331
- headers: { "Content-Type": "text/html" }
332
- });
333
- }
334
- /**
335
- * Wait for OAuth callback or manual input (whichever comes first).
336
- */
337
- #waitForCallback(expectedState) {
338
- const timeoutSignal = AbortSignal.timeout(DEFAULT_TIMEOUT);
339
- const signal = this.ctrl.signal ? AbortSignal.any([this.ctrl.signal, timeoutSignal]) : timeoutSignal;
340
- if (signal.aborted) return Promise.reject(this.#loginCancelledError());
341
- const callback = Promise.withResolvers();
342
- this.#callbackResolve = callback.resolve;
343
- this.#callbackReject = callback.reject;
344
- signal.addEventListener("abort", () => {
345
- this.#callbackResolve = void 0;
346
- this.#callbackReject = void 0;
347
- callback.reject(new LoginCancelledError(`OAuth callback cancelled: ${signal.reason}`));
348
- });
349
- const callbackPromise = callback.promise;
350
- if (this.ctrl.onManualCodeInput) {
351
- const requestManualInput = this.ctrl.onManualCodeInput;
352
- const manualPromise = (async () => {
353
- while (true) {
354
- const result = await Promise.race([callbackPromise, requestManualInput().then((input) => {
355
- const parsed = parseCallbackInput(input);
356
- if (!parsed.code) return null;
357
- if (expectedState && parsed.state && parsed.state !== expectedState) return null;
358
- return {
359
- code: parsed.code,
360
- state: parsed.state ?? ""
361
- };
362
- }).catch(() => null)]);
363
- if (result) return result;
364
- }
365
- })();
366
- return Promise.race([callbackPromise, manualPromise]);
367
- }
368
- return callbackPromise;
369
- }
370
- };
371
- /**
372
- * Parse a redirect URL or code string to extract code and state.
373
- */
374
- function parseCallbackInput(input) {
375
- const value = input.trim();
376
- if (!value) return {};
377
- try {
378
- const url = new URL(value);
379
- return {
380
- code: url.searchParams.get("code") ?? void 0,
381
- state: url.searchParams.get("state") ?? void 0
382
- };
383
- } catch {}
384
- if (value.includes("code=")) {
385
- const params = new URLSearchParams(value.replace(/^[?#]/, ""));
386
- return {
387
- code: params.get("code") ?? void 0,
388
- state: params.get("state") ?? void 0
389
- };
390
- }
391
- const [code, state] = value.split("#", 2);
392
- return {
393
- code,
394
- state
395
- };
396
- }
397
- //#endregion
398
- export { OAuthCallbackFlow as t };
@@ -1,54 +0,0 @@
1
- import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
- __installBunShim();
3
- //#region node_modules/.pnpm/@oh-my-pi+pi-catalog@17.3.5/node_modules/@oh-my-pi/pi-catalog/src/wire/codex.ts
4
- /**
5
- * Constants for OpenAI Codex (ChatGPT OAuth) backend
6
- */
7
- const CODEX_BASE_URL = "https://chatgpt.com/backend-api";
8
- /**
9
- * Pinned OpenAI Codex client version (corresponds to @openai/codex package version).
10
- */
11
- const CODEX_CLIENT_VERSION = "0.144.1";
12
- const OPENAI_HEADERS = {
13
- BETA: "OpenAI-Beta",
14
- /** Codex feature-negotiation header; values identify opt-in wire protocols. */
15
- CODEX_BETA_FEATURES: "x-codex-beta-features",
16
- ACCOUNT_ID: "chatgpt-account-id",
17
- ORIGINATOR: "originator",
18
- VERSION: "version",
19
- SESSION_ID: "session_id",
20
- CONVERSATION_ID: "conversation_id",
21
- SCOPED_SESSION_ID: "session-id",
22
- THREAD_ID: "thread-id",
23
- INSTALLATION_ID: "x-codex-installation-id",
24
- WINDOW_ID: "x-codex-window-id",
25
- TURN_METADATA: "x-codex-turn-metadata",
26
- PARENT_THREAD_ID: "x-codex-parent-thread-id",
27
- SUBAGENT: "x-openai-subagent",
28
- /** Responses Lite transport marker (codex-rs `add_responses_lite_header`); value is always `"true"`. */
29
- RESPONSES_LITE: "x-openai-internal-codex-responses-lite",
30
- /** DeviceCheck attestation envelope (codex-rs `X_OAI_ATTESTATION_HEADER`); sent on ChatGPT-OAuth requests. */
31
- ATTESTATION: "x-oai-attestation"
32
- };
33
- const OPENAI_HEADER_VALUES = {
34
- BETA_RESPONSES: "responses=experimental",
35
- BETA_RESPONSES_WEBSOCKETS_V2: "responses_websockets=2026-02-06",
36
- REMOTE_COMPACTION_V2: "remote_compaction_v2",
37
- ORIGINATOR_CODEX: "pi"
38
- };
39
- /**
40
- * Extract account ID from a Codex JWT access token.
41
- * Returns undefined if the token is not a valid Codex JWT.
42
- */
43
- function getCodexAccountId(accessToken) {
44
- try {
45
- const parts = accessToken.split(".");
46
- if (parts.length !== 3) return void 0;
47
- const decoded = Buffer.from(parts[1] ?? "", "base64").toString("utf-8");
48
- return JSON.parse(decoded)["https://api.openai.com/auth"]?.chatgpt_account_id ?? void 0;
49
- } catch {
50
- return;
51
- }
52
- }
53
- //#endregion
54
- export { getCodexAccountId as a, OPENAI_HEADER_VALUES as i, CODEX_CLIENT_VERSION as n, OPENAI_HEADERS as r, CODEX_BASE_URL as t };
@@ -1,51 +0,0 @@
1
- import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
- __installBunShim();
3
- import { c as OAuthError, h as LoginCancelledError } from "./error-C-f_Wnw4.mjs";
4
- //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/registry/oauth/device-code.ts
5
- const DEVICE_FLOW_CANCEL_MESSAGE = "Login cancelled";
6
- const DEVICE_FLOW_TIMEOUT_MESSAGE = "Device flow timed out";
7
- const DEVICE_FLOW_SLOW_DOWN_TIMEOUT_MESSAGE = "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.";
8
- const MINIMUM_DEVICE_FLOW_INTERVAL_MS = 1e3;
9
- const DEFAULT_DEVICE_FLOW_INTERVAL_SECONDS = 5;
10
- const SLOW_DOWN_INTERVAL_INCREMENT_MS = 5e3;
11
- async function abortableDeviceFlowSleep(ms, signal) {
12
- if (!signal) {
13
- await Bun.sleep(ms);
14
- return;
15
- }
16
- if (signal.aborted) throw new LoginCancelledError(DEVICE_FLOW_CANCEL_MESSAGE);
17
- const { promise, resolve, reject } = Promise.withResolvers();
18
- let timer;
19
- const onAbort = () => {
20
- clearTimeout(timer);
21
- reject(new LoginCancelledError(DEVICE_FLOW_CANCEL_MESSAGE));
22
- };
23
- timer = setTimeout(() => {
24
- signal.removeEventListener("abort", onAbort);
25
- resolve();
26
- }, ms);
27
- signal.addEventListener("abort", onAbort, { once: true });
28
- await promise;
29
- }
30
- /** Poll an OAuth device-code flow until completion, provider failure, timeout, or cancellation. */
31
- async function pollOAuthDeviceCodeFlow(options) {
32
- const deadline = typeof options.expiresInSeconds === "number" ? Date.now() + options.expiresInSeconds * 1e3 : Number.POSITIVE_INFINITY;
33
- let intervalMs = Math.max(MINIMUM_DEVICE_FLOW_INTERVAL_MS, Math.floor((options.intervalSeconds ?? DEFAULT_DEVICE_FLOW_INTERVAL_SECONDS) * 1e3));
34
- let slowDownResponses = 0;
35
- while (Date.now() < deadline) {
36
- if (options.signal?.aborted) throw new LoginCancelledError(DEVICE_FLOW_CANCEL_MESSAGE);
37
- const result = await options.poll();
38
- if (result.status === "complete") return result.value;
39
- if (result.status === "failed") throw new OAuthError(result.message, { kind: "polling" });
40
- if (result.status === "slow_down") {
41
- slowDownResponses += 1;
42
- intervalMs = Math.max(MINIMUM_DEVICE_FLOW_INTERVAL_MS, intervalMs + SLOW_DOWN_INTERVAL_INCREMENT_MS);
43
- }
44
- const remainingMs = deadline - Date.now();
45
- if (remainingMs <= 0) break;
46
- await abortableDeviceFlowSleep(Math.min(intervalMs, remainingMs), options.signal);
47
- }
48
- throw new OAuthError(slowDownResponses > 0 ? DEVICE_FLOW_SLOW_DOWN_TIMEOUT_MESSAGE : DEVICE_FLOW_TIMEOUT_MESSAGE, { kind: "timeout" });
49
- }
50
- //#endregion
51
- export { pollOAuthDeviceCodeFlow as t };
@@ -1,114 +0,0 @@
1
- import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
- __installBunShim();
3
- import { n as discoveryFetch } from "./utils-CQHPEQ3W.mjs";
4
- import { E as create, i as fromBinary, t as toBinary } from "./to-binary-B1BEBIPC.mjs";
5
- import { f as MetadataSchema, i as GetCliModelConfigsResponseSchema, r as GetCliModelConfigsRequestSchema } from "./api_server_pb-CDZgLMta.mjs";
6
- import { gunzipSync } from "node:zlib";
7
- //#region node_modules/.pnpm/@oh-my-pi+pi-catalog@17.3.5/node_modules/@oh-my-pi/pi-catalog/src/discovery/devin.ts
8
- const DEVIN_DEFAULT_BASE_URL = "https://server.codeium.com";
9
- const DEVIN_GET_CLI_MODEL_CONFIGS_PATH = "/exa.api_server_pb.ApiServerService/GetCliModelConfigs";
10
- const DEVIN_IDE_VERSION = "3.2.23";
11
- const DEVIN_EXTENSION_VERSION = "1.48.2";
12
- const DEVIN_SESSION_TOKEN_PREFIX = "devin-session-token$";
13
- const DEFAULT_CONTEXT_WINDOW = 2e5;
14
- const DEFAULT_MAX_TOKENS = 64e3;
15
- /** Best-effort match for labels whose wording implies a thinking / reasoning-effort variant. */
16
- const REASONING_LABEL_PATTERN = /think|thinking|minimal|high|medium|low|xhigh|max|reasoning/i;
17
- const NO_REASONING_LABEL_PATTERN = /\bno thinking\b/i;
18
- function supportsDevinThinking(config) {
19
- if (NO_REASONING_LABEL_PATTERN.test(config.label)) return false;
20
- return config.modelInfo?.modelFeatures?.supportsThinking === true || REASONING_LABEL_PATTERN.test(config.label);
21
- }
22
- /**
23
- * Fetches Devin models through the `GetCliModelConfigs` unary Connect RPC and
24
- * normalizes them into canonical model entries.
25
- *
26
- * Returns `null` on request/decode failures.
27
- * Returns `[]` only when the endpoint responds successfully with no usable models.
28
- */
29
- async function fetchDevinModels(options) {
30
- const timeoutMs = options.timeoutMs ?? 5e3;
31
- const requestUrl = `${(options.baseUrl ?? DEVIN_DEFAULT_BASE_URL).replace(/\/+$/, "")}${DEVIN_GET_CLI_MODEL_CONFIGS_PATH}`;
32
- const controller = new AbortController();
33
- const timer = setTimeout(() => controller.abort(), timeoutMs);
34
- const signal = options.signal ? AbortSignal.any([controller.signal, options.signal]) : controller.signal;
35
- try {
36
- const request = create(GetCliModelConfigsRequestSchema, { metadata: create(MetadataSchema, {
37
- apiKey: normalizeDevinSessionToken(options.apiKey),
38
- ideName: "windsurf",
39
- ideVersion: DEVIN_IDE_VERSION,
40
- extensionName: "windsurf",
41
- extensionVersion: DEVIN_EXTENSION_VERSION
42
- }) });
43
- const body = toBinary(GetCliModelConfigsRequestSchema, request);
44
- const response = await discoveryFetch(options.fetch)(requestUrl, {
45
- method: "POST",
46
- headers: {
47
- "content-type": "application/proto",
48
- "connect-protocol-version": "1",
49
- accept: "*/*"
50
- },
51
- body,
52
- signal
53
- });
54
- if (!response.ok) return null;
55
- const decoded = decodeCliModelConfigsResponse(new Uint8Array(await response.arrayBuffer()));
56
- if (!decoded) return null;
57
- return normalizeDevinModels(decoded.clientModelConfigs, options.baseUrl);
58
- } catch {
59
- return null;
60
- } finally {
61
- clearTimeout(timer);
62
- }
63
- }
64
- function normalizeDevinSessionToken(apiKey) {
65
- if (!apiKey) return "";
66
- return apiKey.startsWith(DEVIN_SESSION_TOKEN_PREFIX) ? apiKey : `${DEVIN_SESSION_TOKEN_PREFIX}${apiKey}`;
67
- }
68
- /**
69
- * Decodes a raw (unframed) `GetCliModelConfigsResponse`. Bun's `fetch` usually
70
- * auto-decompresses gzip, so the direct decode is attempted first; a
71
- * `gunzipSync` fallback covers runtimes that hand back the still-compressed body.
72
- */
73
- function decodeCliModelConfigsResponse(payload) {
74
- try {
75
- return fromBinary(GetCliModelConfigsResponseSchema, payload);
76
- } catch {
77
- try {
78
- return fromBinary(GetCliModelConfigsResponseSchema, gunzipSync(payload));
79
- } catch {
80
- return null;
81
- }
82
- }
83
- }
84
- function normalizeDevinModels(configs, baseUrlOverride) {
85
- const byId = /* @__PURE__ */ new Map();
86
- for (const config of configs) {
87
- if (config.disabled) continue;
88
- const id = config.modelUid.trim();
89
- if (!id) continue;
90
- const input = config.supportsImages ? ["text", "image"] : ["text"];
91
- const contextWindow = config.maxTokens > 0 ? config.maxTokens : DEFAULT_CONTEXT_WINDOW;
92
- byId.set(id, {
93
- id,
94
- name: config.label.trim() || id,
95
- api: "devin-agent",
96
- provider: "devin",
97
- baseUrl: baseUrlOverride ?? DEVIN_DEFAULT_BASE_URL,
98
- reasoning: supportsDevinThinking(config),
99
- input,
100
- supportsTools: true,
101
- cost: {
102
- input: 0,
103
- output: 0,
104
- cacheRead: 0,
105
- cacheWrite: 0
106
- },
107
- contextWindow,
108
- maxTokens: Math.min(config.maxTokens > 0 ? config.maxTokens : DEFAULT_MAX_TOKENS, DEFAULT_MAX_TOKENS)
109
- });
110
- }
111
- return [...byId.values()].sort((a, b) => a.id.localeCompare(b.id));
112
- }
113
- //#endregion
114
- export { fetchDevinModels };