chore: import upstream snapshot with attribution
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
import type { AddFollowupParams, AddFollowupResponse } from '@/tools/cursor/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const addFollowupBase = {
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Cursor API key',
|
||||
},
|
||||
agentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Unique identifier for the cloud agent (e.g., bc_abc123)',
|
||||
},
|
||||
followupPromptText: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The follow-up instruction text for the agent',
|
||||
},
|
||||
promptImages: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'JSON array of image objects with base64 data and dimensions (max 5)',
|
||||
},
|
||||
},
|
||||
request: {
|
||||
url: (params: AddFollowupParams) =>
|
||||
`https://api.cursor.com/v0/agents/${params.agentId.trim()}/followup`,
|
||||
method: 'POST',
|
||||
headers: (params: AddFollowupParams) => ({
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Basic ${Buffer.from(`${params.apiKey}:`).toString('base64')}`,
|
||||
}),
|
||||
body: (params: AddFollowupParams) => {
|
||||
const body: Record<string, any> = {
|
||||
prompt: {
|
||||
text: params.followupPromptText,
|
||||
},
|
||||
}
|
||||
|
||||
if (params.promptImages) {
|
||||
try {
|
||||
body.prompt.images = JSON.parse(params.promptImages)
|
||||
} catch {
|
||||
body.prompt.images = []
|
||||
}
|
||||
}
|
||||
|
||||
return body
|
||||
},
|
||||
},
|
||||
} satisfies Pick<ToolConfig<AddFollowupParams, any>, 'params' | 'request'>
|
||||
|
||||
export const addFollowupTool: ToolConfig<AddFollowupParams, AddFollowupResponse> = {
|
||||
id: 'cursor_add_followup',
|
||||
name: 'Cursor Add Follow-up',
|
||||
description: 'Add a follow-up instruction to an existing cloud agent.',
|
||||
version: '1.0.0',
|
||||
|
||||
...addFollowupBase,
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
|
||||
const content = `Follow-up added to agent ${data.id}`
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
content,
|
||||
metadata: {
|
||||
id: data.id,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
content: { type: 'string', description: 'Success message' },
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Result metadata',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Agent ID' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
interface AddFollowupV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
id: string
|
||||
}
|
||||
}
|
||||
|
||||
export const addFollowupV2Tool: ToolConfig<AddFollowupParams, AddFollowupV2Response> = {
|
||||
...addFollowupBase,
|
||||
id: 'cursor_add_followup_v2',
|
||||
name: 'Cursor Add Follow-up',
|
||||
description:
|
||||
'Add a follow-up instruction to an existing cloud agent. Returns API-aligned fields only.',
|
||||
version: '2.0.0',
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
},
|
||||
}
|
||||
},
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Agent ID' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
import type { DeleteAgentParams, DeleteAgentResponse } from '@/tools/cursor/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const deleteAgentBase = {
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Cursor API key',
|
||||
},
|
||||
agentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Unique identifier for the cloud agent (e.g., bc_abc123)',
|
||||
},
|
||||
},
|
||||
request: {
|
||||
url: (params: DeleteAgentParams) => `https://api.cursor.com/v0/agents/${params.agentId.trim()}`,
|
||||
method: 'DELETE',
|
||||
headers: (params: DeleteAgentParams) => ({
|
||||
Authorization: `Basic ${Buffer.from(`${params.apiKey}:`).toString('base64')}`,
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<DeleteAgentParams, any>, 'params' | 'request'>
|
||||
|
||||
export const deleteAgentTool: ToolConfig<DeleteAgentParams, DeleteAgentResponse> = {
|
||||
id: 'cursor_delete_agent',
|
||||
name: 'Cursor Delete Agent',
|
||||
description: 'Permanently delete a cloud agent. This action cannot be undone.',
|
||||
version: '1.0.0',
|
||||
|
||||
...deleteAgentBase,
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
|
||||
const content = `Agent ${data.id} has been deleted`
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
content,
|
||||
metadata: {
|
||||
id: data.id,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
content: { type: 'string', description: 'Success message' },
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Result metadata',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Agent ID' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
interface DeleteAgentV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
id: string
|
||||
}
|
||||
}
|
||||
|
||||
export const deleteAgentV2Tool: ToolConfig<DeleteAgentParams, DeleteAgentV2Response> = {
|
||||
...deleteAgentBase,
|
||||
id: 'cursor_delete_agent_v2',
|
||||
name: 'Cursor Delete Agent',
|
||||
description: 'Permanently delete a cloud agent. Returns API-aligned fields only.',
|
||||
version: '2.0.0',
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
},
|
||||
}
|
||||
},
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Agent ID' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
import type {
|
||||
DownloadArtifactParams,
|
||||
DownloadArtifactResponse,
|
||||
DownloadArtifactV2Response,
|
||||
} from '@/tools/cursor/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const downloadArtifactBase = {
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Cursor API key',
|
||||
},
|
||||
agentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Unique identifier for the cloud agent (e.g., bc_abc123)',
|
||||
},
|
||||
path: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Absolute path of the artifact to download (e.g., /src/index.ts)',
|
||||
},
|
||||
},
|
||||
request: {
|
||||
url: '/api/tools/cursor/download-artifact',
|
||||
method: 'POST',
|
||||
headers: () => ({
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params: DownloadArtifactParams) => ({
|
||||
apiKey: params.apiKey,
|
||||
agentId: params.agentId?.trim(),
|
||||
path: params.path?.trim(),
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<DownloadArtifactParams, any>, 'params' | 'request'>
|
||||
|
||||
export const downloadArtifactTool: ToolConfig<DownloadArtifactParams, DownloadArtifactResponse> = {
|
||||
id: 'cursor_download_artifact',
|
||||
name: 'Cursor Download Artifact',
|
||||
description: 'Download a generated artifact file from a cloud agent.',
|
||||
version: '1.0.0',
|
||||
|
||||
...downloadArtifactBase,
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!data.success) {
|
||||
throw new Error(data.error || 'Failed to download artifact')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
content: `Downloaded artifact: ${data.output.file.name}`,
|
||||
metadata: {
|
||||
name: data.output.file.name,
|
||||
mimeType: data.output.file.mimeType,
|
||||
data: data.output.file.data,
|
||||
size: data.output.file.size,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
content: { type: 'string', description: 'Human-readable download result' },
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Downloaded file metadata',
|
||||
properties: {
|
||||
name: { type: 'string', description: 'File name' },
|
||||
mimeType: { type: 'string', description: 'MIME type' },
|
||||
data: { type: 'string', description: 'Base64-encoded file contents' },
|
||||
size: { type: 'number', description: 'File size in bytes' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export const downloadArtifactV2Tool: ToolConfig<
|
||||
DownloadArtifactParams,
|
||||
DownloadArtifactV2Response
|
||||
> = {
|
||||
...downloadArtifactBase,
|
||||
id: 'cursor_download_artifact_v2',
|
||||
name: 'Cursor Download Artifact',
|
||||
description:
|
||||
'Download a generated artifact file from a cloud agent. Returns the file for execution storage.',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!data.success) {
|
||||
throw new Error(data.error || 'Failed to download artifact')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
file: data.output.file,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
file: {
|
||||
type: 'file',
|
||||
description: 'Downloaded artifact file stored in execution files',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
import type { GetAgentParams, GetAgentResponse } from '@/tools/cursor/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const getAgentBase = {
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Cursor API key',
|
||||
},
|
||||
agentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Unique identifier for the cloud agent (e.g., bc_abc123)',
|
||||
},
|
||||
},
|
||||
request: {
|
||||
url: (params: GetAgentParams) => `https://api.cursor.com/v0/agents/${params.agentId.trim()}`,
|
||||
method: 'GET',
|
||||
headers: (params: GetAgentParams) => ({
|
||||
Authorization: `Basic ${Buffer.from(`${params.apiKey}:`).toString('base64')}`,
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<GetAgentParams, any>, 'params' | 'request'>
|
||||
|
||||
export const getAgentTool: ToolConfig<GetAgentParams, GetAgentResponse> = {
|
||||
id: 'cursor_get_agent',
|
||||
name: 'Cursor Get Agent',
|
||||
description: 'Retrieve the current status and results of a cloud agent.',
|
||||
version: '1.0.0',
|
||||
|
||||
...getAgentBase,
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
content: `Agent "${data.name}" is ${data.status}`,
|
||||
metadata: data,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
content: { type: 'string', description: 'Human-readable agent details' },
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Agent metadata',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Agent ID' },
|
||||
name: { type: 'string', description: 'Agent name' },
|
||||
status: { type: 'string', description: 'Agent status' },
|
||||
source: { type: 'object', description: 'Source repository info' },
|
||||
target: { type: 'object', description: 'Target branch info' },
|
||||
summary: { type: 'string', description: 'Agent summary', optional: true },
|
||||
createdAt: { type: 'string', description: 'Creation timestamp' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
interface GetAgentV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
id: string
|
||||
name: string
|
||||
status: string
|
||||
source: Record<string, any>
|
||||
target: Record<string, any>
|
||||
summary?: string
|
||||
createdAt: string
|
||||
}
|
||||
}
|
||||
|
||||
export const getAgentV2Tool: ToolConfig<GetAgentParams, GetAgentV2Response> = {
|
||||
...getAgentBase,
|
||||
id: 'cursor_get_agent_v2',
|
||||
name: 'Cursor Get Agent',
|
||||
description:
|
||||
'Retrieve the current status and results of a cloud agent. Returns API-aligned fields only.',
|
||||
version: '2.0.0',
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
status: data.status,
|
||||
source: data.source,
|
||||
target: data.target,
|
||||
summary: data.summary ?? null,
|
||||
createdAt: data.createdAt,
|
||||
},
|
||||
}
|
||||
},
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Agent ID' },
|
||||
name: { type: 'string', description: 'Agent name' },
|
||||
status: { type: 'string', description: 'Agent status' },
|
||||
source: { type: 'json', description: 'Source repository info' },
|
||||
target: { type: 'json', description: 'Target branch/PR info' },
|
||||
summary: { type: 'string', description: 'Agent summary', optional: true },
|
||||
createdAt: { type: 'string', description: 'Creation timestamp' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
import type { GetApiKeyInfoParams, GetApiKeyInfoResponse } from '@/tools/cursor/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const getApiKeyInfoBase = {
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Cursor API key',
|
||||
},
|
||||
},
|
||||
request: {
|
||||
url: () => 'https://api.cursor.com/v0/me',
|
||||
method: 'GET',
|
||||
headers: (params: GetApiKeyInfoParams) => ({
|
||||
Authorization: `Basic ${Buffer.from(`${params.apiKey}:`).toString('base64')}`,
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<GetApiKeyInfoParams, any>, 'params' | 'request'>
|
||||
|
||||
export const getApiKeyInfoTool: ToolConfig<GetApiKeyInfoParams, GetApiKeyInfoResponse> = {
|
||||
id: 'cursor_get_api_key_info',
|
||||
name: 'Cursor Get API Key Info',
|
||||
description: 'Retrieve details about the API key currently in use.',
|
||||
version: '1.0.0',
|
||||
|
||||
...getApiKeyInfoBase,
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
content: `API key "${data.apiKeyName}" for ${data.userEmail}`,
|
||||
metadata: {
|
||||
apiKeyName: data.apiKeyName,
|
||||
createdAt: data.createdAt,
|
||||
userEmail: data.userEmail,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
content: { type: 'string', description: 'Human-readable API key summary' },
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'API key metadata',
|
||||
properties: {
|
||||
apiKeyName: { type: 'string', description: 'Name of the API key' },
|
||||
createdAt: { type: 'string', description: 'API key creation timestamp' },
|
||||
userEmail: { type: 'string', description: 'Email of the key owner' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
interface GetApiKeyInfoV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
apiKeyName: string
|
||||
createdAt: string
|
||||
userEmail: string
|
||||
}
|
||||
}
|
||||
|
||||
export const getApiKeyInfoV2Tool: ToolConfig<GetApiKeyInfoParams, GetApiKeyInfoV2Response> = {
|
||||
...getApiKeyInfoBase,
|
||||
id: 'cursor_get_api_key_info_v2',
|
||||
name: 'Cursor Get API Key Info',
|
||||
description:
|
||||
'Retrieve details about the API key currently in use. Returns API-aligned fields only.',
|
||||
version: '2.0.0',
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
apiKeyName: data.apiKeyName,
|
||||
createdAt: data.createdAt,
|
||||
userEmail: data.userEmail,
|
||||
},
|
||||
}
|
||||
},
|
||||
outputs: {
|
||||
apiKeyName: { type: 'string', description: 'Name of the API key' },
|
||||
createdAt: { type: 'string', description: 'API key creation timestamp' },
|
||||
userEmail: { type: 'string', description: 'Email of the key owner' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
import type { GetConversationParams, GetConversationResponse } from '@/tools/cursor/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const getConversationBase = {
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Cursor API key',
|
||||
},
|
||||
agentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Unique identifier for the cloud agent (e.g., bc_abc123)',
|
||||
},
|
||||
},
|
||||
request: {
|
||||
url: (params: GetConversationParams) =>
|
||||
`https://api.cursor.com/v0/agents/${params.agentId.trim()}/conversation`,
|
||||
method: 'GET',
|
||||
headers: (params: GetConversationParams) => ({
|
||||
Authorization: `Basic ${Buffer.from(`${params.apiKey}:`).toString('base64')}`,
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<GetConversationParams, any>, 'params' | 'request'>
|
||||
|
||||
export const getConversationTool: ToolConfig<GetConversationParams, GetConversationResponse> = {
|
||||
id: 'cursor_get_conversation',
|
||||
name: 'Cursor Get Conversation',
|
||||
description:
|
||||
'Retrieve the conversation history of a cloud agent, including all user prompts and assistant responses.',
|
||||
version: '1.0.0',
|
||||
|
||||
...getConversationBase,
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
content: `Retrieved ${data.messages.length} messages`,
|
||||
metadata: {
|
||||
id: data.id,
|
||||
messages: data.messages,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
content: { type: 'string', description: 'Human-readable conversation history' },
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Conversation metadata',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Agent ID' },
|
||||
messages: {
|
||||
type: 'array',
|
||||
description: 'Array of conversation messages',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
interface GetConversationV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
id: string
|
||||
messages: unknown[]
|
||||
}
|
||||
}
|
||||
|
||||
export const getConversationV2Tool: ToolConfig<GetConversationParams, GetConversationV2Response> = {
|
||||
...getConversationBase,
|
||||
id: 'cursor_get_conversation_v2',
|
||||
name: 'Cursor Get Conversation',
|
||||
description:
|
||||
'Retrieve the conversation history of a cloud agent, including all user prompts and assistant responses. Returns API-aligned fields only.',
|
||||
version: '2.0.0',
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
messages: data.messages,
|
||||
},
|
||||
}
|
||||
},
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Agent ID' },
|
||||
messages: { type: 'array', description: 'Array of conversation messages' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { addFollowupTool, addFollowupV2Tool } from '@/tools/cursor/add_followup'
|
||||
import { deleteAgentTool, deleteAgentV2Tool } from '@/tools/cursor/delete_agent'
|
||||
import { downloadArtifactTool, downloadArtifactV2Tool } from '@/tools/cursor/download_artifact'
|
||||
import { getAgentTool, getAgentV2Tool } from '@/tools/cursor/get_agent'
|
||||
import { getApiKeyInfoTool, getApiKeyInfoV2Tool } from '@/tools/cursor/get_api_key_info'
|
||||
import { getConversationTool, getConversationV2Tool } from '@/tools/cursor/get_conversation'
|
||||
import { launchAgentTool, launchAgentV2Tool } from '@/tools/cursor/launch_agent'
|
||||
import { listAgentsTool, listAgentsV2Tool } from '@/tools/cursor/list_agents'
|
||||
import { listArtifactsTool, listArtifactsV2Tool } from '@/tools/cursor/list_artifacts'
|
||||
import { listModelsTool, listModelsV2Tool } from '@/tools/cursor/list_models'
|
||||
import { listRepositoriesTool, listRepositoriesV2Tool } from '@/tools/cursor/list_repositories'
|
||||
import { stopAgentTool, stopAgentV2Tool } from '@/tools/cursor/stop_agent'
|
||||
|
||||
export const cursorListAgentsTool = listAgentsTool
|
||||
export const cursorGetAgentTool = getAgentTool
|
||||
export const cursorGetConversationTool = getConversationTool
|
||||
export const cursorLaunchAgentTool = launchAgentTool
|
||||
export const cursorAddFollowupTool = addFollowupTool
|
||||
export const cursorStopAgentTool = stopAgentTool
|
||||
export const cursorDeleteAgentTool = deleteAgentTool
|
||||
export const cursorDownloadArtifactTool = downloadArtifactTool
|
||||
export const cursorListArtifactsTool = listArtifactsTool
|
||||
export const cursorListModelsTool = listModelsTool
|
||||
export const cursorListRepositoriesTool = listRepositoriesTool
|
||||
export const cursorGetApiKeyInfoTool = getApiKeyInfoTool
|
||||
|
||||
export const cursorListAgentsV2Tool = listAgentsV2Tool
|
||||
export const cursorGetAgentV2Tool = getAgentV2Tool
|
||||
export const cursorGetConversationV2Tool = getConversationV2Tool
|
||||
export const cursorLaunchAgentV2Tool = launchAgentV2Tool
|
||||
export const cursorAddFollowupV2Tool = addFollowupV2Tool
|
||||
export const cursorStopAgentV2Tool = stopAgentV2Tool
|
||||
export const cursorDeleteAgentV2Tool = deleteAgentV2Tool
|
||||
export const cursorDownloadArtifactV2Tool = downloadArtifactV2Tool
|
||||
export const cursorListArtifactsV2Tool = listArtifactsV2Tool
|
||||
export const cursorListModelsV2Tool = listModelsV2Tool
|
||||
export const cursorListRepositoriesV2Tool = listRepositoriesV2Tool
|
||||
export const cursorGetApiKeyInfoV2Tool = getApiKeyInfoV2Tool
|
||||
@@ -0,0 +1,186 @@
|
||||
import type { LaunchAgentParams, LaunchAgentResponse } from '@/tools/cursor/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const launchAgentBase = {
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Cursor API key',
|
||||
},
|
||||
repository: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'GitHub repository URL (e.g., https://github.com/your-org/your-repo)',
|
||||
},
|
||||
ref: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Branch, tag, or commit to work from (defaults to default branch)',
|
||||
},
|
||||
promptText: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The instruction text for the agent',
|
||||
},
|
||||
promptImages: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'JSON array of image objects with base64 data and dimensions',
|
||||
},
|
||||
model: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Model to use (leave empty for auto-selection)',
|
||||
},
|
||||
branchName: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Custom branch name for the agent to use',
|
||||
},
|
||||
autoCreatePr: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Automatically create a PR when the agent finishes',
|
||||
},
|
||||
openAsCursorGithubApp: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Open the PR as the Cursor GitHub App',
|
||||
},
|
||||
skipReviewerRequest: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Skip requesting reviewers on the PR',
|
||||
},
|
||||
},
|
||||
request: {
|
||||
url: () => 'https://api.cursor.com/v0/agents',
|
||||
method: 'POST',
|
||||
headers: (params: LaunchAgentParams) => ({
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Basic ${Buffer.from(`${params.apiKey}:`).toString('base64')}`,
|
||||
}),
|
||||
body: (params: LaunchAgentParams) => {
|
||||
const body: Record<string, any> = {
|
||||
source: {
|
||||
repository: params.repository,
|
||||
},
|
||||
prompt: {
|
||||
text: params.promptText,
|
||||
},
|
||||
}
|
||||
|
||||
if (params.ref) {
|
||||
body.source.ref = params.ref
|
||||
}
|
||||
|
||||
if (params.promptImages) {
|
||||
try {
|
||||
body.prompt.images = JSON.parse(params.promptImages)
|
||||
} catch {
|
||||
body.prompt.images = []
|
||||
}
|
||||
}
|
||||
|
||||
if (params.model) {
|
||||
body.model = params.model
|
||||
}
|
||||
|
||||
const target: Record<string, any> = {}
|
||||
if (params.branchName) target.branchName = params.branchName
|
||||
if (typeof params.autoCreatePr === 'boolean') target.autoCreatePr = params.autoCreatePr
|
||||
if (typeof params.openAsCursorGithubApp === 'boolean')
|
||||
target.openAsCursorGithubApp = params.openAsCursorGithubApp
|
||||
if (typeof params.skipReviewerRequest === 'boolean')
|
||||
target.skipReviewerRequest = params.skipReviewerRequest
|
||||
|
||||
if (Object.keys(target).length > 0) {
|
||||
body.target = target
|
||||
}
|
||||
|
||||
return body
|
||||
},
|
||||
},
|
||||
} satisfies Pick<ToolConfig<LaunchAgentParams, any>, 'params' | 'request'>
|
||||
|
||||
export const launchAgentTool: ToolConfig<LaunchAgentParams, LaunchAgentResponse> = {
|
||||
id: 'cursor_launch_agent',
|
||||
name: 'Cursor Launch Agent',
|
||||
description:
|
||||
'Start a new cloud agent to work on a GitHub repository with the given instructions.',
|
||||
version: '1.0.0',
|
||||
|
||||
...launchAgentBase,
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
const agentUrl = `https://cursor.com/agents?selectedBcId=${data.id}`
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
content: 'Agent launched successfully!',
|
||||
metadata: {
|
||||
id: data.id,
|
||||
url: agentUrl,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
content: { type: 'string', description: 'Success message with agent details' },
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Launch result metadata',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Agent ID' },
|
||||
url: { type: 'string', description: 'Agent URL' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
interface LaunchAgentV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
id: string
|
||||
url: string
|
||||
}
|
||||
}
|
||||
|
||||
export const launchAgentV2Tool: ToolConfig<LaunchAgentParams, LaunchAgentV2Response> = {
|
||||
...launchAgentBase,
|
||||
id: 'cursor_launch_agent_v2',
|
||||
name: 'Cursor Launch Agent',
|
||||
description:
|
||||
'Start a new cloud agent to work on a GitHub repository with the given instructions. Returns API-aligned fields only.',
|
||||
version: '2.0.0',
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
const agentUrl = `https://cursor.com/agents?selectedBcId=${data.id}`
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
url: agentUrl,
|
||||
},
|
||||
}
|
||||
},
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Agent ID' },
|
||||
url: { type: 'string', description: 'Agent URL' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
import type { ListAgentsParams, ListAgentsResponse } from '@/tools/cursor/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const listAgentsBase = {
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Cursor API key',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of agents to return (default: 20, max: 100)',
|
||||
},
|
||||
cursor: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Pagination cursor from previous response',
|
||||
},
|
||||
prUrl: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter agents by pull request URL',
|
||||
},
|
||||
},
|
||||
request: {
|
||||
url: (params: ListAgentsParams) => {
|
||||
const url = new URL('https://api.cursor.com/v0/agents')
|
||||
if (params.limit) url.searchParams.set('limit', String(params.limit))
|
||||
if (params.cursor) url.searchParams.set('cursor', params.cursor)
|
||||
if (params.prUrl) url.searchParams.set('prUrl', params.prUrl)
|
||||
return url.toString()
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params: ListAgentsParams) => ({
|
||||
Authorization: `Basic ${Buffer.from(`${params.apiKey}:`).toString('base64')}`,
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<ListAgentsParams, any>, 'params' | 'request'>
|
||||
|
||||
export const listAgentsTool: ToolConfig<ListAgentsParams, ListAgentsResponse> = {
|
||||
id: 'cursor_list_agents',
|
||||
name: 'Cursor List Agents',
|
||||
description: 'List all cloud agents for the authenticated user with optional pagination.',
|
||||
version: '1.0.0',
|
||||
|
||||
...listAgentsBase,
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
content: `Found ${data.agents.length} agents`,
|
||||
metadata: {
|
||||
agents: data.agents,
|
||||
nextCursor: data.nextCursor ?? null,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
content: { type: 'string', description: 'Human-readable list of agents' },
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Agent list metadata',
|
||||
properties: {
|
||||
agents: {
|
||||
type: 'array',
|
||||
description: 'Array of agent objects',
|
||||
},
|
||||
nextCursor: {
|
||||
type: 'string',
|
||||
description: 'Pagination cursor for next page',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
interface ListAgentsV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
agents: unknown[]
|
||||
nextCursor?: string
|
||||
}
|
||||
}
|
||||
|
||||
export const listAgentsV2Tool: ToolConfig<ListAgentsParams, ListAgentsV2Response> = {
|
||||
...listAgentsBase,
|
||||
id: 'cursor_list_agents_v2',
|
||||
name: 'Cursor List Agents',
|
||||
description:
|
||||
'List all cloud agents for the authenticated user with optional pagination. Returns API-aligned fields only.',
|
||||
version: '2.0.0',
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
agents: data.agents,
|
||||
nextCursor: data.nextCursor ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
outputs: {
|
||||
agents: { type: 'array', description: 'Array of agent objects' },
|
||||
nextCursor: { type: 'string', description: 'Pagination cursor for next page', optional: true },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
import type { ListArtifactsParams, ListArtifactsResponse } from '@/tools/cursor/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const listArtifactsBase = {
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Cursor API key',
|
||||
},
|
||||
agentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Unique identifier for the cloud agent (e.g., bc_abc123)',
|
||||
},
|
||||
},
|
||||
request: {
|
||||
url: (params: ListArtifactsParams) =>
|
||||
`https://api.cursor.com/v0/agents/${params.agentId.trim()}/artifacts`,
|
||||
method: 'GET',
|
||||
headers: (params: ListArtifactsParams) => ({
|
||||
Authorization: `Basic ${Buffer.from(`${params.apiKey}:`).toString('base64')}`,
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<ListArtifactsParams, any>, 'params' | 'request'>
|
||||
|
||||
export const listArtifactsTool: ToolConfig<ListArtifactsParams, ListArtifactsResponse> = {
|
||||
id: 'cursor_list_artifacts',
|
||||
name: 'Cursor List Artifacts',
|
||||
description: 'List generated artifact files for a cloud agent.',
|
||||
version: '1.0.0',
|
||||
|
||||
...listArtifactsBase,
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
const artifacts = data.artifacts ?? []
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
content: `Found ${artifacts.length} artifact(s)`,
|
||||
metadata: {
|
||||
artifacts,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
content: { type: 'string', description: 'Human-readable artifact count' },
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Artifacts metadata',
|
||||
properties: {
|
||||
artifacts: {
|
||||
type: 'array',
|
||||
description: 'List of artifacts',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
path: { type: 'string', description: 'Artifact file path' },
|
||||
size: { type: 'number', description: 'File size in bytes', optional: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
interface ListArtifactsV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
artifacts: Array<{ path: string; size?: number }>
|
||||
}
|
||||
}
|
||||
|
||||
export const listArtifactsV2Tool: ToolConfig<ListArtifactsParams, ListArtifactsV2Response> = {
|
||||
...listArtifactsBase,
|
||||
id: 'cursor_list_artifacts_v2',
|
||||
name: 'Cursor List Artifacts',
|
||||
description: 'List generated artifact files for a cloud agent. Returns API-aligned fields only.',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
const artifacts = data.artifacts ?? []
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
artifacts: Array.isArray(artifacts) ? artifacts : [],
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
artifacts: {
|
||||
type: 'array',
|
||||
description: 'List of artifact files',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
path: { type: 'string', description: 'Artifact file path' },
|
||||
size: { type: 'number', description: 'File size in bytes', optional: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
import type { ListModelsParams, ListModelsResponse } from '@/tools/cursor/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const listModelsBase = {
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Cursor API key',
|
||||
},
|
||||
},
|
||||
request: {
|
||||
url: () => 'https://api.cursor.com/v0/models',
|
||||
method: 'GET',
|
||||
headers: (params: ListModelsParams) => ({
|
||||
Authorization: `Basic ${Buffer.from(`${params.apiKey}:`).toString('base64')}`,
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<ListModelsParams, any>, 'params' | 'request'>
|
||||
|
||||
export const listModelsTool: ToolConfig<ListModelsParams, ListModelsResponse> = {
|
||||
id: 'cursor_list_models',
|
||||
name: 'Cursor List Models',
|
||||
description: 'List the models available for launching cloud agents.',
|
||||
version: '1.0.0',
|
||||
|
||||
...listModelsBase,
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
const models = data.models ?? []
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
content: `Found ${models.length} model(s)`,
|
||||
metadata: {
|
||||
models,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
content: { type: 'string', description: 'Human-readable model count' },
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Models metadata',
|
||||
properties: {
|
||||
models: {
|
||||
type: 'array',
|
||||
description: 'Array of available model names',
|
||||
items: { type: 'string', description: 'Model name' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
interface ListModelsV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
models: string[]
|
||||
}
|
||||
}
|
||||
|
||||
export const listModelsV2Tool: ToolConfig<ListModelsParams, ListModelsV2Response> = {
|
||||
...listModelsBase,
|
||||
id: 'cursor_list_models_v2',
|
||||
name: 'Cursor List Models',
|
||||
description:
|
||||
'List the models available for launching cloud agents. Returns API-aligned fields only.',
|
||||
version: '2.0.0',
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
models: Array.isArray(data.models) ? data.models : [],
|
||||
},
|
||||
}
|
||||
},
|
||||
outputs: {
|
||||
models: {
|
||||
type: 'array',
|
||||
description: 'Array of available model names',
|
||||
items: { type: 'string', description: 'Model name' },
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
import type { ListRepositoriesParams, ListRepositoriesResponse } from '@/tools/cursor/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const listRepositoriesBase = {
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Cursor API key',
|
||||
},
|
||||
},
|
||||
request: {
|
||||
url: () => 'https://api.cursor.com/v0/repositories',
|
||||
method: 'GET',
|
||||
headers: (params: ListRepositoriesParams) => ({
|
||||
Authorization: `Basic ${Buffer.from(`${params.apiKey}:`).toString('base64')}`,
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<ListRepositoriesParams, any>, 'params' | 'request'>
|
||||
|
||||
export const listRepositoriesTool: ToolConfig<ListRepositoriesParams, ListRepositoriesResponse> = {
|
||||
id: 'cursor_list_repositories',
|
||||
name: 'Cursor List Repositories',
|
||||
description: 'List the GitHub repositories accessible to the authenticated user.',
|
||||
version: '1.0.0',
|
||||
|
||||
...listRepositoriesBase,
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
const repositories = data.repositories ?? []
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
content: `Found ${repositories.length} repository(ies)`,
|
||||
metadata: {
|
||||
repositories,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
content: { type: 'string', description: 'Human-readable repository count' },
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Repositories metadata',
|
||||
properties: {
|
||||
repositories: {
|
||||
type: 'array',
|
||||
description: 'Array of accessible repositories',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
owner: { type: 'string', description: 'Repository owner' },
|
||||
name: { type: 'string', description: 'Repository name' },
|
||||
repository: { type: 'string', description: 'Repository URL' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
interface ListRepositoriesV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
repositories: Array<{ owner: string; name: string; repository: string }>
|
||||
}
|
||||
}
|
||||
|
||||
export const listRepositoriesV2Tool: ToolConfig<
|
||||
ListRepositoriesParams,
|
||||
ListRepositoriesV2Response
|
||||
> = {
|
||||
...listRepositoriesBase,
|
||||
id: 'cursor_list_repositories_v2',
|
||||
name: 'Cursor List Repositories',
|
||||
description:
|
||||
'List the GitHub repositories accessible to the authenticated user. Returns API-aligned fields only.',
|
||||
version: '2.0.0',
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
repositories: Array.isArray(data.repositories) ? data.repositories : [],
|
||||
},
|
||||
}
|
||||
},
|
||||
outputs: {
|
||||
repositories: {
|
||||
type: 'array',
|
||||
description: 'Array of accessible repositories',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
owner: { type: 'string', description: 'Repository owner' },
|
||||
name: { type: 'string', description: 'Repository name' },
|
||||
repository: { type: 'string', description: 'Repository URL' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
import type { StopAgentParams, StopAgentResponse } from '@/tools/cursor/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const stopAgentBase = {
|
||||
params: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Cursor API key',
|
||||
},
|
||||
agentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Unique identifier for the cloud agent (e.g., bc_abc123)',
|
||||
},
|
||||
},
|
||||
request: {
|
||||
url: (params: StopAgentParams) =>
|
||||
`https://api.cursor.com/v0/agents/${params.agentId.trim()}/stop`,
|
||||
method: 'POST',
|
||||
headers: (params: StopAgentParams) => ({
|
||||
Authorization: `Basic ${Buffer.from(`${params.apiKey}:`).toString('base64')}`,
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<StopAgentParams, any>, 'params' | 'request'>
|
||||
|
||||
export const stopAgentTool: ToolConfig<StopAgentParams, StopAgentResponse> = {
|
||||
id: 'cursor_stop_agent',
|
||||
name: 'Cursor Stop Agent',
|
||||
description: 'Stop a running cloud agent. This pauses the agent without deleting it.',
|
||||
version: '1.0.0',
|
||||
|
||||
...stopAgentBase,
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
|
||||
const content = `Agent ${data.id} has been stopped`
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
content,
|
||||
metadata: {
|
||||
id: data.id,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
content: { type: 'string', description: 'Success message' },
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Result metadata',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Agent ID' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
interface StopAgentV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
id: string
|
||||
}
|
||||
}
|
||||
|
||||
export const stopAgentV2Tool: ToolConfig<StopAgentParams, StopAgentV2Response> = {
|
||||
...stopAgentBase,
|
||||
id: 'cursor_stop_agent_v2',
|
||||
name: 'Cursor Stop Agent',
|
||||
description: 'Stop a running cloud agent. Returns API-aligned fields only.',
|
||||
version: '2.0.0',
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
},
|
||||
}
|
||||
},
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Agent ID' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
import type { ToolResponse } from '@/tools/types'
|
||||
|
||||
interface BaseCursorParams {
|
||||
apiKey: string
|
||||
}
|
||||
|
||||
export interface ListAgentsParams extends BaseCursorParams {
|
||||
limit?: number
|
||||
cursor?: string
|
||||
prUrl?: string
|
||||
}
|
||||
|
||||
export interface GetAgentParams extends BaseCursorParams {
|
||||
agentId: string
|
||||
}
|
||||
|
||||
export interface GetConversationParams extends BaseCursorParams {
|
||||
agentId: string
|
||||
}
|
||||
|
||||
export interface LaunchAgentParams extends BaseCursorParams {
|
||||
repository: string
|
||||
ref?: string
|
||||
promptText: string
|
||||
promptImages?: string
|
||||
model?: string
|
||||
branchName?: string
|
||||
autoCreatePr?: boolean
|
||||
openAsCursorGithubApp?: boolean
|
||||
skipReviewerRequest?: boolean
|
||||
}
|
||||
|
||||
export interface AddFollowupParams extends BaseCursorParams {
|
||||
agentId: string
|
||||
followupPromptText: string
|
||||
promptImages?: string
|
||||
}
|
||||
|
||||
export interface StopAgentParams extends BaseCursorParams {
|
||||
agentId: string
|
||||
}
|
||||
|
||||
export interface DeleteAgentParams extends BaseCursorParams {
|
||||
agentId: string
|
||||
}
|
||||
|
||||
export type ListModelsParams = BaseCursorParams
|
||||
|
||||
export type ListRepositoriesParams = BaseCursorParams
|
||||
|
||||
export type GetApiKeyInfoParams = BaseCursorParams
|
||||
|
||||
interface AgentSource {
|
||||
repository: string
|
||||
ref: string
|
||||
}
|
||||
|
||||
interface AgentTarget {
|
||||
branchName: string
|
||||
url: string
|
||||
prUrl?: string
|
||||
autoCreatePr: boolean
|
||||
openAsCursorGithubApp?: boolean
|
||||
skipReviewerRequest?: boolean
|
||||
}
|
||||
|
||||
interface AgentMetadata {
|
||||
id: string
|
||||
name: string
|
||||
status: string
|
||||
source: AgentSource
|
||||
target: AgentTarget
|
||||
summary?: string
|
||||
createdAt: string
|
||||
}
|
||||
|
||||
interface ConversationMessage {
|
||||
id: string
|
||||
type: 'user_message' | 'assistant_message'
|
||||
text: string
|
||||
}
|
||||
|
||||
interface RepositoryMetadata {
|
||||
owner: string
|
||||
name: string
|
||||
repository: string
|
||||
}
|
||||
|
||||
interface ApiKeyInfoMetadata {
|
||||
apiKeyName: string
|
||||
createdAt: string
|
||||
userEmail: string
|
||||
}
|
||||
|
||||
export interface ListAgentsResponse extends ToolResponse {
|
||||
output: {
|
||||
content: string
|
||||
metadata: {
|
||||
agents: AgentMetadata[]
|
||||
nextCursor?: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface GetAgentResponse extends ToolResponse {
|
||||
output: {
|
||||
content: string
|
||||
metadata: AgentMetadata
|
||||
}
|
||||
}
|
||||
|
||||
export interface GetConversationResponse extends ToolResponse {
|
||||
output: {
|
||||
content: string
|
||||
metadata: {
|
||||
id: string
|
||||
messages: ConversationMessage[]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface LaunchAgentResponse extends ToolResponse {
|
||||
output: {
|
||||
content: string
|
||||
metadata: {
|
||||
id: string
|
||||
url: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface AddFollowupResponse extends ToolResponse {
|
||||
output: {
|
||||
content: string
|
||||
metadata: {
|
||||
id: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface StopAgentResponse extends ToolResponse {
|
||||
output: {
|
||||
content: string
|
||||
metadata: {
|
||||
id: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface DeleteAgentResponse extends ToolResponse {
|
||||
output: {
|
||||
content: string
|
||||
metadata: {
|
||||
id: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface GetApiKeyInfoResponse extends ToolResponse {
|
||||
output: {
|
||||
content: string
|
||||
metadata: ApiKeyInfoMetadata
|
||||
}
|
||||
}
|
||||
|
||||
export interface ListModelsResponse extends ToolResponse {
|
||||
output: {
|
||||
content: string
|
||||
metadata: {
|
||||
models: string[]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface ListRepositoriesResponse extends ToolResponse {
|
||||
output: {
|
||||
content: string
|
||||
metadata: {
|
||||
repositories: RepositoryMetadata[]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface ListArtifactsParams extends BaseCursorParams {
|
||||
agentId: string
|
||||
}
|
||||
|
||||
interface ArtifactMetadata {
|
||||
path: string
|
||||
size?: number
|
||||
}
|
||||
|
||||
export interface ListArtifactsResponse extends ToolResponse {
|
||||
output: {
|
||||
content: string
|
||||
metadata: {
|
||||
artifacts: ArtifactMetadata[]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface DownloadArtifactParams extends BaseCursorParams {
|
||||
agentId: string
|
||||
path: string
|
||||
}
|
||||
|
||||
export interface DownloadArtifactResponse extends ToolResponse {
|
||||
output: {
|
||||
content: string
|
||||
metadata: {
|
||||
name: string
|
||||
mimeType: string
|
||||
data: string
|
||||
size: number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface DownloadArtifactV2Response extends ToolResponse {
|
||||
output: {
|
||||
file: {
|
||||
name: string
|
||||
mimeType: string
|
||||
data: string
|
||||
size: number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export type CursorResponse =
|
||||
| ListAgentsResponse
|
||||
| GetAgentResponse
|
||||
| GetConversationResponse
|
||||
| LaunchAgentResponse
|
||||
| AddFollowupResponse
|
||||
| StopAgentResponse
|
||||
| DeleteAgentResponse
|
||||
| GetApiKeyInfoResponse
|
||||
| ListModelsResponse
|
||||
| ListRepositoriesResponse
|
||||
| ListArtifactsResponse
|
||||
| DownloadArtifactResponse
|
||||
| DownloadArtifactV2Response
|
||||
Reference in New Issue
Block a user