@code-yeongyu/senpi 2026.8.17 → 2026.8.18-2
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/CHANGELOG.md +51 -0
- package/dist/core/cursor-exec-bridge-session.d.ts.map +1 -1
- package/dist/core/cursor-exec-bridge-session.js +1 -3
- package/dist/core/cursor-exec-bridge-session.js.map +1 -1
- package/dist/core/cursor-exec-bridge.d.ts +2 -2
- package/dist/core/cursor-exec-bridge.d.ts.map +1 -1
- package/dist/core/cursor-exec-bridge.js +29 -20
- package/dist/core/cursor-exec-bridge.js.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/account-command.d.ts +4 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/account-command.d.ts.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/account-command.js +27 -7
- package/dist/core/extensions/builtin/cursor-cli-oauth/account-command.js.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/index.d.ts +1 -0
- package/dist/core/extensions/builtin/cursor-cli-oauth/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/index.js +21 -2
- package/dist/core/extensions/builtin/cursor-cli-oauth/index.js.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/native-bootstrap.d.ts +14 -0
- package/dist/core/extensions/builtin/cursor-cli-oauth/native-bootstrap.d.ts.map +1 -0
- package/dist/core/extensions/builtin/cursor-cli-oauth/native-bootstrap.js +58 -0
- package/dist/core/extensions/builtin/cursor-cli-oauth/native-bootstrap.js.map +1 -0
- package/dist/core/extensions/builtin/cursor-cli-oauth/oauth-login.d.ts +4 -0
- package/dist/core/extensions/builtin/cursor-cli-oauth/oauth-login.d.ts.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/oauth-login.js +33 -2
- package/dist/core/extensions/builtin/cursor-cli-oauth/oauth-login.js.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/settings.d.ts +2 -0
- package/dist/core/extensions/builtin/cursor-cli-oauth/settings.d.ts.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/settings.js +20 -10
- package/dist/core/extensions/builtin/cursor-cli-oauth/settings.js.map +1 -1
- package/dist/core/extensions/builtin/goal/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/index.js +14 -3
- package/dist/core/extensions/builtin/goal/index.js.map +1 -1
- package/dist/core/extensions/builtin/goal/monitor-continuation.d.ts +9 -0
- package/dist/core/extensions/builtin/goal/monitor-continuation.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/monitor-continuation.js +16 -0
- package/dist/core/extensions/builtin/goal/monitor-continuation.js.map +1 -1
- package/dist/core/extensions/builtin/goal/reload-reengagement.d.ts +30 -0
- package/dist/core/extensions/builtin/goal/reload-reengagement.d.ts.map +1 -0
- package/dist/core/extensions/builtin/goal/reload-reengagement.js +36 -0
- package/dist/core/extensions/builtin/goal/reload-reengagement.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +12 -5
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/docs/providers.md +9 -6
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +24 -0
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts +3 -2
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.js +6 -2
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/baseten.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-workers-ai.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/huggingface.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai-codex.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/xai.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-message-snapshot.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-message-snapshot.js +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-message-snapshot.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +2 -2
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/cursor-cli-oauth/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD,OAAO,EAAE,+BAA+B,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAAE,gCAAgC,EAAE,4BAA4B,EAAE,MAAM,iBAAiB,CAAC;AACjG,OAAO,EAAE,4BAA4B,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACrF,OAAO,EAAE,4BAA4B,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAC5F,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/cursor-cli-oauth/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Credential, CredentialStore } from \"@earendil-works/pi-ai\";\nimport { getAgentDir } from \"../../../../config.ts\";\nimport { AuthStorage } from \"../../../auth-storage.ts\";\nimport type { ExtensionAPI, ProviderModelConfig } from \"../../types.ts\";\nimport { registerCursorCliAccountCommand } from \"./account-command.ts\";\nimport { defaultCursorAgentExecutableDeps, resolveCursorAgentExecutable } from \"./executable.ts\";\nimport { resolveCursorCliModelCatalog, STATIC_CURSOR_CLI_MODELS } from \"./models.ts\";\nimport { createCursorCliOauthCredentialReader } from \"./native-bootstrap.ts\";\nimport { CURSOR_CLI_OAUTH_PROVIDER_ID, createCursorCliOauthConfig } from \"./oauth-login.ts\";\nimport {\n\ttype CursorCliOauthProviderSettings,\n\tloadCursorCliOauthProviderSettingsFromDisk,\n\tpersistCursorCliNoApprovalAcknowledgement,\n\tpersistCursorCliOauthEnabled,\n} from \"./settings.ts\";\nimport { streamCursorCliOauth } from \"./stream.ts\";\n\nexport { CURSOR_CLI_OAUTH_PROVIDER_ID } from \"./oauth-login.ts\";\nexport type { CursorCliStreamDeps } from \"./stream.ts\";\n\n/** Injectable seams; every default resolves real on-disk state. */\nexport type CursorCliOauthExtensionDeps = {\n\treadonly cwd?: string;\n\treadonly agentDir?: string;\n\treadonly store?: CredentialStore;\n\treadonly readCurrent?: () => Promise<Credential | undefined>;\n\treadonly readNativeCredential?: () => Credential | undefined | Promise<Credential | undefined>;\n\treadonly loadSettings?: (cwd: string) => CursorCliOauthProviderSettings;\n\treadonly resolveExecutable?: (settings: { executablePath?: string }) => string;\n};\n\nconst defaultResolveExecutable = (settings: { executablePath?: string }): string =>\n\tresolveCursorAgentExecutable({ ...defaultCursorAgentExecutableDeps(), settings });\n\n/**\n * Registers the cursor-cli-oauth provider lane. Registration is unconditional:\n * the provider ships with the offline model fallback and reports availability\n * through the oauth `check`, so a missing cursor-agent binary never hides the\n * lane - it only makes `check` name the install guidance.\n */\nexport function registerCursorCliOauthExtension(pi: ExtensionAPI, deps: CursorCliOauthExtensionDeps = {}): void {\n\tconst cwd = deps.cwd ?? process.cwd();\n\tconst agentDir = deps.agentDir ?? getAgentDir();\n\tconst store = deps.store ?? AuthStorage.create();\n\tconst readCurrent =\n\t\tdeps.readCurrent ??\n\t\tcreateCursorCliOauthCredentialReader({\n\t\t\tstore,\n\t\t\treadNativeCredential: deps.readNativeCredential ?? (() => store.read(\"cursor\")),\n\t\t\tcanBootstrap: () => {\n\t\t\t\tconst settings = loadSettings(cwd);\n\t\t\t\tif (!settings.enabled) return false;\n\t\t\t\ttry {\n\t\t\t\t\tresolveExecutable(settings);\n\t\t\t\t\treturn true;\n\t\t\t\t} catch {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\tconst loadSettings = deps.loadSettings ?? loadCursorCliOauthProviderSettingsFromDisk;\n\tconst resolveExecutable = deps.resolveExecutable ?? defaultResolveExecutable;\n\n\t// Todo 21: /cursor-account command plus the reload/shutdown teardown for\n\t// this extension generation (minimal additive wiring).\n\tregisterCursorCliAccountCommand(pi);\n\n\tconst register = (models: readonly ProviderModelConfig[]): void => {\n\t\tpi.registerProvider(CURSOR_CLI_OAUTH_PROVIDER_ID, {\n\t\t\tbaseUrl: CURSOR_CLI_OAUTH_PROVIDER_ID,\n\t\t\tapi: CURSOR_CLI_OAUTH_PROVIDER_ID,\n\t\t\tmodels: models.map((entry) => ({ ...entry })),\n\t\t\t// Settings, accounts, and the executable are re-resolved inside every\n\t\t\t// turn; nothing captured here outlives a settings or credential change.\n\t\t\tstreamSimple: (model, context, options) =>\n\t\t\t\tstreamCursorCliOauth(model, context, options, { cwd, agentDir, store }),\n\t\t\toauth: createCursorCliOauthConfig({\n\t\t\t\treadCurrent,\n\t\t\t\treadSettings: () => loadSettings(cwd),\n\t\t\t\tresolveExecutable,\n\t\t\t\tpersistAcknowledgement: (acknowledgedAt) => persistCursorCliNoApprovalAcknowledgement(cwd, acknowledgedAt),\n\t\t\t\tpersistEnabled: (enabled) => persistCursorCliOauthEnabled(cwd, enabled),\n\t\t\t}),\n\t\t});\n\t};\n\n\t// Register immediately with the offline fallback so a missing, hanging, or\n\t// broken cursor-agent can never delay or block provider registration; the\n\t// probe-backed catalog replaces it once resolved.\n\tregister(STATIC_CURSOR_CLI_MODELS);\n\tconst settings = loadSettings(cwd);\n\tvoid resolveCursorCliModelCatalog({\n\t\tagentDir,\n\t\tsettings: {\n\t\t\tmodelCatalogTtlHours: settings.modelCatalogTtlHours,\n\t\t\texecutablePath: settings.executablePath,\n\t\t},\n\t\tdeps: { resolveExecutable: () => resolveExecutable({ executablePath: settings.executablePath }) },\n\t})\n\t\t.then((models) => {\n\t\t\tconst resolved = models.map((entry) => entry.id).join(\"\\n\");\n\t\t\tif (resolved !== STATIC_CURSOR_CLI_MODELS.map((entry) => entry.id).join(\"\\n\")) register(models);\n\t\t})\n\t\t.catch(() => {\n\t\t\t// The loader degrades to the static fallback itself; keep the registered fallback.\n\t\t});\n}\n\nexport default function cursorCliOauthExtension(pi: ExtensionAPI): void {\n\tregisterCursorCliOauthExtension(pi);\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Credential, CredentialStore } from "@earendil-works/pi-ai";
|
|
2
|
+
export type CursorCliNativeBootstrapDeps = {
|
|
3
|
+
store: CredentialStore;
|
|
4
|
+
readNativeCredential: () => Credential | undefined | Promise<Credential | undefined>;
|
|
5
|
+
canBootstrap?: () => boolean | Promise<boolean>;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Read the managed credential afresh and bootstrap it once from the native
|
|
9
|
+
* Cursor OAuth credential when empty. Concurrent reads share only the
|
|
10
|
+
* in-flight operation; later turns re-read storage so login/import changes are
|
|
11
|
+
* immediately visible.
|
|
12
|
+
*/
|
|
13
|
+
export declare function createCursorCliOauthCredentialReader(deps: CursorCliNativeBootstrapDeps): () => Promise<Credential | undefined>;
|
|
14
|
+
//# sourceMappingURL=native-bootstrap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-bootstrap.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/cursor-cli-oauth/native-bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAIzE,MAAM,MAAM,4BAA4B,GAAG;IAC1C,KAAK,EAAE,eAAe,CAAC;IACvB,oBAAoB,EAAE,MAAM,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;IACrF,YAAY,CAAC,EAAE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAChD,CAAC;AAoCF;;;;;GAKG;AACH,wBAAgB,oCAAoC,CACnD,IAAI,EAAE,4BAA4B,GAChC,MAAM,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CASvC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { emptyCredential, listAccounts, SENTINEL_OAUTH_FIELDS } from "./accounts.js";
|
|
2
|
+
import { CURSOR_CLI_OAUTH_PROVIDER_ID, importNativeCursorCredential } from "./oauth-login.js";
|
|
3
|
+
function asManagedCredential(credential) {
|
|
4
|
+
if (credential?.type !== "oauth")
|
|
5
|
+
return undefined;
|
|
6
|
+
const managed = credential;
|
|
7
|
+
return Array.isArray(managed.accounts) &&
|
|
8
|
+
managed.access === SENTINEL_OAUTH_FIELDS.access &&
|
|
9
|
+
managed.refresh === SENTINEL_OAUTH_FIELDS.refresh &&
|
|
10
|
+
managed.expires === SENTINEL_OAUTH_FIELDS.expires
|
|
11
|
+
? managed
|
|
12
|
+
: undefined;
|
|
13
|
+
}
|
|
14
|
+
async function bootstrapNativeCredential(deps) {
|
|
15
|
+
let current;
|
|
16
|
+
try {
|
|
17
|
+
current = await deps.store.read(CURSOR_CLI_OAUTH_PROVIDER_ID);
|
|
18
|
+
const managed = asManagedCredential(current);
|
|
19
|
+
if (managed && listAccounts(managed).length > 0)
|
|
20
|
+
return current;
|
|
21
|
+
if (current !== undefined && !managed)
|
|
22
|
+
return current;
|
|
23
|
+
if (deps.canBootstrap !== undefined && !(await deps.canBootstrap()))
|
|
24
|
+
return current;
|
|
25
|
+
const native = await deps.readNativeCredential();
|
|
26
|
+
if (native === undefined)
|
|
27
|
+
return current;
|
|
28
|
+
return await deps.store.modify(CURSOR_CLI_OAUTH_PROVIDER_ID, async (latest) => {
|
|
29
|
+
const latestManaged = asManagedCredential(latest);
|
|
30
|
+
if (latestManaged && listAccounts(latestManaged).length > 0)
|
|
31
|
+
return latest;
|
|
32
|
+
if (latest !== undefined && !latestManaged)
|
|
33
|
+
return latest;
|
|
34
|
+
return importNativeCursorCredential(latestManaged ?? emptyCredential(), async () => native);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return current;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Read the managed credential afresh and bootstrap it once from the native
|
|
43
|
+
* Cursor OAuth credential when empty. Concurrent reads share only the
|
|
44
|
+
* in-flight operation; later turns re-read storage so login/import changes are
|
|
45
|
+
* immediately visible.
|
|
46
|
+
*/
|
|
47
|
+
export function createCursorCliOauthCredentialReader(deps) {
|
|
48
|
+
let inFlight;
|
|
49
|
+
return () => {
|
|
50
|
+
if (inFlight)
|
|
51
|
+
return inFlight;
|
|
52
|
+
inFlight = bootstrapNativeCredential(deps).finally(() => {
|
|
53
|
+
inFlight = undefined;
|
|
54
|
+
});
|
|
55
|
+
return inFlight;
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=native-bootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-bootstrap.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/cursor-cli-oauth/native-bootstrap.ts"],"names":[],"mappings":"AACA,OAAO,EAAiC,eAAe,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACpH,OAAO,EAAE,4BAA4B,EAAE,4BAA4B,EAAE,MAAM,kBAAkB,CAAC;AAQ9F,SAAS,mBAAmB,CAAC,UAAkC;IAC9D,IAAI,UAAU,EAAE,IAAI,KAAK,OAAO;QAAE,OAAO,SAAS,CAAC;IACnD,MAAM,OAAO,GAAG,UAAsC,CAAC;IACvD,OAAO,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC;QACrC,OAAO,CAAC,MAAM,KAAK,qBAAqB,CAAC,MAAM;QAC/C,OAAO,CAAC,OAAO,KAAK,qBAAqB,CAAC,OAAO;QACjD,OAAO,CAAC,OAAO,KAAK,qBAAqB,CAAC,OAAO;QACjD,CAAC,CAAC,OAAO;QACT,CAAC,CAAC,SAAS,CAAC;AACd,CAAC;AAED,KAAK,UAAU,yBAAyB,CAAC,IAAkC;IAC1E,IAAI,OAA+B,CAAC;IACpC,IAAI,CAAC;QACJ,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QAC9D,MAAM,OAAO,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;QAC7C,IAAI,OAAO,IAAI,YAAY,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,OAAO,CAAC;QAChE,IAAI,OAAO,KAAK,SAAS,IAAI,CAAC,OAAO;YAAE,OAAO,OAAO,CAAC;QACtD,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;YAAE,OAAO,OAAO,CAAC;QAEpF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,oBAAoB,EAAE,CAAC;QACjD,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,OAAO,CAAC;QAEzC,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,4BAA4B,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YAC7E,MAAM,aAAa,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;YAClD,IAAI,aAAa,IAAI,YAAY,CAAC,aAAa,CAAC,CAAC,MAAM,GAAG,CAAC;gBAAE,OAAO,MAAM,CAAC;YAC3E,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,aAAa;gBAAE,OAAO,MAAM,CAAC;YAC1D,OAAO,4BAA4B,CAAC,aAAa,IAAI,eAAe,EAAE,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC;QAC7F,CAAC,CAAC,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,OAAO,CAAC;IAChB,CAAC;AACF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oCAAoC,CACnD,IAAkC;IAElC,IAAI,QAAqD,CAAC;IAC1D,OAAO,GAAG,EAAE;QACX,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC9B,QAAQ,GAAG,yBAAyB,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;YACvD,QAAQ,GAAG,SAAS,CAAC;QACtB,CAAC,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC;IACjB,CAAC,CAAC;AACH,CAAC","sourcesContent":["import type { Credential, CredentialStore } from \"@earendil-works/pi-ai\";\nimport { type CursorCliOauthCredential, emptyCredential, listAccounts, SENTINEL_OAUTH_FIELDS } from \"./accounts.ts\";\nimport { CURSOR_CLI_OAUTH_PROVIDER_ID, importNativeCursorCredential } from \"./oauth-login.ts\";\n\nexport type CursorCliNativeBootstrapDeps = {\n\tstore: CredentialStore;\n\treadNativeCredential: () => Credential | undefined | Promise<Credential | undefined>;\n\tcanBootstrap?: () => boolean | Promise<boolean>;\n};\n\nfunction asManagedCredential(credential: Credential | undefined): CursorCliOauthCredential | undefined {\n\tif (credential?.type !== \"oauth\") return undefined;\n\tconst managed = credential as CursorCliOauthCredential;\n\treturn Array.isArray(managed.accounts) &&\n\t\tmanaged.access === SENTINEL_OAUTH_FIELDS.access &&\n\t\tmanaged.refresh === SENTINEL_OAUTH_FIELDS.refresh &&\n\t\tmanaged.expires === SENTINEL_OAUTH_FIELDS.expires\n\t\t? managed\n\t\t: undefined;\n}\n\nasync function bootstrapNativeCredential(deps: CursorCliNativeBootstrapDeps): Promise<Credential | undefined> {\n\tlet current: Credential | undefined;\n\ttry {\n\t\tcurrent = await deps.store.read(CURSOR_CLI_OAUTH_PROVIDER_ID);\n\t\tconst managed = asManagedCredential(current);\n\t\tif (managed && listAccounts(managed).length > 0) return current;\n\t\tif (current !== undefined && !managed) return current;\n\t\tif (deps.canBootstrap !== undefined && !(await deps.canBootstrap())) return current;\n\n\t\tconst native = await deps.readNativeCredential();\n\t\tif (native === undefined) return current;\n\n\t\treturn await deps.store.modify(CURSOR_CLI_OAUTH_PROVIDER_ID, async (latest) => {\n\t\t\tconst latestManaged = asManagedCredential(latest);\n\t\t\tif (latestManaged && listAccounts(latestManaged).length > 0) return latest;\n\t\t\tif (latest !== undefined && !latestManaged) return latest;\n\t\t\treturn importNativeCursorCredential(latestManaged ?? emptyCredential(), async () => native);\n\t\t});\n\t} catch {\n\t\treturn current;\n\t}\n}\n\n/**\n * Read the managed credential afresh and bootstrap it once from the native\n * Cursor OAuth credential when empty. Concurrent reads share only the\n * in-flight operation; later turns re-read storage so login/import changes are\n * immediately visible.\n */\nexport function createCursorCliOauthCredentialReader(\n\tdeps: CursorCliNativeBootstrapDeps,\n): () => Promise<Credential | undefined> {\n\tlet inFlight: Promise<Credential | undefined> | undefined;\n\treturn () => {\n\t\tif (inFlight) return inFlight;\n\t\tinFlight = bootstrapNativeCredential(deps).finally(() => {\n\t\t\tinFlight = undefined;\n\t\t});\n\t\treturn inFlight;\n\t};\n}\n"]}
|
|
@@ -21,6 +21,8 @@ export type CursorCliOauthConfigDeps = {
|
|
|
21
21
|
now?: () => Date;
|
|
22
22
|
/** Persists the no-approval acknowledgement; the disk default is wired in defaultCursorCliOauthConfig. */
|
|
23
23
|
persistAcknowledgement?: (acknowledgedAt: string) => void;
|
|
24
|
+
/** Persists explicit provider activation after a successful login. */
|
|
25
|
+
persistEnabled?: (enabled: boolean) => void;
|
|
24
26
|
};
|
|
25
27
|
export type CursorCliOauthLaneResolution = {
|
|
26
28
|
lane: typeof FILE_STORE_LANE;
|
|
@@ -68,6 +70,8 @@ export declare function confirmCursorCliNoApprovalAcknowledgement(onPrompt: ((pr
|
|
|
68
70
|
export declare function createCursorCliOauthConfig(deps: CursorCliOauthConfigDeps): CursorCliOauthConfig;
|
|
69
71
|
/** Explicitly copy the user's local Cursor credential into this provider's managed account slots. */
|
|
70
72
|
export declare function importLocalCursorCredential(current: CursorCliOauthCredential, deps?: LocalCursorImportDeps): Promise<CursorCliOauthCredential>;
|
|
73
|
+
/** Explicitly copy Senpi's native `cursor` OAuth credential into a managed CLI account slot. */
|
|
74
|
+
export declare function importNativeCursorCredential(current: CursorCliOauthCredential, readNativeCredential: () => Credential | undefined | Promise<Credential | undefined>): Promise<CursorCliOauthCredential>;
|
|
71
75
|
export declare function defaultCursorCliOauthConfig(cwd: string, readCurrent: () => Promise<Credential | undefined>): CursorCliOauthConfig;
|
|
72
76
|
export {};
|
|
73
77
|
//# sourceMappingURL=oauth-login.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-login.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/cursor-cli-oauth/oauth-login.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACX,SAAS,EACT,WAAW,EACX,UAAU,EACV,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EAEnB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAEN,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAI7B,MAAM,eAAe,CAAC;AAOvB,OAAO,EACN,KAAK,8BAA8B,
|
|
1
|
+
{"version":3,"file":"oauth-login.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/cursor-cli-oauth/oauth-login.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,7 +6,7 @@ import { cursorProvider } from "@earendil-works/pi-ai/providers/cursor";
|
|
|
6
6
|
import { addAccount, emptyCredential, listAccounts, SENTINEL_OAUTH_FIELDS, } from "./accounts.js";
|
|
7
7
|
import { defaultCursorAgentExecutableDeps, resolveCursorAgentExecutable, } from "./executable.js";
|
|
8
8
|
import { CURSOR_CLI_OAUTH_NO_APPROVAL_EXPLANATION } from "./guardrails.js";
|
|
9
|
-
import { loadCursorCliOauthProviderSettingsFromDisk, persistCursorCliNoApprovalAcknowledgement, } from "./settings.js";
|
|
9
|
+
import { loadCursorCliOauthProviderSettingsFromDisk, persistCursorCliNoApprovalAcknowledgement, persistCursorCliOauthEnabled, } from "./settings.js";
|
|
10
10
|
export const CURSOR_CLI_OAUTH_PROVIDER_ID = "cursor-cli-oauth";
|
|
11
11
|
export const CURSOR_CLI_OAUTH_NAME = "Cursor CLI (OAuth)";
|
|
12
12
|
const NO_ACCOUNTS_MESSAGE = "no accounts: run /login cursor-cli-oauth";
|
|
@@ -209,7 +209,9 @@ export function createCursorCliOauthConfig(deps) {
|
|
|
209
209
|
const acknowledgedAt = await confirmCursorCliNoApprovalAcknowledgement(callbacks.onPrompt, deps.now ?? (() => new Date()));
|
|
210
210
|
if (acknowledgedAt !== undefined)
|
|
211
211
|
deps.persistAcknowledgement?.(acknowledgedAt);
|
|
212
|
-
|
|
212
|
+
const credential = addAccount(current, slotFromCredential(loggedIn, name, "login"));
|
|
213
|
+
deps.persistEnabled?.(true);
|
|
214
|
+
return credential;
|
|
213
215
|
},
|
|
214
216
|
async refreshToken(credentials, signal) {
|
|
215
217
|
if (!isCursorCliOauthCredential(credentials))
|
|
@@ -312,6 +314,34 @@ export async function importLocalCursorCredential(current, deps = {}) {
|
|
|
312
314
|
expires: imported.expires ?? Date.now() + DEFAULT_IMPORTED_EXPIRY_MS,
|
|
313
315
|
}, name, "import"));
|
|
314
316
|
}
|
|
317
|
+
function isUsableFlatOAuthCredential(value) {
|
|
318
|
+
return (value?.type === "oauth" &&
|
|
319
|
+
typeof value.access === "string" &&
|
|
320
|
+
value.access.length > 0 &&
|
|
321
|
+
typeof value.refresh === "string" &&
|
|
322
|
+
value.refresh.length > 0 &&
|
|
323
|
+
typeof value.expires === "number" &&
|
|
324
|
+
Number.isFinite(value.expires));
|
|
325
|
+
}
|
|
326
|
+
function nativeAccountName(existing) {
|
|
327
|
+
const names = new Set(existing.map((account) => account.name));
|
|
328
|
+
if (!names.has("native"))
|
|
329
|
+
return "native";
|
|
330
|
+
for (let index = 2; index <= 10_000; index++) {
|
|
331
|
+
const candidate = `native-${index}`;
|
|
332
|
+
if (!names.has(candidate))
|
|
333
|
+
return candidate;
|
|
334
|
+
}
|
|
335
|
+
throw new Error("Could not allocate a Cursor CLI OAuth native account name");
|
|
336
|
+
}
|
|
337
|
+
/** Explicitly copy Senpi's native `cursor` OAuth credential into a managed CLI account slot. */
|
|
338
|
+
export async function importNativeCursorCredential(current, readNativeCredential) {
|
|
339
|
+
const native = await readNativeCredential();
|
|
340
|
+
if (!isUsableFlatOAuthCredential(native)) {
|
|
341
|
+
throw new Error("No stored native Cursor OAuth credential found");
|
|
342
|
+
}
|
|
343
|
+
return addAccount(current, slotFromCredential(native, nativeAccountName(listAccounts(current)), "import"));
|
|
344
|
+
}
|
|
315
345
|
export function defaultCursorCliOauthConfig(cwd, readCurrent) {
|
|
316
346
|
return createCursorCliOauthConfig({
|
|
317
347
|
readCurrent,
|
|
@@ -325,6 +355,7 @@ export function defaultCursorCliOauthConfig(cwd, readCurrent) {
|
|
|
325
355
|
},
|
|
326
356
|
now: () => new Date(),
|
|
327
357
|
persistAcknowledgement: (acknowledgedAt) => persistCursorCliNoApprovalAcknowledgement(cwd, acknowledgedAt),
|
|
358
|
+
persistEnabled: (enabled) => persistCursorCliOauthEnabled(cwd, enabled),
|
|
328
359
|
});
|
|
329
360
|
}
|
|
330
361
|
//# sourceMappingURL=oauth-login.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-login.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/cursor-cli-oauth/oauth-login.ts"],"names":[],"mappings":"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","sourcesContent":["import { execFile as nodeExecFile } from \"node:child_process\";\nimport { readFile as nodeReadFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type {\n\tAuthCheck,\n\tAuthContext,\n\tCredential,\n\tOAuthAuth,\n\tOAuthCredential,\n\tOAuthCredentials,\n\tOAuthLoginCallbacks,\n\tProviderAuthInteraction,\n} from \"@earendil-works/pi-ai\";\nimport { cursorProvider } from \"@earendil-works/pi-ai/providers/cursor\";\nimport {\n\taddAccount,\n\ttype CursorCliAccountSlot,\n\ttype CursorCliOauthCredential,\n\temptyCredential,\n\tlistAccounts,\n\tSENTINEL_OAUTH_FIELDS,\n} from \"./accounts.ts\";\nimport {\n\ttype CursorAgentExecutableDeps,\n\tdefaultCursorAgentExecutableDeps,\n\tresolveCursorAgentExecutable,\n} from \"./executable.ts\";\nimport { CURSOR_CLI_OAUTH_NO_APPROVAL_EXPLANATION } from \"./guardrails.ts\";\nimport {\n\ttype CursorCliOauthProviderSettings,\n\tloadCursorCliOauthProviderSettingsFromDisk,\n\tpersistCursorCliNoApprovalAcknowledgement,\n} from \"./settings.ts\";\n\nexport const CURSOR_CLI_OAUTH_PROVIDER_ID = \"cursor-cli-oauth\";\nexport const CURSOR_CLI_OAUTH_NAME = \"Cursor CLI (OAuth)\";\n\nconst NO_ACCOUNTS_MESSAGE = \"no accounts: run /login cursor-cli-oauth\";\nconst DISABLED_MESSAGE = \"disabled by settings\";\nconst FILE_STORE_LANE = \"file-store\" as const;\nconst DEFAULT_IMPORTED_EXPIRY_MS = 60 * 60 * 1000;\n\ntype CursorCliOauthSettings = Pick<CursorCliOauthProviderSettings, \"enabled\" | \"executablePath\">;\n\ntype ImportedCursorCredential = {\n\taccess: string;\n\trefresh: string;\n\texpires?: number;\n};\n\nexport type CursorCliOauthConfigDeps = {\n\treadCurrent: () => Promise<Credential | undefined>;\n\treadSettings: () => CursorCliOauthSettings;\n\tresolveExecutable: (settings: CursorCliOauthSettings) => string;\n\tloadOAuth?: () => Promise<OAuthAuth>;\n\treadCursorFile?: () => Promise<ImportedCursorCredential | undefined>;\n\treadCursorKeychain?: () => Promise<ImportedCursorCredential | undefined>;\n\t/** Clock for acknowledgement timestamps; injectable so tests stay deterministic. */\n\tnow?: () => Date;\n\t/** Persists the no-approval acknowledgement; the disk default is wired in defaultCursorCliOauthConfig. */\n\tpersistAcknowledgement?: (acknowledgedAt: string) => void;\n};\n\nexport type CursorCliOauthLaneResolution = {\n\tlane: typeof FILE_STORE_LANE;\n\taccount: CursorCliAccountSlot;\n\taccounts: CursorCliAccountSlot[];\n};\n\nexport type CursorCliOauthConfig = {\n\tname: string;\n\tisSubscription: true;\n\tcheck(input: {\n\t\tctx: AuthContext;\n\t\tcredential?: OAuthCredential;\n\t\tsignal?: AbortSignal;\n\t}): Promise<AuthCheck | undefined>;\n\tlogin(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials>;\n\trefreshToken(credentials: OAuthCredentials, signal: AbortSignal): Promise<OAuthCredentials>;\n\tgetApiKey(credentials: OAuthCredentials): string;\n};\n\nexport type LocalCursorImportDeps = {\n\tplatform?: NodeJS.Platform;\n\treadCursorFile?: () => Promise<ImportedCursorCredential | undefined>;\n\treadCursorKeychain?: () => Promise<ImportedCursorCredential | undefined>;\n\tonPrompt?: OAuthLoginCallbacks[\"onPrompt\"];\n};\n\ntype ConfigurationAssessment = {\n\taccounts: CursorCliAccountSlot[];\n\tmessage: string;\n};\n\n/** The single condition evaluation behind both the tolerant `check` and the throwing turn-time resolution. */\ntype ConfigurationOutcome =\n\t| { status: \"disabled\" }\n\t| { status: \"not-installed\"; error: unknown }\n\t| { status: \"no-accounts\" }\n\t| { status: \"configured\"; assessment: ConfigurationAssessment };\n\n/**\n * One predicate so availability and resolution cannot disagree: evaluates the\n * same conditions for every caller and reports why the lane is unusable\n * instead of deciding per call-site whether that is fatal.\n */\nasync function assessConfiguration(deps: CursorCliOauthConfigDeps): Promise<ConfigurationOutcome> {\n\tconst settings = deps.readSettings();\n\tif (!settings.enabled) return { status: \"disabled\" };\n\ttry {\n\t\tdeps.resolveExecutable(settings);\n\t} catch (error) {\n\t\treturn { status: \"not-installed\", error };\n\t}\n\n\tconst accounts = usableAccounts(await deps.readCurrent());\n\tif (accounts.length === 0) return { status: \"no-accounts\" };\n\treturn {\n\t\tstatus: \"configured\",\n\t\tassessment: { accounts, message: `configured (file-store, ${accounts.length} accounts)` },\n\t};\n}\n\n/** The throwing view used by turn-time resolution; a turn attempted on an unusable lane must still error clearly. */\nasync function configuredFor(deps: CursorCliOauthConfigDeps): Promise<ConfigurationAssessment> {\n\tconst outcome = await assessConfiguration(deps);\n\tswitch (outcome.status) {\n\t\tcase \"disabled\":\n\t\t\tthrow new Error(DISABLED_MESSAGE);\n\t\tcase \"not-installed\":\n\t\t\tthrow cursorAgentNotInstalledError(outcome.error);\n\t\tcase \"no-accounts\":\n\t\t\tthrow new Error(NO_ACCOUNTS_MESSAGE);\n\t\tdefault:\n\t\t\treturn outcome.assessment;\n\t}\n}\n\nfunction isCursorCliOauthCredential(\n\tvalue: Credential | OAuthCredentials | undefined,\n): value is CursorCliOauthCredential {\n\tif (typeof value !== \"object\" || value === null) return false;\n\tconst candidate = value as Partial<CursorCliOauthCredential>;\n\treturn candidate.type === \"oauth\" && Array.isArray(candidate.accounts);\n}\n\nfunction usableAccounts(value: Credential | OAuthCredentials | undefined): CursorCliAccountSlot[] {\n\tif (!isCursorCliOauthCredential(value)) return [];\n\treturn listAccounts(value).filter(\n\t\t(slot) =>\n\t\t\ttypeof slot.name === \"string\" &&\n\t\t\ttypeof slot.access === \"string\" &&\n\t\t\tslot.access.trim().length > 0 &&\n\t\t\ttypeof slot.refresh === \"string\" &&\n\t\t\tslot.refresh.trim().length > 0 &&\n\t\t\ttypeof slot.expires === \"number\" &&\n\t\t\tNumber.isFinite(slot.expires),\n\t);\n}\n\nfunction installationMessage(error: unknown): string {\n\tconst detail = error instanceof Error ? error.message : String(error);\n\treturn `cursor-agent not installed: ${detail.replace(/^Cursor CLI is not installed\\.\\s*/, \"\")}`;\n}\n\n/**\n * The typed turn-path error for a missing cursor-agent binary: carries the\n * `cursor-agent not installed` marker plus the install guidance verbatim, with\n * the underlying resolution failure preserved as `cause`.\n */\nexport function cursorAgentNotInstalledError(cause: unknown): Error {\n\tconst error = new Error(installationMessage(cause));\n\terror.name = \"CursorAgentNotInstalledError\";\n\terror.cause = cause;\n\treturn error;\n}\n\n/** Resolve credentials immediately before execution so a concurrent refresh cannot leave a stale token in memory. */\nexport async function resolveCursorCliOauthLane(deps: CursorCliOauthConfigDeps): Promise<CursorCliOauthLaneResolution> {\n\tconst assessment = await configuredFor(deps);\n\tconst account = assessment.accounts[0];\n\tif (!account) throw new Error(NO_ACCOUNTS_MESSAGE);\n\treturn { lane: FILE_STORE_LANE, account, accounts: assessment.accounts };\n}\n\nasync function loadCursorOAuthFlow(): Promise<OAuthAuth> {\n\tconst flow = cursorProvider().auth.oauth;\n\tif (!flow) throw new Error(\"Cursor OAuth flow is unavailable\");\n\treturn flow;\n}\n\nfunction providerInteraction(callbacks: OAuthLoginCallbacks): ProviderAuthInteraction {\n\treturn {\n\t\tsignal: callbacks.signal ?? new AbortController().signal,\n\t\tprompt: async (prompt) => {\n\t\t\tswitch (prompt.type) {\n\t\t\t\tcase \"select\":\n\t\t\t\t\treturn (await callbacks.onSelect(prompt)) ?? \"\";\n\t\t\t\tcase \"manual_code\":\n\t\t\t\t\treturn callbacks.onManualCodeInput?.() ?? callbacks.onPrompt(prompt);\n\t\t\t\tdefault:\n\t\t\t\t\treturn callbacks.onPrompt(prompt);\n\t\t\t}\n\t\t},\n\t\tnotify: (event) => {\n\t\t\tswitch (event.type) {\n\t\t\t\tcase \"auth_url\":\n\t\t\t\t\tcallbacks.onAuth({ url: event.url, instructions: event.instructions });\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"device_code\":\n\t\t\t\t\tcallbacks.onDeviceCode(event);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"progress\":\n\t\t\t\t\tcallbacks.onProgress?.(event.message);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"info\":\n\t\t\t\t\tcallbacks.onProgress?.(event.message);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t},\n\t};\n}\n\nasync function accountName(\n\texisting: CursorCliAccountSlot[],\n\tonPrompt: OAuthLoginCallbacks[\"onPrompt\"] | undefined,\n): Promise<string> {\n\tif (existing.length === 0) return \"default\";\n\tconst fallback = `account-${existing.length + 1}`;\n\tif (!onPrompt) return fallback;\n\tconst answer = (\n\t\tawait onPrompt({\n\t\t\tmessage: `Name for this account (existing: ${existing.map((slot) => slot.name).join(\", \")})`,\n\t\t\tplaceholder: fallback,\n\t\t})\n\t).trim();\n\treturn answer || fallback;\n}\n\nfunction slotFromCredential(\n\tcredential: Pick<OAuthCredentials, \"access\" | \"refresh\" | \"expires\">,\n\tname: string,\n\tsource: CursorCliAccountSlot[\"source\"],\n): CursorCliAccountSlot {\n\treturn {\n\t\tname,\n\t\taccess: credential.access,\n\t\trefresh: credential.refresh,\n\t\texpires: credential.expires,\n\t\tsource,\n\t};\n}\n\n/** The one-screen login explanation: what unattended Cursor CLI execution gives up, and the plan-mode alternative. */\nexport const CURSOR_CLI_OAUTH_LOGIN_ACKNOWLEDGEMENT_EXPLANATION = `${CURSOR_CLI_OAUTH_NO_APPROVAL_EXPLANATION} Plan mode (planning only, no tool execution) is available via the executionMode setting.`;\n\nconst ACKNOWLEDGEMENT_ACCEPTANCE = new Set([\"yes\", \"y\"]);\n\n/**\n * Present the no-approval explanation exactly once and return the ISO\n * acknowledgement timestamp on explicit confirmation, undefined otherwise.\n * Shared by the login flow and the /cursor-account acknowledge subcommand so\n * both surfaces present the identical explanation and persist identically.\n */\nexport async function confirmCursorCliNoApprovalAcknowledgement(\n\tonPrompt: ((prompt: { message: string; placeholder?: string }) => Promise<string>) | undefined,\n\tnow: () => Date,\n): Promise<string | undefined> {\n\tif (!onPrompt) return undefined;\n\tconst answer = (\n\t\tawait onPrompt({\n\t\t\tmessage: `${CURSOR_CLI_OAUTH_LOGIN_ACKNOWLEDGEMENT_EXPLANATION}\\nType \"yes\" to acknowledge and allow unattended Cursor CLI tool execution; anything else leaves it off.`,\n\t\t})\n\t)\n\t\t.trim()\n\t\t.toLowerCase();\n\treturn ACKNOWLEDGEMENT_ACCEPTANCE.has(answer) ? now().toISOString() : undefined;\n}\n\nexport function createCursorCliOauthConfig(deps: CursorCliOauthConfigDeps): CursorCliOauthConfig {\n\treturn {\n\t\tname: CURSOR_CLI_OAUTH_NAME,\n\t\tisSubscription: true,\n\n\t\tasync check(input) {\n\t\t\t// Tolerant by contract: ModelsImpl.getAvailable runs every provider's\n\t\t\t// check under Promise.all (packages/ai/src/models.ts:544-548) and turns a\n\t\t\t// throw into a rejecting ModelsError, so one throwing check would reject\n\t\t\t// all model listing. Not usable (disabled / not installed / no accounts)\n\t\t\t// reports undefined here - as claude-sdk-oauth's check does - while\n\t\t\t// turn-time resolution keeps throwing via configuredFor.\n\t\t\t//\n\t\t\t// One nuance: the auth-resolution path (checkAuth, resolveStoredOAuth)\n\t\t\t// always passes the stored credential, while bare model listing does not.\n\t\t\t// A credential-backed lane whose executable is missing stays selectable\n\t\t\t// with the install guidance as its source, so a TURN reaches\n\t\t\t// streamCursorCliOauth, which throws the typed not-installed error;\n\t\t\t// without a credential the lane hides exactly as before.\n\t\t\tconst outcome = await assessConfiguration(deps);\n\t\t\tif (outcome.status === \"disabled\" || outcome.status === \"no-accounts\") return undefined;\n\t\t\tif (outcome.status === \"not-installed\") {\n\t\t\t\treturn input.credential === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: { type: \"oauth\", source: installationMessage(outcome.error) };\n\t\t\t}\n\t\t\treturn { type: \"oauth\", source: outcome.assessment.message };\n\t\t},\n\n\t\tasync login(callbacks) {\n\t\t\tconst stored = await deps.readCurrent();\n\t\t\tconst current = isCursorCliOauthCredential(stored) ? stored : emptyCredential();\n\t\t\tconst existing = listAccounts(current);\n\t\t\tconst flow = await (deps.loadOAuth ?? loadCursorOAuthFlow)();\n\t\t\tconst loggedIn = await flow.login(providerInteraction(callbacks));\n\t\t\tconst name = await accountName(existing, callbacks.onPrompt);\n\t\t\t// After the PKCE flow succeeds and before the slot is stored: the\n\t\t\t// one-screen no-approval explanation, confirmed once. Declining still\n\t\t\t// stores the slot; only the acknowledgement stays unset, so force turns\n\t\t\t// refuse until the user acknowledges later.\n\t\t\tconst acknowledgedAt = await confirmCursorCliNoApprovalAcknowledgement(\n\t\t\t\tcallbacks.onPrompt,\n\t\t\t\tdeps.now ?? (() => new Date()),\n\t\t\t);\n\t\t\tif (acknowledgedAt !== undefined) deps.persistAcknowledgement?.(acknowledgedAt);\n\t\t\treturn addAccount(current, slotFromCredential(loggedIn, name, \"login\"));\n\t\t},\n\n\t\tasync refreshToken(credentials, signal) {\n\t\t\tif (!isCursorCliOauthCredential(credentials)) return credentials;\n\t\t\tconst flow = await (deps.loadOAuth ?? loadCursorOAuthFlow)();\n\t\t\tconst accounts: CursorCliAccountSlot[] = [];\n\t\t\tfor (const slot of listAccounts(credentials)) {\n\t\t\t\tif (Date.now() < slot.expires) {\n\t\t\t\t\taccounts.push(slot);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst refreshed = await flow.refresh(\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"oauth\",\n\t\t\t\t\t\taccess: slot.access,\n\t\t\t\t\t\trefresh: slot.refresh,\n\t\t\t\t\t\texpires: slot.expires,\n\t\t\t\t\t},\n\t\t\t\t\tsignal,\n\t\t\t\t);\n\t\t\t\taccounts.push({\n\t\t\t\t\t...slot,\n\t\t\t\t\taccess: refreshed.access,\n\t\t\t\t\trefresh: refreshed.refresh,\n\t\t\t\t\texpires: refreshed.expires,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { ...credentials, ...SENTINEL_OAUTH_FIELDS, accounts };\n\t\t},\n\n\t\tgetApiKey() {\n\t\t\treturn SENTINEL_OAUTH_FIELDS.access;\n\t\t},\n\t};\n}\n\nfunction execFileOutput(file: string, args: string[]): Promise<string | undefined> {\n\treturn new Promise((resolve) => {\n\t\tnodeExecFile(file, args, { encoding: \"utf8\" }, (error, stdout) => {\n\t\t\tif (error) {\n\t\t\t\tresolve(undefined);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst value = stdout.trim();\n\t\t\tresolve(value.length > 0 ? value : undefined);\n\t\t});\n\t});\n}\n\nasync function defaultKeychainCredential(): Promise<ImportedCursorCredential | undefined> {\n\tif (process.platform !== \"darwin\") return undefined;\n\tconst [access, refresh] = await Promise.all([\n\t\texecFileOutput(\"security\", [\"find-generic-password\", \"-a\", \"cursor-user\", \"-s\", \"cursor-access-token\", \"-w\"]),\n\t\texecFileOutput(\"security\", [\"find-generic-password\", \"-a\", \"cursor-user\", \"-s\", \"cursor-refresh-token\", \"-w\"]),\n\t]);\n\treturn access && refresh ? { access, refresh } : undefined;\n}\n\nfunction localCursorAuthPath(platform: NodeJS.Platform): string | undefined {\n\tswitch (platform) {\n\t\tcase \"darwin\":\n\t\t\treturn join(homedir(), \".cursor\", \"auth.json\");\n\t\tcase \"linux\":\n\t\t\treturn join(process.env.XDG_CONFIG_HOME ?? join(homedir(), \".config\"), \"cursor\", \"auth.json\");\n\t\tcase \"win32\": {\n\t\t\tconst appData = process.env.APPDATA;\n\t\t\treturn appData ? join(appData, \"Cursor\", \"auth.json\") : undefined;\n\t\t}\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n\nasync function defaultFileCredential(platform: NodeJS.Platform): Promise<ImportedCursorCredential | undefined> {\n\tconst path = localCursorAuthPath(platform);\n\tif (!path) return undefined;\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(await nodeReadFile(path, \"utf8\"));\n\t\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) return undefined;\n\t\tconst record = parsed as Record<string, unknown>;\n\t\tconst access = record.accessToken;\n\t\tconst refresh = record.refreshToken;\n\t\tif (typeof access !== \"string\" || access.length === 0 || typeof refresh !== \"string\" || refresh.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn { access, refresh };\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/** Explicitly copy the user's local Cursor credential into this provider's managed account slots. */\nexport async function importLocalCursorCredential(\n\tcurrent: CursorCliOauthCredential,\n\tdeps: LocalCursorImportDeps = {},\n): Promise<CursorCliOauthCredential> {\n\tconst platform = deps.platform ?? process.platform;\n\tconst readKeychain = deps.readCursorKeychain ?? defaultKeychainCredential;\n\tconst readFile = deps.readCursorFile ?? (() => defaultFileCredential(platform));\n\tconst imported = platform === \"darwin\" ? ((await readKeychain()) ?? (await readFile())) : await readFile();\n\tif (!imported) throw new Error(\"No local Cursor OAuth credential found\");\n\tconst existing = listAccounts(current);\n\tconst name = await accountName(existing, deps.onPrompt);\n\treturn addAccount(\n\t\tcurrent,\n\t\tslotFromCredential(\n\t\t\t{\n\t\t\t\taccess: imported.access,\n\t\t\t\trefresh: imported.refresh,\n\t\t\t\texpires: imported.expires ?? Date.now() + DEFAULT_IMPORTED_EXPIRY_MS,\n\t\t\t},\n\t\t\tname,\n\t\t\t\"import\",\n\t\t),\n\t);\n}\n\nexport function defaultCursorCliOauthConfig(\n\tcwd: string,\n\treadCurrent: () => Promise<Credential | undefined>,\n): CursorCliOauthConfig {\n\treturn createCursorCliOauthConfig({\n\t\treadCurrent,\n\t\treadSettings: () => loadCursorCliOauthProviderSettingsFromDisk(cwd),\n\t\tresolveExecutable: (settings) => {\n\t\t\tconst executableDeps: CursorAgentExecutableDeps = {\n\t\t\t\t...defaultCursorAgentExecutableDeps(),\n\t\t\t\tsettings,\n\t\t\t};\n\t\t\treturn resolveCursorAgentExecutable(executableDeps);\n\t\t},\n\t\tnow: () => new Date(),\n\t\tpersistAcknowledgement: (acknowledgedAt: string) =>\n\t\t\tpersistCursorCliNoApprovalAcknowledgement(cwd, acknowledgedAt),\n\t});\n}\n"]}
|
|
1
|
+
{"version":3,"file":"oauth-login.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/cursor-cli-oauth/oauth-login.ts"],"names":[],"mappings":"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","sourcesContent":["import { execFile as nodeExecFile } from \"node:child_process\";\nimport { readFile as nodeReadFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type {\n\tAuthCheck,\n\tAuthContext,\n\tCredential,\n\tOAuthAuth,\n\tOAuthCredential,\n\tOAuthCredentials,\n\tOAuthLoginCallbacks,\n\tProviderAuthInteraction,\n} from \"@earendil-works/pi-ai\";\nimport { cursorProvider } from \"@earendil-works/pi-ai/providers/cursor\";\nimport {\n\taddAccount,\n\ttype CursorCliAccountSlot,\n\ttype CursorCliOauthCredential,\n\temptyCredential,\n\tlistAccounts,\n\tSENTINEL_OAUTH_FIELDS,\n} from \"./accounts.ts\";\nimport {\n\ttype CursorAgentExecutableDeps,\n\tdefaultCursorAgentExecutableDeps,\n\tresolveCursorAgentExecutable,\n} from \"./executable.ts\";\nimport { CURSOR_CLI_OAUTH_NO_APPROVAL_EXPLANATION } from \"./guardrails.ts\";\nimport {\n\ttype CursorCliOauthProviderSettings,\n\tloadCursorCliOauthProviderSettingsFromDisk,\n\tpersistCursorCliNoApprovalAcknowledgement,\n\tpersistCursorCliOauthEnabled,\n} from \"./settings.ts\";\n\nexport const CURSOR_CLI_OAUTH_PROVIDER_ID = \"cursor-cli-oauth\";\nexport const CURSOR_CLI_OAUTH_NAME = \"Cursor CLI (OAuth)\";\n\nconst NO_ACCOUNTS_MESSAGE = \"no accounts: run /login cursor-cli-oauth\";\nconst DISABLED_MESSAGE = \"disabled by settings\";\nconst FILE_STORE_LANE = \"file-store\" as const;\nconst DEFAULT_IMPORTED_EXPIRY_MS = 60 * 60 * 1000;\n\ntype CursorCliOauthSettings = Pick<CursorCliOauthProviderSettings, \"enabled\" | \"executablePath\">;\n\ntype ImportedCursorCredential = {\n\taccess: string;\n\trefresh: string;\n\texpires?: number;\n};\n\nexport type CursorCliOauthConfigDeps = {\n\treadCurrent: () => Promise<Credential | undefined>;\n\treadSettings: () => CursorCliOauthSettings;\n\tresolveExecutable: (settings: CursorCliOauthSettings) => string;\n\tloadOAuth?: () => Promise<OAuthAuth>;\n\treadCursorFile?: () => Promise<ImportedCursorCredential | undefined>;\n\treadCursorKeychain?: () => Promise<ImportedCursorCredential | undefined>;\n\t/** Clock for acknowledgement timestamps; injectable so tests stay deterministic. */\n\tnow?: () => Date;\n\t/** Persists the no-approval acknowledgement; the disk default is wired in defaultCursorCliOauthConfig. */\n\tpersistAcknowledgement?: (acknowledgedAt: string) => void;\n\t/** Persists explicit provider activation after a successful login. */\n\tpersistEnabled?: (enabled: boolean) => void;\n};\n\nexport type CursorCliOauthLaneResolution = {\n\tlane: typeof FILE_STORE_LANE;\n\taccount: CursorCliAccountSlot;\n\taccounts: CursorCliAccountSlot[];\n};\n\nexport type CursorCliOauthConfig = {\n\tname: string;\n\tisSubscription: true;\n\tcheck(input: {\n\t\tctx: AuthContext;\n\t\tcredential?: OAuthCredential;\n\t\tsignal?: AbortSignal;\n\t}): Promise<AuthCheck | undefined>;\n\tlogin(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials>;\n\trefreshToken(credentials: OAuthCredentials, signal: AbortSignal): Promise<OAuthCredentials>;\n\tgetApiKey(credentials: OAuthCredentials): string;\n};\n\nexport type LocalCursorImportDeps = {\n\tplatform?: NodeJS.Platform;\n\treadCursorFile?: () => Promise<ImportedCursorCredential | undefined>;\n\treadCursorKeychain?: () => Promise<ImportedCursorCredential | undefined>;\n\tonPrompt?: OAuthLoginCallbacks[\"onPrompt\"];\n};\n\ntype ConfigurationAssessment = {\n\taccounts: CursorCliAccountSlot[];\n\tmessage: string;\n};\n\n/** The single condition evaluation behind both the tolerant `check` and the throwing turn-time resolution. */\ntype ConfigurationOutcome =\n\t| { status: \"disabled\" }\n\t| { status: \"not-installed\"; error: unknown }\n\t| { status: \"no-accounts\" }\n\t| { status: \"configured\"; assessment: ConfigurationAssessment };\n\n/**\n * One predicate so availability and resolution cannot disagree: evaluates the\n * same conditions for every caller and reports why the lane is unusable\n * instead of deciding per call-site whether that is fatal.\n */\nasync function assessConfiguration(deps: CursorCliOauthConfigDeps): Promise<ConfigurationOutcome> {\n\tconst settings = deps.readSettings();\n\tif (!settings.enabled) return { status: \"disabled\" };\n\ttry {\n\t\tdeps.resolveExecutable(settings);\n\t} catch (error) {\n\t\treturn { status: \"not-installed\", error };\n\t}\n\n\tconst accounts = usableAccounts(await deps.readCurrent());\n\tif (accounts.length === 0) return { status: \"no-accounts\" };\n\treturn {\n\t\tstatus: \"configured\",\n\t\tassessment: { accounts, message: `configured (file-store, ${accounts.length} accounts)` },\n\t};\n}\n\n/** The throwing view used by turn-time resolution; a turn attempted on an unusable lane must still error clearly. */\nasync function configuredFor(deps: CursorCliOauthConfigDeps): Promise<ConfigurationAssessment> {\n\tconst outcome = await assessConfiguration(deps);\n\tswitch (outcome.status) {\n\t\tcase \"disabled\":\n\t\t\tthrow new Error(DISABLED_MESSAGE);\n\t\tcase \"not-installed\":\n\t\t\tthrow cursorAgentNotInstalledError(outcome.error);\n\t\tcase \"no-accounts\":\n\t\t\tthrow new Error(NO_ACCOUNTS_MESSAGE);\n\t\tdefault:\n\t\t\treturn outcome.assessment;\n\t}\n}\n\nfunction isCursorCliOauthCredential(\n\tvalue: Credential | OAuthCredentials | undefined,\n): value is CursorCliOauthCredential {\n\tif (typeof value !== \"object\" || value === null) return false;\n\tconst candidate = value as Partial<CursorCliOauthCredential>;\n\treturn candidate.type === \"oauth\" && Array.isArray(candidate.accounts);\n}\n\nfunction usableAccounts(value: Credential | OAuthCredentials | undefined): CursorCliAccountSlot[] {\n\tif (!isCursorCliOauthCredential(value)) return [];\n\treturn listAccounts(value).filter(\n\t\t(slot) =>\n\t\t\ttypeof slot.name === \"string\" &&\n\t\t\ttypeof slot.access === \"string\" &&\n\t\t\tslot.access.trim().length > 0 &&\n\t\t\ttypeof slot.refresh === \"string\" &&\n\t\t\tslot.refresh.trim().length > 0 &&\n\t\t\ttypeof slot.expires === \"number\" &&\n\t\t\tNumber.isFinite(slot.expires),\n\t);\n}\n\nfunction installationMessage(error: unknown): string {\n\tconst detail = error instanceof Error ? error.message : String(error);\n\treturn `cursor-agent not installed: ${detail.replace(/^Cursor CLI is not installed\\.\\s*/, \"\")}`;\n}\n\n/**\n * The typed turn-path error for a missing cursor-agent binary: carries the\n * `cursor-agent not installed` marker plus the install guidance verbatim, with\n * the underlying resolution failure preserved as `cause`.\n */\nexport function cursorAgentNotInstalledError(cause: unknown): Error {\n\tconst error = new Error(installationMessage(cause));\n\terror.name = \"CursorAgentNotInstalledError\";\n\terror.cause = cause;\n\treturn error;\n}\n\n/** Resolve credentials immediately before execution so a concurrent refresh cannot leave a stale token in memory. */\nexport async function resolveCursorCliOauthLane(deps: CursorCliOauthConfigDeps): Promise<CursorCliOauthLaneResolution> {\n\tconst assessment = await configuredFor(deps);\n\tconst account = assessment.accounts[0];\n\tif (!account) throw new Error(NO_ACCOUNTS_MESSAGE);\n\treturn { lane: FILE_STORE_LANE, account, accounts: assessment.accounts };\n}\n\nasync function loadCursorOAuthFlow(): Promise<OAuthAuth> {\n\tconst flow = cursorProvider().auth.oauth;\n\tif (!flow) throw new Error(\"Cursor OAuth flow is unavailable\");\n\treturn flow;\n}\n\nfunction providerInteraction(callbacks: OAuthLoginCallbacks): ProviderAuthInteraction {\n\treturn {\n\t\tsignal: callbacks.signal ?? new AbortController().signal,\n\t\tprompt: async (prompt) => {\n\t\t\tswitch (prompt.type) {\n\t\t\t\tcase \"select\":\n\t\t\t\t\treturn (await callbacks.onSelect(prompt)) ?? \"\";\n\t\t\t\tcase \"manual_code\":\n\t\t\t\t\treturn callbacks.onManualCodeInput?.() ?? callbacks.onPrompt(prompt);\n\t\t\t\tdefault:\n\t\t\t\t\treturn callbacks.onPrompt(prompt);\n\t\t\t}\n\t\t},\n\t\tnotify: (event) => {\n\t\t\tswitch (event.type) {\n\t\t\t\tcase \"auth_url\":\n\t\t\t\t\tcallbacks.onAuth({ url: event.url, instructions: event.instructions });\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"device_code\":\n\t\t\t\t\tcallbacks.onDeviceCode(event);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"progress\":\n\t\t\t\t\tcallbacks.onProgress?.(event.message);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"info\":\n\t\t\t\t\tcallbacks.onProgress?.(event.message);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t},\n\t};\n}\n\nasync function accountName(\n\texisting: CursorCliAccountSlot[],\n\tonPrompt: OAuthLoginCallbacks[\"onPrompt\"] | undefined,\n): Promise<string> {\n\tif (existing.length === 0) return \"default\";\n\tconst fallback = `account-${existing.length + 1}`;\n\tif (!onPrompt) return fallback;\n\tconst answer = (\n\t\tawait onPrompt({\n\t\t\tmessage: `Name for this account (existing: ${existing.map((slot) => slot.name).join(\", \")})`,\n\t\t\tplaceholder: fallback,\n\t\t})\n\t).trim();\n\treturn answer || fallback;\n}\n\nfunction slotFromCredential(\n\tcredential: Pick<OAuthCredentials, \"access\" | \"refresh\" | \"expires\">,\n\tname: string,\n\tsource: CursorCliAccountSlot[\"source\"],\n): CursorCliAccountSlot {\n\treturn {\n\t\tname,\n\t\taccess: credential.access,\n\t\trefresh: credential.refresh,\n\t\texpires: credential.expires,\n\t\tsource,\n\t};\n}\n\n/** The one-screen login explanation: what unattended Cursor CLI execution gives up, and the plan-mode alternative. */\nexport const CURSOR_CLI_OAUTH_LOGIN_ACKNOWLEDGEMENT_EXPLANATION = `${CURSOR_CLI_OAUTH_NO_APPROVAL_EXPLANATION} Plan mode (planning only, no tool execution) is available via the executionMode setting.`;\n\nconst ACKNOWLEDGEMENT_ACCEPTANCE = new Set([\"yes\", \"y\"]);\n\n/**\n * Present the no-approval explanation exactly once and return the ISO\n * acknowledgement timestamp on explicit confirmation, undefined otherwise.\n * Shared by the login flow and the /cursor-account acknowledge subcommand so\n * both surfaces present the identical explanation and persist identically.\n */\nexport async function confirmCursorCliNoApprovalAcknowledgement(\n\tonPrompt: ((prompt: { message: string; placeholder?: string }) => Promise<string>) | undefined,\n\tnow: () => Date,\n): Promise<string | undefined> {\n\tif (!onPrompt) return undefined;\n\tconst answer = (\n\t\tawait onPrompt({\n\t\t\tmessage: `${CURSOR_CLI_OAUTH_LOGIN_ACKNOWLEDGEMENT_EXPLANATION}\\nType \"yes\" to acknowledge and allow unattended Cursor CLI tool execution; anything else leaves it off.`,\n\t\t})\n\t)\n\t\t.trim()\n\t\t.toLowerCase();\n\treturn ACKNOWLEDGEMENT_ACCEPTANCE.has(answer) ? now().toISOString() : undefined;\n}\n\nexport function createCursorCliOauthConfig(deps: CursorCliOauthConfigDeps): CursorCliOauthConfig {\n\treturn {\n\t\tname: CURSOR_CLI_OAUTH_NAME,\n\t\tisSubscription: true,\n\n\t\tasync check(input) {\n\t\t\t// Tolerant by contract: ModelsImpl.getAvailable runs every provider's\n\t\t\t// check under Promise.all (packages/ai/src/models.ts:544-548) and turns a\n\t\t\t// throw into a rejecting ModelsError, so one throwing check would reject\n\t\t\t// all model listing. Not usable (disabled / not installed / no accounts)\n\t\t\t// reports undefined here - as claude-sdk-oauth's check does - while\n\t\t\t// turn-time resolution keeps throwing via configuredFor.\n\t\t\t//\n\t\t\t// One nuance: the auth-resolution path (checkAuth, resolveStoredOAuth)\n\t\t\t// always passes the stored credential, while bare model listing does not.\n\t\t\t// A credential-backed lane whose executable is missing stays selectable\n\t\t\t// with the install guidance as its source, so a TURN reaches\n\t\t\t// streamCursorCliOauth, which throws the typed not-installed error;\n\t\t\t// without a credential the lane hides exactly as before.\n\t\t\tconst outcome = await assessConfiguration(deps);\n\t\t\tif (outcome.status === \"disabled\" || outcome.status === \"no-accounts\") return undefined;\n\t\t\tif (outcome.status === \"not-installed\") {\n\t\t\t\treturn input.credential === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: { type: \"oauth\", source: installationMessage(outcome.error) };\n\t\t\t}\n\t\t\treturn { type: \"oauth\", source: outcome.assessment.message };\n\t\t},\n\n\t\tasync login(callbacks) {\n\t\t\tconst stored = await deps.readCurrent();\n\t\t\tconst current = isCursorCliOauthCredential(stored) ? stored : emptyCredential();\n\t\t\tconst existing = listAccounts(current);\n\t\t\tconst flow = await (deps.loadOAuth ?? loadCursorOAuthFlow)();\n\t\t\tconst loggedIn = await flow.login(providerInteraction(callbacks));\n\t\t\tconst name = await accountName(existing, callbacks.onPrompt);\n\t\t\t// After the PKCE flow succeeds and before the slot is stored: the\n\t\t\t// one-screen no-approval explanation, confirmed once. Declining still\n\t\t\t// stores the slot; only the acknowledgement stays unset, so force turns\n\t\t\t// refuse until the user acknowledges later.\n\t\t\tconst acknowledgedAt = await confirmCursorCliNoApprovalAcknowledgement(\n\t\t\t\tcallbacks.onPrompt,\n\t\t\t\tdeps.now ?? (() => new Date()),\n\t\t\t);\n\t\t\tif (acknowledgedAt !== undefined) deps.persistAcknowledgement?.(acknowledgedAt);\n\t\t\tconst credential = addAccount(current, slotFromCredential(loggedIn, name, \"login\"));\n\t\t\tdeps.persistEnabled?.(true);\n\t\t\treturn credential;\n\t\t},\n\n\t\tasync refreshToken(credentials, signal) {\n\t\t\tif (!isCursorCliOauthCredential(credentials)) return credentials;\n\t\t\tconst flow = await (deps.loadOAuth ?? loadCursorOAuthFlow)();\n\t\t\tconst accounts: CursorCliAccountSlot[] = [];\n\t\t\tfor (const slot of listAccounts(credentials)) {\n\t\t\t\tif (Date.now() < slot.expires) {\n\t\t\t\t\taccounts.push(slot);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst refreshed = await flow.refresh(\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"oauth\",\n\t\t\t\t\t\taccess: slot.access,\n\t\t\t\t\t\trefresh: slot.refresh,\n\t\t\t\t\t\texpires: slot.expires,\n\t\t\t\t\t},\n\t\t\t\t\tsignal,\n\t\t\t\t);\n\t\t\t\taccounts.push({\n\t\t\t\t\t...slot,\n\t\t\t\t\taccess: refreshed.access,\n\t\t\t\t\trefresh: refreshed.refresh,\n\t\t\t\t\texpires: refreshed.expires,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { ...credentials, ...SENTINEL_OAUTH_FIELDS, accounts };\n\t\t},\n\n\t\tgetApiKey() {\n\t\t\treturn SENTINEL_OAUTH_FIELDS.access;\n\t\t},\n\t};\n}\n\nfunction execFileOutput(file: string, args: string[]): Promise<string | undefined> {\n\treturn new Promise((resolve) => {\n\t\tnodeExecFile(file, args, { encoding: \"utf8\" }, (error, stdout) => {\n\t\t\tif (error) {\n\t\t\t\tresolve(undefined);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst value = stdout.trim();\n\t\t\tresolve(value.length > 0 ? value : undefined);\n\t\t});\n\t});\n}\n\nasync function defaultKeychainCredential(): Promise<ImportedCursorCredential | undefined> {\n\tif (process.platform !== \"darwin\") return undefined;\n\tconst [access, refresh] = await Promise.all([\n\t\texecFileOutput(\"security\", [\"find-generic-password\", \"-a\", \"cursor-user\", \"-s\", \"cursor-access-token\", \"-w\"]),\n\t\texecFileOutput(\"security\", [\"find-generic-password\", \"-a\", \"cursor-user\", \"-s\", \"cursor-refresh-token\", \"-w\"]),\n\t]);\n\treturn access && refresh ? { access, refresh } : undefined;\n}\n\nfunction localCursorAuthPath(platform: NodeJS.Platform): string | undefined {\n\tswitch (platform) {\n\t\tcase \"darwin\":\n\t\t\treturn join(homedir(), \".cursor\", \"auth.json\");\n\t\tcase \"linux\":\n\t\t\treturn join(process.env.XDG_CONFIG_HOME ?? join(homedir(), \".config\"), \"cursor\", \"auth.json\");\n\t\tcase \"win32\": {\n\t\t\tconst appData = process.env.APPDATA;\n\t\t\treturn appData ? join(appData, \"Cursor\", \"auth.json\") : undefined;\n\t\t}\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n\nasync function defaultFileCredential(platform: NodeJS.Platform): Promise<ImportedCursorCredential | undefined> {\n\tconst path = localCursorAuthPath(platform);\n\tif (!path) return undefined;\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(await nodeReadFile(path, \"utf8\"));\n\t\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) return undefined;\n\t\tconst record = parsed as Record<string, unknown>;\n\t\tconst access = record.accessToken;\n\t\tconst refresh = record.refreshToken;\n\t\tif (typeof access !== \"string\" || access.length === 0 || typeof refresh !== \"string\" || refresh.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn { access, refresh };\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/** Explicitly copy the user's local Cursor credential into this provider's managed account slots. */\nexport async function importLocalCursorCredential(\n\tcurrent: CursorCliOauthCredential,\n\tdeps: LocalCursorImportDeps = {},\n): Promise<CursorCliOauthCredential> {\n\tconst platform = deps.platform ?? process.platform;\n\tconst readKeychain = deps.readCursorKeychain ?? defaultKeychainCredential;\n\tconst readFile = deps.readCursorFile ?? (() => defaultFileCredential(platform));\n\tconst imported = platform === \"darwin\" ? ((await readKeychain()) ?? (await readFile())) : await readFile();\n\tif (!imported) throw new Error(\"No local Cursor OAuth credential found\");\n\tconst existing = listAccounts(current);\n\tconst name = await accountName(existing, deps.onPrompt);\n\treturn addAccount(\n\t\tcurrent,\n\t\tslotFromCredential(\n\t\t\t{\n\t\t\t\taccess: imported.access,\n\t\t\t\trefresh: imported.refresh,\n\t\t\t\texpires: imported.expires ?? Date.now() + DEFAULT_IMPORTED_EXPIRY_MS,\n\t\t\t},\n\t\t\tname,\n\t\t\t\"import\",\n\t\t),\n\t);\n}\n\nfunction isUsableFlatOAuthCredential(value: Credential | undefined): value is OAuthCredential {\n\treturn (\n\t\tvalue?.type === \"oauth\" &&\n\t\ttypeof value.access === \"string\" &&\n\t\tvalue.access.length > 0 &&\n\t\ttypeof value.refresh === \"string\" &&\n\t\tvalue.refresh.length > 0 &&\n\t\ttypeof value.expires === \"number\" &&\n\t\tNumber.isFinite(value.expires)\n\t);\n}\n\nfunction nativeAccountName(existing: readonly CursorCliAccountSlot[]): string {\n\tconst names = new Set(existing.map((account) => account.name));\n\tif (!names.has(\"native\")) return \"native\";\n\tfor (let index = 2; index <= 10_000; index++) {\n\t\tconst candidate = `native-${index}`;\n\t\tif (!names.has(candidate)) return candidate;\n\t}\n\tthrow new Error(\"Could not allocate a Cursor CLI OAuth native account name\");\n}\n\n/** Explicitly copy Senpi's native `cursor` OAuth credential into a managed CLI account slot. */\nexport async function importNativeCursorCredential(\n\tcurrent: CursorCliOauthCredential,\n\treadNativeCredential: () => Credential | undefined | Promise<Credential | undefined>,\n): Promise<CursorCliOauthCredential> {\n\tconst native = await readNativeCredential();\n\tif (!isUsableFlatOAuthCredential(native)) {\n\t\tthrow new Error(\"No stored native Cursor OAuth credential found\");\n\t}\n\treturn addAccount(current, slotFromCredential(native, nativeAccountName(listAccounts(current)), \"import\"));\n}\n\nexport function defaultCursorCliOauthConfig(\n\tcwd: string,\n\treadCurrent: () => Promise<Credential | undefined>,\n): CursorCliOauthConfig {\n\treturn createCursorCliOauthConfig({\n\t\treadCurrent,\n\t\treadSettings: () => loadCursorCliOauthProviderSettingsFromDisk(cwd),\n\t\tresolveExecutable: (settings) => {\n\t\t\tconst executableDeps: CursorAgentExecutableDeps = {\n\t\t\t\t...defaultCursorAgentExecutableDeps(),\n\t\t\t\tsettings,\n\t\t\t};\n\t\t\treturn resolveCursorAgentExecutable(executableDeps);\n\t\t},\n\t\tnow: () => new Date(),\n\t\tpersistAcknowledgement: (acknowledgedAt: string) =>\n\t\t\tpersistCursorCliNoApprovalAcknowledgement(cwd, acknowledgedAt),\n\t\tpersistEnabled: (enabled: boolean) => persistCursorCliOauthEnabled(cwd, enabled),\n\t});\n}\n"]}
|
|
@@ -24,6 +24,8 @@ export declare function parseCursorCliOauthProviderSettings(value: unknown, envi
|
|
|
24
24
|
export declare function createCursorCliOauthSandboxModeValidator(acceptedModes: ReadonlySet<string>, onWarning: (message: string) => void): (value: string | undefined) => string | undefined;
|
|
25
25
|
/** Load global and project settings afresh, with env values taking final precedence. */
|
|
26
26
|
export declare function loadCursorCliOauthProviderSettingsFromDisk(cwd: string): CursorCliOauthProviderSettings;
|
|
27
|
+
/** Persist explicit provider activation while preserving every sibling setting. */
|
|
28
|
+
export declare function persistCursorCliOauthEnabled(cwd: string, enabled: boolean): void;
|
|
27
29
|
/**
|
|
28
30
|
* Read-modify-write `noApprovalAcknowledgedAt` into the provider block of the
|
|
29
31
|
* global settings file, preserving every other key. An unparseable file is
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/cursor-cli-oauth/settings.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,2BAA2B,GAAG,OAAO,GAAG,MAAM,CAAC;AAC3D,MAAM,MAAM,wBAAwB,GAAG,MAAM,GAAG,KAAK,CAAC;AAEtD,MAAM,WAAW,8BAA8B;IAC9C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,wBAAwB,EAAE,MAAM,GAAG,SAAS,CAAC;IACtD,QAAQ,CAAC,aAAa,EAAE,2BAA2B,CAAC;IACpD,QAAQ,CAAC,UAAU,EAAE,wBAAwB,CAAC;IAC9C,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,yBAAyB,EAAE,OAAO,CAAC;IAC5C,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,gFAAgF;IAChF,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAMD,KAAK,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;AAmJhE,mFAAmF;AACnF,wBAAgB,mCAAmC,CAClD,KAAK,EAAE,OAAO,EACd,WAAW,EAAE,WAAW,GACtB,8BAA8B,CAEhC;AAED;;;GAGG;AACH,wBAAgB,wCAAwC,CACvD,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,EAClC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAClC,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,MAAM,GAAG,SAAS,CAUnD;AAED,wFAAwF;AACxF,wBAAgB,0CAA0C,CAAC,GAAG,EAAE,MAAM,GAAG,8BAA8B,CAStG;AAED;;;;;GAKG;AACH,wBAAgB,yCAAyC,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/cursor-cli-oauth/settings.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,2BAA2B,GAAG,OAAO,GAAG,MAAM,CAAC;AAC3D,MAAM,MAAM,wBAAwB,GAAG,MAAM,GAAG,KAAK,CAAC;AAEtD,MAAM,WAAW,8BAA8B;IAC9C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,wBAAwB,EAAE,MAAM,GAAG,SAAS,CAAC;IACtD,QAAQ,CAAC,aAAa,EAAE,2BAA2B,CAAC;IACpD,QAAQ,CAAC,UAAU,EAAE,wBAAwB,CAAC;IAC9C,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,yBAAyB,EAAE,OAAO,CAAC;IAC5C,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,gFAAgF;IAChF,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAMD,KAAK,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;AAmJhE,mFAAmF;AACnF,wBAAgB,mCAAmC,CAClD,KAAK,EAAE,OAAO,EACd,WAAW,EAAE,WAAW,GACtB,8BAA8B,CAEhC;AAED;;;GAGG;AACH,wBAAgB,wCAAwC,CACvD,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,EAClC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAClC,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,MAAM,GAAG,SAAS,CAUnD;AAED,wFAAwF;AACxF,wBAAgB,0CAA0C,CAAC,GAAG,EAAE,MAAM,GAAG,8BAA8B,CAStG;AA4BD,mFAAmF;AACnF,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAEhF;AAED;;;;;GAKG;AACH,wBAAgB,yCAAyC,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,CAKnG"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getAgentDir } from "../../../../config.js";
|
|
2
2
|
import { FileSettingsStorage, parseSettingsJson, SettingsManager } from "../../../settings-manager.js";
|
|
3
3
|
const DEFAULT_SETTINGS = {
|
|
4
|
-
enabled:
|
|
4
|
+
enabled: true,
|
|
5
5
|
executablePath: undefined,
|
|
6
6
|
forceExecution: true,
|
|
7
7
|
noApprovalAcknowledgedAt: undefined,
|
|
@@ -158,13 +158,7 @@ export function loadCursorCliOauthProviderSettingsFromDisk(cwd) {
|
|
|
158
158
|
const project = settingsManager.getProjectSettings();
|
|
159
159
|
return resolveSettings(parseProviderSettings(global.cursorCliOauthProvider), parseProviderSettings(project.cursorCliOauthProvider), parseEnvironmentSettings(process.env));
|
|
160
160
|
}
|
|
161
|
-
|
|
162
|
-
* Read-modify-write `noApprovalAcknowledgedAt` into the provider block of the
|
|
163
|
-
* global settings file, preserving every other key. An unparseable file is
|
|
164
|
-
* reported instead of silently clobbered, so an acknowledgement can never
|
|
165
|
-
* claim success while leaving the settings unwritten.
|
|
166
|
-
*/
|
|
167
|
-
export function persistCursorCliNoApprovalAcknowledgement(cwd, acknowledgedAt) {
|
|
161
|
+
function persistCursorCliOauthProviderPatch(cwd, action, patch) {
|
|
168
162
|
const storage = new FileSettingsStorage(cwd, getAgentDir());
|
|
169
163
|
storage.selectSource("global");
|
|
170
164
|
storage.withLock("global", (current) => {
|
|
@@ -173,14 +167,30 @@ export function persistCursorCliNoApprovalAcknowledgement(cwd, acknowledgedAt) {
|
|
|
173
167
|
root = current === undefined ? {} : parseSettingsJson(current);
|
|
174
168
|
}
|
|
175
169
|
catch (error) {
|
|
176
|
-
throw new Error(`Cannot persist the cursor-cli-oauth
|
|
170
|
+
throw new Error(`Cannot persist the cursor-cli-oauth ${action}: the settings file is unparseable (${error instanceof Error ? error.message : String(error)})`);
|
|
177
171
|
}
|
|
178
172
|
const provider = typeof root.cursorCliOauthProvider === "object" &&
|
|
179
173
|
root.cursorCliOauthProvider !== null &&
|
|
180
174
|
!Array.isArray(root.cursorCliOauthProvider)
|
|
181
175
|
? { ...root.cursorCliOauthProvider }
|
|
182
176
|
: {};
|
|
183
|
-
return JSON.stringify({ ...root, cursorCliOauthProvider: { ...provider,
|
|
177
|
+
return JSON.stringify({ ...root, cursorCliOauthProvider: { ...provider, ...patch } }, null, 2);
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
/** Persist explicit provider activation while preserving every sibling setting. */
|
|
181
|
+
export function persistCursorCliOauthEnabled(cwd, enabled) {
|
|
182
|
+
persistCursorCliOauthProviderPatch(cwd, "enabled state", { enabled });
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Read-modify-write `noApprovalAcknowledgedAt` into the provider block of the
|
|
186
|
+
* global settings file, preserving every other key. An unparseable file is
|
|
187
|
+
* reported instead of silently clobbered, so an acknowledgement can never
|
|
188
|
+
* claim success while leaving the settings unwritten.
|
|
189
|
+
*/
|
|
190
|
+
export function persistCursorCliNoApprovalAcknowledgement(cwd, acknowledgedAt) {
|
|
191
|
+
persistCursorCliOauthProviderPatch(cwd, "acknowledgement", {
|
|
192
|
+
enabled: true,
|
|
193
|
+
noApprovalAcknowledgedAt: acknowledgedAt,
|
|
184
194
|
});
|
|
185
195
|
}
|
|
186
196
|
//# sourceMappingURL=settings.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/cursor-cli-oauth/settings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAiB,eAAe,EAAE,MAAM,8BAA8B,CAAC;AA2BtH,MAAM,gBAAgB,GAAmC;IACxD,OAAO,EAAE,KAAK;IACd,cAAc,EAAE,SAAS;IACzB,cAAc,EAAE,IAAI;IACpB,wBAAwB,EAAE,SAAS;IACnC,aAAa,EAAE,OAAO;IACtB,UAAU,EAAE,MAAM;IAClB,aAAa,EAAE,SAAS;IACxB,yBAAyB,EAAE,IAAI;IAC/B,oBAAoB,EAAE,EAAE;IACxB,WAAW,EAAE,SAAS;IACtB,YAAY,EAAE,EAAE;CAChB,CAAC;AAEF,SAAS,QAAQ,CAAC,KAAc;IAC/B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC7E,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IACnC,OAAO,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACvD,CAAC;AAED,SAAS,uBAAuB,CAAC,KAAyB;IACzD,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1C,QAAQ,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;QAC7B,KAAK,GAAG,CAAC;QACT,KAAK,MAAM;YACV,OAAO,IAAI,CAAC;QACb,KAAK,GAAG,CAAC;QACT,KAAK,OAAO;YACX,OAAO,KAAK,CAAC;QACd;YACC,OAAO,SAAS,CAAC;IACnB,CAAC;AACF,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAc;IAC1C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1E,CAAC;AAED,iGAAiG;AACjG,SAAS,iBAAiB,CAAC,KAAc;IACxC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC5C,OAAO,KAAK;SACV,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC;SAC7D,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;SAC5B,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED,+FAA+F;AAC/F,SAAS,4BAA4B,CAAC,KAAyB;IAC9D,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAChE,OAAO,KAAK;SACV,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;SAC5B,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,cAAc,CAAC,KAAc;IACrC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,oDAAoD,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACpG,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC;AAC5D,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAc;IACzC,OAAO,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAClE,CAAC;AAED,SAAS,eAAe,CAAC,KAAc;IACtC,OAAO,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAChE,CAAC;AAED,SAAS,yBAAyB,CAAC,KAAc;IAChD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7F,CAAC;AAED,SAAS,oCAAoC,CAAC,KAAyB;IACtE,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAChE,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AACnE,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAc;IAC5C,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAChC,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC5C,MAAM,cAAc,GAAG,mBAAmB,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IACjE,MAAM,cAAc,GAAG,YAAY,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAC1D,MAAM,wBAAwB,GAAG,cAAc,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAChF,MAAM,aAAa,GAAG,kBAAkB,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IAC9D,MAAM,UAAU,GAAG,eAAe,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACrD,MAAM,aAAa,GAAG,mBAAmB,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IAC/D,MAAM,yBAAyB,GAAG,YAAY,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAChF,MAAM,oBAAoB,GAAG,yBAAyB,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;IACnF,MAAM,WAAW,GAAG,mBAAmB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAC3D,MAAM,YAAY,GAAG,iBAAiB,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IAC3D,OAAO;QACN,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7C,GAAG,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3D,GAAG,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3D,GAAG,CAAC,wBAAwB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,wBAAwB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/E,GAAG,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnD,GAAG,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,GAAG,CAAC,yBAAyB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,yBAAyB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjF,GAAG,CAAC,oBAAoB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,oBAAoB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrD,GAAG,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACvD,CAAC;AACH,CAAC;AAED,SAAS,wBAAwB,CAAC,WAAwB;IACzD,MAAM,cAAc,GACnB,mBAAmB,CAAC,WAAW,CAAC,iCAAiC,CAAC;QAClE,mBAAmB,CAAC,WAAW,CAAC,uBAAuB,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG,uBAAuB,CAAC,WAAW,CAAC,8BAA8B,CAAC,CAAC;IACpF,MAAM,cAAc,GAAG,uBAAuB,CAAC,WAAW,CAAC,4BAA4B,CAAC,CAAC;IACzF,MAAM,aAAa,GAAG,kBAAkB,CAAC,WAAW,CAAC,qCAAqC,CAAC,CAAC;IAC5F,MAAM,UAAU,GAAG,eAAe,CAAC,WAAW,CAAC,6BAA6B,CAAC,CAAC;IAC9E,MAAM,aAAa,GAAG,mBAAmB,CAAC,WAAW,CAAC,qCAAqC,CAAC,CAAC;IAC7F,MAAM,yBAAyB,GAAG,uBAAuB,CAAC,WAAW,CAAC,4BAA4B,CAAC,CAAC;IACpG,MAAM,oBAAoB,GAAG,oCAAoC,CAChE,WAAW,CAAC,8CAA8C,CAC1D,CAAC;IACF,MAAM,WAAW,GAAG,mBAAmB,CAAC,WAAW,CAAC,mCAAmC,CAAC,CAAC;IACzF,MAAM,YAAY,GAAG,4BAA4B,CAAC,WAAW,CAAC,oCAAoC,CAAC,CAAC;IACpG,OAAO;QACN,GAAG,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3D,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7C,GAAG,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3D,GAAG,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnD,GAAG,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,GAAG,CAAC,yBAAyB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,yBAAyB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjF,GAAG,CAAC,oBAAoB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,oBAAoB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrD,GAAG,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACvD,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,GAAG,MAAiC;IAC5D,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAAC,CAAC;AACvD,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,mCAAmC,CAClD,KAAc,EACd,WAAwB;IAExB,OAAO,eAAe,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAAE,wBAAwB,CAAC,WAAW,CAAC,CAAC,CAAC;AAC7F,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,wCAAwC,CACvD,aAAkC,EAClC,SAAoC;IAEpC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IACtC,OAAO,CAAC,KAAK,EAAE,EAAE;QAChB,IAAI,KAAK,KAAK,SAAS,IAAI,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QAClE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7B,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACvB,SAAS,CAAC,wDAAwD,KAAK,EAAE,CAAC,CAAC;QAC5E,CAAC;QACD,OAAO,SAAS,CAAC;IAClB,CAAC,CAAC;AACH,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,0CAA0C,CAAC,GAAW;IACrE,MAAM,eAAe,GAAG,eAAe,CAAC,MAAM,CAAC,GAAG,EAAE,WAAW,EAAE,CAAC,CAAC;IACnE,MAAM,MAAM,GAAG,eAAe,CAAC,iBAAiB,EAAwC,CAAC;IACzF,MAAM,OAAO,GAAG,eAAe,CAAC,kBAAkB,EAAwC,CAAC;IAC3F,OAAO,eAAe,CACrB,qBAAqB,CAAC,MAAM,CAAC,sBAAsB,CAAC,EACpD,qBAAqB,CAAC,OAAO,CAAC,sBAAsB,CAAC,EACrD,wBAAwB,CAAC,OAAO,CAAC,GAAG,CAAC,CACrC,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,yCAAyC,CAAC,GAAW,EAAE,cAAsB;IAC5F,MAAM,OAAO,GAAG,IAAI,mBAAmB,CAAC,GAAG,EAAE,WAAW,EAAE,CAAC,CAAC;IAC5D,OAAO,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC/B,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE;QACtC,IAAI,IAA6B,CAAC;QAClC,IAAI,CAAC;YACJ,IAAI,GAAG,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAChE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CACd,0FAA0F,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CACnJ,CAAC;QACH,CAAC;QACD,MAAM,QAAQ,GACb,OAAO,IAAI,CAAC,sBAAsB,KAAK,QAAQ;YAC/C,IAAI,CAAC,sBAAsB,KAAK,IAAI;YACpC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,sBAAsB,CAAC;YAC1C,CAAC,CAAC,EAAE,GAAI,IAAI,CAAC,sBAAkD,EAAE;YACjE,CAAC,CAAC,EAAE,CAAC;QACP,OAAO,IAAI,CAAC,SAAS,CACpB,EAAE,GAAG,IAAI,EAAE,sBAAsB,EAAE,EAAE,GAAG,QAAQ,EAAE,wBAAwB,EAAE,cAAc,EAAE,EAAE,EAC9F,IAAI,EACJ,CAAC,CACD,CAAC;IACH,CAAC,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { getAgentDir } from \"../../../../config.ts\";\nimport { FileSettingsStorage, parseSettingsJson, type Settings, SettingsManager } from \"../../../settings-manager.ts\";\n\nexport type CursorCliOauthExecutionMode = \"agent\" | \"plan\";\nexport type CursorCliOauthResumeMode = \"auto\" | \"off\";\n\nexport interface CursorCliOauthProviderSettings {\n\treadonly enabled: boolean;\n\treadonly executablePath: string | undefined;\n\treadonly forceExecution: boolean;\n\treadonly noApprovalAcknowledgedAt: string | undefined;\n\treadonly executionMode: CursorCliOauthExecutionMode;\n\treadonly resumeMode: CursorCliOauthResumeMode;\n\treadonly pinnedAccount: string | undefined;\n\treadonly contextRecapOnModelSwitch: boolean;\n\treadonly modelCatalogTtlHours: number;\n\treadonly sandboxMode: string | undefined;\n\t/** Exact full commands the spawned CLI must refuse; globs are not supported. */\n\treadonly denyCommands?: string[];\n}\n\ntype SettingsWithCursorCliOauthProvider = Settings & {\n\tcursorCliOauthProvider?: unknown;\n};\n\ntype Environment = Readonly<Record<string, string | undefined>>;\ntype ParsedSettings = Partial<CursorCliOauthProviderSettings>;\n\nconst DEFAULT_SETTINGS: CursorCliOauthProviderSettings = {\n\tenabled: false,\n\texecutablePath: undefined,\n\tforceExecution: true,\n\tnoApprovalAcknowledgedAt: undefined,\n\texecutionMode: \"agent\",\n\tresumeMode: \"auto\",\n\tpinnedAccount: undefined,\n\tcontextRecapOnModelSwitch: true,\n\tmodelCatalogTtlHours: 24,\n\tsandboxMode: undefined,\n\tdenyCommands: [],\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction parseBoolean(value: unknown): boolean | undefined {\n\treturn typeof value === \"boolean\" ? value : undefined;\n}\n\nfunction parseEnvironmentBoolean(value: string | undefined): boolean | undefined {\n\tif (value === undefined) return undefined;\n\tswitch (value.toLowerCase()) {\n\t\tcase \"1\":\n\t\tcase \"true\":\n\t\t\treturn true;\n\t\tcase \"0\":\n\t\tcase \"false\":\n\t\t\treturn false;\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n\nfunction parseNonEmptyString(value: unknown): string | undefined {\n\treturn typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\n/** Exact full commands only: string entries are trimmed, non-strings and empties are dropped. */\nfunction parseDenyCommands(value: unknown): string[] | undefined {\n\tif (!Array.isArray(value)) return undefined;\n\treturn value\n\t\t.filter((entry): entry is string => typeof entry === \"string\")\n\t\t.map((entry) => entry.trim())\n\t\t.filter((command) => command.length > 0);\n}\n\n/** Comma-separated exact full commands; a missing or empty value leaves settings untouched. */\nfunction parseEnvironmentDenyCommands(value: string | undefined): string[] | undefined {\n\tif (value === undefined || value.length === 0) return undefined;\n\treturn value\n\t\t.split(\",\")\n\t\t.map((entry) => entry.trim())\n\t\t.filter((command) => command.length > 0);\n}\n\nfunction parseIsoString(value: unknown): string | undefined {\n\tif (typeof value !== \"string\" || !/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{3})?Z$/.test(value)) {\n\t\treturn undefined;\n\t}\n\treturn Number.isNaN(Date.parse(value)) ? undefined : value;\n}\n\nfunction parseExecutionMode(value: unknown): CursorCliOauthExecutionMode | undefined {\n\treturn value === \"agent\" || value === \"plan\" ? value : undefined;\n}\n\nfunction parseResumeMode(value: unknown): CursorCliOauthResumeMode | undefined {\n\treturn value === \"auto\" || value === \"off\" ? value : undefined;\n}\n\nfunction parsePositiveFiniteNumber(value: unknown): number | undefined {\n\treturn typeof value === \"number\" && Number.isFinite(value) && value > 0 ? value : undefined;\n}\n\nfunction parseEnvironmentPositiveFiniteNumber(value: string | undefined): number | undefined {\n\tif (value === undefined || value.length === 0) return undefined;\n\tconst parsed = Number(value);\n\treturn Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;\n}\n\nfunction parseProviderSettings(value: unknown): ParsedSettings {\n\tif (!isRecord(value)) return {};\n\tconst enabled = parseBoolean(value.enabled);\n\tconst executablePath = parseNonEmptyString(value.executablePath);\n\tconst forceExecution = parseBoolean(value.forceExecution);\n\tconst noApprovalAcknowledgedAt = parseIsoString(value.noApprovalAcknowledgedAt);\n\tconst executionMode = parseExecutionMode(value.executionMode);\n\tconst resumeMode = parseResumeMode(value.resumeMode);\n\tconst pinnedAccount = parseNonEmptyString(value.pinnedAccount);\n\tconst contextRecapOnModelSwitch = parseBoolean(value.contextRecapOnModelSwitch);\n\tconst modelCatalogTtlHours = parsePositiveFiniteNumber(value.modelCatalogTtlHours);\n\tconst sandboxMode = parseNonEmptyString(value.sandboxMode);\n\tconst denyCommands = parseDenyCommands(value.denyCommands);\n\treturn {\n\t\t...(enabled !== undefined ? { enabled } : {}),\n\t\t...(executablePath !== undefined ? { executablePath } : {}),\n\t\t...(forceExecution !== undefined ? { forceExecution } : {}),\n\t\t...(noApprovalAcknowledgedAt !== undefined ? { noApprovalAcknowledgedAt } : {}),\n\t\t...(executionMode !== undefined ? { executionMode } : {}),\n\t\t...(resumeMode !== undefined ? { resumeMode } : {}),\n\t\t...(pinnedAccount !== undefined ? { pinnedAccount } : {}),\n\t\t...(contextRecapOnModelSwitch !== undefined ? { contextRecapOnModelSwitch } : {}),\n\t\t...(modelCatalogTtlHours !== undefined ? { modelCatalogTtlHours } : {}),\n\t\t...(sandboxMode !== undefined ? { sandboxMode } : {}),\n\t\t...(denyCommands !== undefined ? { denyCommands } : {}),\n\t};\n}\n\nfunction parseEnvironmentSettings(environment: Environment): ParsedSettings {\n\tconst executablePath =\n\t\tparseNonEmptyString(environment.SENPI_CURSOR_CLI_OAUTH_EXECUTABLE) ??\n\t\tparseNonEmptyString(environment.CURSOR_AGENT_EXECUTABLE);\n\tconst enabled = parseEnvironmentBoolean(environment.SENPI_CURSOR_CLI_OAUTH_ENABLED);\n\tconst forceExecution = parseEnvironmentBoolean(environment.SENPI_CURSOR_CLI_OAUTH_FORCE);\n\tconst executionMode = parseExecutionMode(environment.SENPI_CURSOR_CLI_OAUTH_EXECUTION_MODE);\n\tconst resumeMode = parseResumeMode(environment.SENPI_CURSOR_CLI_OAUTH_RESUME);\n\tconst pinnedAccount = parseNonEmptyString(environment.SENPI_CURSOR_CLI_OAUTH_PINNED_ACCOUNT);\n\tconst contextRecapOnModelSwitch = parseEnvironmentBoolean(environment.SENPI_CURSOR_CLI_OAUTH_RECAP);\n\tconst modelCatalogTtlHours = parseEnvironmentPositiveFiniteNumber(\n\t\tenvironment.SENPI_CURSOR_CLI_OAUTH_MODEL_CATALOG_TTL_HOURS,\n\t);\n\tconst sandboxMode = parseNonEmptyString(environment.SENPI_CURSOR_CLI_OAUTH_SANDBOX_MODE);\n\tconst denyCommands = parseEnvironmentDenyCommands(environment.SENPI_CURSOR_CLI_OAUTH_DENY_COMMANDS);\n\treturn {\n\t\t...(executablePath !== undefined ? { executablePath } : {}),\n\t\t...(enabled !== undefined ? { enabled } : {}),\n\t\t...(forceExecution !== undefined ? { forceExecution } : {}),\n\t\t...(executionMode !== undefined ? { executionMode } : {}),\n\t\t...(resumeMode !== undefined ? { resumeMode } : {}),\n\t\t...(pinnedAccount !== undefined ? { pinnedAccount } : {}),\n\t\t...(contextRecapOnModelSwitch !== undefined ? { contextRecapOnModelSwitch } : {}),\n\t\t...(modelCatalogTtlHours !== undefined ? { modelCatalogTtlHours } : {}),\n\t\t...(sandboxMode !== undefined ? { sandboxMode } : {}),\n\t\t...(denyCommands !== undefined ? { denyCommands } : {}),\n\t};\n}\n\nfunction resolveSettings(...layers: readonly ParsedSettings[]): CursorCliOauthProviderSettings {\n\treturn Object.assign({}, DEFAULT_SETTINGS, ...layers);\n}\n\n/** Parse one provider settings block with environment values taking precedence. */\nexport function parseCursorCliOauthProviderSettings(\n\tvalue: unknown,\n\tenvironment: Environment,\n): CursorCliOauthProviderSettings {\n\treturn resolveSettings(parseProviderSettings(value), parseEnvironmentSettings(environment));\n}\n\n/**\n * Build the probe-owned sandbox allowlist validator without hardcoding modes in settings parsing.\n * Each distinct rejected mode is reported once through the supplied warning hook.\n */\nexport function createCursorCliOauthSandboxModeValidator(\n\tacceptedModes: ReadonlySet<string>,\n\tonWarning: (message: string) => void,\n): (value: string | undefined) => string | undefined {\n\tconst warnedModes = new Set<string>();\n\treturn (value) => {\n\t\tif (value === undefined || acceptedModes.has(value)) return value;\n\t\tif (!warnedModes.has(value)) {\n\t\t\twarnedModes.add(value);\n\t\t\tonWarning(`Ignoring unrecognized Cursor CLI OAuth sandbox mode: ${value}`);\n\t\t}\n\t\treturn undefined;\n\t};\n}\n\n/** Load global and project settings afresh, with env values taking final precedence. */\nexport function loadCursorCliOauthProviderSettingsFromDisk(cwd: string): CursorCliOauthProviderSettings {\n\tconst settingsManager = SettingsManager.create(cwd, getAgentDir());\n\tconst global = settingsManager.getGlobalSettings() as SettingsWithCursorCliOauthProvider;\n\tconst project = settingsManager.getProjectSettings() as SettingsWithCursorCliOauthProvider;\n\treturn resolveSettings(\n\t\tparseProviderSettings(global.cursorCliOauthProvider),\n\t\tparseProviderSettings(project.cursorCliOauthProvider),\n\t\tparseEnvironmentSettings(process.env),\n\t);\n}\n\n/**\n * Read-modify-write `noApprovalAcknowledgedAt` into the provider block of the\n * global settings file, preserving every other key. An unparseable file is\n * reported instead of silently clobbered, so an acknowledgement can never\n * claim success while leaving the settings unwritten.\n */\nexport function persistCursorCliNoApprovalAcknowledgement(cwd: string, acknowledgedAt: string): void {\n\tconst storage = new FileSettingsStorage(cwd, getAgentDir());\n\tstorage.selectSource(\"global\");\n\tstorage.withLock(\"global\", (current) => {\n\t\tlet root: Record<string, unknown>;\n\t\ttry {\n\t\t\troot = current === undefined ? {} : parseSettingsJson(current);\n\t\t} catch (error) {\n\t\t\tthrow new Error(\n\t\t\t\t`Cannot persist the cursor-cli-oauth acknowledgement: the settings file is unparseable (${error instanceof Error ? error.message : String(error)})`,\n\t\t\t);\n\t\t}\n\t\tconst provider =\n\t\t\ttypeof root.cursorCliOauthProvider === \"object\" &&\n\t\t\troot.cursorCliOauthProvider !== null &&\n\t\t\t!Array.isArray(root.cursorCliOauthProvider)\n\t\t\t\t? { ...(root.cursorCliOauthProvider as Record<string, unknown>) }\n\t\t\t\t: {};\n\t\treturn JSON.stringify(\n\t\t\t{ ...root, cursorCliOauthProvider: { ...provider, noApprovalAcknowledgedAt: acknowledgedAt } },\n\t\t\tnull,\n\t\t\t2,\n\t\t);\n\t});\n}\n"]}
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/cursor-cli-oauth/settings.ts"],"names":[],"mappings":"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","sourcesContent":["import { getAgentDir } from \"../../../../config.ts\";\nimport { FileSettingsStorage, parseSettingsJson, type Settings, SettingsManager } from \"../../../settings-manager.ts\";\n\nexport type CursorCliOauthExecutionMode = \"agent\" | \"plan\";\nexport type CursorCliOauthResumeMode = \"auto\" | \"off\";\n\nexport interface CursorCliOauthProviderSettings {\n\treadonly enabled: boolean;\n\treadonly executablePath: string | undefined;\n\treadonly forceExecution: boolean;\n\treadonly noApprovalAcknowledgedAt: string | undefined;\n\treadonly executionMode: CursorCliOauthExecutionMode;\n\treadonly resumeMode: CursorCliOauthResumeMode;\n\treadonly pinnedAccount: string | undefined;\n\treadonly contextRecapOnModelSwitch: boolean;\n\treadonly modelCatalogTtlHours: number;\n\treadonly sandboxMode: string | undefined;\n\t/** Exact full commands the spawned CLI must refuse; globs are not supported. */\n\treadonly denyCommands?: string[];\n}\n\ntype SettingsWithCursorCliOauthProvider = Settings & {\n\tcursorCliOauthProvider?: unknown;\n};\n\ntype Environment = Readonly<Record<string, string | undefined>>;\ntype ParsedSettings = Partial<CursorCliOauthProviderSettings>;\n\nconst DEFAULT_SETTINGS: CursorCliOauthProviderSettings = {\n\tenabled: true,\n\texecutablePath: undefined,\n\tforceExecution: true,\n\tnoApprovalAcknowledgedAt: undefined,\n\texecutionMode: \"agent\",\n\tresumeMode: \"auto\",\n\tpinnedAccount: undefined,\n\tcontextRecapOnModelSwitch: true,\n\tmodelCatalogTtlHours: 24,\n\tsandboxMode: undefined,\n\tdenyCommands: [],\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction parseBoolean(value: unknown): boolean | undefined {\n\treturn typeof value === \"boolean\" ? value : undefined;\n}\n\nfunction parseEnvironmentBoolean(value: string | undefined): boolean | undefined {\n\tif (value === undefined) return undefined;\n\tswitch (value.toLowerCase()) {\n\t\tcase \"1\":\n\t\tcase \"true\":\n\t\t\treturn true;\n\t\tcase \"0\":\n\t\tcase \"false\":\n\t\t\treturn false;\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n\nfunction parseNonEmptyString(value: unknown): string | undefined {\n\treturn typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\n/** Exact full commands only: string entries are trimmed, non-strings and empties are dropped. */\nfunction parseDenyCommands(value: unknown): string[] | undefined {\n\tif (!Array.isArray(value)) return undefined;\n\treturn value\n\t\t.filter((entry): entry is string => typeof entry === \"string\")\n\t\t.map((entry) => entry.trim())\n\t\t.filter((command) => command.length > 0);\n}\n\n/** Comma-separated exact full commands; a missing or empty value leaves settings untouched. */\nfunction parseEnvironmentDenyCommands(value: string | undefined): string[] | undefined {\n\tif (value === undefined || value.length === 0) return undefined;\n\treturn value\n\t\t.split(\",\")\n\t\t.map((entry) => entry.trim())\n\t\t.filter((command) => command.length > 0);\n}\n\nfunction parseIsoString(value: unknown): string | undefined {\n\tif (typeof value !== \"string\" || !/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{3})?Z$/.test(value)) {\n\t\treturn undefined;\n\t}\n\treturn Number.isNaN(Date.parse(value)) ? undefined : value;\n}\n\nfunction parseExecutionMode(value: unknown): CursorCliOauthExecutionMode | undefined {\n\treturn value === \"agent\" || value === \"plan\" ? value : undefined;\n}\n\nfunction parseResumeMode(value: unknown): CursorCliOauthResumeMode | undefined {\n\treturn value === \"auto\" || value === \"off\" ? value : undefined;\n}\n\nfunction parsePositiveFiniteNumber(value: unknown): number | undefined {\n\treturn typeof value === \"number\" && Number.isFinite(value) && value > 0 ? value : undefined;\n}\n\nfunction parseEnvironmentPositiveFiniteNumber(value: string | undefined): number | undefined {\n\tif (value === undefined || value.length === 0) return undefined;\n\tconst parsed = Number(value);\n\treturn Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;\n}\n\nfunction parseProviderSettings(value: unknown): ParsedSettings {\n\tif (!isRecord(value)) return {};\n\tconst enabled = parseBoolean(value.enabled);\n\tconst executablePath = parseNonEmptyString(value.executablePath);\n\tconst forceExecution = parseBoolean(value.forceExecution);\n\tconst noApprovalAcknowledgedAt = parseIsoString(value.noApprovalAcknowledgedAt);\n\tconst executionMode = parseExecutionMode(value.executionMode);\n\tconst resumeMode = parseResumeMode(value.resumeMode);\n\tconst pinnedAccount = parseNonEmptyString(value.pinnedAccount);\n\tconst contextRecapOnModelSwitch = parseBoolean(value.contextRecapOnModelSwitch);\n\tconst modelCatalogTtlHours = parsePositiveFiniteNumber(value.modelCatalogTtlHours);\n\tconst sandboxMode = parseNonEmptyString(value.sandboxMode);\n\tconst denyCommands = parseDenyCommands(value.denyCommands);\n\treturn {\n\t\t...(enabled !== undefined ? { enabled } : {}),\n\t\t...(executablePath !== undefined ? { executablePath } : {}),\n\t\t...(forceExecution !== undefined ? { forceExecution } : {}),\n\t\t...(noApprovalAcknowledgedAt !== undefined ? { noApprovalAcknowledgedAt } : {}),\n\t\t...(executionMode !== undefined ? { executionMode } : {}),\n\t\t...(resumeMode !== undefined ? { resumeMode } : {}),\n\t\t...(pinnedAccount !== undefined ? { pinnedAccount } : {}),\n\t\t...(contextRecapOnModelSwitch !== undefined ? { contextRecapOnModelSwitch } : {}),\n\t\t...(modelCatalogTtlHours !== undefined ? { modelCatalogTtlHours } : {}),\n\t\t...(sandboxMode !== undefined ? { sandboxMode } : {}),\n\t\t...(denyCommands !== undefined ? { denyCommands } : {}),\n\t};\n}\n\nfunction parseEnvironmentSettings(environment: Environment): ParsedSettings {\n\tconst executablePath =\n\t\tparseNonEmptyString(environment.SENPI_CURSOR_CLI_OAUTH_EXECUTABLE) ??\n\t\tparseNonEmptyString(environment.CURSOR_AGENT_EXECUTABLE);\n\tconst enabled = parseEnvironmentBoolean(environment.SENPI_CURSOR_CLI_OAUTH_ENABLED);\n\tconst forceExecution = parseEnvironmentBoolean(environment.SENPI_CURSOR_CLI_OAUTH_FORCE);\n\tconst executionMode = parseExecutionMode(environment.SENPI_CURSOR_CLI_OAUTH_EXECUTION_MODE);\n\tconst resumeMode = parseResumeMode(environment.SENPI_CURSOR_CLI_OAUTH_RESUME);\n\tconst pinnedAccount = parseNonEmptyString(environment.SENPI_CURSOR_CLI_OAUTH_PINNED_ACCOUNT);\n\tconst contextRecapOnModelSwitch = parseEnvironmentBoolean(environment.SENPI_CURSOR_CLI_OAUTH_RECAP);\n\tconst modelCatalogTtlHours = parseEnvironmentPositiveFiniteNumber(\n\t\tenvironment.SENPI_CURSOR_CLI_OAUTH_MODEL_CATALOG_TTL_HOURS,\n\t);\n\tconst sandboxMode = parseNonEmptyString(environment.SENPI_CURSOR_CLI_OAUTH_SANDBOX_MODE);\n\tconst denyCommands = parseEnvironmentDenyCommands(environment.SENPI_CURSOR_CLI_OAUTH_DENY_COMMANDS);\n\treturn {\n\t\t...(executablePath !== undefined ? { executablePath } : {}),\n\t\t...(enabled !== undefined ? { enabled } : {}),\n\t\t...(forceExecution !== undefined ? { forceExecution } : {}),\n\t\t...(executionMode !== undefined ? { executionMode } : {}),\n\t\t...(resumeMode !== undefined ? { resumeMode } : {}),\n\t\t...(pinnedAccount !== undefined ? { pinnedAccount } : {}),\n\t\t...(contextRecapOnModelSwitch !== undefined ? { contextRecapOnModelSwitch } : {}),\n\t\t...(modelCatalogTtlHours !== undefined ? { modelCatalogTtlHours } : {}),\n\t\t...(sandboxMode !== undefined ? { sandboxMode } : {}),\n\t\t...(denyCommands !== undefined ? { denyCommands } : {}),\n\t};\n}\n\nfunction resolveSettings(...layers: readonly ParsedSettings[]): CursorCliOauthProviderSettings {\n\treturn Object.assign({}, DEFAULT_SETTINGS, ...layers);\n}\n\n/** Parse one provider settings block with environment values taking precedence. */\nexport function parseCursorCliOauthProviderSettings(\n\tvalue: unknown,\n\tenvironment: Environment,\n): CursorCliOauthProviderSettings {\n\treturn resolveSettings(parseProviderSettings(value), parseEnvironmentSettings(environment));\n}\n\n/**\n * Build the probe-owned sandbox allowlist validator without hardcoding modes in settings parsing.\n * Each distinct rejected mode is reported once through the supplied warning hook.\n */\nexport function createCursorCliOauthSandboxModeValidator(\n\tacceptedModes: ReadonlySet<string>,\n\tonWarning: (message: string) => void,\n): (value: string | undefined) => string | undefined {\n\tconst warnedModes = new Set<string>();\n\treturn (value) => {\n\t\tif (value === undefined || acceptedModes.has(value)) return value;\n\t\tif (!warnedModes.has(value)) {\n\t\t\twarnedModes.add(value);\n\t\t\tonWarning(`Ignoring unrecognized Cursor CLI OAuth sandbox mode: ${value}`);\n\t\t}\n\t\treturn undefined;\n\t};\n}\n\n/** Load global and project settings afresh, with env values taking final precedence. */\nexport function loadCursorCliOauthProviderSettingsFromDisk(cwd: string): CursorCliOauthProviderSettings {\n\tconst settingsManager = SettingsManager.create(cwd, getAgentDir());\n\tconst global = settingsManager.getGlobalSettings() as SettingsWithCursorCliOauthProvider;\n\tconst project = settingsManager.getProjectSettings() as SettingsWithCursorCliOauthProvider;\n\treturn resolveSettings(\n\t\tparseProviderSettings(global.cursorCliOauthProvider),\n\t\tparseProviderSettings(project.cursorCliOauthProvider),\n\t\tparseEnvironmentSettings(process.env),\n\t);\n}\n\nfunction persistCursorCliOauthProviderPatch(\n\tcwd: string,\n\taction: string,\n\tpatch: Readonly<Record<string, unknown>>,\n): void {\n\tconst storage = new FileSettingsStorage(cwd, getAgentDir());\n\tstorage.selectSource(\"global\");\n\tstorage.withLock(\"global\", (current) => {\n\t\tlet root: Record<string, unknown>;\n\t\ttry {\n\t\t\troot = current === undefined ? {} : parseSettingsJson(current);\n\t\t} catch (error) {\n\t\t\tthrow new Error(\n\t\t\t\t`Cannot persist the cursor-cli-oauth ${action}: the settings file is unparseable (${error instanceof Error ? error.message : String(error)})`,\n\t\t\t);\n\t\t}\n\t\tconst provider =\n\t\t\ttypeof root.cursorCliOauthProvider === \"object\" &&\n\t\t\troot.cursorCliOauthProvider !== null &&\n\t\t\t!Array.isArray(root.cursorCliOauthProvider)\n\t\t\t\t? { ...(root.cursorCliOauthProvider as Record<string, unknown>) }\n\t\t\t\t: {};\n\t\treturn JSON.stringify({ ...root, cursorCliOauthProvider: { ...provider, ...patch } }, null, 2);\n\t});\n}\n\n/** Persist explicit provider activation while preserving every sibling setting. */\nexport function persistCursorCliOauthEnabled(cwd: string, enabled: boolean): void {\n\tpersistCursorCliOauthProviderPatch(cwd, \"enabled state\", { enabled });\n}\n\n/**\n * Read-modify-write `noApprovalAcknowledgedAt` into the provider block of the\n * global settings file, preserving every other key. An unparseable file is\n * reported instead of silently clobbered, so an acknowledgement can never\n * claim success while leaving the settings unwritten.\n */\nexport function persistCursorCliNoApprovalAcknowledgement(cwd: string, acknowledgedAt: string): void {\n\tpersistCursorCliOauthProviderPatch(cwd, \"acknowledgement\", {\n\t\tenabled: true,\n\t\tnoApprovalAcknowledgedAt: acknowledgedAt,\n\t});\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,gBAAgB,CAAC;AAkCrE,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAoY5D"}
|
|
@@ -11,6 +11,7 @@ import { formatGoalForTool, goalStatusLabel } from "./format.js";
|
|
|
11
11
|
import { isResumeOfStoppedGoal, queueGoalContinuation } from "./lifecycle-helpers.js";
|
|
12
12
|
import { GOAL_CONTINUATION_SCHEDULED_EVENT, MonitorAwareGoalContinuation } from "./monitor-continuation.js";
|
|
13
13
|
import { migrateLegacyGoalFile } from "./persistence.js";
|
|
14
|
+
import { reengageGoalAfterReload } from "./reload-reengagement.js";
|
|
14
15
|
import { accountGoalUsage, readGoal, updateGoal } from "./store.js";
|
|
15
16
|
import { GOAL_STORE_CHANGED_EVENT, isGoalStoreChangedEvent } from "./store-changed-event.js";
|
|
16
17
|
import { goalStoreRef as buildGoalStoreRef } from "./store-ref.js";
|
|
@@ -130,9 +131,19 @@ export default function goalExtension(pi) {
|
|
|
130
131
|
if (await maybePromptResumeStoppedGoal(pi, ctx, event.reason, goal)) {
|
|
131
132
|
return;
|
|
132
133
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
134
|
+
if (goal && event.reason === "reload") {
|
|
135
|
+
// A reload retires the extension generation and every armed continuation
|
|
136
|
+
// timer with it. Re-engage through the reload path: stopped goals stay
|
|
137
|
+
// stopped, active goals resume the wait the reload tore down.
|
|
138
|
+
await reengageGoalAfterReload({
|
|
139
|
+
ctx,
|
|
140
|
+
goal,
|
|
141
|
+
monitor: monitorContinuation,
|
|
142
|
+
countTrailingContinuations: () => countTrailingGoalContinuationEntries(ctx.sessionManager.getBranch()),
|
|
143
|
+
queueContinuation: () => queueGoalContinuationForCurrentSession(pi, ctx, goal),
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
else if (goal) {
|
|
136
147
|
// Migration-lite admission: a resumed session carrying a trailing flood of
|
|
137
148
|
// historical continuations must not reignite on load. Skip the auto-queue,
|
|
138
149
|
// leave the goal active (no status rewrite), and tell the user how to resume.
|