@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,273 @@
|
|
|
1
|
+
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
|
+
__installBunShim();
|
|
3
|
+
import { A as semverGte, D as bareModelId, O as parseGlmModel, r as getBundledModels, y as isKimiK3ModelId } from "./models-D_XnT6ay.mjs";
|
|
4
|
+
import "./identity-xRP7_eSR.mjs";
|
|
5
|
+
import { r as toModelSpec } from "./bundled-references-sLN0YdXU.mjs";
|
|
6
|
+
import { E as create, i as fromBinary, t as toBinary } from "./to-binary-B1BEBIPC.mjs";
|
|
7
|
+
import { H as GetUsableModelsRequestSchema, U as GetUsableModelsResponseSchema } from "./agent_pb-Rizyt9Zg.mjs";
|
|
8
|
+
import { type } from "@oh-my-pi/omptype";
|
|
9
|
+
import * as http2$1 from "node:http2";
|
|
10
|
+
//#region node_modules/.pnpm/@oh-my-pi+pi-catalog@17.3.5/node_modules/@oh-my-pi/pi-catalog/src/discovery/cursor.ts
|
|
11
|
+
const CURSOR_DEFAULT_BASE_URL = "https://api2.cursor.sh";
|
|
12
|
+
const CURSOR_DEFAULT_CLIENT_VERSION = "cli-2026.02.13-41ac335";
|
|
13
|
+
const CURSOR_GET_USABLE_MODELS_PATH = "/agent.v1.AgentService/GetUsableModels";
|
|
14
|
+
const DEFAULT_CONTEXT_WINDOW = 2e5;
|
|
15
|
+
const DEFAULT_MAX_TOKENS = 64e3;
|
|
16
|
+
/**
|
|
17
|
+
* `GetUsableModels` carries no context-window field, so the 1M ceiling is
|
|
18
|
+
* recovered from the signals Cursor does send:
|
|
19
|
+
* - display-name labels ("Opus 5 1M", "GPT-5.5 1M High") across families,
|
|
20
|
+
* - natively 1M families Cursor serves unlabeled (Kimi K3, GLM 5.2+),
|
|
21
|
+
* - the max-mode flag on Claude/Gemini ids, whose max-mode ceiling is 1M.
|
|
22
|
+
*/
|
|
23
|
+
const CURSOR_1M_CONTEXT_WINDOW = 1e6;
|
|
24
|
+
const CURSOR_1M_NAME_PATTERN = /\b1m\b/i;
|
|
25
|
+
const CURSOR_MAX_MODE_1M_ID_PATTERN = /claude|gemini/;
|
|
26
|
+
/** Kimi's official bare K3 id (`k3`, `kimi/k3`); `k3-256k` is the 256k SKU and stays out. */
|
|
27
|
+
const CURSOR_KIMI_K3_BARE_ID_PATTERN = /(^|\/)k3$/i;
|
|
28
|
+
/**
|
|
29
|
+
* Model-id families whose native catalogs (anthropic, openai/openai-codex,
|
|
30
|
+
* google) are multimodal. Cursor-only or text-only families (`composer-*`,
|
|
31
|
+
* `grok-code-*`) intentionally stay outside this pattern.
|
|
32
|
+
*/
|
|
33
|
+
const CURSOR_MULTIMODAL_ID_PATTERN = /claude|gemini|gpt-|codex/;
|
|
34
|
+
const OptionalDisplayNameSchema = type("unknown").pipe((raw) => typeof raw === "string" ? raw : void 0);
|
|
35
|
+
const CursorAliasesSchema = type("unknown").pipe((raw) => {
|
|
36
|
+
if (Array.isArray(raw)) return raw.filter((alias) => typeof alias === "string");
|
|
37
|
+
return [];
|
|
38
|
+
});
|
|
39
|
+
const CursorModelDetailsSchema = type({
|
|
40
|
+
modelId: "string",
|
|
41
|
+
displayName: OptionalDisplayNameSchema.default(void 0),
|
|
42
|
+
displayNameShort: OptionalDisplayNameSchema.default(void 0),
|
|
43
|
+
displayModelId: OptionalDisplayNameSchema.default(void 0),
|
|
44
|
+
aliases: CursorAliasesSchema.default(() => []),
|
|
45
|
+
"thinkingDetails?": "unknown",
|
|
46
|
+
maxMode: "boolean = false"
|
|
47
|
+
});
|
|
48
|
+
const CursorModelsInnerSchema = type("unknown[]");
|
|
49
|
+
const ResilientCursorModelsSchema = type("unknown").pipe((raw) => {
|
|
50
|
+
const out = CursorModelsInnerSchema(raw);
|
|
51
|
+
return out instanceof type.errors ? [] : out;
|
|
52
|
+
});
|
|
53
|
+
const CursorDecodedResponseSchema = type({ models: ResilientCursorModelsSchema.default(() => []) });
|
|
54
|
+
/**
|
|
55
|
+
* Fetches Cursor models through `GetUsableModels` and normalizes them into canonical model entries.
|
|
56
|
+
*
|
|
57
|
+
* Returns `null` on request/decode failures.
|
|
58
|
+
* Returns `[]` only when the endpoint responds successfully with no usable models.
|
|
59
|
+
*/
|
|
60
|
+
async function fetchCursorUsableModels(options) {
|
|
61
|
+
const timeoutMs = options.timeoutMs ?? 5e3;
|
|
62
|
+
try {
|
|
63
|
+
const requestPayload = create(GetUsableModelsRequestSchema, { customModelIds: normalizeCustomModelIds(options.customModelIds) });
|
|
64
|
+
const body = toBinary(GetUsableModelsRequestSchema, requestPayload);
|
|
65
|
+
const responseBuffer = await fetchViaHttp2((options.baseUrl ?? CURSOR_DEFAULT_BASE_URL).replace(/\/+$/, ""), body, options, timeoutMs);
|
|
66
|
+
if (!responseBuffer) return null;
|
|
67
|
+
const decoded = decodeGetUsableModelsResponse(responseBuffer);
|
|
68
|
+
const parsedDecoded = CursorDecodedResponseSchema(decoded);
|
|
69
|
+
if (parsedDecoded instanceof type.errors) return null;
|
|
70
|
+
const references = createCursorReferenceMap();
|
|
71
|
+
return normalizeCursorModels(parsedDecoded.models, options.baseUrl, references);
|
|
72
|
+
} catch {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function buildRequestHeaders(options) {
|
|
77
|
+
return {
|
|
78
|
+
"content-type": "application/proto",
|
|
79
|
+
te: "trailers",
|
|
80
|
+
authorization: `Bearer ${options.apiKey}`,
|
|
81
|
+
"x-ghost-mode": "true",
|
|
82
|
+
"x-cursor-client-version": options.clientVersion ?? CURSOR_DEFAULT_CLIENT_VERSION,
|
|
83
|
+
"x-cursor-client-type": "cli"
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/** HTTP/2 transport required by Cursor API (HTTP/1.1 is rejected with 464). */
|
|
87
|
+
async function fetchViaHttp2(baseUrl, body, options, timeoutMs) {
|
|
88
|
+
const { promise, resolve } = Promise.withResolvers();
|
|
89
|
+
const client = http2$1.connect(baseUrl);
|
|
90
|
+
const timer = setTimeout(() => {
|
|
91
|
+
client.destroy();
|
|
92
|
+
resolve(null);
|
|
93
|
+
}, timeoutMs);
|
|
94
|
+
client.on("error", () => {
|
|
95
|
+
clearTimeout(timer);
|
|
96
|
+
resolve(null);
|
|
97
|
+
});
|
|
98
|
+
const req = client.request({
|
|
99
|
+
":method": "POST",
|
|
100
|
+
":path": CURSOR_GET_USABLE_MODELS_PATH,
|
|
101
|
+
...buildRequestHeaders(options)
|
|
102
|
+
});
|
|
103
|
+
const chunks = [];
|
|
104
|
+
req.on("data", (chunk) => chunks.push(chunk));
|
|
105
|
+
req.on("end", () => {
|
|
106
|
+
clearTimeout(timer);
|
|
107
|
+
client.close();
|
|
108
|
+
resolve(new Uint8Array(Buffer.concat(chunks)));
|
|
109
|
+
});
|
|
110
|
+
req.on("error", () => {
|
|
111
|
+
clearTimeout(timer);
|
|
112
|
+
client.close();
|
|
113
|
+
resolve(null);
|
|
114
|
+
});
|
|
115
|
+
req.on("response", (headers) => {
|
|
116
|
+
const status = Number(headers[":status"] ?? 0);
|
|
117
|
+
if (status < 200 || status >= 300) {
|
|
118
|
+
clearTimeout(timer);
|
|
119
|
+
client.close();
|
|
120
|
+
resolve(null);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
if (body.length > 0) req.end(Buffer.from(body));
|
|
124
|
+
else req.end();
|
|
125
|
+
return promise;
|
|
126
|
+
}
|
|
127
|
+
function normalizeCustomModelIds(customModelIds) {
|
|
128
|
+
if (!customModelIds) return [];
|
|
129
|
+
const normalized = /* @__PURE__ */ new Set();
|
|
130
|
+
for (const value of customModelIds) {
|
|
131
|
+
if (typeof value !== "string") continue;
|
|
132
|
+
const trimmed = value.trim();
|
|
133
|
+
if (!trimmed) continue;
|
|
134
|
+
normalized.add(trimmed);
|
|
135
|
+
}
|
|
136
|
+
return [...normalized];
|
|
137
|
+
}
|
|
138
|
+
function createCursorReferenceMap() {
|
|
139
|
+
const references = /* @__PURE__ */ new Map();
|
|
140
|
+
for (const model of getBundledModels("cursor")) references.set(model.id, toModelSpec(model));
|
|
141
|
+
return references;
|
|
142
|
+
}
|
|
143
|
+
function decodeGetUsableModelsResponse(payload) {
|
|
144
|
+
if (payload.length === 0) return null;
|
|
145
|
+
const framedBody = decodeConnectUnaryBody(payload);
|
|
146
|
+
if (framedBody) try {
|
|
147
|
+
return fromBinary(GetUsableModelsResponseSchema, framedBody);
|
|
148
|
+
} catch {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
try {
|
|
152
|
+
return fromBinary(GetUsableModelsResponseSchema, payload);
|
|
153
|
+
} catch {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
function decodeConnectUnaryBody(payload) {
|
|
158
|
+
if (payload.length < 5) return null;
|
|
159
|
+
let offset = 0;
|
|
160
|
+
while (offset + 5 <= payload.length) {
|
|
161
|
+
const flags = payload[offset];
|
|
162
|
+
const messageLength = new DataView(payload.buffer, payload.byteOffset + offset, payload.byteLength - offset).getUint32(1, false);
|
|
163
|
+
const frameEnd = offset + 5 + messageLength;
|
|
164
|
+
if (frameEnd > payload.length) return null;
|
|
165
|
+
if ((flags & 1) !== 0) return null;
|
|
166
|
+
if (!((flags & 2) !== 0)) return payload.subarray(offset + 5, frameEnd);
|
|
167
|
+
offset = frameEnd;
|
|
168
|
+
}
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
function normalizeCursorModels(models, baseUrlOverride, references) {
|
|
172
|
+
if (!models || models.length === 0) return [];
|
|
173
|
+
const byId = /* @__PURE__ */ new Map();
|
|
174
|
+
for (const model of models) {
|
|
175
|
+
const normalized = normalizeCursorModel(model, baseUrlOverride, references);
|
|
176
|
+
if (!normalized) continue;
|
|
177
|
+
byId.set(normalized.id, normalized);
|
|
178
|
+
}
|
|
179
|
+
return [...byId.values()].sort((a, b) => a.id.localeCompare(b.id));
|
|
180
|
+
}
|
|
181
|
+
function normalizeCursorModel(model, baseUrlOverride, references) {
|
|
182
|
+
const parsedModel = CursorModelDetailsSchema(model);
|
|
183
|
+
if (parsedModel instanceof type.errors) return null;
|
|
184
|
+
const details = parsedModel;
|
|
185
|
+
const id = details.modelId.trim();
|
|
186
|
+
if (!id) return null;
|
|
187
|
+
const name = pickModelDisplayName(details, id);
|
|
188
|
+
const reference = references.get(id);
|
|
189
|
+
const reasoning = isKimiK3ModelId(id) || Boolean(details.thinkingDetails) || reference?.reasoning === true;
|
|
190
|
+
if (reference) return {
|
|
191
|
+
...reference,
|
|
192
|
+
id,
|
|
193
|
+
name,
|
|
194
|
+
baseUrl: baseUrlOverride ?? reference.baseUrl,
|
|
195
|
+
reasoning,
|
|
196
|
+
contextWindow: resolveCursorContextWindow(details, id, reference.contextWindow),
|
|
197
|
+
cursorMaxMode: details.maxMode
|
|
198
|
+
};
|
|
199
|
+
return {
|
|
200
|
+
id,
|
|
201
|
+
name,
|
|
202
|
+
api: "cursor-agent",
|
|
203
|
+
provider: "cursor",
|
|
204
|
+
baseUrl: baseUrlOverride ?? CURSOR_DEFAULT_BASE_URL,
|
|
205
|
+
reasoning,
|
|
206
|
+
input: inferInputFromCursorId(id),
|
|
207
|
+
cost: {
|
|
208
|
+
input: 0,
|
|
209
|
+
output: 0,
|
|
210
|
+
cacheRead: 0,
|
|
211
|
+
cacheWrite: 0
|
|
212
|
+
},
|
|
213
|
+
contextWindow: resolveCursorContextWindow(details, id, DEFAULT_CONTEXT_WINDOW),
|
|
214
|
+
maxTokens: DEFAULT_MAX_TOKENS,
|
|
215
|
+
cursorMaxMode: details.maxMode
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Context window for a discovered Cursor model: the 1M ceiling when any 1M
|
|
220
|
+
* signal fires (never below a larger bundled reference), else the fallback.
|
|
221
|
+
*/
|
|
222
|
+
function resolveCursorContextWindow(model, id, fallback) {
|
|
223
|
+
if (CURSOR_1M_NAME_PATTERN.test(id) || [
|
|
224
|
+
model.displayName,
|
|
225
|
+
model.displayNameShort,
|
|
226
|
+
model.displayModelId,
|
|
227
|
+
...model.aliases
|
|
228
|
+
].some((candidate) => typeof candidate === "string" && CURSOR_1M_NAME_PATTERN.test(candidate)) || isCursorNative1MModelId(id) || model.maxMode && CURSOR_MAX_MODE_1M_ID_PATTERN.test(id)) return Math.max(fallback ?? 0, CURSOR_1M_CONTEXT_WINDOW);
|
|
229
|
+
return fallback;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Natively 1M-context families Cursor serves without a "1M" label: Kimi K3 and
|
|
233
|
+
* GLM 5.2+ coding SKUs. The shared family parsers cover namespace forms
|
|
234
|
+
* (`moonshotai/kimi-k3`, `z-ai/glm-5.2`) and future GLM versions (`glm-5.10`,
|
|
235
|
+
* `glm-6`); vision and sub-1M variants stay out via the same gates as
|
|
236
|
+
* `isGlm52ReasoningEffortModelId`.
|
|
237
|
+
*/
|
|
238
|
+
function isCursorNative1MModelId(id) {
|
|
239
|
+
if (isKimiK3ModelId(id) || CURSOR_KIMI_K3_BARE_ID_PATTERN.test(id)) return true;
|
|
240
|
+
const glm = parseGlmModel(bareModelId(id));
|
|
241
|
+
if (!glm || glm.vision) return false;
|
|
242
|
+
if (glm.variant !== "base" && glm.variant !== "air" && glm.variant !== "turbo") return false;
|
|
243
|
+
return semverGte(glm.version, "5.2");
|
|
244
|
+
}
|
|
245
|
+
function pickModelDisplayName(model, fallbackId) {
|
|
246
|
+
const candidates = [
|
|
247
|
+
model.displayName,
|
|
248
|
+
model.displayNameShort,
|
|
249
|
+
model.displayModelId,
|
|
250
|
+
...model.aliases,
|
|
251
|
+
fallbackId
|
|
252
|
+
];
|
|
253
|
+
for (const candidate of candidates) {
|
|
254
|
+
if (typeof candidate !== "string") continue;
|
|
255
|
+
const trimmed = candidate.trim();
|
|
256
|
+
if (trimmed) return trimmed;
|
|
257
|
+
}
|
|
258
|
+
return fallbackId;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Infers input modalities for Cursor models without a bundled reference.
|
|
262
|
+
*
|
|
263
|
+
* `GetUsableModels` carries no per-model modality metadata, so classification
|
|
264
|
+
* falls back to the model family: families that are multimodal in OMP's own
|
|
265
|
+
* native catalogs accept images, everything else stays text-only. Mirrors
|
|
266
|
+
* `inferInputFromGeminiId` in ./gemini.ts.
|
|
267
|
+
*/
|
|
268
|
+
function inferInputFromCursorId(id) {
|
|
269
|
+
if (CURSOR_MULTIMODAL_ID_PATTERN.test(id.toLowerCase())) return ["text", "image"];
|
|
270
|
+
return ["text"];
|
|
271
|
+
}
|
|
272
|
+
//#endregion
|
|
273
|
+
export { fetchCursorUsableModels };
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
|
+
__installBunShim();
|
|
3
|
+
import { r as __exportAll } from "./fs-promises-shim-Bx0fpxuk.mjs";
|
|
4
|
+
import { c as OAuthError } from "./error-Dd8DIqs-.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/cursor.ts
|
|
7
|
+
var cursor_exports = /* @__PURE__ */ __exportAll({
|
|
8
|
+
extractCursorAccessTokenUserId: () => extractCursorAccessTokenUserId,
|
|
9
|
+
generateCursorAuthParams: () => generateCursorAuthParams,
|
|
10
|
+
loginCursor: () => loginCursor,
|
|
11
|
+
pollCursorAuth: () => pollCursorAuth,
|
|
12
|
+
refreshCursorToken: () => refreshCursorToken
|
|
13
|
+
});
|
|
14
|
+
const CURSOR_LOGIN_URL = "https://cursor.com/loginDeepControl";
|
|
15
|
+
const CURSOR_POLL_URL = "https://api2.cursor.sh/auth/poll";
|
|
16
|
+
const CURSOR_REFRESH_URL = "https://api2.cursor.sh/auth/exchange_user_api_key";
|
|
17
|
+
const POLL_MAX_ATTEMPTS = 150;
|
|
18
|
+
const POLL_BASE_DELAY = 1e3;
|
|
19
|
+
const POLL_MAX_DELAY = 1e4;
|
|
20
|
+
const POLL_BACKOFF_MULTIPLIER = 1.2;
|
|
21
|
+
async function generateCursorAuthParams() {
|
|
22
|
+
const { verifier, challenge } = await generatePKCE();
|
|
23
|
+
const uuid = crypto.randomUUID();
|
|
24
|
+
const params = new URLSearchParams({
|
|
25
|
+
challenge,
|
|
26
|
+
uuid,
|
|
27
|
+
mode: "login",
|
|
28
|
+
redirectTarget: "cli"
|
|
29
|
+
});
|
|
30
|
+
return {
|
|
31
|
+
verifier,
|
|
32
|
+
challenge,
|
|
33
|
+
uuid,
|
|
34
|
+
loginUrl: `${CURSOR_LOGIN_URL}?${params.toString()}`
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
async function pollCursorAuth(uuid, verifier) {
|
|
38
|
+
let delay = POLL_BASE_DELAY;
|
|
39
|
+
let consecutiveErrors = 0;
|
|
40
|
+
for (let attempt = 0; attempt < POLL_MAX_ATTEMPTS; attempt++) {
|
|
41
|
+
await Bun.sleep(delay);
|
|
42
|
+
try {
|
|
43
|
+
const response = await fetch(`${CURSOR_POLL_URL}?uuid=${uuid}&verifier=${verifier}`);
|
|
44
|
+
if (response.status === 404) {
|
|
45
|
+
consecutiveErrors = 0;
|
|
46
|
+
delay = Math.min(delay * POLL_BACKOFF_MULTIPLIER, POLL_MAX_DELAY);
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (response.ok) {
|
|
50
|
+
const data = await response.json();
|
|
51
|
+
return {
|
|
52
|
+
accessToken: data.accessToken,
|
|
53
|
+
refreshToken: data.refreshToken
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
throw new OAuthError(`Poll failed: ${response.status}`, {
|
|
57
|
+
kind: "polling",
|
|
58
|
+
provider: "cursor",
|
|
59
|
+
status: response.status
|
|
60
|
+
});
|
|
61
|
+
} catch {
|
|
62
|
+
consecutiveErrors++;
|
|
63
|
+
if (consecutiveErrors >= 3) throw new OAuthError("Too many consecutive errors during Cursor auth polling", {
|
|
64
|
+
kind: "polling",
|
|
65
|
+
provider: "cursor"
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
throw new OAuthError("Cursor authentication polling timeout", {
|
|
70
|
+
kind: "timeout",
|
|
71
|
+
provider: "cursor"
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
async function loginCursor(onAuthUrl, onPollStart) {
|
|
75
|
+
const { verifier, uuid, loginUrl } = await generateCursorAuthParams();
|
|
76
|
+
onAuthUrl(loginUrl);
|
|
77
|
+
onPollStart?.();
|
|
78
|
+
const { accessToken, refreshToken } = await pollCursorAuth(uuid, verifier);
|
|
79
|
+
return {
|
|
80
|
+
access: accessToken,
|
|
81
|
+
refresh: refreshToken,
|
|
82
|
+
expires: getTokenExpiry(accessToken)
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
async function refreshCursorToken(apiKeyOrRefreshToken) {
|
|
86
|
+
const response = await fetch(CURSOR_REFRESH_URL, {
|
|
87
|
+
method: "POST",
|
|
88
|
+
headers: {
|
|
89
|
+
Authorization: `Bearer ${apiKeyOrRefreshToken}`,
|
|
90
|
+
"Content-Type": "application/json"
|
|
91
|
+
},
|
|
92
|
+
body: "{}"
|
|
93
|
+
});
|
|
94
|
+
if (!response.ok) {
|
|
95
|
+
const error = await response.text();
|
|
96
|
+
throw new OAuthError(`Cursor token refresh failed: ${error}`, {
|
|
97
|
+
kind: "token-refresh",
|
|
98
|
+
provider: "cursor"
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
const data = await response.json();
|
|
102
|
+
const expiresAt = getTokenExpiry(data.accessToken);
|
|
103
|
+
return {
|
|
104
|
+
access: data.accessToken,
|
|
105
|
+
refresh: data.refreshToken || apiKeyOrRefreshToken,
|
|
106
|
+
expires: expiresAt
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function decodeCursorAccessTokenPayload(token) {
|
|
110
|
+
const parts = token.split(".");
|
|
111
|
+
if (parts.length !== 3) return void 0;
|
|
112
|
+
const payload = parts[1];
|
|
113
|
+
if (!payload) return void 0;
|
|
114
|
+
return JSON.parse(atob(payload.replace(/-/g, "+").replace(/_/g, "/")));
|
|
115
|
+
}
|
|
116
|
+
function extractCursorAccessTokenUserId(accessToken) {
|
|
117
|
+
try {
|
|
118
|
+
const payload = decodeCursorAccessTokenPayload(accessToken);
|
|
119
|
+
if (!payload || typeof payload !== "object" || !("sub" in payload) || typeof payload.sub !== "string") return;
|
|
120
|
+
const { sub } = payload;
|
|
121
|
+
const parts = sub.split("|");
|
|
122
|
+
return (parts.length > 1 ? parts[1] : sub).trim() || void 0;
|
|
123
|
+
} catch {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function getTokenExpiry(token) {
|
|
128
|
+
try {
|
|
129
|
+
const decoded = decodeCursorAccessTokenPayload(token);
|
|
130
|
+
if (decoded && typeof decoded === "object" && "exp" in decoded && typeof decoded.exp === "number") return decoded.exp * 1e3 - 3e5;
|
|
131
|
+
} catch {}
|
|
132
|
+
return Date.now() + 36e5;
|
|
133
|
+
}
|
|
134
|
+
//#endregion
|
|
135
|
+
export { extractCursorAccessTokenUserId as n, cursor_exports as t };
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
|
+
__installBunShim();
|
|
3
|
+
import { r as __exportAll } from "./fs-promises-shim-B-9cMxz5.mjs";
|
|
4
|
+
import { c as OAuthError } from "./error-B3bevhrs.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/cursor.ts
|
|
7
|
+
var cursor_exports = /* @__PURE__ */ __exportAll({
|
|
8
|
+
extractCursorAccessTokenUserId: () => extractCursorAccessTokenUserId,
|
|
9
|
+
generateCursorAuthParams: () => generateCursorAuthParams,
|
|
10
|
+
loginCursor: () => loginCursor,
|
|
11
|
+
pollCursorAuth: () => pollCursorAuth,
|
|
12
|
+
refreshCursorToken: () => refreshCursorToken
|
|
13
|
+
});
|
|
14
|
+
const CURSOR_LOGIN_URL = "https://cursor.com/loginDeepControl";
|
|
15
|
+
const CURSOR_POLL_URL = "https://api2.cursor.sh/auth/poll";
|
|
16
|
+
const CURSOR_REFRESH_URL = "https://api2.cursor.sh/auth/exchange_user_api_key";
|
|
17
|
+
const POLL_MAX_ATTEMPTS = 150;
|
|
18
|
+
const POLL_BASE_DELAY = 1e3;
|
|
19
|
+
const POLL_MAX_DELAY = 1e4;
|
|
20
|
+
const POLL_BACKOFF_MULTIPLIER = 1.2;
|
|
21
|
+
async function generateCursorAuthParams() {
|
|
22
|
+
const { verifier, challenge } = await generatePKCE();
|
|
23
|
+
const uuid = crypto.randomUUID();
|
|
24
|
+
const params = new URLSearchParams({
|
|
25
|
+
challenge,
|
|
26
|
+
uuid,
|
|
27
|
+
mode: "login",
|
|
28
|
+
redirectTarget: "cli"
|
|
29
|
+
});
|
|
30
|
+
return {
|
|
31
|
+
verifier,
|
|
32
|
+
challenge,
|
|
33
|
+
uuid,
|
|
34
|
+
loginUrl: `${CURSOR_LOGIN_URL}?${params.toString()}`
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
async function pollCursorAuth(uuid, verifier) {
|
|
38
|
+
let delay = POLL_BASE_DELAY;
|
|
39
|
+
let consecutiveErrors = 0;
|
|
40
|
+
for (let attempt = 0; attempt < POLL_MAX_ATTEMPTS; attempt++) {
|
|
41
|
+
await Bun.sleep(delay);
|
|
42
|
+
try {
|
|
43
|
+
const response = await fetch(`${CURSOR_POLL_URL}?uuid=${uuid}&verifier=${verifier}`);
|
|
44
|
+
if (response.status === 404) {
|
|
45
|
+
consecutiveErrors = 0;
|
|
46
|
+
delay = Math.min(delay * POLL_BACKOFF_MULTIPLIER, POLL_MAX_DELAY);
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (response.ok) {
|
|
50
|
+
const data = await response.json();
|
|
51
|
+
return {
|
|
52
|
+
accessToken: data.accessToken,
|
|
53
|
+
refreshToken: data.refreshToken
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
throw new OAuthError(`Poll failed: ${response.status}`, {
|
|
57
|
+
kind: "polling",
|
|
58
|
+
provider: "cursor",
|
|
59
|
+
status: response.status
|
|
60
|
+
});
|
|
61
|
+
} catch {
|
|
62
|
+
consecutiveErrors++;
|
|
63
|
+
if (consecutiveErrors >= 3) throw new OAuthError("Too many consecutive errors during Cursor auth polling", {
|
|
64
|
+
kind: "polling",
|
|
65
|
+
provider: "cursor"
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
throw new OAuthError("Cursor authentication polling timeout", {
|
|
70
|
+
kind: "timeout",
|
|
71
|
+
provider: "cursor"
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
async function loginCursor(onAuthUrl, onPollStart) {
|
|
75
|
+
const { verifier, uuid, loginUrl } = await generateCursorAuthParams();
|
|
76
|
+
onAuthUrl(loginUrl);
|
|
77
|
+
onPollStart?.();
|
|
78
|
+
const { accessToken, refreshToken } = await pollCursorAuth(uuid, verifier);
|
|
79
|
+
return {
|
|
80
|
+
access: accessToken,
|
|
81
|
+
refresh: refreshToken,
|
|
82
|
+
expires: getTokenExpiry(accessToken)
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
async function refreshCursorToken(apiKeyOrRefreshToken) {
|
|
86
|
+
const response = await fetch(CURSOR_REFRESH_URL, {
|
|
87
|
+
method: "POST",
|
|
88
|
+
headers: {
|
|
89
|
+
Authorization: `Bearer ${apiKeyOrRefreshToken}`,
|
|
90
|
+
"Content-Type": "application/json"
|
|
91
|
+
},
|
|
92
|
+
body: "{}"
|
|
93
|
+
});
|
|
94
|
+
if (!response.ok) {
|
|
95
|
+
const error = await response.text();
|
|
96
|
+
throw new OAuthError(`Cursor token refresh failed: ${error}`, {
|
|
97
|
+
kind: "token-refresh",
|
|
98
|
+
provider: "cursor"
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
const data = await response.json();
|
|
102
|
+
const expiresAt = getTokenExpiry(data.accessToken);
|
|
103
|
+
return {
|
|
104
|
+
access: data.accessToken,
|
|
105
|
+
refresh: data.refreshToken || apiKeyOrRefreshToken,
|
|
106
|
+
expires: expiresAt
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function decodeCursorAccessTokenPayload(token) {
|
|
110
|
+
const parts = token.split(".");
|
|
111
|
+
if (parts.length !== 3) return void 0;
|
|
112
|
+
const payload = parts[1];
|
|
113
|
+
if (!payload) return void 0;
|
|
114
|
+
return JSON.parse(atob(payload.replace(/-/g, "+").replace(/_/g, "/")));
|
|
115
|
+
}
|
|
116
|
+
function extractCursorAccessTokenUserId(accessToken) {
|
|
117
|
+
try {
|
|
118
|
+
const payload = decodeCursorAccessTokenPayload(accessToken);
|
|
119
|
+
if (!payload || typeof payload !== "object" || !("sub" in payload) || typeof payload.sub !== "string") return;
|
|
120
|
+
const { sub } = payload;
|
|
121
|
+
const parts = sub.split("|");
|
|
122
|
+
return (parts.length > 1 ? parts[1] : sub).trim() || void 0;
|
|
123
|
+
} catch {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function getTokenExpiry(token) {
|
|
128
|
+
try {
|
|
129
|
+
const decoded = decodeCursorAccessTokenPayload(token);
|
|
130
|
+
if (decoded && typeof decoded === "object" && "exp" in decoded && typeof decoded.exp === "number") return decoded.exp * 1e3 - 3e5;
|
|
131
|
+
} catch {}
|
|
132
|
+
return Date.now() + 36e5;
|
|
133
|
+
}
|
|
134
|
+
//#endregion
|
|
135
|
+
export { extractCursorAccessTokenUserId as n, cursor_exports as t };
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
|
+
__installBunShim();
|
|
3
|
+
import { r as __exportAll } from "./fs-promises-shim-B-9cMxz5.mjs";
|
|
4
|
+
import { c as OAuthError } from "./error-yCSG0mGC.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/cursor.ts
|
|
7
|
+
var cursor_exports = /* @__PURE__ */ __exportAll({
|
|
8
|
+
extractCursorAccessTokenUserId: () => extractCursorAccessTokenUserId,
|
|
9
|
+
generateCursorAuthParams: () => generateCursorAuthParams,
|
|
10
|
+
loginCursor: () => loginCursor,
|
|
11
|
+
pollCursorAuth: () => pollCursorAuth,
|
|
12
|
+
refreshCursorToken: () => refreshCursorToken
|
|
13
|
+
});
|
|
14
|
+
const CURSOR_LOGIN_URL = "https://cursor.com/loginDeepControl";
|
|
15
|
+
const CURSOR_POLL_URL = "https://api2.cursor.sh/auth/poll";
|
|
16
|
+
const CURSOR_REFRESH_URL = "https://api2.cursor.sh/auth/exchange_user_api_key";
|
|
17
|
+
const POLL_MAX_ATTEMPTS = 150;
|
|
18
|
+
const POLL_BASE_DELAY = 1e3;
|
|
19
|
+
const POLL_MAX_DELAY = 1e4;
|
|
20
|
+
const POLL_BACKOFF_MULTIPLIER = 1.2;
|
|
21
|
+
async function generateCursorAuthParams() {
|
|
22
|
+
const { verifier, challenge } = await generatePKCE();
|
|
23
|
+
const uuid = crypto.randomUUID();
|
|
24
|
+
const params = new URLSearchParams({
|
|
25
|
+
challenge,
|
|
26
|
+
uuid,
|
|
27
|
+
mode: "login",
|
|
28
|
+
redirectTarget: "cli"
|
|
29
|
+
});
|
|
30
|
+
return {
|
|
31
|
+
verifier,
|
|
32
|
+
challenge,
|
|
33
|
+
uuid,
|
|
34
|
+
loginUrl: `${CURSOR_LOGIN_URL}?${params.toString()}`
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
async function pollCursorAuth(uuid, verifier) {
|
|
38
|
+
let delay = POLL_BASE_DELAY;
|
|
39
|
+
let consecutiveErrors = 0;
|
|
40
|
+
for (let attempt = 0; attempt < POLL_MAX_ATTEMPTS; attempt++) {
|
|
41
|
+
await Bun.sleep(delay);
|
|
42
|
+
try {
|
|
43
|
+
const response = await fetch(`${CURSOR_POLL_URL}?uuid=${uuid}&verifier=${verifier}`);
|
|
44
|
+
if (response.status === 404) {
|
|
45
|
+
consecutiveErrors = 0;
|
|
46
|
+
delay = Math.min(delay * POLL_BACKOFF_MULTIPLIER, POLL_MAX_DELAY);
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (response.ok) {
|
|
50
|
+
const data = await response.json();
|
|
51
|
+
return {
|
|
52
|
+
accessToken: data.accessToken,
|
|
53
|
+
refreshToken: data.refreshToken
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
throw new OAuthError(`Poll failed: ${response.status}`, {
|
|
57
|
+
kind: "polling",
|
|
58
|
+
provider: "cursor",
|
|
59
|
+
status: response.status
|
|
60
|
+
});
|
|
61
|
+
} catch {
|
|
62
|
+
consecutiveErrors++;
|
|
63
|
+
if (consecutiveErrors >= 3) throw new OAuthError("Too many consecutive errors during Cursor auth polling", {
|
|
64
|
+
kind: "polling",
|
|
65
|
+
provider: "cursor"
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
throw new OAuthError("Cursor authentication polling timeout", {
|
|
70
|
+
kind: "timeout",
|
|
71
|
+
provider: "cursor"
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
async function loginCursor(onAuthUrl, onPollStart) {
|
|
75
|
+
const { verifier, uuid, loginUrl } = await generateCursorAuthParams();
|
|
76
|
+
onAuthUrl(loginUrl);
|
|
77
|
+
onPollStart?.();
|
|
78
|
+
const { accessToken, refreshToken } = await pollCursorAuth(uuid, verifier);
|
|
79
|
+
return {
|
|
80
|
+
access: accessToken,
|
|
81
|
+
refresh: refreshToken,
|
|
82
|
+
expires: getTokenExpiry(accessToken)
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
async function refreshCursorToken(apiKeyOrRefreshToken) {
|
|
86
|
+
const response = await fetch(CURSOR_REFRESH_URL, {
|
|
87
|
+
method: "POST",
|
|
88
|
+
headers: {
|
|
89
|
+
Authorization: `Bearer ${apiKeyOrRefreshToken}`,
|
|
90
|
+
"Content-Type": "application/json"
|
|
91
|
+
},
|
|
92
|
+
body: "{}"
|
|
93
|
+
});
|
|
94
|
+
if (!response.ok) {
|
|
95
|
+
const error = await response.text();
|
|
96
|
+
throw new OAuthError(`Cursor token refresh failed: ${error}`, {
|
|
97
|
+
kind: "token-refresh",
|
|
98
|
+
provider: "cursor"
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
const data = await response.json();
|
|
102
|
+
const expiresAt = getTokenExpiry(data.accessToken);
|
|
103
|
+
return {
|
|
104
|
+
access: data.accessToken,
|
|
105
|
+
refresh: data.refreshToken || apiKeyOrRefreshToken,
|
|
106
|
+
expires: expiresAt
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function decodeCursorAccessTokenPayload(token) {
|
|
110
|
+
const parts = token.split(".");
|
|
111
|
+
if (parts.length !== 3) return void 0;
|
|
112
|
+
const payload = parts[1];
|
|
113
|
+
if (!payload) return void 0;
|
|
114
|
+
return JSON.parse(atob(payload.replace(/-/g, "+").replace(/_/g, "/")));
|
|
115
|
+
}
|
|
116
|
+
function extractCursorAccessTokenUserId(accessToken) {
|
|
117
|
+
try {
|
|
118
|
+
const payload = decodeCursorAccessTokenPayload(accessToken);
|
|
119
|
+
if (!payload || typeof payload !== "object" || !("sub" in payload) || typeof payload.sub !== "string") return;
|
|
120
|
+
const { sub } = payload;
|
|
121
|
+
const parts = sub.split("|");
|
|
122
|
+
return (parts.length > 1 ? parts[1] : sub).trim() || void 0;
|
|
123
|
+
} catch {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function getTokenExpiry(token) {
|
|
128
|
+
try {
|
|
129
|
+
const decoded = decodeCursorAccessTokenPayload(token);
|
|
130
|
+
if (decoded && typeof decoded === "object" && "exp" in decoded && typeof decoded.exp === "number") return decoded.exp * 1e3 - 3e5;
|
|
131
|
+
} catch {}
|
|
132
|
+
return Date.now() + 36e5;
|
|
133
|
+
}
|
|
134
|
+
//#endregion
|
|
135
|
+
export { extractCursorAccessTokenUserId as n, cursor_exports as t };
|