@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.
- package/README.en.md +122 -0
- package/README.md +3 -2
- package/THIRD_PARTY_NOTICES.md +4 -35
- package/lib/abort-B7izMMna.mjs +51 -0
- package/lib/abort-D1_Z5Ut5.mjs +51 -0
- package/lib/abort-dIkZBV7Q.mjs +51 -0
- package/lib/amazon-bedrock-B0nxT06F.mjs +917 -0
- package/lib/amazon-bedrock-D-shAr1X.mjs +917 -0
- package/lib/amazon-bedrock-WQhvjHYu.mjs +917 -0
- package/lib/anthropic-BWsZFzU8.mjs +262 -0
- package/lib/anthropic-CJCauvYz.mjs +3115 -0
- package/lib/anthropic-CMT1Qj1t.mjs +3115 -0
- package/lib/anthropic-CZghe_9U.mjs +3115 -0
- package/lib/anthropic-sCMH7JID.mjs +262 -0
- package/lib/anthropic-tTntD8BD.mjs +262 -0
- package/lib/api-key-login-BzqNdM2y.mjs +157 -0
- package/lib/api-key-login-CWVwvHT1.mjs +157 -0
- package/lib/api-key-login-CpzSezsi.mjs +157 -0
- package/lib/aws-credentials-8Mgn5MAy.mjs +867 -0
- package/lib/aws-credentials-CXryMobh.mjs +867 -0
- package/lib/aws-credentials-ChG79ey-.mjs +867 -0
- package/lib/azure-openai-responses-CNkHiLUh.mjs +274 -0
- package/lib/azure-openai-responses-Cgmc-rbL.mjs +274 -0
- package/lib/azure-openai-responses-DuukbD0F.mjs +274 -0
- package/lib/bun-shim.mjs +252 -12
- package/lib/bundled-references-CSuBco5p.mjs +55 -0
- package/lib/bundled-references-Cavaffah.mjs +55 -0
- package/lib/bundled-references-sLN0YdXU.mjs +55 -0
- package/lib/callback-server-BEFNf-jf.mjs +398 -0
- package/lib/callback-server-CQ5Jo8F-.mjs +398 -0
- package/lib/callback-server-DDSrZ6l_.mjs +398 -0
- package/lib/client.js +111 -41
- package/lib/cursor-B3zg7EHj.mjs +273 -0
- package/lib/cursor-B6TUEmgP.mjs +135 -0
- package/lib/cursor-BIQfBC6V.mjs +135 -0
- package/lib/cursor-D8gvtTL3.mjs +135 -0
- package/lib/cursor-DNk6eXDd.mjs +5470 -0
- package/lib/cursor-DkSX2h3H.mjs +5441 -0
- package/lib/cursor-MjSm74IJ.mjs +273 -0
- package/lib/cursor-aJrXeYCb.mjs +273 -0
- package/lib/cursor-mJQwUKXK.mjs +5441 -0
- package/lib/device-code-DBo3B5nh.mjs +51 -0
- package/lib/device-code-DIb0FU-H.mjs +51 -0
- package/lib/device-code-OI_tQcmc.mjs +51 -0
- package/lib/devin-BHZZyMhO.mjs +95 -0
- package/lib/devin-BK7DHeca.mjs +114 -0
- package/lib/devin-CfMp3cXS.mjs +95 -0
- package/lib/devin-CldyPD8K.mjs +95 -0
- package/lib/devin-CzRpTUOA.mjs +114 -0
- package/lib/devin-D9zR5B_R.mjs +542 -0
- package/lib/devin-DXOeNyU7.mjs +542 -0
- package/lib/devin-Q1yem3lp.mjs +114 -0
- package/lib/devin-vNZTNUON.mjs +542 -0
- package/lib/error-B3bevhrs.mjs +1449 -0
- package/lib/error-Dd8DIqs-.mjs +1449 -0
- package/lib/error-yCSG0mGC.mjs +1449 -0
- package/lib/event-stream-BDPi64mK.mjs +151 -0
- package/lib/event-stream-BbFZJy-z.mjs +151 -0
- package/lib/event-stream-loUa0s1T.mjs +151 -0
- package/lib/fs-promises-shim-Bx0fpxuk.mjs +57 -0
- package/lib/github-copilot-4GaMtQmg.mjs +208 -0
- package/lib/github-copilot-B1yiyVRh.mjs +104 -0
- package/lib/github-copilot-B2HGSIJK.mjs +104 -0
- package/lib/github-copilot-BWT3eAOF.mjs +208 -0
- package/lib/github-copilot-CYkjeTi3.mjs +208 -0
- package/lib/github-copilot-jscUZ8Hf.mjs +104 -0
- package/lib/gitlab-duo-CM7Ref1H.mjs +155 -0
- package/lib/gitlab-duo-akICyfeD.mjs +155 -0
- package/lib/gitlab-duo-gubO4FNw.mjs +155 -0
- package/lib/gitlab-duo-workflow-BGAF6JDw.mjs +91 -0
- package/lib/gitlab-duo-workflow-CSEgYk3N.mjs +91 -0
- package/lib/gitlab-duo-workflow-D78tdn8E.mjs +91 -0
- package/lib/google-BS4T25Pn.mjs +30 -0
- package/lib/google-TFe-7-of.mjs +30 -0
- package/lib/google-antigravity-DGmwC2KV.mjs +198 -0
- package/lib/google-antigravity-DNYhgTpA.mjs +198 -0
- package/lib/google-antigravity-Dlkdhahq.mjs +198 -0
- package/lib/google-auth-B6gjsZvg.mjs +232 -0
- package/lib/google-auth-De7_s3eo.mjs +232 -0
- package/lib/google-auth-DhqpOYrX.mjs +232 -0
- package/lib/google-gemini-cli-BG_LRdIV.mjs +850 -0
- package/lib/google-gemini-cli-CWu8HvXW.mjs +211 -0
- package/lib/google-gemini-cli-Cb97bzQc.mjs +850 -0
- package/lib/google-gemini-cli-Cqds_Q5T.mjs +850 -0
- package/lib/google-gemini-cli-Dsztq0N5.mjs +211 -0
- package/lib/google-gemini-cli-zJhiOcND.mjs +211 -0
- package/lib/google-oauth-shared-CuEHaDDj.mjs +147 -0
- package/lib/google-oauth-shared-CwNWYdmR.mjs +147 -0
- package/lib/google-oauth-shared-yqlyqPPC.mjs +147 -0
- package/lib/google-shared-CgKmmdO3.mjs +760 -0
- package/lib/google-shared-Dr-VG-ap.mjs +760 -0
- package/lib/google-shared-DzhCb9b0.mjs +760 -0
- package/lib/google-vertex-BDN2tLaD.mjs +99 -0
- package/lib/google-vertex-DopVOQOG.mjs +99 -0
- package/lib/google-vertex-kscbkyRb.mjs +99 -0
- package/lib/google-zyDOG9x7.mjs +30 -0
- package/lib/identity-Da1GPU9a.mjs +219 -0
- package/lib/identity-DnB63pS7.mjs +219 -0
- package/lib/identity-xRP7_eSR.mjs +219 -0
- package/lib/idle-iterator-Baoyn3Hp.mjs +366 -0
- package/lib/idle-iterator-C6XbWcuB.mjs +366 -0
- package/lib/idle-iterator-DUjKQEGT.mjs +366 -0
- package/lib/index.mjs +4608 -3935
- package/lib/kimi--wUOWER5.mjs +236 -0
- package/lib/kimi-DMVI-zrZ.mjs +236 -0
- package/lib/kimi-Dh0pv3WZ.mjs +236 -0
- package/lib/markit-BL3cH47U.mjs +1417 -0
- package/lib/markit-BNiNY6SE.mjs +1417 -0
- package/lib/markit-M0jhziqU.mjs +1417 -0
- package/lib/minimax-code-BK-3eBbz.mjs +53 -0
- package/lib/minimax-code-DCbuA6Yk.mjs +53 -0
- package/lib/minimax-code-Uq8Qu9LW.mjs +53 -0
- package/lib/models-CfT4coYT.mjs +104660 -0
- package/lib/models-D_XnT6ay.mjs +104660 -0
- package/lib/models-SGASygJ3.mjs +104660 -0
- package/lib/ollama-BQMGPxtV.mjs +589 -0
- package/lib/ollama-DPzBmq89.mjs +589 -0
- package/lib/ollama-DoBz5SFm.mjs +589 -0
- package/lib/openai-codex-Bi-4S4PX.mjs +255 -0
- package/lib/openai-codex-CQL_kvYL.mjs +255 -0
- package/lib/openai-codex-Ch8CkT3p.mjs +255 -0
- package/lib/openai-codex-responses-CvxL_FMF.mjs +3144 -0
- package/lib/openai-codex-responses-Cz-2qpC7.mjs +3144 -0
- package/lib/openai-codex-responses-pejZgdZo.mjs +3144 -0
- package/lib/openai-completions-CF8IyNtP.mjs +1360 -0
- package/lib/openai-completions-DIf361kF.mjs +1360 -0
- package/lib/openai-completions-i8doczAk.mjs +1360 -0
- package/lib/openai-reasoning-fallback-DGVVLgd1.mjs +286 -0
- package/lib/openai-reasoning-fallback-Nj6yB2rY.mjs +286 -0
- package/lib/openai-reasoning-fallback-OdJREP1o.mjs +286 -0
- package/lib/openai-responses-BqXJInHX.mjs +867 -0
- package/lib/openai-responses-DTkBiiy-.mjs +867 -0
- package/lib/openai-responses-Db_a-U4-.mjs +867 -0
- package/lib/opencode-DaJjcUbf.mjs +38 -0
- package/lib/opencode-DhMolSoB.mjs +38 -0
- package/lib/opencode-Rq_Q2vAO.mjs +38 -0
- package/lib/perplexity-9b-RQ0mV.mjs +194 -0
- package/lib/perplexity-C4iLVMUj.mjs +194 -0
- package/lib/perplexity-Uu7Jzg5b.mjs +194 -0
- package/lib/proxy-DDqrmjjC.mjs +190 -0
- package/lib/proxy-ZtUcl6r5.mjs +190 -0
- package/lib/proxy-pM_NIv-H.mjs +190 -0
- package/lib/request-debug-HJMoJncL.mjs +183 -0
- package/lib/sanitize-text-CfcXzw5X.mjs +33 -0
- package/lib/scrapers-BkFfcPHj.mjs +9198 -0
- package/lib/scrapers-CL-WgdU1.mjs +9198 -0
- package/lib/scrapers-CVptboMs.mjs +9198 -0
- package/lib/scrapers-CipyKyCH.mjs +9198 -0
- package/lib/scrapers-DGfrYhtw.mjs +9198 -0
- package/lib/scrapers-DSUPYoUF.mjs +9198 -0
- package/lib/scrapers-DZ2GXmp7.mjs +9198 -0
- package/lib/scrapers-nhQAvc8d.mjs +9198 -0
- package/lib/shell-snapshot-fn-env.sh +67 -43
- package/lib/src-BgpusnsB.mjs +5076 -0
- package/lib/src-DTid0g4K.mjs +5001 -0
- package/lib/src-lDmkSRbm.mjs +5006 -0
- package/lib/stream-BlldLkVq.mjs +10236 -0
- package/lib/stream-CRtexYLe.mjs +10236 -0
- package/lib/stream-C_RAoxJC.mjs +10236 -0
- package/lib/stream-markup-healing-2toHXWXM.mjs +491 -0
- package/lib/stream-markup-healing-DMsxBx1L.mjs +491 -0
- package/lib/stream-markup-healing-KMkiAA00.mjs +491 -0
- package/lib/turndown-DN7ByzEI.mjs +667 -0
- package/lib/types/client/locales.d.ts +1 -1
- package/lib/types/config/fields.d.ts +1 -1
- package/lib/types/config/settings.d.ts +25 -3
- package/lib/types/config/truncate.d.ts +9 -5
- package/lib/types/tools/bash/background.d.ts +1 -1
- package/lib/types/tools/bash/bash-executor.d.ts +4 -0
- package/lib/types/tools/bash/bash-interceptor.d.ts +10 -8
- package/lib/types/tools/bash/cd-workdir.d.ts +35 -0
- package/lib/types/tools/bash/non-interactive-env.d.ts +2 -0
- package/lib/types/tools/bash/render.d.ts +4 -3
- package/lib/types/tools/bash/sanitize-text.d.ts +5 -0
- package/lib/types/tools/bash/shell-snapshot.d.ts +4 -1
- package/lib/types/tools/bash/shell-tokenize.d.ts +60 -0
- package/lib/types/tools/bash/streaming-output.d.ts +12 -212
- package/lib/types/tools/bash/which.d.ts +20 -0
- package/lib/types/tools/bash/windows-shell.d.ts +31 -0
- package/lib/types/tools/edit/adapter/index.d.ts +25 -3
- package/lib/types/tools/edit/adapter/tools/auto-generated-guard.d.ts +7 -17
- package/lib/types/tools/glob/adapter/index.d.ts +27 -1
- package/lib/types/tools/grep/adapter/index.d.ts +29 -1
- package/lib/types/tools/omp/edit/dispatch.d.ts +43 -0
- package/lib/types/tools/omp/edit/hashline/noop-loop-guard.d.ts +3 -1
- package/lib/types/tools/omp/sdk.d.ts +6 -0
- package/lib/types/tools/omp/tools/auto-generated-guard.d.ts +20 -0
- package/lib/types/tools/omp/tools/fetch.d.ts +2 -0
- package/lib/types/tools/omp/tools/read.d.ts +2 -8
- package/lib/types/tools/omp/tools/write.d.ts +4 -4
- package/lib/types/tools/omp/utils/image-loading.d.ts +10 -36
- package/lib/types/tools/read/adapter/index.d.ts +4 -1
- package/lib/types/tools/read-image/index.d.ts +4 -0
- package/lib/types/tools/shared/auto-generated-guard.dsh.d.ts +16 -4
- package/lib/types/tools/shared/bun-shim.d.ts +39 -3
- package/lib/types/tools/shared/fs-promises-shim.d.ts +3 -1
- package/lib/types/tools/shared/image-bridge.d.ts +98 -0
- package/lib/types/tools/shared/omp-prompt.d.ts +17 -9
- package/lib/types/tools/shared/session-state.d.ts +9 -3
- package/lib/utils-2Wq2eATG.mjs +8119 -0
- package/lib/utils-BnX8O3vi.mjs +12303 -0
- package/lib/utils-Bw139LTz.mjs +8119 -0
- package/lib/utils-CE8N8P4Q.mjs +12315 -0
- package/lib/utils-CZw4tVZQ.mjs +12315 -0
- package/lib/utils-C_MrQ_0z.mjs +12301 -0
- package/lib/utils-CiGN7OHR.mjs +12315 -0
- package/lib/utils-Cp76gCyk.mjs +8119 -0
- package/lib/utils-D0GRDgAr.mjs +12315 -0
- package/lib/utils-D0Z1fyoO.mjs +12299 -0
- package/lib/utils-D2YknRk4.mjs +51 -0
- package/lib/utils-DppGHXQB.mjs +51 -0
- package/lib/utils-DzXZDfYc.mjs +51 -0
- package/lib/utils-W8WdSBpX.mjs +12315 -0
- package/lib/vision-guard-01qSwFpf.mjs +92 -0
- package/lib/vision-guard-BDD4OrKo.mjs +92 -0
- package/lib/vision-guard-DzZGaOga.mjs +92 -0
- package/lib/wafer-CgtPHerf.mjs +17 -0
- package/lib/wafer-DRU0EjZX.mjs +17 -0
- package/lib/wafer-cBtrn6q9.mjs +17 -0
- package/lib/xai-oauth-Buk8XVvM.mjs +446 -0
- package/lib/xai-oauth-CMal8l1O.mjs +446 -0
- package/lib/xai-oauth-DPHDXKD7.mjs +446 -0
- package/lib/xiaomi-CZgwvX2G.mjs +157 -0
- package/lib/xiaomi-D2qT5cAC.mjs +157 -0
- package/lib/xiaomi-Dd87KSg5.mjs +157 -0
- package/lib/zai-7DWMkEqM.mjs +203 -0
- package/lib/zai-C59YnomG.mjs +203 -0
- package/lib/zai-CFeOt-53.mjs +203 -0
- package/lib/zip-Cg9ANN_U.mjs +1316 -0
- package/lib/zip-D36ZKsP8.mjs +1316 -0
- package/lib/zip-D6QXpvaJ.mjs +1316 -0
- package/package.json +14 -10
- package/presets/package.json +1 -1
- package/presets/tool-plus-ptc/preset.yml +1 -1
- package/presets/tool-plus-standard/preset.yml +1 -1
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
|
+
__installBunShim();
|
|
3
|
+
import { c as OAuthError, h as LoginCancelledError } from "./error-Dd8DIqs-.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 };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
|
+
__installBunShim();
|
|
3
|
+
import { c as OAuthError, h as LoginCancelledError } from "./error-yCSG0mGC.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 };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
|
+
__installBunShim();
|
|
3
|
+
import { c as OAuthError, h as LoginCancelledError } from "./error-B3bevhrs.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 };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
|
+
__installBunShim();
|
|
3
|
+
import { c as OAuthError } from "./error-Dd8DIqs-.mjs";
|
|
4
|
+
import { t as OAuthCallbackFlow } from "./callback-server-CQ5Jo8F-.mjs";
|
|
5
|
+
import { t as generatePKCE } from "./pkce-BlQikGPu.mjs";
|
|
6
|
+
//#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/registry/oauth/devin.ts
|
|
7
|
+
const DEVIN_WEBAPP_URL = "https://app.devin.ai";
|
|
8
|
+
const DEVIN_API_URL = "https://api.devin.ai";
|
|
9
|
+
const CALLBACK_PORT = 59653;
|
|
10
|
+
const CALLBACK_PATH = "/callback";
|
|
11
|
+
const TOKEN_PATH = "/auth/cli/token";
|
|
12
|
+
const FALLBACK_EXPIRES_MS = 31536e6;
|
|
13
|
+
async function loginDevin(ctrl) {
|
|
14
|
+
return new DevinOAuthFlow(ctrl).login();
|
|
15
|
+
}
|
|
16
|
+
var DevinOAuthFlow = class extends OAuthCallbackFlow {
|
|
17
|
+
#pkce;
|
|
18
|
+
constructor(ctrl) {
|
|
19
|
+
super(ctrl, {
|
|
20
|
+
preferredPort: CALLBACK_PORT,
|
|
21
|
+
callbackPath: CALLBACK_PATH,
|
|
22
|
+
callbackHostname: "127.0.0.1"
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
generateState() {
|
|
26
|
+
return crypto.randomUUID();
|
|
27
|
+
}
|
|
28
|
+
async generateAuthUrl(state, redirectUri) {
|
|
29
|
+
this.#pkce = await generatePKCE();
|
|
30
|
+
const params = new URLSearchParams({
|
|
31
|
+
redirect_uri: redirectUri,
|
|
32
|
+
state,
|
|
33
|
+
prompt: "select_account",
|
|
34
|
+
code_challenge: this.#pkce.challenge,
|
|
35
|
+
code_challenge_method: "S256"
|
|
36
|
+
});
|
|
37
|
+
return {
|
|
38
|
+
url: `${DEVIN_WEBAPP_URL}/auth/cli/continue?${params.toString()}`,
|
|
39
|
+
instructions: "Sign in to Devin in your browser."
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
async exchangeToken(code) {
|
|
43
|
+
if (!this.#pkce) throw new OAuthError("Devin PKCE verifier was not initialized", {
|
|
44
|
+
kind: "configuration",
|
|
45
|
+
provider: "devin"
|
|
46
|
+
});
|
|
47
|
+
const token = await exchangeDevinCliToken(code, this.#pkce.verifier, this.ctrl.fetch);
|
|
48
|
+
return {
|
|
49
|
+
access: token,
|
|
50
|
+
refresh: token,
|
|
51
|
+
expires: getTokenExpiry(token),
|
|
52
|
+
apiEndpoint: DEVIN_API_URL,
|
|
53
|
+
enterpriseUrl: DEVIN_WEBAPP_URL
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
async function exchangeDevinCliToken(authorizationCode, codeVerifier, fetchImpl = fetch) {
|
|
58
|
+
const response = await fetchImpl(`${DEVIN_API_URL}${TOKEN_PATH}`, {
|
|
59
|
+
method: "POST",
|
|
60
|
+
headers: {
|
|
61
|
+
Accept: "application/json",
|
|
62
|
+
"Content-Type": "application/json"
|
|
63
|
+
},
|
|
64
|
+
body: JSON.stringify({
|
|
65
|
+
code: authorizationCode,
|
|
66
|
+
code_verifier: codeVerifier
|
|
67
|
+
})
|
|
68
|
+
});
|
|
69
|
+
if (!response.ok) {
|
|
70
|
+
const error = await response.text();
|
|
71
|
+
throw new OAuthError(`Devin CLI token exchange failed: ${response.status} ${error}`.trim(), {
|
|
72
|
+
kind: "token-exchange",
|
|
73
|
+
provider: "devin",
|
|
74
|
+
status: response.status
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
const data = await response.json();
|
|
78
|
+
if (typeof data.token !== "string" || data.token.length === 0) throw new OAuthError("Devin CLI token exchange returned an empty token", {
|
|
79
|
+
kind: "validation",
|
|
80
|
+
provider: "devin"
|
|
81
|
+
});
|
|
82
|
+
return data.token;
|
|
83
|
+
}
|
|
84
|
+
function getTokenExpiry(token) {
|
|
85
|
+
try {
|
|
86
|
+
const [, payload] = token.split(".");
|
|
87
|
+
if (payload) {
|
|
88
|
+
const decoded = JSON.parse(Buffer.from(payload, "base64url").toString("utf8"));
|
|
89
|
+
if (typeof decoded.exp === "number" && Number.isFinite(decoded.exp)) return decoded.exp * 1e3 - 3e5;
|
|
90
|
+
}
|
|
91
|
+
} catch {}
|
|
92
|
+
return Date.now() + FALLBACK_EXPIRES_MS;
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
export { loginDevin };
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
|
+
__installBunShim();
|
|
3
|
+
import { n as discoveryFetch } from "./utils-D2YknRk4.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 };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
|
+
__installBunShim();
|
|
3
|
+
import { c as OAuthError } from "./error-yCSG0mGC.mjs";
|
|
4
|
+
import { t as OAuthCallbackFlow } from "./callback-server-DDSrZ6l_.mjs";
|
|
5
|
+
import { t as generatePKCE } from "./pkce-BlQikGPu.mjs";
|
|
6
|
+
//#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/registry/oauth/devin.ts
|
|
7
|
+
const DEVIN_WEBAPP_URL = "https://app.devin.ai";
|
|
8
|
+
const DEVIN_API_URL = "https://api.devin.ai";
|
|
9
|
+
const CALLBACK_PORT = 59653;
|
|
10
|
+
const CALLBACK_PATH = "/callback";
|
|
11
|
+
const TOKEN_PATH = "/auth/cli/token";
|
|
12
|
+
const FALLBACK_EXPIRES_MS = 31536e6;
|
|
13
|
+
async function loginDevin(ctrl) {
|
|
14
|
+
return new DevinOAuthFlow(ctrl).login();
|
|
15
|
+
}
|
|
16
|
+
var DevinOAuthFlow = class extends OAuthCallbackFlow {
|
|
17
|
+
#pkce;
|
|
18
|
+
constructor(ctrl) {
|
|
19
|
+
super(ctrl, {
|
|
20
|
+
preferredPort: CALLBACK_PORT,
|
|
21
|
+
callbackPath: CALLBACK_PATH,
|
|
22
|
+
callbackHostname: "127.0.0.1"
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
generateState() {
|
|
26
|
+
return crypto.randomUUID();
|
|
27
|
+
}
|
|
28
|
+
async generateAuthUrl(state, redirectUri) {
|
|
29
|
+
this.#pkce = await generatePKCE();
|
|
30
|
+
const params = new URLSearchParams({
|
|
31
|
+
redirect_uri: redirectUri,
|
|
32
|
+
state,
|
|
33
|
+
prompt: "select_account",
|
|
34
|
+
code_challenge: this.#pkce.challenge,
|
|
35
|
+
code_challenge_method: "S256"
|
|
36
|
+
});
|
|
37
|
+
return {
|
|
38
|
+
url: `${DEVIN_WEBAPP_URL}/auth/cli/continue?${params.toString()}`,
|
|
39
|
+
instructions: "Sign in to Devin in your browser."
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
async exchangeToken(code) {
|
|
43
|
+
if (!this.#pkce) throw new OAuthError("Devin PKCE verifier was not initialized", {
|
|
44
|
+
kind: "configuration",
|
|
45
|
+
provider: "devin"
|
|
46
|
+
});
|
|
47
|
+
const token = await exchangeDevinCliToken(code, this.#pkce.verifier, this.ctrl.fetch);
|
|
48
|
+
return {
|
|
49
|
+
access: token,
|
|
50
|
+
refresh: token,
|
|
51
|
+
expires: getTokenExpiry(token),
|
|
52
|
+
apiEndpoint: DEVIN_API_URL,
|
|
53
|
+
enterpriseUrl: DEVIN_WEBAPP_URL
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
async function exchangeDevinCliToken(authorizationCode, codeVerifier, fetchImpl = fetch) {
|
|
58
|
+
const response = await fetchImpl(`${DEVIN_API_URL}${TOKEN_PATH}`, {
|
|
59
|
+
method: "POST",
|
|
60
|
+
headers: {
|
|
61
|
+
Accept: "application/json",
|
|
62
|
+
"Content-Type": "application/json"
|
|
63
|
+
},
|
|
64
|
+
body: JSON.stringify({
|
|
65
|
+
code: authorizationCode,
|
|
66
|
+
code_verifier: codeVerifier
|
|
67
|
+
})
|
|
68
|
+
});
|
|
69
|
+
if (!response.ok) {
|
|
70
|
+
const error = await response.text();
|
|
71
|
+
throw new OAuthError(`Devin CLI token exchange failed: ${response.status} ${error}`.trim(), {
|
|
72
|
+
kind: "token-exchange",
|
|
73
|
+
provider: "devin",
|
|
74
|
+
status: response.status
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
const data = await response.json();
|
|
78
|
+
if (typeof data.token !== "string" || data.token.length === 0) throw new OAuthError("Devin CLI token exchange returned an empty token", {
|
|
79
|
+
kind: "validation",
|
|
80
|
+
provider: "devin"
|
|
81
|
+
});
|
|
82
|
+
return data.token;
|
|
83
|
+
}
|
|
84
|
+
function getTokenExpiry(token) {
|
|
85
|
+
try {
|
|
86
|
+
const [, payload] = token.split(".");
|
|
87
|
+
if (payload) {
|
|
88
|
+
const decoded = JSON.parse(Buffer.from(payload, "base64url").toString("utf8"));
|
|
89
|
+
if (typeof decoded.exp === "number" && Number.isFinite(decoded.exp)) return decoded.exp * 1e3 - 3e5;
|
|
90
|
+
}
|
|
91
|
+
} catch {}
|
|
92
|
+
return Date.now() + FALLBACK_EXPIRES_MS;
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
export { loginDevin };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
|
+
__installBunShim();
|
|
3
|
+
import { c as OAuthError } from "./error-B3bevhrs.mjs";
|
|
4
|
+
import { t as OAuthCallbackFlow } from "./callback-server-BEFNf-jf.mjs";
|
|
5
|
+
import { t as generatePKCE } from "./pkce-BlQikGPu.mjs";
|
|
6
|
+
//#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/registry/oauth/devin.ts
|
|
7
|
+
const DEVIN_WEBAPP_URL = "https://app.devin.ai";
|
|
8
|
+
const DEVIN_API_URL = "https://api.devin.ai";
|
|
9
|
+
const CALLBACK_PORT = 59653;
|
|
10
|
+
const CALLBACK_PATH = "/callback";
|
|
11
|
+
const TOKEN_PATH = "/auth/cli/token";
|
|
12
|
+
const FALLBACK_EXPIRES_MS = 31536e6;
|
|
13
|
+
async function loginDevin(ctrl) {
|
|
14
|
+
return new DevinOAuthFlow(ctrl).login();
|
|
15
|
+
}
|
|
16
|
+
var DevinOAuthFlow = class extends OAuthCallbackFlow {
|
|
17
|
+
#pkce;
|
|
18
|
+
constructor(ctrl) {
|
|
19
|
+
super(ctrl, {
|
|
20
|
+
preferredPort: CALLBACK_PORT,
|
|
21
|
+
callbackPath: CALLBACK_PATH,
|
|
22
|
+
callbackHostname: "127.0.0.1"
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
generateState() {
|
|
26
|
+
return crypto.randomUUID();
|
|
27
|
+
}
|
|
28
|
+
async generateAuthUrl(state, redirectUri) {
|
|
29
|
+
this.#pkce = await generatePKCE();
|
|
30
|
+
const params = new URLSearchParams({
|
|
31
|
+
redirect_uri: redirectUri,
|
|
32
|
+
state,
|
|
33
|
+
prompt: "select_account",
|
|
34
|
+
code_challenge: this.#pkce.challenge,
|
|
35
|
+
code_challenge_method: "S256"
|
|
36
|
+
});
|
|
37
|
+
return {
|
|
38
|
+
url: `${DEVIN_WEBAPP_URL}/auth/cli/continue?${params.toString()}`,
|
|
39
|
+
instructions: "Sign in to Devin in your browser."
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
async exchangeToken(code) {
|
|
43
|
+
if (!this.#pkce) throw new OAuthError("Devin PKCE verifier was not initialized", {
|
|
44
|
+
kind: "configuration",
|
|
45
|
+
provider: "devin"
|
|
46
|
+
});
|
|
47
|
+
const token = await exchangeDevinCliToken(code, this.#pkce.verifier, this.ctrl.fetch);
|
|
48
|
+
return {
|
|
49
|
+
access: token,
|
|
50
|
+
refresh: token,
|
|
51
|
+
expires: getTokenExpiry(token),
|
|
52
|
+
apiEndpoint: DEVIN_API_URL,
|
|
53
|
+
enterpriseUrl: DEVIN_WEBAPP_URL
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
async function exchangeDevinCliToken(authorizationCode, codeVerifier, fetchImpl = fetch) {
|
|
58
|
+
const response = await fetchImpl(`${DEVIN_API_URL}${TOKEN_PATH}`, {
|
|
59
|
+
method: "POST",
|
|
60
|
+
headers: {
|
|
61
|
+
Accept: "application/json",
|
|
62
|
+
"Content-Type": "application/json"
|
|
63
|
+
},
|
|
64
|
+
body: JSON.stringify({
|
|
65
|
+
code: authorizationCode,
|
|
66
|
+
code_verifier: codeVerifier
|
|
67
|
+
})
|
|
68
|
+
});
|
|
69
|
+
if (!response.ok) {
|
|
70
|
+
const error = await response.text();
|
|
71
|
+
throw new OAuthError(`Devin CLI token exchange failed: ${response.status} ${error}`.trim(), {
|
|
72
|
+
kind: "token-exchange",
|
|
73
|
+
provider: "devin",
|
|
74
|
+
status: response.status
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
const data = await response.json();
|
|
78
|
+
if (typeof data.token !== "string" || data.token.length === 0) throw new OAuthError("Devin CLI token exchange returned an empty token", {
|
|
79
|
+
kind: "validation",
|
|
80
|
+
provider: "devin"
|
|
81
|
+
});
|
|
82
|
+
return data.token;
|
|
83
|
+
}
|
|
84
|
+
function getTokenExpiry(token) {
|
|
85
|
+
try {
|
|
86
|
+
const [, payload] = token.split(".");
|
|
87
|
+
if (payload) {
|
|
88
|
+
const decoded = JSON.parse(Buffer.from(payload, "base64url").toString("utf8"));
|
|
89
|
+
if (typeof decoded.exp === "number" && Number.isFinite(decoded.exp)) return decoded.exp * 1e3 - 3e5;
|
|
90
|
+
}
|
|
91
|
+
} catch {}
|
|
92
|
+
return Date.now() + FALLBACK_EXPIRES_MS;
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
export { loginDevin };
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
|
+
__installBunShim();
|
|
3
|
+
import { n as discoveryFetch } from "./utils-DppGHXQB.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 };
|