@ai-sdk/harness-cursor 1.0.20 → 1.0.22
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 +22 -0
- package/dist/index.js +84 -4
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/src/cursor-harness.ts +3 -1
- package/src/cursor-subscription.ts +103 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @ai-sdk/harness-cursor
|
|
2
2
|
|
|
3
|
+
## 1.0.22
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- @ai-sdk/harness@1.0.109
|
|
8
|
+
- @ai-sdk/harness-acp@1.0.47
|
|
9
|
+
|
|
10
|
+
## 1.0.21
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- cdc12a1: feat(harness): add support for using adapter-native subscriptions where available
|
|
15
|
+
- Updated dependencies [4d1bf28]
|
|
16
|
+
- Updated dependencies [cdc12a1]
|
|
17
|
+
- Updated dependencies [d70a334]
|
|
18
|
+
- Updated dependencies [81ba84c]
|
|
19
|
+
- Updated dependencies [813bb36]
|
|
20
|
+
- Updated dependencies [c43e4b7]
|
|
21
|
+
- @ai-sdk/harness@1.0.108
|
|
22
|
+
- @ai-sdk/harness-acp@1.0.46
|
|
23
|
+
- @ai-sdk/provider-utils@5.0.40
|
|
24
|
+
|
|
3
25
|
## 1.0.20
|
|
4
26
|
|
|
5
27
|
### Patch Changes
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,86 @@ import { tool } from "@ai-sdk/provider-utils";
|
|
|
7
7
|
import { z } from "zod/v4";
|
|
8
8
|
|
|
9
9
|
// src/version.ts
|
|
10
|
-
var VERSION = true ? "1.0.
|
|
10
|
+
var VERSION = true ? "1.0.22" : "0.0.0-test";
|
|
11
|
+
|
|
12
|
+
// src/cursor-subscription.ts
|
|
13
|
+
import { readFile } from "fs/promises";
|
|
14
|
+
import { homedir } from "os";
|
|
15
|
+
import { join } from "path";
|
|
16
|
+
import {
|
|
17
|
+
getJwtExpiresAt,
|
|
18
|
+
isAccessTokenExpiringSoon,
|
|
19
|
+
isHarnessAuthenticationEnvironment,
|
|
20
|
+
isLinux,
|
|
21
|
+
isMacOS,
|
|
22
|
+
isWindows,
|
|
23
|
+
readMacOSKeychainPassword,
|
|
24
|
+
shouldResolveNativeSubscription
|
|
25
|
+
} from "@ai-sdk/harness/utils";
|
|
26
|
+
import { isRecord, safeParseJSON } from "@ai-sdk/provider-utils";
|
|
27
|
+
async function resolveCursorSubscriptionEnvironment({
|
|
28
|
+
auth,
|
|
29
|
+
env
|
|
30
|
+
}) {
|
|
31
|
+
if (isHarnessAuthenticationEnvironment(auth)) return auth;
|
|
32
|
+
if (!shouldResolveNativeSubscription({
|
|
33
|
+
auth,
|
|
34
|
+
env,
|
|
35
|
+
hasDirectCredential: env.CURSOR_API_KEY != null
|
|
36
|
+
})) {
|
|
37
|
+
return env;
|
|
38
|
+
}
|
|
39
|
+
const subscription = await readCursorSubscription({ env });
|
|
40
|
+
return subscription == null ? env : { ...env, CURSOR_API_KEY: subscription };
|
|
41
|
+
}
|
|
42
|
+
async function readCursorSubscription({
|
|
43
|
+
env = process.env,
|
|
44
|
+
homeDirectory = homedir(),
|
|
45
|
+
platform = process.platform
|
|
46
|
+
} = {}) {
|
|
47
|
+
if (env.AGENT_CLI_CREDENTIAL_STORE === "memory") return void 0;
|
|
48
|
+
const authPath = resolveCursorAuthPath({ env, homeDirectory, platform });
|
|
49
|
+
const text = await readFile(authPath, "utf8").catch(() => void 0);
|
|
50
|
+
const fileCredential = text == null ? void 0 : await parseAccessToken(text);
|
|
51
|
+
const accessToken = fileCredential ?? (isMacOS(platform) && env.AGENT_CLI_CREDENTIAL_STORE !== "file" ? await readMacOSKeychainPassword({
|
|
52
|
+
service: "cursor-access-token",
|
|
53
|
+
account: "cursor-user"
|
|
54
|
+
}) : void 0);
|
|
55
|
+
if (accessToken == null) return void 0;
|
|
56
|
+
const expiresAt = await getJwtExpiresAt({ token: accessToken });
|
|
57
|
+
if (expiresAt != null && isAccessTokenExpiringSoon({ expiresAt })) {
|
|
58
|
+
throw new Error(
|
|
59
|
+
"Cursor subscription access token is expiring soon. Run Cursor login again."
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
return accessToken;
|
|
63
|
+
}
|
|
64
|
+
function resolveCursorAuthPath({
|
|
65
|
+
env,
|
|
66
|
+
homeDirectory,
|
|
67
|
+
platform
|
|
68
|
+
}) {
|
|
69
|
+
if (isWindows(platform)) {
|
|
70
|
+
return join(
|
|
71
|
+
env.APPDATA ?? join(homeDirectory, "AppData", "Roaming"),
|
|
72
|
+
"Cursor",
|
|
73
|
+
"auth.json"
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
if (isLinux(platform)) {
|
|
77
|
+
return join(
|
|
78
|
+
env.XDG_CONFIG_HOME ?? join(homeDirectory, ".config"),
|
|
79
|
+
"cursor",
|
|
80
|
+
"auth.json"
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
return join(homeDirectory, ".cursor", "auth.json");
|
|
84
|
+
}
|
|
85
|
+
async function parseAccessToken(text) {
|
|
86
|
+
const parsed = await safeParseJSON({ text });
|
|
87
|
+
if (!parsed.success || !isRecord(parsed.value)) return void 0;
|
|
88
|
+
return typeof parsed.value.accessToken === "string" ? parsed.value.accessToken : void 0;
|
|
89
|
+
}
|
|
11
90
|
|
|
12
91
|
// src/cursor-harness.ts
|
|
13
92
|
var CURSOR_CLIENT_APP = `ai-sdk/harness-cursor/${VERSION}`;
|
|
@@ -292,7 +371,8 @@ function createCursor(settings = {}) {
|
|
|
292
371
|
warnCursorAuthenticationConfiguration({ auth: settings.auth });
|
|
293
372
|
}
|
|
294
373
|
return createACP({
|
|
295
|
-
auth:
|
|
374
|
+
auth: settings.auth,
|
|
375
|
+
resolveAuthenticationEnvironment: resolveCursorSubscriptionEnvironment,
|
|
296
376
|
credentialForwarding: settings.credentialForwarding,
|
|
297
377
|
port: settings.port,
|
|
298
378
|
portEndpoint: settings.portEndpoint,
|
|
@@ -300,7 +380,7 @@ function createCursor(settings = {}) {
|
|
|
300
380
|
mcpServers: settings.mcpServers,
|
|
301
381
|
isMcpToolCall: (toolCall) => {
|
|
302
382
|
const rawInput = toolCall.rawInput;
|
|
303
|
-
return
|
|
383
|
+
return isRecord2(rawInput) && typeof rawInput.providerIdentifier === "string" && typeof rawInput.toolName === "string" && isRecord2(rawInput.args);
|
|
304
384
|
},
|
|
305
385
|
mintBridgeToken: settings.mintBridgeToken,
|
|
306
386
|
version: "v1",
|
|
@@ -369,7 +449,7 @@ function warnCursorAuthenticationConfiguration({
|
|
|
369
449
|
`[cursor] auth: ${JSON.stringify(auth)} cannot configure Cursor provider authentication. ${detail} CURSOR_API_KEY is still required for Cursor CLI authentication.`
|
|
370
450
|
);
|
|
371
451
|
}
|
|
372
|
-
function
|
|
452
|
+
function isRecord2(value) {
|
|
373
453
|
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
374
454
|
}
|
|
375
455
|
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cursor-harness.ts","../src/version.ts","../src/index.ts"],"sourcesContent":["import {\n commonTool,\n type HarnessV1,\n type HarnessV1BuiltinTool,\n type HarnessV1CredentialForwarding,\n type HarnessV1MintBridgeTokenCallback,\n type HarnessV1PortEndpoint,\n} from '@ai-sdk/harness';\nimport { createACP, type ACPAuthenticationMode } from '@ai-sdk/harness-acp';\nimport { tool } from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\nimport { VERSION } from './version';\n\nconst CURSOR_CLIENT_APP = `ai-sdk/harness-cursor/${VERSION}`;\n\nexport type CursorAuthenticationMode = ACPAuthenticationMode;\n\nexport type CursorHarnessSettings = {\n /**\n * Declares the provider authentication configured in Cursor, or supplies an\n * isolated environment for Cursor CLI authentication. The adapter cannot\n * change provider routing and warns for explicit routing modes.\n */\n readonly auth?: CursorAuthenticationMode;\n /**\n * Customizes each credential value before it is forwarded into a sandbox\n * process. This does not restrict which credentials the harness adapter can\n * discover, read, or otherwise access in the host process.\n */\n readonly credentialForwarding?: HarnessV1CredentialForwarding;\n /**\n * Overrides the sandbox port used by the ACP bridge.\n */\n readonly port?: number;\n /**\n * Override the host endpoint used to connect to the sandbox bridge. Required\n * together with `port` when using a basic sandbox session.\n */\n readonly portEndpoint?: HarnessV1PortEndpoint;\n /**\n * Maximum milliseconds to wait for the ACP bridge to start.\n */\n readonly startupTimeoutMs?: number;\n /**\n * MCP server definitions keyed by server name. Each definition uses the\n * underlying runtime's native MCP server configuration format.\n */\n readonly mcpServers?: Record<string, unknown>;\n /**\n * Creates the authentication token used by the sandbox bridge. Defaults to\n * a random 32-byte hexadecimal token.\n */\n readonly mintBridgeToken?: HarnessV1MintBridgeTokenCallback;\n};\n\n/*\n * Tool variants, display titles, ACP kinds, and raw input projections were\n * captured from the official Cursor CLI 2026.08.11-e8db854 ACP implementation.\n * `mcpToolCall` is dynamic and `truncatedToolCall` is a transport sentinel, so\n * neither is exposed as a built-in.\n */\nconst CURSOR_BUILTIN_TOOLS = {\n bash: {\n ...commonTool('bash', {\n nativeName: 'shellToolCall',\n toolUseKind: 'bash',\n inputSchema: z.looseObject({ command: z.string() }),\n }),\n title: 'Terminal',\n },\n delete: {\n ...tool({\n title: 'Delete',\n inputSchema: z.looseObject({ path: z.string() }),\n }),\n nativeName: 'deleteToolCall',\n toolUseKind: 'edit',\n },\n glob: {\n ...commonTool('glob', {\n nativeName: 'globToolCall',\n toolUseKind: 'readonly',\n inputSchema: z.looseObject({ pattern: z.string() }),\n }),\n title: 'Find',\n },\n grep: {\n ...commonTool('grep', {\n nativeName: 'grepToolCall',\n toolUseKind: 'readonly',\n inputSchema: z.looseObject({\n pattern: z.string(),\n path: z.string().optional(),\n }),\n }),\n title: 'grep',\n },\n read: {\n ...tool({\n title: 'Read',\n inputSchema: z.looseObject({ path: z.string() }),\n }),\n nativeName: 'readToolCall',\n toolUseKind: 'readonly',\n },\n updateTodos: {\n ...tool({\n title: 'Update TODOs',\n inputSchema: z.looseObject({\n _toolName: z.literal('updateTodos'),\n todos: z\n .array(\n z.looseObject({\n id: z.string(),\n content: z.string(),\n status: z.string(),\n }),\n )\n .optional(),\n }),\n }),\n nativeName: 'updateTodosToolCall',\n },\n readTodos: {\n ...tool({\n title: 'Read TODOs',\n inputSchema: z.looseObject({}),\n }),\n nativeName: 'readTodosToolCall',\n toolUseKind: 'readonly',\n },\n edit: {\n ...tool({\n title: 'Edit',\n inputSchema: z.looseObject({ path: z.string() }),\n }),\n nativeName: 'editToolCall',\n toolUseKind: 'edit',\n },\n ls: {\n ...tool({\n title: 'List',\n inputSchema: z.looseObject({ path: z.string() }),\n }),\n nativeName: 'lsToolCall',\n toolUseKind: 'readonly',\n },\n readLints: {\n ...tool({\n title: 'Read Lints',\n inputSchema: z.looseObject({ paths: z.array(z.string()) }),\n }),\n nativeName: 'readLintsToolCall',\n toolUseKind: 'readonly',\n },\n semanticSearch: {\n ...tool({\n title: 'Codebase Search',\n inputSchema: z.looseObject({ query: z.string() }),\n }),\n nativeName: 'semSearchToolCall',\n toolUseKind: 'readonly',\n },\n createPlan: {\n ...tool({\n title: 'Create Plan',\n inputSchema: z.looseObject({\n _toolName: z.literal('createPlan'),\n name: z.string().optional(),\n plan: z.string().optional(),\n }),\n }),\n nativeName: 'createPlanToolCall',\n },\n webSearch: {\n ...tool({\n title: 'Web Search',\n inputSchema: z.looseObject({ searchTerm: z.string() }),\n }),\n nativeName: 'webSearchToolCall',\n toolUseKind: 'readonly',\n },\n task: {\n ...tool({\n title: 'Task',\n inputSchema: z.looseObject({\n _toolName: z.literal('task'),\n prompt: z.string().optional(),\n description: z.string().optional(),\n subagentType: z.unknown().optional(),\n }),\n }),\n nativeName: 'taskToolCall',\n },\n listMcpResources: {\n ...tool({\n title: 'List MCP Resources',\n inputSchema: z.looseObject({ server: z.string().optional() }),\n }),\n nativeName: 'listMcpResourcesToolCall',\n toolUseKind: 'readonly',\n },\n readMcpResource: {\n ...tool({\n title: 'Fetch MCP Resource',\n inputSchema: z.looseObject({\n server: z.string().optional(),\n uri: z.string().optional(),\n downloadPath: z.string().optional(),\n }),\n }),\n nativeName: 'readMcpResourceToolCall',\n toolUseKind: 'readonly',\n },\n applyAgentDiff: {\n ...tool({\n title: 'Apply Agent Diff',\n inputSchema: z.looseObject({ path: z.string().optional() }),\n }),\n nativeName: 'applyAgentDiffToolCall',\n toolUseKind: 'edit',\n },\n fetch: {\n ...tool({\n title: 'Fetch',\n inputSchema: z.looseObject({ url: z.string() }),\n }),\n nativeName: 'fetchToolCall',\n toolUseKind: 'readonly',\n },\n switchMode: {\n ...tool({\n title: 'Switch Mode',\n inputSchema: z.looseObject({\n targetModeId: z.string(),\n explanation: z.string().optional(),\n }),\n }),\n nativeName: 'switchModeToolCall',\n },\n generateImage: {\n ...tool({\n title: 'Generate Image',\n inputSchema: z.looseObject({\n _toolName: z.literal('generateImage'),\n description: z.string().optional(),\n filename: z.string().optional(),\n }),\n }),\n nativeName: 'generateImageToolCall',\n },\n recordScreen: {\n ...tool({\n title: 'Record Screen',\n inputSchema: z.looseObject({}),\n }),\n nativeName: 'recordScreenToolCall',\n },\n computerUse: {\n ...tool({\n title: 'Computer Use',\n inputSchema: z.looseObject({\n action: z.string().optional(),\n coordinate: z.unknown().optional(),\n text: z.string().optional(),\n }),\n }),\n nativeName: 'computerUseToolCall',\n toolUseKind: 'bash',\n },\n writeShellStdin: {\n ...tool({\n title: 'Write to stdin',\n inputSchema: z.looseObject({\n shellId: z.number().optional(),\n chars: z.string().optional(),\n }),\n }),\n nativeName: 'writeShellStdinToolCall',\n toolUseKind: 'bash',\n },\n reflect: {\n ...tool({\n title: 'Reflect',\n inputSchema: z.looseObject({ reflection: z.string().optional() }),\n }),\n nativeName: 'reflectToolCall',\n toolUseKind: 'readonly',\n },\n setupVmEnvironment: {\n ...tool({\n title: 'Setup VM Environment',\n inputSchema: z.looseObject({}),\n }),\n nativeName: 'setupVmEnvironmentToolCall',\n toolUseKind: 'bash',\n },\n replaceEnv: {\n ...tool({\n title: 'Replace Environment',\n inputSchema: z.looseObject({}),\n }),\n nativeName: 'replaceEnvToolCall',\n toolUseKind: 'bash',\n },\n startGrindExecution: {\n ...tool({\n title: 'Start Grind Execution',\n inputSchema: z.looseObject({}),\n }),\n nativeName: 'startGrindExecutionToolCall',\n toolUseKind: 'bash',\n },\n startGrindPlanning: {\n ...tool({\n title: 'Start Grind Planning',\n inputSchema: z.looseObject({}),\n }),\n nativeName: 'startGrindPlanningToolCall',\n toolUseKind: 'readonly',\n },\n webFetch: {\n ...tool({\n title: 'Web Fetch',\n inputSchema: z.looseObject({ url: z.string() }),\n }),\n nativeName: 'webFetchToolCall',\n toolUseKind: 'readonly',\n },\n reportBugfixResults: {\n ...tool({\n title: 'Report Bugfix Results',\n inputSchema: z.looseObject({}),\n }),\n nativeName: 'reportBugfixResultsToolCall',\n },\n} as const satisfies Record<string, HarnessV1BuiltinTool<any, any>>;\n\nexport function createCursor(\n settings: CursorHarnessSettings = {},\n): HarnessV1<typeof CURSOR_BUILTIN_TOOLS> {\n const clientAppSegments = CURSOR_CLIENT_APP.split('/');\n const clientAppVersion = clientAppSegments.pop()!;\n\n if (settings.auth === 'direct' || settings.auth === 'ai-gateway') {\n warnCursorAuthenticationConfiguration({ auth: settings.auth });\n }\n\n return createACP({\n auth: typeof settings.auth === 'string' ? undefined : settings.auth,\n credentialForwarding: settings.credentialForwarding,\n port: settings.port,\n portEndpoint: settings.portEndpoint,\n startupTimeoutMs: settings.startupTimeoutMs,\n mcpServers: settings.mcpServers,\n isMcpToolCall: toolCall => {\n const rawInput = toolCall.rawInput;\n return (\n isRecord(rawInput) &&\n typeof rawInput.providerIdentifier === 'string' &&\n typeof rawInput.toolName === 'string' &&\n isRecord(rawInput.args)\n );\n },\n mintBridgeToken: settings.mintBridgeToken,\n version: 'v1',\n harnessId: 'cursor',\n builtinTools: CURSOR_BUILTIN_TOOLS,\n clientApp: {\n name: clientAppSegments.join('/'),\n version: clientAppVersion,\n },\n source: {\n type: 'install-command',\n command: 'curl https://cursor.com/install -fsS | bash',\n },\n executable: 'agent',\n args: ['--disable-auto-update', 'acp'],\n modelMapping: {\n type: 'session-config-option',\n path: 'model',\n },\n clientCapabilities: {\n _meta: { parameterizedModelPicker: true },\n },\n credentialEnv: ['CURSOR_API_KEY'],\n credentialBrokering: ({ env, sandboxEnv, headers }) => {\n const transformations = [];\n if (env.CURSOR_API_KEY && sandboxEnv?.CURSOR_API_KEY) {\n transformations.push({\n match: {\n host: 'api2.cursor.sh',\n path: { exact: '/auth/exchange_user_api_key' },\n method: ['POST'],\n headers: [\n {\n key: { exact: 'Authorization' },\n value: {\n exact: `Bearer ${sandboxEnv.CURSOR_API_KEY}`,\n },\n },\n ],\n },\n transform: {\n headers: {\n Authorization: `Bearer ${env.CURSOR_API_KEY}`,\n },\n },\n });\n }\n if (headers != null) {\n transformations.push({\n match:\n settings.auth === 'ai-gateway'\n ? {\n host: 'ai-gateway.vercel.sh',\n path: { startsWith: '/cursor/v1' },\n }\n : { host: 'api2.cursor.sh' },\n transform: { headers },\n });\n }\n return transformations;\n },\n });\n}\n\nfunction warnCursorAuthenticationConfiguration({\n auth,\n}: {\n auth: Exclude<CursorAuthenticationMode, 'auto'>;\n}): void {\n const detail =\n auth === 'ai-gateway'\n ? \"Configure an AI Gateway API key as Cursor's OpenAI API key and set Override OpenAI Base URL to https://ai-gateway.vercel.sh/cursor/v1.\"\n : 'Configure Cursor to use its direct model-provider routing.';\n console.warn(\n `[cursor] auth: ${JSON.stringify(auth)} cannot configure Cursor provider authentication. ${detail} CURSOR_API_KEY is still required for Cursor CLI authentication.`,\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value != null && typeof value === 'object' && !Array.isArray(value);\n}\n","declare const __PACKAGE_VERSION__: string | undefined;\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ !== 'undefined'\n ? __PACKAGE_VERSION__\n : '0.0.0-test';\n","import { createCursor } from './cursor-harness';\n\n/**\n * Default Cursor harness instance. Equivalent to `createCursor()`.\n */\nexport const cursor = createCursor();\n\nexport { createCursor } from './cursor-harness';\nexport type {\n CursorAuthenticationMode,\n CursorHarnessSettings,\n} from './cursor-harness';\nexport { VERSION } from './version';\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/cursor-harness.ts","../src/version.ts","../src/cursor-subscription.ts","../src/index.ts"],"sourcesContent":["import {\n commonTool,\n type HarnessV1,\n type HarnessV1BuiltinTool,\n type HarnessV1CredentialForwarding,\n type HarnessV1MintBridgeTokenCallback,\n type HarnessV1PortEndpoint,\n} from '@ai-sdk/harness';\nimport { createACP, type ACPAuthenticationMode } from '@ai-sdk/harness-acp';\nimport { tool } from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\nimport { VERSION } from './version';\nimport { resolveCursorSubscriptionEnvironment } from './cursor-subscription';\n\nconst CURSOR_CLIENT_APP = `ai-sdk/harness-cursor/${VERSION}`;\n\nexport type CursorAuthenticationMode = ACPAuthenticationMode;\n\nexport type CursorHarnessSettings = {\n /**\n * Declares the provider authentication configured in Cursor, or supplies an\n * isolated environment for Cursor CLI authentication. The adapter cannot\n * change provider routing and warns for explicit routing modes.\n */\n readonly auth?: CursorAuthenticationMode;\n /**\n * Customizes each credential value before it is forwarded into a sandbox\n * process. This does not restrict which credentials the harness adapter can\n * discover, read, or otherwise access in the host process.\n */\n readonly credentialForwarding?: HarnessV1CredentialForwarding;\n /**\n * Overrides the sandbox port used by the ACP bridge.\n */\n readonly port?: number;\n /**\n * Override the host endpoint used to connect to the sandbox bridge. Required\n * together with `port` when using a basic sandbox session.\n */\n readonly portEndpoint?: HarnessV1PortEndpoint;\n /**\n * Maximum milliseconds to wait for the ACP bridge to start.\n */\n readonly startupTimeoutMs?: number;\n /**\n * MCP server definitions keyed by server name. Each definition uses the\n * underlying runtime's native MCP server configuration format.\n */\n readonly mcpServers?: Record<string, unknown>;\n /**\n * Creates the authentication token used by the sandbox bridge. Defaults to\n * a random 32-byte hexadecimal token.\n */\n readonly mintBridgeToken?: HarnessV1MintBridgeTokenCallback;\n};\n\n/*\n * Tool variants, display titles, ACP kinds, and raw input projections were\n * captured from the official Cursor CLI 2026.08.11-e8db854 ACP implementation.\n * `mcpToolCall` is dynamic and `truncatedToolCall` is a transport sentinel, so\n * neither is exposed as a built-in.\n */\nconst CURSOR_BUILTIN_TOOLS = {\n bash: {\n ...commonTool('bash', {\n nativeName: 'shellToolCall',\n toolUseKind: 'bash',\n inputSchema: z.looseObject({ command: z.string() }),\n }),\n title: 'Terminal',\n },\n delete: {\n ...tool({\n title: 'Delete',\n inputSchema: z.looseObject({ path: z.string() }),\n }),\n nativeName: 'deleteToolCall',\n toolUseKind: 'edit',\n },\n glob: {\n ...commonTool('glob', {\n nativeName: 'globToolCall',\n toolUseKind: 'readonly',\n inputSchema: z.looseObject({ pattern: z.string() }),\n }),\n title: 'Find',\n },\n grep: {\n ...commonTool('grep', {\n nativeName: 'grepToolCall',\n toolUseKind: 'readonly',\n inputSchema: z.looseObject({\n pattern: z.string(),\n path: z.string().optional(),\n }),\n }),\n title: 'grep',\n },\n read: {\n ...tool({\n title: 'Read',\n inputSchema: z.looseObject({ path: z.string() }),\n }),\n nativeName: 'readToolCall',\n toolUseKind: 'readonly',\n },\n updateTodos: {\n ...tool({\n title: 'Update TODOs',\n inputSchema: z.looseObject({\n _toolName: z.literal('updateTodos'),\n todos: z\n .array(\n z.looseObject({\n id: z.string(),\n content: z.string(),\n status: z.string(),\n }),\n )\n .optional(),\n }),\n }),\n nativeName: 'updateTodosToolCall',\n },\n readTodos: {\n ...tool({\n title: 'Read TODOs',\n inputSchema: z.looseObject({}),\n }),\n nativeName: 'readTodosToolCall',\n toolUseKind: 'readonly',\n },\n edit: {\n ...tool({\n title: 'Edit',\n inputSchema: z.looseObject({ path: z.string() }),\n }),\n nativeName: 'editToolCall',\n toolUseKind: 'edit',\n },\n ls: {\n ...tool({\n title: 'List',\n inputSchema: z.looseObject({ path: z.string() }),\n }),\n nativeName: 'lsToolCall',\n toolUseKind: 'readonly',\n },\n readLints: {\n ...tool({\n title: 'Read Lints',\n inputSchema: z.looseObject({ paths: z.array(z.string()) }),\n }),\n nativeName: 'readLintsToolCall',\n toolUseKind: 'readonly',\n },\n semanticSearch: {\n ...tool({\n title: 'Codebase Search',\n inputSchema: z.looseObject({ query: z.string() }),\n }),\n nativeName: 'semSearchToolCall',\n toolUseKind: 'readonly',\n },\n createPlan: {\n ...tool({\n title: 'Create Plan',\n inputSchema: z.looseObject({\n _toolName: z.literal('createPlan'),\n name: z.string().optional(),\n plan: z.string().optional(),\n }),\n }),\n nativeName: 'createPlanToolCall',\n },\n webSearch: {\n ...tool({\n title: 'Web Search',\n inputSchema: z.looseObject({ searchTerm: z.string() }),\n }),\n nativeName: 'webSearchToolCall',\n toolUseKind: 'readonly',\n },\n task: {\n ...tool({\n title: 'Task',\n inputSchema: z.looseObject({\n _toolName: z.literal('task'),\n prompt: z.string().optional(),\n description: z.string().optional(),\n subagentType: z.unknown().optional(),\n }),\n }),\n nativeName: 'taskToolCall',\n },\n listMcpResources: {\n ...tool({\n title: 'List MCP Resources',\n inputSchema: z.looseObject({ server: z.string().optional() }),\n }),\n nativeName: 'listMcpResourcesToolCall',\n toolUseKind: 'readonly',\n },\n readMcpResource: {\n ...tool({\n title: 'Fetch MCP Resource',\n inputSchema: z.looseObject({\n server: z.string().optional(),\n uri: z.string().optional(),\n downloadPath: z.string().optional(),\n }),\n }),\n nativeName: 'readMcpResourceToolCall',\n toolUseKind: 'readonly',\n },\n applyAgentDiff: {\n ...tool({\n title: 'Apply Agent Diff',\n inputSchema: z.looseObject({ path: z.string().optional() }),\n }),\n nativeName: 'applyAgentDiffToolCall',\n toolUseKind: 'edit',\n },\n fetch: {\n ...tool({\n title: 'Fetch',\n inputSchema: z.looseObject({ url: z.string() }),\n }),\n nativeName: 'fetchToolCall',\n toolUseKind: 'readonly',\n },\n switchMode: {\n ...tool({\n title: 'Switch Mode',\n inputSchema: z.looseObject({\n targetModeId: z.string(),\n explanation: z.string().optional(),\n }),\n }),\n nativeName: 'switchModeToolCall',\n },\n generateImage: {\n ...tool({\n title: 'Generate Image',\n inputSchema: z.looseObject({\n _toolName: z.literal('generateImage'),\n description: z.string().optional(),\n filename: z.string().optional(),\n }),\n }),\n nativeName: 'generateImageToolCall',\n },\n recordScreen: {\n ...tool({\n title: 'Record Screen',\n inputSchema: z.looseObject({}),\n }),\n nativeName: 'recordScreenToolCall',\n },\n computerUse: {\n ...tool({\n title: 'Computer Use',\n inputSchema: z.looseObject({\n action: z.string().optional(),\n coordinate: z.unknown().optional(),\n text: z.string().optional(),\n }),\n }),\n nativeName: 'computerUseToolCall',\n toolUseKind: 'bash',\n },\n writeShellStdin: {\n ...tool({\n title: 'Write to stdin',\n inputSchema: z.looseObject({\n shellId: z.number().optional(),\n chars: z.string().optional(),\n }),\n }),\n nativeName: 'writeShellStdinToolCall',\n toolUseKind: 'bash',\n },\n reflect: {\n ...tool({\n title: 'Reflect',\n inputSchema: z.looseObject({ reflection: z.string().optional() }),\n }),\n nativeName: 'reflectToolCall',\n toolUseKind: 'readonly',\n },\n setupVmEnvironment: {\n ...tool({\n title: 'Setup VM Environment',\n inputSchema: z.looseObject({}),\n }),\n nativeName: 'setupVmEnvironmentToolCall',\n toolUseKind: 'bash',\n },\n replaceEnv: {\n ...tool({\n title: 'Replace Environment',\n inputSchema: z.looseObject({}),\n }),\n nativeName: 'replaceEnvToolCall',\n toolUseKind: 'bash',\n },\n startGrindExecution: {\n ...tool({\n title: 'Start Grind Execution',\n inputSchema: z.looseObject({}),\n }),\n nativeName: 'startGrindExecutionToolCall',\n toolUseKind: 'bash',\n },\n startGrindPlanning: {\n ...tool({\n title: 'Start Grind Planning',\n inputSchema: z.looseObject({}),\n }),\n nativeName: 'startGrindPlanningToolCall',\n toolUseKind: 'readonly',\n },\n webFetch: {\n ...tool({\n title: 'Web Fetch',\n inputSchema: z.looseObject({ url: z.string() }),\n }),\n nativeName: 'webFetchToolCall',\n toolUseKind: 'readonly',\n },\n reportBugfixResults: {\n ...tool({\n title: 'Report Bugfix Results',\n inputSchema: z.looseObject({}),\n }),\n nativeName: 'reportBugfixResultsToolCall',\n },\n} as const satisfies Record<string, HarnessV1BuiltinTool<any, any>>;\n\nexport function createCursor(\n settings: CursorHarnessSettings = {},\n): HarnessV1<typeof CURSOR_BUILTIN_TOOLS> {\n const clientAppSegments = CURSOR_CLIENT_APP.split('/');\n const clientAppVersion = clientAppSegments.pop()!;\n\n if (settings.auth === 'direct' || settings.auth === 'ai-gateway') {\n warnCursorAuthenticationConfiguration({ auth: settings.auth });\n }\n\n return createACP({\n auth: settings.auth,\n resolveAuthenticationEnvironment: resolveCursorSubscriptionEnvironment,\n credentialForwarding: settings.credentialForwarding,\n port: settings.port,\n portEndpoint: settings.portEndpoint,\n startupTimeoutMs: settings.startupTimeoutMs,\n mcpServers: settings.mcpServers,\n isMcpToolCall: toolCall => {\n const rawInput = toolCall.rawInput;\n return (\n isRecord(rawInput) &&\n typeof rawInput.providerIdentifier === 'string' &&\n typeof rawInput.toolName === 'string' &&\n isRecord(rawInput.args)\n );\n },\n mintBridgeToken: settings.mintBridgeToken,\n version: 'v1',\n harnessId: 'cursor',\n builtinTools: CURSOR_BUILTIN_TOOLS,\n clientApp: {\n name: clientAppSegments.join('/'),\n version: clientAppVersion,\n },\n source: {\n type: 'install-command',\n command: 'curl https://cursor.com/install -fsS | bash',\n },\n executable: 'agent',\n args: ['--disable-auto-update', 'acp'],\n modelMapping: {\n type: 'session-config-option',\n path: 'model',\n },\n clientCapabilities: {\n _meta: { parameterizedModelPicker: true },\n },\n credentialEnv: ['CURSOR_API_KEY'],\n credentialBrokering: ({ env, sandboxEnv, headers }) => {\n const transformations = [];\n if (env.CURSOR_API_KEY && sandboxEnv?.CURSOR_API_KEY) {\n transformations.push({\n match: {\n host: 'api2.cursor.sh',\n path: { exact: '/auth/exchange_user_api_key' },\n method: ['POST'],\n headers: [\n {\n key: { exact: 'Authorization' },\n value: {\n exact: `Bearer ${sandboxEnv.CURSOR_API_KEY}`,\n },\n },\n ],\n },\n transform: {\n headers: {\n Authorization: `Bearer ${env.CURSOR_API_KEY}`,\n },\n },\n });\n }\n if (headers != null) {\n transformations.push({\n match:\n settings.auth === 'ai-gateway'\n ? {\n host: 'ai-gateway.vercel.sh',\n path: { startsWith: '/cursor/v1' },\n }\n : { host: 'api2.cursor.sh' },\n transform: { headers },\n });\n }\n return transformations;\n },\n });\n}\n\nfunction warnCursorAuthenticationConfiguration({\n auth,\n}: {\n auth: Exclude<CursorAuthenticationMode, 'auto'>;\n}): void {\n const detail =\n auth === 'ai-gateway'\n ? \"Configure an AI Gateway API key as Cursor's OpenAI API key and set Override OpenAI Base URL to https://ai-gateway.vercel.sh/cursor/v1.\"\n : 'Configure Cursor to use its direct model-provider routing.';\n console.warn(\n `[cursor] auth: ${JSON.stringify(auth)} cannot configure Cursor provider authentication. ${detail} CURSOR_API_KEY is still required for Cursor CLI authentication.`,\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value != null && typeof value === 'object' && !Array.isArray(value);\n}\n","declare const __PACKAGE_VERSION__: string | undefined;\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ !== 'undefined'\n ? __PACKAGE_VERSION__\n : '0.0.0-test';\n","import { readFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport type { ACPAuthenticationMode } from '@ai-sdk/harness-acp';\nimport {\n getJwtExpiresAt,\n isAccessTokenExpiringSoon,\n isHarnessAuthenticationEnvironment,\n isLinux,\n isMacOS,\n isWindows,\n readMacOSKeychainPassword,\n shouldResolveNativeSubscription,\n} from '@ai-sdk/harness/utils';\nimport { isRecord, safeParseJSON } from '@ai-sdk/provider-utils';\n\nexport async function resolveCursorSubscriptionEnvironment({\n auth,\n env,\n}: {\n auth: ACPAuthenticationMode | undefined;\n env: Readonly<Record<string, string | undefined>>;\n}): Promise<Readonly<Record<string, string | undefined>>> {\n if (isHarnessAuthenticationEnvironment(auth)) return auth;\n if (\n !shouldResolveNativeSubscription({\n auth,\n env,\n hasDirectCredential: env.CURSOR_API_KEY != null,\n })\n ) {\n return env;\n }\n const subscription = await readCursorSubscription({ env });\n return subscription == null ? env : { ...env, CURSOR_API_KEY: subscription };\n}\n\nexport async function readCursorSubscription({\n env = process.env,\n homeDirectory = homedir(),\n platform = process.platform,\n}: {\n env?: Readonly<Record<string, string | undefined>>;\n homeDirectory?: string;\n platform?: NodeJS.Platform;\n} = {}): Promise<string | undefined> {\n if (env.AGENT_CLI_CREDENTIAL_STORE === 'memory') return undefined;\n const authPath = resolveCursorAuthPath({ env, homeDirectory, platform });\n const text = await readFile(authPath, 'utf8').catch(() => undefined);\n const fileCredential =\n text == null ? undefined : await parseAccessToken(text);\n const accessToken =\n fileCredential ??\n (isMacOS(platform) && env.AGENT_CLI_CREDENTIAL_STORE !== 'file'\n ? await readMacOSKeychainPassword({\n service: 'cursor-access-token',\n account: 'cursor-user',\n })\n : undefined);\n if (accessToken == null) return undefined;\n\n const expiresAt = await getJwtExpiresAt({ token: accessToken });\n if (expiresAt != null && isAccessTokenExpiringSoon({ expiresAt })) {\n throw new Error(\n 'Cursor subscription access token is expiring soon. Run Cursor login again.',\n );\n }\n return accessToken;\n}\n\nexport function resolveCursorAuthPath({\n env,\n homeDirectory,\n platform,\n}: {\n env: Readonly<Record<string, string | undefined>>;\n homeDirectory: string;\n platform: NodeJS.Platform;\n}): string {\n if (isWindows(platform)) {\n return join(\n env.APPDATA ?? join(homeDirectory, 'AppData', 'Roaming'),\n 'Cursor',\n 'auth.json',\n );\n }\n if (isLinux(platform)) {\n return join(\n env.XDG_CONFIG_HOME ?? join(homeDirectory, '.config'),\n 'cursor',\n 'auth.json',\n );\n }\n return join(homeDirectory, '.cursor', 'auth.json');\n}\n\nasync function parseAccessToken(text: string): Promise<string | undefined> {\n const parsed = await safeParseJSON({ text });\n if (!parsed.success || !isRecord(parsed.value)) return undefined;\n return typeof parsed.value.accessToken === 'string'\n ? parsed.value.accessToken\n : undefined;\n}\n","import { createCursor } from './cursor-harness';\n\n/**\n * Default Cursor harness instance. Equivalent to `createCursor()`.\n */\nexport const cursor = createCursor();\n\nexport { createCursor } from './cursor-harness';\nexport type {\n CursorAuthenticationMode,\n CursorHarnessSettings,\n} from './cursor-harness';\nexport { VERSION } from './version';\n"],"mappings":"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","names":["isRecord"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/harness-cursor",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.22",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@ai-sdk/harness": "1.0.
|
|
30
|
-
"@ai-sdk/harness-acp": "1.0.
|
|
31
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
29
|
+
"@ai-sdk/harness": "1.0.109",
|
|
30
|
+
"@ai-sdk/harness-acp": "1.0.47",
|
|
31
|
+
"@ai-sdk/provider-utils": "5.0.40"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
34
|
"zod": "^3.25.76 || ^4.1.8"
|
package/src/cursor-harness.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { createACP, type ACPAuthenticationMode } from '@ai-sdk/harness-acp';
|
|
|
10
10
|
import { tool } from '@ai-sdk/provider-utils';
|
|
11
11
|
import { z } from 'zod/v4';
|
|
12
12
|
import { VERSION } from './version';
|
|
13
|
+
import { resolveCursorSubscriptionEnvironment } from './cursor-subscription';
|
|
13
14
|
|
|
14
15
|
const CURSOR_CLIENT_APP = `ai-sdk/harness-cursor/${VERSION}`;
|
|
15
16
|
|
|
@@ -347,7 +348,8 @@ export function createCursor(
|
|
|
347
348
|
}
|
|
348
349
|
|
|
349
350
|
return createACP({
|
|
350
|
-
auth:
|
|
351
|
+
auth: settings.auth,
|
|
352
|
+
resolveAuthenticationEnvironment: resolveCursorSubscriptionEnvironment,
|
|
351
353
|
credentialForwarding: settings.credentialForwarding,
|
|
352
354
|
port: settings.port,
|
|
353
355
|
portEndpoint: settings.portEndpoint,
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import type { ACPAuthenticationMode } from '@ai-sdk/harness-acp';
|
|
5
|
+
import {
|
|
6
|
+
getJwtExpiresAt,
|
|
7
|
+
isAccessTokenExpiringSoon,
|
|
8
|
+
isHarnessAuthenticationEnvironment,
|
|
9
|
+
isLinux,
|
|
10
|
+
isMacOS,
|
|
11
|
+
isWindows,
|
|
12
|
+
readMacOSKeychainPassword,
|
|
13
|
+
shouldResolveNativeSubscription,
|
|
14
|
+
} from '@ai-sdk/harness/utils';
|
|
15
|
+
import { isRecord, safeParseJSON } from '@ai-sdk/provider-utils';
|
|
16
|
+
|
|
17
|
+
export async function resolveCursorSubscriptionEnvironment({
|
|
18
|
+
auth,
|
|
19
|
+
env,
|
|
20
|
+
}: {
|
|
21
|
+
auth: ACPAuthenticationMode | undefined;
|
|
22
|
+
env: Readonly<Record<string, string | undefined>>;
|
|
23
|
+
}): Promise<Readonly<Record<string, string | undefined>>> {
|
|
24
|
+
if (isHarnessAuthenticationEnvironment(auth)) return auth;
|
|
25
|
+
if (
|
|
26
|
+
!shouldResolveNativeSubscription({
|
|
27
|
+
auth,
|
|
28
|
+
env,
|
|
29
|
+
hasDirectCredential: env.CURSOR_API_KEY != null,
|
|
30
|
+
})
|
|
31
|
+
) {
|
|
32
|
+
return env;
|
|
33
|
+
}
|
|
34
|
+
const subscription = await readCursorSubscription({ env });
|
|
35
|
+
return subscription == null ? env : { ...env, CURSOR_API_KEY: subscription };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function readCursorSubscription({
|
|
39
|
+
env = process.env,
|
|
40
|
+
homeDirectory = homedir(),
|
|
41
|
+
platform = process.platform,
|
|
42
|
+
}: {
|
|
43
|
+
env?: Readonly<Record<string, string | undefined>>;
|
|
44
|
+
homeDirectory?: string;
|
|
45
|
+
platform?: NodeJS.Platform;
|
|
46
|
+
} = {}): Promise<string | undefined> {
|
|
47
|
+
if (env.AGENT_CLI_CREDENTIAL_STORE === 'memory') return undefined;
|
|
48
|
+
const authPath = resolveCursorAuthPath({ env, homeDirectory, platform });
|
|
49
|
+
const text = await readFile(authPath, 'utf8').catch(() => undefined);
|
|
50
|
+
const fileCredential =
|
|
51
|
+
text == null ? undefined : await parseAccessToken(text);
|
|
52
|
+
const accessToken =
|
|
53
|
+
fileCredential ??
|
|
54
|
+
(isMacOS(platform) && env.AGENT_CLI_CREDENTIAL_STORE !== 'file'
|
|
55
|
+
? await readMacOSKeychainPassword({
|
|
56
|
+
service: 'cursor-access-token',
|
|
57
|
+
account: 'cursor-user',
|
|
58
|
+
})
|
|
59
|
+
: undefined);
|
|
60
|
+
if (accessToken == null) return undefined;
|
|
61
|
+
|
|
62
|
+
const expiresAt = await getJwtExpiresAt({ token: accessToken });
|
|
63
|
+
if (expiresAt != null && isAccessTokenExpiringSoon({ expiresAt })) {
|
|
64
|
+
throw new Error(
|
|
65
|
+
'Cursor subscription access token is expiring soon. Run Cursor login again.',
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
return accessToken;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function resolveCursorAuthPath({
|
|
72
|
+
env,
|
|
73
|
+
homeDirectory,
|
|
74
|
+
platform,
|
|
75
|
+
}: {
|
|
76
|
+
env: Readonly<Record<string, string | undefined>>;
|
|
77
|
+
homeDirectory: string;
|
|
78
|
+
platform: NodeJS.Platform;
|
|
79
|
+
}): string {
|
|
80
|
+
if (isWindows(platform)) {
|
|
81
|
+
return join(
|
|
82
|
+
env.APPDATA ?? join(homeDirectory, 'AppData', 'Roaming'),
|
|
83
|
+
'Cursor',
|
|
84
|
+
'auth.json',
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
if (isLinux(platform)) {
|
|
88
|
+
return join(
|
|
89
|
+
env.XDG_CONFIG_HOME ?? join(homeDirectory, '.config'),
|
|
90
|
+
'cursor',
|
|
91
|
+
'auth.json',
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
return join(homeDirectory, '.cursor', 'auth.json');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async function parseAccessToken(text: string): Promise<string | undefined> {
|
|
98
|
+
const parsed = await safeParseJSON({ text });
|
|
99
|
+
if (!parsed.success || !isRecord(parsed.value)) return undefined;
|
|
100
|
+
return typeof parsed.value.accessToken === 'string'
|
|
101
|
+
? parsed.value.accessToken
|
|
102
|
+
: undefined;
|
|
103
|
+
}
|