diff --git a/.gitignore b/.gitignore index 3c45938..2ca7ce1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules/ *.log .DS_Store +dist/ diff --git a/dist/cli.d.ts b/dist/cli.d.ts deleted file mode 100644 index d9ae194..0000000 --- a/dist/cli.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -export {}; -//# sourceMappingURL=cli.d.ts.map \ No newline at end of file diff --git a/dist/cli.d.ts.map b/dist/cli.d.ts.map deleted file mode 100644 index f022439..0000000 --- a/dist/cli.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/cli.js b/dist/cli.js deleted file mode 100644 index ddce974..0000000 --- a/dist/cli.js +++ /dev/null @@ -1,19 +0,0 @@ -import { getCursorAuth } from "./cursor/auth.js"; -async function main() { - console.log("Attempting to authenticate with Cursor..."); - const result = await getCursorAuth(); - if (result.type === "success" && result.token) { - console.log("Authentication Successful!"); - console.log("Source:", result.source); - console.log("Email:", result.token.email); - console.log("Expires At:", result.token.expiresAt ? new Date(result.token.expiresAt).toISOString() : "Unknown"); - console.log("Access Token (first 20 chars):", result.token.accessToken.substring(0, 20) + "..."); - console.log("Refresh Token (present):", !!result.token.refreshToken); - } - else { - console.error("Authentication Failed:", result.error); - process.exit(1); - } -} -main().catch(console.error); -//# sourceMappingURL=cli.js.map \ No newline at end of file diff --git a/dist/cli.js.map b/dist/cli.js.map deleted file mode 100644 index 4b9e199..0000000 --- a/dist/cli.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,KAAK,UAAU,IAAI;IACjB,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,MAAM,aAAa,EAAE,CAAC;IAErC,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAC9C,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAChH,OAAO,CAAC,GAAG,CAAC,gCAAgC,EAAE,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC;QACjG,OAAO,CAAC,GAAG,CAAC,0BAA0B,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACvE,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/constants.d.ts b/dist/constants.d.ts deleted file mode 100644 index efddbb1..0000000 --- a/dist/constants.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -export declare const CURSOR_PROVIDER_ID = "cursor"; -export declare const CURSOR_API_BASE_URL = "https://api2.cursor.sh"; -//# sourceMappingURL=constants.d.ts.map \ No newline at end of file diff --git a/dist/constants.d.ts.map b/dist/constants.d.ts.map deleted file mode 100644 index b259609..0000000 --- a/dist/constants.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB,WAAW,CAAC;AAC3C,eAAO,MAAM,mBAAmB,2BAA2B,CAAC"} \ No newline at end of file diff --git a/dist/constants.js b/dist/constants.js deleted file mode 100644 index bf5f555..0000000 --- a/dist/constants.js +++ /dev/null @@ -1,3 +0,0 @@ -export const CURSOR_PROVIDER_ID = "cursor"; -export const CURSOR_API_BASE_URL = "https://api2.cursor.sh"; // Best guess based on agent behavior -//# sourceMappingURL=constants.js.map \ No newline at end of file diff --git a/dist/constants.js.map b/dist/constants.js.map deleted file mode 100644 index 7170434..0000000 --- a/dist/constants.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,kBAAkB,GAAG,QAAQ,CAAC;AAC3C,MAAM,CAAC,MAAM,mBAAmB,GAAG,wBAAwB,CAAC,CAAC,qCAAqC"} \ No newline at end of file diff --git a/dist/cursor/agent.d.ts b/dist/cursor/agent.d.ts deleted file mode 100644 index 20cad05..0000000 --- a/dist/cursor/agent.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -import type { CursorAuthResult } from "./types.js"; -export declare function loginAgent(): Promise; -//# sourceMappingURL=agent.d.ts.map \ No newline at end of file diff --git a/dist/cursor/agent.d.ts.map b/dist/cursor/agent.d.ts.map deleted file mode 100644 index 64817ef..0000000 --- a/dist/cursor/agent.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/cursor/agent.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAoBnD,wBAAsB,UAAU,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAkD5D"} \ No newline at end of file diff --git a/dist/cursor/agent.js b/dist/cursor/agent.js deleted file mode 100644 index 7cd2972..0000000 --- a/dist/cursor/agent.js +++ /dev/null @@ -1,67 +0,0 @@ -import fs from "node:fs"; -import path from "node:path"; -import os from "node:os"; -import { decodeJWT } from "../utils/jwt.js"; -function getAgentAuthPath() { - const platform = os.platform(); - const home = os.homedir(); - const domain = "cursor"; - switch (platform) { - case "win32": - const appData = process.env.APPDATA || path.join(home, "AppData", "Roaming"); - return path.join(appData, "Cursor", "auth.json"); - case "darwin": - return path.join(home, ".cursor", "auth.json"); - case "linux": - default: - const configDir = process.env.XDG_CONFIG_HOME || path.join(home, ".config"); - return path.join(configDir, domain, "auth.json"); - } -} -export async function loginAgent() { - const authPath = getAgentAuthPath(); - if (!fs.existsSync(authPath)) { - return { - type: "failed", - error: `No cursor-agent auth file found at ${authPath}`, - }; - } - try { - const content = fs.readFileSync(authPath, "utf-8"); - const data = JSON.parse(content); - if (!data.accessToken) { - return { - type: "failed", - error: "Invalid agent auth file: missing accessToken", - }; - } - const accessToken = data.accessToken; - const refreshToken = data.refreshToken || ""; - let email = undefined; - let expiresAt; - const payload = decodeJWT(accessToken); - if (payload) { - if (typeof payload.email === "string") - email = payload.email; - if (typeof payload.exp === "number") - expiresAt = payload.exp * 1000; - } - return { - type: "success", - source: "agent", - token: { - accessToken, - refreshToken, - email, - expiresAt, - }, - }; - } - catch (error) { - return { - type: "failed", - error: `Failed to read agent auth file: ${error instanceof Error ? error.message : String(error)}`, - }; - } -} -//# sourceMappingURL=agent.js.map \ No newline at end of file diff --git a/dist/cursor/agent.js.map b/dist/cursor/agent.js.map deleted file mode 100644 index fa41315..0000000 --- a/dist/cursor/agent.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/cursor/agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,SAAS,gBAAgB;IACvB,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;IAC/B,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;IAC1B,MAAM,MAAM,GAAG,QAAQ,CAAC;IAExB,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,OAAO;YACV,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;YAC7E,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;QACnD,KAAK,QAAQ;YACX,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;QACjD,KAAK,OAAO,CAAC;QACb;YACE,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YAC5E,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;IACrD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC;IAEpC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,sCAAsC,QAAQ,EAAE;SACxD,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACnD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAEjC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,OAAO;gBACL,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,8CAA8C;aACtD,CAAC;QACJ,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;QACrC,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,EAAE,CAAC;QAE7C,IAAI,KAAK,GAAG,SAAS,CAAC;QACtB,IAAI,SAA6B,CAAC;QAElC,MAAM,OAAO,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC;QACvC,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ;gBAAE,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;YAC7D,IAAI,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ;gBAAE,SAAS,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;QACtE,CAAC;QAED,OAAO;YACL,IAAI,EAAE,SAAS;YACf,MAAM,EAAE,OAAO;YACf,KAAK,EAAE;gBACL,WAAW;gBACX,YAAY;gBACZ,KAAK;gBACL,SAAS;aACV;SACF,CAAC;IAEJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,mCAAmC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;SACnG,CAAC;IACJ,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/dist/cursor/auth.d.ts b/dist/cursor/auth.d.ts deleted file mode 100644 index d1733e4..0000000 --- a/dist/cursor/auth.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -import type { CursorAuthResult } from "./types.js"; -export declare function getCursorAuth(): Promise; -//# sourceMappingURL=auth.d.ts.map \ No newline at end of file diff --git a/dist/cursor/auth.d.ts.map b/dist/cursor/auth.d.ts.map deleted file mode 100644 index 3602486..0000000 --- a/dist/cursor/auth.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/cursor/auth.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,wBAAsB,aAAa,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAmB/D"} \ No newline at end of file diff --git a/dist/cursor/auth.js b/dist/cursor/auth.js deleted file mode 100644 index 1072710..0000000 --- a/dist/cursor/auth.js +++ /dev/null @@ -1,21 +0,0 @@ -import { loginLocal } from "./local.js"; -import { loginAgent } from "./agent.js"; -export async function getCursorAuth() { - // 1. Try Local DB (IDE) - const localResult = await loginLocal(); - if (localResult.type === "success") { - return localResult; - } - // 2. Try Agent Config - const agentResult = await loginAgent(); - if (agentResult.type === "success") { - return agentResult; - } - return { - type: "failed", - error: `No authentication found. - Checked Local DB: ${localResult.error} - Checked Agent Config: ${agentResult.error}` - }; -} -//# sourceMappingURL=auth.js.map \ No newline at end of file diff --git a/dist/cursor/auth.js.map b/dist/cursor/auth.js.map deleted file mode 100644 index 191a891..0000000 --- a/dist/cursor/auth.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/cursor/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAGxC,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,wBAAwB;IACxB,MAAM,WAAW,GAAG,MAAM,UAAU,EAAE,CAAC;IACvC,IAAI,WAAW,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QACnC,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,sBAAsB;IACtB,MAAM,WAAW,GAAG,MAAM,UAAU,EAAE,CAAC;IACvC,IAAI,WAAW,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QACnC,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE;wBACa,WAAW,CAAC,KAAK;4BACb,WAAW,CAAC,KAAK,EAAE;KAC5C,CAAC;AACJ,CAAC"} \ No newline at end of file diff --git a/dist/cursor/local.d.ts b/dist/cursor/local.d.ts deleted file mode 100644 index a3cbafd..0000000 --- a/dist/cursor/local.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -import type { CursorAuthResult } from "./types.js"; -export declare function loginLocal(): Promise; -//# sourceMappingURL=local.d.ts.map \ No newline at end of file diff --git a/dist/cursor/local.d.ts.map b/dist/cursor/local.d.ts.map deleted file mode 100644 index 5890c58..0000000 --- a/dist/cursor/local.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../src/cursor/local.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,wBAAsB,UAAU,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAyC5D"} \ No newline at end of file diff --git a/dist/cursor/local.js b/dist/cursor/local.js deleted file mode 100644 index aee07da..0000000 --- a/dist/cursor/local.js +++ /dev/null @@ -1,40 +0,0 @@ -import { getCursorStateDbPath } from "../utils/platform.js"; -import { getDbValue } from "../utils/db.js"; -import { decodeJWT } from "../utils/jwt.js"; -export async function loginLocal() { - const dbPath = getCursorStateDbPath(); - const accessToken = await getDbValue(dbPath, "cursorAuth/accessToken"); - const refreshToken = await getDbValue(dbPath, "cursorAuth/refreshToken"); - // Sometimes email is stored separately - let email = await getDbValue(dbPath, "cursorAuth/cachedEmail"); - if (!accessToken) { - return { - type: "failed", - error: "No access token found in local Cursor installation.", - }; - } - // Try to extract email from JWT if not found in DB - if (!email) { - const payload = decodeJWT(accessToken); - if (payload && typeof payload.email === "string") { - email = payload.email; - } - } - // Parse expiry - let expiresAt; - const payload = decodeJWT(accessToken); - if (payload && typeof payload.exp === "number") { - expiresAt = payload.exp * 1000; - } - return { - type: "success", - source: "local", - token: { - accessToken, - refreshToken: refreshToken || "", - email: email || undefined, - expiresAt, - }, - }; -} -//# sourceMappingURL=local.js.map \ No newline at end of file diff --git a/dist/cursor/local.js.map b/dist/cursor/local.js.map deleted file mode 100644 index e6aeae1..0000000 --- a/dist/cursor/local.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"local.js","sourceRoot":"","sources":["../../src/cursor/local.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,MAAM,GAAG,oBAAoB,EAAE,CAAC;IAEtC,MAAM,WAAW,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;IACvE,MAAM,YAAY,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC;IAEzE,uCAAuC;IACvC,IAAI,KAAK,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;IAE/D,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,qDAAqD;SAC7D,CAAC;IACJ,CAAC;IAED,mDAAmD;IACnD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,OAAO,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC;QACvC,IAAI,OAAO,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACjD,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QACxB,CAAC;IACH,CAAC;IAED,eAAe;IACf,IAAI,SAA6B,CAAC;IAClC,MAAM,OAAO,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC;IACvC,IAAI,OAAO,IAAI,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC/C,SAAS,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;IACjC,CAAC;IAED,OAAO;QACL,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,OAAO;QACf,KAAK,EAAE;YACL,WAAW;YACX,YAAY,EAAE,YAAY,IAAI,EAAE;YAChC,KAAK,EAAE,KAAK,IAAI,SAAS;YACzB,SAAS;SACV;KACF,CAAC;AACJ,CAAC"} \ No newline at end of file diff --git a/dist/cursor/types.d.ts b/dist/cursor/types.d.ts deleted file mode 100644 index 5e28b37..0000000 --- a/dist/cursor/types.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -export interface CursorToken { - accessToken: string; - refreshToken: string; - expiresIn?: number | undefined; - expiresAt?: number | undefined; - email?: string | undefined; -} -export interface CursorAuthResult { - type: "success" | "failed"; - token?: CursorToken; - error?: string; - source?: "local" | "agent" | "oauth"; -} -export interface AuthStrategy { - login(): Promise; -} -//# sourceMappingURL=types.d.ts.map \ No newline at end of file diff --git a/dist/cursor/types.d.ts.map b/dist/cursor/types.d.ts.map deleted file mode 100644 index 42cb28d..0000000 --- a/dist/cursor/types.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/cursor/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC3B,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;CACtC;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACpC"} \ No newline at end of file diff --git a/dist/cursor/types.js b/dist/cursor/types.js deleted file mode 100644 index 718fd38..0000000 --- a/dist/cursor/types.js +++ /dev/null @@ -1,2 +0,0 @@ -export {}; -//# sourceMappingURL=types.js.map \ No newline at end of file diff --git a/dist/cursor/types.js.map b/dist/cursor/types.js.map deleted file mode 100644 index 80fb028..0000000 --- a/dist/cursor/types.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/cursor/types.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/index.d.ts b/dist/index.d.ts deleted file mode 100644 index 8053abf..0000000 --- a/dist/index.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { CursorAuthPlugin } from "./plugin.js"; -//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/index.d.ts.map b/dist/index.d.ts.map deleted file mode 100644 index 746625f..0000000 --- a/dist/index.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC"} \ No newline at end of file diff --git a/dist/index.js b/dist/index.js deleted file mode 100644 index eed03d6..0000000 --- a/dist/index.js +++ /dev/null @@ -1,2 +0,0 @@ -export { CursorAuthPlugin } from "./plugin.js"; -//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/index.js.map b/dist/index.js.map deleted file mode 100644 index bf335e4..0000000 --- a/dist/index.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC"} \ No newline at end of file diff --git a/dist/plugin.d.ts b/dist/plugin.d.ts deleted file mode 100644 index bce884f..0000000 --- a/dist/plugin.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -import type { Plugin } from "@opencode-ai/plugin"; -export declare const CursorAuthPlugin: Plugin; -//# sourceMappingURL=plugin.d.ts.map \ No newline at end of file diff --git a/dist/plugin.d.ts.map b/dist/plugin.d.ts.map deleted file mode 100644 index e290ee7..0000000 --- a/dist/plugin.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAe,MAAM,qBAAqB,CAAC;AAwgB/D,eAAO,MAAM,gBAAgB,EAAE,MA+C9B,CAAC"} \ No newline at end of file diff --git a/dist/plugin.js b/dist/plugin.js deleted file mode 100644 index bfb2671..0000000 --- a/dist/plugin.js +++ /dev/null @@ -1,489 +0,0 @@ -const CURSOR_PROVIDER_ID = "cursor"; -// Local proxy server that translates OpenAI-compatible HTTP to cursor-agent CLI. -const CURSOR_PROXY_HOST = "127.0.0.1"; -const CURSOR_PROXY_DEFAULT_PORT = 32123; -const CURSOR_PROXY_DEFAULT_BASE_URL = `http://${CURSOR_PROXY_HOST}:${CURSOR_PROXY_DEFAULT_PORT}/v1`; -function openAIError(status, message, details) { - const body = { - error: { - message: details ? `${message}\n${details}` : message, - type: "cursor_agent_error", - param: null, - code: null, - }, - }; - return new Response(JSON.stringify(body), { - status, - headers: { "Content-Type": "application/json" }, - }); -} -function normalizeCursorAgentModel(model) { - if (!model) - return "auto"; - const aliases = { - "gpt-5": "gpt-5.2", - "sonnet-4": "sonnet-4.5", - }; - return aliases[model] || model; -} -function summarizeTool(tool) { - const name = tool?.function?.name || "unknown"; - const description = tool?.function?.description || ""; - const params = tool?.function?.parameters; - let paramsSummary = ""; - if (params && typeof params === "object") { - const props = params.properties && typeof params.properties === "object" ? Object.keys(params.properties) : []; - const required = Array.isArray(params.required) ? params.required : []; - paramsSummary = `args: { ${props.join(", ")} } required: [${required.join(", ")}]`; - } - return `- ${name}${description ? `: ${description}` : ""}${paramsSummary ? ` (${paramsSummary})` : ""}`; -} -function extractPromptFromChatCompletions(body) { - const model = typeof body?.model === "string" ? body.model : undefined; - const stream = body?.stream === true; - const tools = Array.isArray(body?.tools) ? body.tools : []; - const messages = Array.isArray(body?.messages) ? body.messages : []; - const lines = []; - for (const message of messages) { - const role = typeof message.role === "string" ? message.role : "user"; - if (role === "tool") { - const name = typeof message.name === "string" ? message.name : "tool"; - const toolCallId = typeof message.tool_call_id === "string" ? message.tool_call_id : ""; - const content = typeof message.content === "string" ? message.content : JSON.stringify(message.content ?? ""); - lines.push(`TOOL RESULT (${name}${toolCallId ? `, id=${toolCallId}` : ""}): ${content}`); - continue; - } - if (role === "assistant" && Array.isArray(message.tool_calls)) { - lines.push(`ASSISTANT TOOL_CALLS: ${JSON.stringify(message.tool_calls)}`); - continue; - } - const content = message.content; - if (typeof content === "string") { - lines.push(`${role.toUpperCase()}: ${content}`); - continue; - } - if (Array.isArray(content)) { - const textParts = content - .map((part) => { - if (part && typeof part === "object" && part.type === "text" && typeof part.text === "string") { - return part.text; - } - return ""; - }) - .filter(Boolean); - if (textParts.length) { - lines.push(`${role.toUpperCase()}: ${textParts.join("\n")}`); - } - continue; - } - } - return { prompt: lines.join("\n\n"), model, stream, tools }; -} -function parseToolCallPlan(output) { - const start = output.indexOf("{"); - const end = output.lastIndexOf("}"); - if (start === -1 || end === -1 || end <= start) - return null; - const jsonText = output.slice(start, end + 1); - try { - const parsed = JSON.parse(jsonText); - if (parsed && parsed.action === "final" && typeof parsed.content === "string") { - return { action: "final", content: parsed.content }; - } - if (parsed && parsed.action === "tool_call" && Array.isArray(parsed.tool_calls)) { - return { - action: "tool_call", - tool_calls: parsed.tool_calls - .filter((t) => t && typeof t.name === "string") - .map((t) => ({ name: t.name, arguments: t.arguments ?? {} })), - }; - } - return null; - } - catch { - return null; - } -} -function buildToolCallingPrompt(conversation, tools, workspaceDirectory) { - const toolList = tools.length ? tools.map(summarizeTool).join("\n") : "(none)"; - return [ - "You are a tool-calling assistant running inside OpenCode.", - `Workspace directory: ${workspaceDirectory}`, - "", - "Available tools:", - toolList, - "", - "STRICT OUTPUT:", - "- Output MUST be exactly one JSON object and nothing else.", - "- If you output anything outside JSON, your answer is discarded.", - "", - "RESPONSE FORMAT:", - "- Call tool(s):", - '{"action":"tool_call","tool_calls":[{"name":"list","arguments":{"path":"/ABSOLUTE/PATH"}}]}', - "- Final answer:", - '{"action":"final","content":"..."}', - "", - "Task:", - conversation, - ].join("\n"); -} -function createChatCompletionResponse(model, content) { - return { - id: `cursor-agent-${Date.now()}`, - object: "chat.completion", - created: Math.floor(Date.now() / 1000), - model, - choices: [ - { - index: 0, - message: { role: "assistant", content }, - finish_reason: "stop", - }, - ], - }; -} -function createChatCompletionChunk(id, created, model, deltaContent, done = false) { - return { - id, - object: "chat.completion.chunk", - created, - model, - choices: [ - { - index: 0, - delta: deltaContent ? { content: deltaContent } : {}, - finish_reason: done ? "stop" : null, - }, - ], - }; -} -function getGlobalKey() { - return "__opencode_cursor_proxy_server__"; -} -async function ensureCursorProxyServer(workspaceDirectory) { - const key = getGlobalKey(); - const g = globalThis; - const existingBaseURL = g[key]?.baseURL; - if (typeof existingBaseURL === "string" && existingBaseURL.length > 0) { - return existingBaseURL; - } - // Mark as starting to avoid duplicate starts in-process. - g[key] = { baseURL: "" }; - const handler = async (req) => { - try { - const url = new URL(req.url); - if (url.pathname === "/health") { - return new Response(JSON.stringify({ ok: true }), { - status: 200, - headers: { "Content-Type": "application/json" }, - }); - } - if (url.pathname !== "/v1/chat/completions" && url.pathname !== "/chat/completions") { - return openAIError(404, `Unsupported path: ${url.pathname}`); - } - const body = await req.json().catch(() => ({})); - const { prompt, model, stream, tools } = extractPromptFromChatCompletions(body); - let selectedModel = normalizeCursorAgentModel(model); - // When tool-calling is enabled and model is "auto", pick a strict model. - if (tools.length && selectedModel === "auto") { - selectedModel = "sonnet-4.5-thinking"; - } - const effectivePrompt = tools.length ? buildToolCallingPrompt(prompt, tools, workspaceDirectory) : prompt; - const bunAny = globalThis; - if (!bunAny.Bun?.spawn) { - return openAIError(500, "This provider requires Bun runtime."); - } - const cmd = [ - "cursor-agent", - "--print", - "--output-format", - "text", - "--workspace", - workspaceDirectory, - "--model", - selectedModel, - effectivePrompt, - ]; - const child = bunAny.Bun.spawn({ - cmd, - stdout: "pipe", - stderr: "pipe", - env: bunAny.Bun.env, - }); - if (!stream) { - const [stdoutText, stderrText] = await Promise.all([ - new Response(child.stdout).text(), - new Response(child.stderr).text(), - ]); - const stdout = (stdoutText || "").trim(); - const stderr = (stderrText || "").trim(); - // If tools were requested and we can parse a plan, treat it as success even if exitCode != 0. - const plan = tools.length ? parseToolCallPlan(stdout) : null; - if (plan?.action === "tool_call") { - const toolCalls = plan.tool_calls.map((tc, i) => ({ - id: `call_${Date.now()}_${i}`, - type: "function", - function: { - name: tc.name, - arguments: JSON.stringify(tc.arguments ?? {}), - }, - })); - const payload = { - id: `cursor-agent-${Date.now()}`, - object: "chat.completion", - created: Math.floor(Date.now() / 1000), - model: selectedModel, - choices: [ - { - index: 0, - message: { - role: "assistant", - content: "", - tool_calls: toolCalls, - }, - finish_reason: "tool_calls", - }, - ], - }; - return new Response(JSON.stringify(payload), { - status: 200, - headers: { "Content-Type": "application/json" }, - }); - } - if (plan?.action === "final") { - const payload = createChatCompletionResponse(selectedModel, plan.content); - return new Response(JSON.stringify(payload), { - status: 200, - headers: { "Content-Type": "application/json" }, - }); - } - // cursor-agent sometimes returns non-zero even with usable stdout. - // Treat stdout as success unless we have explicit stderr. - if (child.exitCode !== 0 && stderr.length > 0) { - return openAIError(401, "cursor-agent failed.", stderr); - } - const payload = createChatCompletionResponse(selectedModel, stdout || stderr); - return new Response(JSON.stringify(payload), { - status: 200, - headers: { "Content-Type": "application/json" }, - }); - } - // Streaming. - const encoder = new TextEncoder(); - const id = `cursor-agent-${Date.now()}`; - const created = Math.floor(Date.now() / 1000); - const sse = new ReadableStream({ - async start(controller) { - let closed = false; - try { - // Tool-calling + streaming: buffer stdout to decide whether to emit tool_calls. - if (tools.length) { - // Keep the SSE connection alive while cursor-agent thinks. - const heartbeat = () => { - if (closed) - return; - try { - const pingChunk = createChatCompletionChunk(id, created, selectedModel, "", false); - controller.enqueue(encoder.encode(`data: ${JSON.stringify(pingChunk)}\n\n`)); - } - catch { - // ignore - } - }; - heartbeat(); - const interval = setInterval(heartbeat, 1000); - const [stdoutText, stderrText] = await Promise.all([ - new Response(child.stdout).text(), - new Response(child.stderr).text(), - ]).finally(() => { - clearInterval(interval); - }); - const stdout = (stdoutText || "").trim(); - const stderr = (stderrText || "").trim(); - const plan = parseToolCallPlan(stdout); - if (plan?.action === "tool_call") { - const toolCalls = plan.tool_calls.map((tc, i) => ({ - index: i, - id: `call_${Date.now()}_${i}`, - type: "function", - function: { - name: tc.name, - arguments: JSON.stringify(tc.arguments ?? {}), - }, - })); - const chunk = { - id, - object: "chat.completion.chunk", - created, - model: selectedModel, - choices: [ - { - index: 0, - delta: { - role: "assistant", - tool_calls: toolCalls, - }, - finish_reason: "tool_calls", - }, - ], - }; - controller.enqueue(encoder.encode(`data: ${JSON.stringify(chunk)}\n\n`)); - controller.enqueue(encoder.encode("data: [DONE]\n\n")); - return; - } - const content = plan?.action === "final" ? plan.content : stdout; - if (child.exitCode !== 0 && !plan) { - // Don't fail hard if stdout is usable; emit it as final content. - const msg = stdout || stderr; - const finalChunk = createChatCompletionChunk(id, created, selectedModel, msg, true); - controller.enqueue(encoder.encode(`data: ${JSON.stringify(finalChunk)}\n\n`)); - controller.enqueue(encoder.encode("data: [DONE]\n\n")); - return; - } - const finalChunk = createChatCompletionChunk(id, created, selectedModel, content, true); - controller.enqueue(encoder.encode(`data: ${JSON.stringify(finalChunk)}\n\n`)); - controller.enqueue(encoder.encode("data: [DONE]\n\n")); - return; - } - // No tools: stream stdout as text deltas. - const decoder = new TextDecoder(); - const reader = child.stdout.getReader(); - while (true) { - const { value, done } = await reader.read(); - if (done) - break; - if (!value || value.length === 0) - continue; - const text = decoder.decode(value, { stream: true }); - if (!text) - continue; - const chunk = createChatCompletionChunk(id, created, selectedModel, text, false); - controller.enqueue(encoder.encode(`data: ${JSON.stringify(chunk)}\n\n`)); - } - if (child.exitCode !== 0) { - const stderrText = await new Response(child.stderr).text(); - const msg = `cursor-agent failed: ${(stderrText || "").trim()}`; - const errChunk = createChatCompletionChunk(id, created, selectedModel, msg, true); - controller.enqueue(encoder.encode(`data: ${JSON.stringify(errChunk)}\n\n`)); - controller.enqueue(encoder.encode("data: [DONE]\n\n")); - return; - } - const doneChunk = createChatCompletionChunk(id, created, selectedModel, "", true); - controller.enqueue(encoder.encode(`data: ${JSON.stringify(doneChunk)}\n\n`)); - controller.enqueue(encoder.encode("data: [DONE]\n\n")); - } - finally { - closed = true; - controller.close(); - } - }, - }); - return new Response(sse, { - status: 200, - headers: { - "Content-Type": "text/event-stream", - "Cache-Control": "no-cache", - Connection: "keep-alive", - }, - }); - } - catch (error) { - const message = error instanceof Error ? error.message : String(error); - return openAIError(500, "Proxy error", message); - } - }; - const bunAny = globalThis; - if (typeof bunAny.Bun !== "undefined" && typeof bunAny.Bun.serve === "function") { - // If another process already started a proxy on the default port, reuse it. - try { - const res = await fetch(`http://${CURSOR_PROXY_HOST}:${CURSOR_PROXY_DEFAULT_PORT}/health`).catch(() => null); - if (res && res.ok) { - g[key].baseURL = CURSOR_PROXY_DEFAULT_BASE_URL; - return CURSOR_PROXY_DEFAULT_BASE_URL; - } - } - catch { - // ignore - } - const startServer = (port) => { - return bunAny.Bun.serve({ - hostname: CURSOR_PROXY_HOST, - port, - fetch: handler, - }); - }; - try { - const server = startServer(CURSOR_PROXY_DEFAULT_PORT); - const baseURL = `http://${CURSOR_PROXY_HOST}:${server.port}/v1`; - g[key].baseURL = baseURL; - return baseURL; - } - catch (error) { - const code = error?.code; - if (code !== "EADDRINUSE") { - throw error; - } - // Something is already bound to the default port. Only reuse it if it looks like our proxy. - try { - const res = await fetch(`http://${CURSOR_PROXY_HOST}:${CURSOR_PROXY_DEFAULT_PORT}/health`).catch(() => null); - if (res && res.ok) { - g[key].baseURL = CURSOR_PROXY_DEFAULT_BASE_URL; - return CURSOR_PROXY_DEFAULT_BASE_URL; - } - } - catch { - // ignore - } - // Fallback: start on a random free port. - const server = startServer(0); - const baseURL = `http://${CURSOR_PROXY_HOST}:${server.port}/v1`; - g[key].baseURL = baseURL; - return baseURL; - } - } - throw new Error("Cursor proxy server requires Bun runtime"); -} -export const CursorAuthPlugin = async ({ $, directory }) => { - const proxyBaseURL = await ensureCursorProxyServer(directory); - return { - auth: { - provider: CURSOR_PROVIDER_ID, - async loader(_getAuth) { - return {}; - }, - methods: [ - { - label: "Login via cursor-agent (opens browser)", - type: "api", - authorize: async () => { - const check = await $ `cursor-agent --version`.quiet().nothrow(); - if (check.exitCode !== 0) { - return { type: "failed" }; - } - const whoami = await $ `cursor-agent whoami`.quiet().nothrow(); - const whoamiText = whoami.text(); - if (whoamiText.includes("Not logged in")) { - const login = await $ `cursor-agent login`.nothrow(); - if (login.exitCode !== 0) { - return { type: "failed" }; - } - } - return { - type: "success", - key: "cursor-agent", - }; - }, - }, - ], - }, - async "chat.params"(input, output) { - if (input.model.providerID !== CURSOR_PROVIDER_ID) { - return; - } - // Always point to the actual proxy base URL (may be dynamically allocated). - output.options.baseURL = proxyBaseURL; - output.options.apiKey = output.options.apiKey || "cursor-agent"; - }, - }; -}; -//# sourceMappingURL=plugin.js.map \ No newline at end of file diff --git a/dist/plugin.js.map b/dist/plugin.js.map deleted file mode 100644 index cf17672..0000000 --- a/dist/plugin.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAGA,MAAM,kBAAkB,GAAG,QAAQ,CAAC;AAEpC,iFAAiF;AACjF,MAAM,iBAAiB,GAAG,WAAW,CAAC;AACtC,MAAM,yBAAyB,GAAG,KAAK,CAAC;AACxC,MAAM,6BAA6B,GAAG,UAAU,iBAAiB,IAAI,yBAAyB,KAAK,CAAC;AAepG,SAAS,WAAW,CAAC,MAAc,EAAE,OAAe,EAAE,OAAgB;IACpE,MAAM,IAAI,GAAG;QACX,KAAK,EAAE;YACL,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO;YACrD,IAAI,EAAE,oBAAoB;YAC1B,KAAK,EAAE,IAAI;YACX,IAAI,EAAE,IAAI;SACX;KACF,CAAC;IAEF,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE;QACxC,MAAM;QACN,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;KAChD,CAAC,CAAC;AACL,CAAC;AAED,SAAS,yBAAyB,CAAC,KAAc;IAC/C,IAAI,CAAC,KAAK;QAAE,OAAO,MAAM,CAAC;IAE1B,MAAM,OAAO,GAA2B;QACtC,OAAO,EAAE,SAAS;QAClB,UAAU,EAAE,YAAY;KACzB,CAAC;IAEF,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC;AACjC,CAAC;AAED,SAAS,aAAa,CAAC,IAAa;IAClC,MAAM,IAAI,GAAG,IAAI,EAAE,QAAQ,EAAE,IAAI,IAAI,SAAS,CAAC;IAC/C,MAAM,WAAW,GAAG,IAAI,EAAE,QAAQ,EAAE,WAAW,IAAI,EAAE,CAAC;IACtD,MAAM,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,UAAU,CAAC;IAE1C,IAAI,aAAa,GAAG,EAAE,CAAC;IACvB,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/G,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,aAAa,GAAG,WAAW,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;IACrF,CAAC;IAED,OAAO,KAAK,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,aAAa,CAAC,CAAC,CAAC,KAAK,aAAa,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AAC1G,CAAC;AAED,SAAS,gCAAgC,CAAC,IAAS;IAMjD,MAAM,KAAK,GAAG,OAAO,IAAI,EAAE,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACvE,MAAM,MAAM,GAAG,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,MAAM,KAAK,GAAc,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAEtE,MAAM,QAAQ,GAAe,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IAEhF,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;QAEtE,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACpB,MAAM,IAAI,GAAG,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;YACtE,MAAM,UAAU,GAAG,OAAO,OAAO,CAAC,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;YACxF,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;YAC9G,KAAK,CAAC,IAAI,CAAC,gBAAgB,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,QAAQ,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,OAAO,EAAE,CAAC,CAAC;YACzF,SAAS;QACX,CAAC;QAED,IAAI,IAAI,KAAK,WAAW,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9D,KAAK,CAAC,IAAI,CAAC,yBAAyB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;YAC1E,SAAS;QACX,CAAC;QAED,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAEhC,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,KAAK,OAAO,EAAE,CAAC,CAAC;YAChD,SAAS;QACX,CAAC;QAED,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,MAAM,SAAS,GAAG,OAAO;iBACtB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;gBACZ,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBAC9F,OAAO,IAAI,CAAC,IAAI,CAAC;gBACnB,CAAC;gBACD,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC;iBACD,MAAM,CAAC,OAAO,CAAC,CAAC;YACnB,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;gBACrB,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,KAAK,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC/D,CAAC;YACD,SAAS;QACX,CAAC;IACH,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AAC9D,CAAC;AAED,SAAS,iBAAiB,CAAC,MAAc;IACvC,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,KAAK,KAAK,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,IAAI,GAAG,IAAI,KAAK;QAAE,OAAO,IAAI,CAAC;IAE5D,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;IAC9C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACpC,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9E,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;QACtD,CAAC;QACD,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;YAChF,OAAO;gBACL,MAAM,EAAE,WAAW;gBACnB,UAAU,EAAE,MAAM,CAAC,UAAU;qBAC1B,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC;qBACnD,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,IAAI,EAAE,EAAE,CAAC,CAAC;aACrE,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,sBAAsB,CAAC,YAAoB,EAAE,KAAgB,EAAE,kBAA0B;IAChG,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAE/E,OAAO;QACL,2DAA2D;QAC3D,wBAAwB,kBAAkB,EAAE;QAC5C,EAAE;QACF,kBAAkB;QAClB,QAAQ;QACR,EAAE;QACF,gBAAgB;QAChB,4DAA4D;QAC5D,kEAAkE;QAClE,EAAE;QACF,kBAAkB;QAClB,iBAAiB;QACjB,6FAA6F;QAC7F,iBAAiB;QACjB,oCAAoC;QACpC,EAAE;QACF,OAAO;QACP,YAAY;KACb,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,SAAS,4BAA4B,CAAC,KAAa,EAAE,OAAe;IAClE,OAAO;QACL,EAAE,EAAE,gBAAgB,IAAI,CAAC,GAAG,EAAE,EAAE;QAChC,MAAM,EAAE,iBAAiB;QACzB,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;QACtC,KAAK;QACL,OAAO,EAAE;YACP;gBACE,KAAK,EAAE,CAAC;gBACR,OAAO,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE;gBACvC,aAAa,EAAE,MAAM;aACtB;SACF;KACF,CAAC;AACJ,CAAC;AAED,SAAS,yBAAyB,CAAC,EAAU,EAAE,OAAe,EAAE,KAAa,EAAE,YAAoB,EAAE,IAAI,GAAG,KAAK;IAC/G,OAAO;QACL,EAAE;QACF,MAAM,EAAE,uBAAuB;QAC/B,OAAO;QACP,KAAK;QACL,OAAO,EAAE;YACP;gBACE,KAAK,EAAE,CAAC;gBACR,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE;gBACpD,aAAa,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI;aACpC;SACF;KACF,CAAC;AACJ,CAAC;AAED,SAAS,YAAY;IACnB,OAAO,kCAAkC,CAAC;AAC5C,CAAC;AAED,KAAK,UAAU,uBAAuB,CAAC,kBAA0B;IAC/D,MAAM,GAAG,GAAG,YAAY,EAAE,CAAC;IAC3B,MAAM,CAAC,GAAG,UAAiB,CAAC;IAE5B,MAAM,eAAe,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;IACxC,IAAI,OAAO,eAAe,KAAK,QAAQ,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtE,OAAO,eAAe,CAAC;IACzB,CAAC;IAED,yDAAyD;IACzD,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAEzB,MAAM,OAAO,GAAG,KAAK,EAAE,GAAY,EAAqB,EAAE;QACxD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAE7B,IAAI,GAAG,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC/B,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE;oBAChD,MAAM,EAAE,GAAG;oBACX,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;iBAChD,CAAC,CAAC;YACL,CAAC;YAED,IAAI,GAAG,CAAC,QAAQ,KAAK,sBAAsB,IAAI,GAAG,CAAC,QAAQ,KAAK,mBAAmB,EAAE,CAAC;gBACpF,OAAO,WAAW,CAAC,GAAG,EAAE,qBAAqB,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC/D,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAChD,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,gCAAgC,CAAC,IAAI,CAAC,CAAC;YAChF,IAAI,aAAa,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAC;YAErD,yEAAyE;YACzE,IAAI,KAAK,CAAC,MAAM,IAAI,aAAa,KAAK,MAAM,EAAE,CAAC;gBAC7C,aAAa,GAAG,qBAAqB,CAAC;YACxC,CAAC;YAED,MAAM,eAAe,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,sBAAsB,CAAC,MAAM,EAAE,KAAK,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;YAE1G,MAAM,MAAM,GAAG,UAAiB,CAAC;YACjC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC;gBACvB,OAAO,WAAW,CAAC,GAAG,EAAE,qCAAqC,CAAC,CAAC;YACjE,CAAC;YAED,MAAM,GAAG,GAAG;gBACV,cAAc;gBACd,SAAS;gBACT,iBAAiB;gBACjB,MAAM;gBACN,aAAa;gBACb,kBAAkB;gBAClB,SAAS;gBACT,aAAa;gBACb,eAAe;aAChB,CAAC;YAEF,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;gBAC7B,GAAG;gBACH,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,MAAM;gBACd,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG;aACpB,CAAC,CAAC;YAEH,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,CAAC,UAAU,EAAE,UAAU,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;oBACjD,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE;oBACjC,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE;iBAClC,CAAC,CAAC;gBAEH,MAAM,MAAM,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACzC,MAAM,MAAM,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBAEzC,8FAA8F;gBAC9F,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;gBAC7D,IAAI,IAAI,EAAE,MAAM,KAAK,WAAW,EAAE,CAAC;oBACjC,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;wBAChD,EAAE,EAAE,QAAQ,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE;wBAC7B,IAAI,EAAE,UAAU;wBAChB,QAAQ,EAAE;4BACR,IAAI,EAAE,EAAE,CAAC,IAAI;4BACb,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,IAAI,EAAE,CAAC;yBAC9C;qBACF,CAAC,CAAC,CAAC;oBAEJ,MAAM,OAAO,GAAG;wBACd,EAAE,EAAE,gBAAgB,IAAI,CAAC,GAAG,EAAE,EAAE;wBAChC,MAAM,EAAE,iBAAiB;wBACzB,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;wBACtC,KAAK,EAAE,aAAa;wBACpB,OAAO,EAAE;4BACP;gCACE,KAAK,EAAE,CAAC;gCACR,OAAO,EAAE;oCACP,IAAI,EAAE,WAAW;oCACjB,OAAO,EAAE,EAAE;oCACX,UAAU,EAAE,SAAS;iCACtB;gCACD,aAAa,EAAE,YAAY;6BAC5B;yBACF;qBACF,CAAC;oBAEF,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE;wBAC3C,MAAM,EAAE,GAAG;wBACX,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;qBAChD,CAAC,CAAC;gBACL,CAAC;gBAED,IAAI,IAAI,EAAE,MAAM,KAAK,OAAO,EAAE,CAAC;oBAC7B,MAAM,OAAO,GAAG,4BAA4B,CAAC,aAAa,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;oBAC1E,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE;wBAC3C,MAAM,EAAE,GAAG;wBACX,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;qBAChD,CAAC,CAAC;gBACL,CAAC;gBAED,mEAAmE;gBACnE,0DAA0D;gBAC1D,IAAI,KAAK,CAAC,QAAQ,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC9C,OAAO,WAAW,CAAC,GAAG,EAAE,sBAAsB,EAAE,MAAM,CAAC,CAAC;gBAC1D,CAAC;gBAED,MAAM,OAAO,GAAG,4BAA4B,CAAC,aAAa,EAAE,MAAM,IAAI,MAAM,CAAC,CAAC;gBAC9E,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE;oBAC3C,MAAM,EAAE,GAAG;oBACX,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;iBAChD,CAAC,CAAC;YACL,CAAC;YAED,aAAa;YACb,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;YAClC,MAAM,EAAE,GAAG,gBAAgB,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YACxC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;YAE9C,MAAM,GAAG,GAAG,IAAI,cAAc,CAAC;gBAC7B,KAAK,CAAC,KAAK,CAAC,UAAU;oBACpB,IAAI,MAAM,GAAG,KAAK,CAAC;oBACnB,IAAI,CAAC;wBACH,gFAAgF;wBAChF,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;4BACjB,2DAA2D;4BAC3D,MAAM,SAAS,GAAG,GAAG,EAAE;gCACrB,IAAI,MAAM;oCAAE,OAAO;gCACnB,IAAI,CAAC;oCACH,MAAM,SAAS,GAAG,yBAAyB,CAAC,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;oCACnF,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;gCAC/E,CAAC;gCAAC,MAAM,CAAC;oCACP,SAAS;gCACX,CAAC;4BACH,CAAC,CAAC;4BACF,SAAS,EAAE,CAAC;4BACZ,MAAM,QAAQ,GAAG,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;4BAE9C,MAAM,CAAC,UAAU,EAAE,UAAU,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;gCACjD,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE;gCACjC,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE;6BAClC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;gCACd,aAAa,CAAC,QAAQ,CAAC,CAAC;4BAC1B,CAAC,CAAC,CAAC;4BAEH,MAAM,MAAM,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;4BACzC,MAAM,MAAM,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;4BAEzC,MAAM,IAAI,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;4BACvC,IAAI,IAAI,EAAE,MAAM,KAAK,WAAW,EAAE,CAAC;gCACjC,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;oCAChD,KAAK,EAAE,CAAC;oCACR,EAAE,EAAE,QAAQ,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE;oCAC7B,IAAI,EAAE,UAAU;oCAChB,QAAQ,EAAE;wCACR,IAAI,EAAE,EAAE,CAAC,IAAI;wCACb,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,IAAI,EAAE,CAAC;qCAC9C;iCACF,CAAC,CAAC,CAAC;gCAEJ,MAAM,KAAK,GAAG;oCACZ,EAAE;oCACF,MAAM,EAAE,uBAAuB;oCAC/B,OAAO;oCACP,KAAK,EAAE,aAAa;oCACpB,OAAO,EAAE;wCACP;4CACE,KAAK,EAAE,CAAC;4CACR,KAAK,EAAE;gDACL,IAAI,EAAE,WAAW;gDACjB,UAAU,EAAE,SAAS;6CACtB;4CACD,aAAa,EAAE,YAAY;yCAC5B;qCACF;iCACF,CAAC;gCAEF,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;gCACzE,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC;gCACvD,OAAO;4BACT,CAAC;4BAED,MAAM,OAAO,GAAG,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;4BACjE,IAAI,KAAK,CAAC,QAAQ,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;gCAClC,iEAAiE;gCACjE,MAAM,GAAG,GAAG,MAAM,IAAI,MAAM,CAAC;gCAC7B,MAAM,UAAU,GAAG,yBAAyB,CAAC,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;gCACpF,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;gCAC9E,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC;gCACvD,OAAO;4BACT,CAAC;4BAED,MAAM,UAAU,GAAG,yBAAyB,CAAC,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;4BACxF,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;4BAC9E,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC;4BACvD,OAAO;wBACT,CAAC;wBAED,0CAA0C;wBAC1C,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;wBAClC,MAAM,MAAM,GAAI,KAAK,CAAC,MAAqC,CAAC,SAAS,EAAE,CAAC;wBAExE,OAAO,IAAI,EAAE,CAAC;4BACZ,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;4BAC5C,IAAI,IAAI;gCAAE,MAAM;4BAChB,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;gCAAE,SAAS;4BAC3C,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;4BACrD,IAAI,CAAC,IAAI;gCAAE,SAAS;4BAEpB,MAAM,KAAK,GAAG,yBAAyB,CAAC,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;4BACjF,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;wBAC3E,CAAC;wBAED,IAAI,KAAK,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;4BACzB,MAAM,UAAU,GAAG,MAAM,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;4BAC3D,MAAM,GAAG,GAAG,wBAAwB,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;4BAChE,MAAM,QAAQ,GAAG,yBAAyB,CAAC,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;4BAClF,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;4BAC5E,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC;4BACvD,OAAO;wBACT,CAAC;wBAED,MAAM,SAAS,GAAG,yBAAyB,CAAC,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;wBAClF,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;wBAC7E,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC;oBACzD,CAAC;4BAAS,CAAC;wBACT,MAAM,GAAG,IAAI,CAAC;wBACd,UAAU,CAAC,KAAK,EAAE,CAAC;oBACrB,CAAC;gBACH,CAAC;aACF,CAAC,CAAC;YAEH,OAAO,IAAI,QAAQ,CAAC,GAAG,EAAE;gBACvB,MAAM,EAAE,GAAG;gBACX,OAAO,EAAE;oBACP,cAAc,EAAE,mBAAmB;oBACnC,eAAe,EAAE,UAAU;oBAC3B,UAAU,EAAE,YAAY;iBACzB;aACF,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,OAAO,WAAW,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,CAAC,CAAC;QAClD,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,MAAM,GAAG,UAAiB,CAAC;IACjC,IAAI,OAAO,MAAM,CAAC,GAAG,KAAK,WAAW,IAAI,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;QAChF,4EAA4E;QAC5E,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,UAAU,iBAAiB,IAAI,yBAAyB,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;YAC7G,IAAI,GAAG,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;gBAClB,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,GAAG,6BAA6B,CAAC;gBAC/C,OAAO,6BAA6B,CAAC;YACvC,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QAED,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,EAAE;YACnC,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;gBACtB,QAAQ,EAAE,iBAAiB;gBAC3B,IAAI;gBACJ,KAAK,EAAE,OAAO;aACf,CAAC,CAAC;QACL,CAAC,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,WAAW,CAAC,yBAAyB,CAAC,CAAC;YACtD,MAAM,OAAO,GAAG,UAAU,iBAAiB,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC;YAChE,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,GAAG,OAAO,CAAC;YACzB,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,GAAI,KAAa,EAAE,IAAI,CAAC;YAClC,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;gBAC1B,MAAM,KAAK,CAAC;YACd,CAAC;YAED,4FAA4F;YAC5F,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,UAAU,iBAAiB,IAAI,yBAAyB,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;gBAC7G,IAAI,GAAG,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;oBAClB,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,GAAG,6BAA6B,CAAC;oBAC/C,OAAO,6BAA6B,CAAC;gBACvC,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;YAED,yCAAyC;YACzC,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;YAC9B,MAAM,OAAO,GAAG,UAAU,iBAAiB,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC;YAChE,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,GAAG,OAAO,CAAC;YACzB,OAAO,OAAO,CAAC;QACjB,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAW,KAAK,EAAE,EAAE,CAAC,EAAE,SAAS,EAAe,EAAE,EAAE;IAC9E,MAAM,YAAY,GAAG,MAAM,uBAAuB,CAAC,SAAS,CAAC,CAAC;IAE9D,OAAO;QACL,IAAI,EAAE;YACJ,QAAQ,EAAE,kBAAkB;YAC5B,KAAK,CAAC,MAAM,CAAC,QAA6B;gBACxC,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,OAAO,EAAE;gBACP;oBACE,KAAK,EAAE,wCAAwC;oBAC/C,IAAI,EAAE,KAAK;oBACX,SAAS,EAAE,KAAK,IAAI,EAAE;wBACpB,MAAM,KAAK,GAAG,MAAM,CAAC,CAAA,wBAAwB,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,CAAC;wBAChE,IAAI,KAAK,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;4BACzB,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;wBAC5B,CAAC;wBAED,MAAM,MAAM,GAAG,MAAM,CAAC,CAAA,qBAAqB,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,CAAC;wBAC9D,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;wBACjC,IAAI,UAAU,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;4BACzC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAA,oBAAoB,CAAC,OAAO,EAAE,CAAC;4BACpD,IAAI,KAAK,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;gCACzB,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;4BAC5B,CAAC;wBACH,CAAC;wBAED,OAAO;4BACL,IAAI,EAAE,SAAS;4BACf,GAAG,EAAE,cAAc;yBACpB,CAAC;oBACJ,CAAC;iBACF;aACF;SACF;QAED,KAAK,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM;YAC/B,IAAI,KAAK,CAAC,KAAK,CAAC,UAAU,KAAK,kBAAkB,EAAE,CAAC;gBAClD,OAAO;YACT,CAAC;YAED,4EAA4E;YAC5E,MAAM,CAAC,OAAO,CAAC,OAAO,GAAG,YAAY,CAAC;YACtC,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,IAAI,cAAc,CAAC;QAClE,CAAC;KACF,CAAC;AACJ,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/utils/db.d.ts b/dist/utils/db.d.ts deleted file mode 100644 index cb3e701..0000000 --- a/dist/utils/db.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -export declare function getDbValue(dbPath: string, key: string): Promise; -//# sourceMappingURL=db.d.ts.map \ No newline at end of file diff --git a/dist/utils/db.d.ts.map b/dist/utils/db.d.ts.map deleted file mode 100644 index 271a1f7..0000000 --- a/dist/utils/db.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/utils/db.ts"],"names":[],"mappings":"AAUA,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiCpF"} \ No newline at end of file diff --git a/dist/utils/db.js b/dist/utils/db.js deleted file mode 100644 index 1266570..0000000 --- a/dist/utils/db.js +++ /dev/null @@ -1,38 +0,0 @@ -import fs from "node:fs"; -function isBunRuntime() { - // Bun exposes globalThis.Bun and process.versions.bun - return (typeof globalThis.Bun !== "undefined" || - typeof process?.versions?.bun === "string"); -} -export async function getDbValue(dbPath, key) { - if (!fs.existsSync(dbPath)) { - return null; - } - try { - // Bun runtime (used by opencode) cannot load native Node addons (.node) - // so we prefer bun:sqlite. - if (isBunRuntime()) { - const mod = await import("bun:sqlite"); - const Database = mod.Database; - const db = new Database(dbPath, { readonly: true }); - const row = db.query("SELECT value FROM ItemTable WHERE key = ?").get(key); - db.close(); - return row?.value ?? null; - } - // Node runtime (optional): use better-sqlite3 if available. - const mod = await import("better-sqlite3"); - const Database = (mod.default ?? mod); - const db = new Database(dbPath, { readonly: true }); - const stmt = db.prepare("SELECT value FROM ItemTable WHERE key = ?"); - const row = stmt.get(key); - db.close(); - return row?.value ?? null; - } - catch (error) { - // Avoid noisy stacks during auth; treat as "no token". - const message = error instanceof Error ? error.message : String(error); - console.warn(`[Cursor Auth] Failed to read Cursor DB at ${dbPath}: ${message}`); - return null; - } -} -//# sourceMappingURL=db.js.map \ No newline at end of file diff --git a/dist/utils/db.js.map b/dist/utils/db.js.map deleted file mode 100644 index 29f0459..0000000 --- a/dist/utils/db.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/utils/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,SAAS,YAAY;IACnB,sDAAsD;IACtD,OAAO,CACL,OAAQ,UAAkB,CAAC,GAAG,KAAK,WAAW;QAC9C,OAAQ,OAAe,EAAE,QAAQ,EAAE,GAAG,KAAK,QAAQ,CACpD,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAc,EAAE,GAAW;IAC1D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,wEAAwE;QACxE,2BAA2B;QAC3B,IAAI,YAAY,EAAE,EAAE,CAAC;YACnB,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;YACvC,MAAM,QAAQ,GAAI,GAAW,CAAC,QAAe,CAAC;YAC9C,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YACpD,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC,GAAG,CAAC,GAAG,CAE5D,CAAC;YACd,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,GAAG,EAAE,KAAK,IAAI,IAAI,CAAC;QAC5B,CAAC;QAED,4DAA4D;QAC5D,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAC3C,MAAM,QAAQ,GAAG,CAAE,GAAW,CAAC,OAAO,IAAI,GAAG,CAAQ,CAAC;QACtD,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC,2CAA2C,CAAC,CAAC;QACrE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAmC,CAAC;QAC5D,EAAE,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,GAAG,EAAE,KAAK,IAAI,IAAI,CAAC;IAC5B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,uDAAuD;QACvD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,OAAO,CAAC,IAAI,CAAC,6CAA6C,MAAM,KAAK,OAAO,EAAE,CAAC,CAAC;QAChF,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/dist/utils/jwt.d.ts b/dist/utils/jwt.d.ts deleted file mode 100644 index 10a11f8..0000000 --- a/dist/utils/jwt.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -export interface JWTPayload { - sub?: string; - email?: string; - exp?: number; - iss?: string; - aud?: string; - [key: string]: unknown; -} -export declare function decodeJWT(token: string): JWTPayload | null; -//# sourceMappingURL=jwt.d.ts.map \ No newline at end of file diff --git a/dist/utils/jwt.d.ts.map b/dist/utils/jwt.d.ts.map deleted file mode 100644 index f4e05d4..0000000 --- a/dist/utils/jwt.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../src/utils/jwt.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAe1D"} \ No newline at end of file diff --git a/dist/utils/jwt.js b/dist/utils/jwt.js deleted file mode 100644 index 1016ffb..0000000 --- a/dist/utils/jwt.js +++ /dev/null @@ -1,18 +0,0 @@ -export function decodeJWT(token) { - try { - const parts = token.split("."); - if (parts.length !== 3) { - return null; - } - const payload = parts[1]; - if (typeof payload !== 'string') { - return null; - } - const decoded = Buffer.from(payload, "base64").toString("utf-8"); - return JSON.parse(decoded); - } - catch { - return null; - } -} -//# sourceMappingURL=jwt.js.map \ No newline at end of file diff --git a/dist/utils/jwt.js.map b/dist/utils/jwt.js.map deleted file mode 100644 index 5d176c0..0000000 --- a/dist/utils/jwt.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../src/utils/jwt.ts"],"names":[],"mappings":"AASA,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACjE,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/dist/utils/platform.d.ts b/dist/utils/platform.d.ts deleted file mode 100644 index 6ac4111..0000000 --- a/dist/utils/platform.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -export declare function getCursorStateDbPath(): string; -//# sourceMappingURL=platform.d.ts.map \ No newline at end of file diff --git a/dist/utils/platform.d.ts.map b/dist/utils/platform.d.ts.map deleted file mode 100644 index b4b9769..0000000 --- a/dist/utils/platform.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../src/utils/platform.ts"],"names":[],"mappings":"AAGA,wBAAgB,oBAAoB,IAAI,MAAM,CA8B7C"} \ No newline at end of file diff --git a/dist/utils/platform.js b/dist/utils/platform.js deleted file mode 100644 index fc6ee0d..0000000 --- a/dist/utils/platform.js +++ /dev/null @@ -1,19 +0,0 @@ -import os from "node:os"; -import path from "node:path"; -export function getCursorStateDbPath() { - const home = os.homedir(); - const platform = os.platform(); - switch (platform) { - case "darwin": - return path.join(home, "Library", "Application Support", "Cursor", "User", "globalStorage", "state.vscdb"); - case "win32": - return path.join(process.env.APPDATA || path.join(home, "AppData", "Roaming"), "Cursor", "User", "globalStorage", "state.vscdb"); - case "linux": - // Check for XDG_CONFIG_HOME usually, but standard Cursor install is ~/.config/Cursor - const configDir = process.env.XDG_CONFIG_HOME || path.join(home, ".config"); - return path.join(configDir, "Cursor", "User", "globalStorage", "state.vscdb"); - default: - throw new Error(`Unsupported platform: ${platform}`); - } -} -//# sourceMappingURL=platform.js.map \ No newline at end of file diff --git a/dist/utils/platform.js.map b/dist/utils/platform.js.map deleted file mode 100644 index 72576a0..0000000 --- a/dist/utils/platform.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"platform.js","sourceRoot":"","sources":["../../src/utils/platform.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,UAAU,oBAAoB;IAClC,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;IAC1B,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;IAE/B,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,QAAQ;YACX,OAAO,IAAI,CAAC,IAAI,CACd,IAAI,EACJ,SAAS,EACT,qBAAqB,EACrB,QAAQ,EACR,MAAM,EACN,eAAe,EACf,aAAa,CACd,CAAC;QACJ,KAAK,OAAO;YACV,OAAO,IAAI,CAAC,IAAI,CACd,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,EAC5D,QAAQ,EACR,MAAM,EACN,eAAe,EACf,aAAa,CACd,CAAC;QACJ,KAAK,OAAO;YACV,qFAAqF;YACrF,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YAC5E,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,aAAa,CAAC,CAAC;QAChF;YACE,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,EAAE,CAAC,CAAC;IACzD,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/src/plugin.ts b/src/plugin.ts index 1659a90..255641d 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -201,10 +201,20 @@ function createChatCompletionChunk(id: string, created: number, model: string, d } function getGlobalKey(): string { - return "__opencode_cursor_proxy_server__"; + // Single shared proxy for all instances + return `__opencode_cursor_proxy_server__`; } -async function ensureCursorProxyServer(workspaceDirectory: string): Promise { +// Global session → directory map shared across all requests +function getSessionDirectoryMap(): Map { + const g = globalThis as any; + if (!g.__opencode_session_directory_map__) { + g.__opencode_session_directory_map__ = new Map(); + } + return g.__opencode_session_directory_map__; +} + +async function ensureCursorProxyServer(): Promise { const key = getGlobalKey(); const g = globalThis as any; @@ -216,6 +226,9 @@ async function ensureCursorProxyServer(workspaceDirectory: string): Promise => { try { const url = new URL(req.url); @@ -227,11 +240,46 @@ async function ensureCursorProxyServer(workspaceDirectory: string): Promise ({})); + const sessionID = typeof regBody?.sessionID === "string" ? regBody.sessionID : null; + const directory = typeof regBody?.directory === "string" ? regBody.directory : null; + if (sessionID && directory) { + sessionDirectoryMap.set(sessionID, directory); + } + return new Response(JSON.stringify({ ok: true }), { + status: 200, + headers: { "Content-Type": "application/json" }, + }); + } catch { + return new Response(JSON.stringify({ ok: false }), { + status: 400, + headers: { "Content-Type": "application/json" }, + }); + } + } + + if (url.pathname !== "/v1/chat/completions" && url.pathname !== "/chat/completions") { return openAIError(404, `Unsupported path: ${url.pathname}`); } const body = await req.json().catch(() => ({})); + + // Extract sessionID from apiKey field (format: "cursor-agent||sessionID") + const rawApiKey = typeof body?.apiKey === "string" ? body.apiKey : ""; + let extractedSessionID: string | null = null; + if (rawApiKey.includes("||")) { + const parts = rawApiKey.split("||"); + extractedSessionID = parts[1] || null; + } + + // Look up session directory from the shared map (registered by chat.params) + const mappedDirectory = extractedSessionID ? sessionDirectoryMap.get(extractedSessionID) : null; + const workspaceDirectory = mappedDirectory || process.cwd(); + const { prompt, model, stream, tools } = extractPromptFromChatCompletions(body); let selectedModel = normalizeCursorAgentModel(model); @@ -466,15 +514,16 @@ async function ensureCursorProxyServer(workspaceDirectory: string): Promise null); if (res && res.ok) { + // Reuse existing proxy - all instances share the same proxy g[key].baseURL = CURSOR_PROXY_DEFAULT_BASE_URL; return CURSOR_PROXY_DEFAULT_BASE_URL; } } catch { - // ignore + // ignore - will try to start server } const startServer = (port: number) => { @@ -496,7 +545,7 @@ async function ensureCursorProxyServer(workspaceDirectory: string): Promise null); if (res && res.ok) { @@ -507,7 +556,7 @@ async function ensureCursorProxyServer(workspaceDirectory: string): Promise { - const proxyBaseURL = await ensureCursorProxyServer(directory); +export const CursorAuthPlugin: Plugin = async ({ $, client, directory: pluginDirectory }: PluginInput) => { + // Single shared proxy for all instances + const proxyBaseURL = await ensureCursorProxyServer(); return { auth: { @@ -560,9 +610,35 @@ export const CursorAuthPlugin: Plugin = async ({ $, directory }: PluginInput) => return; } - // Always point to the actual proxy base URL (may be dynamically allocated). + // Get the actual session directory (may differ from pluginDirectory if user switched projects) + let sessionDirectory = pluginDirectory; + try { + const session = await client.session.get({ path: { id: input.sessionID } }); + if (session.data?.directory) { + sessionDirectory = session.data.directory; + } + } catch { + // Fall back to plugin directory + } + + // Register session → directory mapping with the shared proxy via HTTP + // This is necessary because each opencode instance runs in a separate process + // and globalThis Maps are not shared across processes + const proxyRoot = proxyBaseURL.replace('/v1', ''); + try { + await fetch(`${proxyRoot}/register-session`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ sessionID: input.sessionID, directory: sessionDirectory }), + }); + } catch { + // Ignore registration failures + } + + // Point to the shared proxy output.options.baseURL = proxyBaseURL; - output.options.apiKey = output.options.apiKey || "cursor-agent"; + // Encode sessionID in apiKey since it gets passed through to the proxy + output.options.apiKey = `cursor-agent||${input.sessionID}`; }, }; };