diff --git a/apps/docs/content/docs/en/tools/cursor.mdx b/apps/docs/content/docs/en/tools/cursor.mdx index 4e6f165c014..e182f7ddd5c 100644 --- a/apps/docs/content/docs/en/tools/cursor.mdx +++ b/apps/docs/content/docs/en/tools/cursor.mdx @@ -211,4 +211,57 @@ Download a generated artifact file from a cloud agent. Returns the file for exec | --------- | ---- | ----------- | | `file` | file | Downloaded artifact file stored in execution files | +### `cursor_list_models` + +List the models available for launching cloud agents. Returns API-aligned fields only. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Cursor API key | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `models` | array | Array of available model names | + +### `cursor_list_repositories` + +List the GitHub repositories accessible to the authenticated user. Returns API-aligned fields only. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Cursor API key | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `repositories` | array | Array of accessible repositories | +| ↳ `owner` | string | Repository owner | +| ↳ `name` | string | Repository name | +| ↳ `repository` | string | Repository URL | + +### `cursor_get_api_key_info` + +Retrieve details about the API key currently in use. Returns API-aligned fields only. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Cursor API key | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `apiKeyName` | string | Name of the API key | +| `createdAt` | string | API key creation timestamp | +| `userEmail` | string | Email of the key owner | + diff --git a/apps/docs/content/docs/en/tools/devin.mdx b/apps/docs/content/docs/en/tools/devin.mdx index 4ea369fcccb..eb38d6a03c1 100644 --- a/apps/docs/content/docs/en/tools/devin.mdx +++ b/apps/docs/content/docs/en/tools/devin.mdx @@ -50,6 +50,7 @@ Create a new Devin session with a prompt. Devin will autonomously work on the ta | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | | `apiKey` | string | Yes | Devin API key \(service user credential starting with cog_\) | +| `orgId` | string | Yes | Devin organization ID \(prefixed with org-\) | | `prompt` | string | Yes | The task prompt for Devin to work on | | `playbookId` | string | No | Optional playbook ID to guide the session | | `maxAcuLimit` | number | No | Maximum ACU limit for the session | @@ -67,10 +68,11 @@ Create a new Devin session with a prompt. Devin will autonomously work on the ta | `createdAt` | number | Unix timestamp when the session was created | | `updatedAt` | number | Unix timestamp when the session was last updated | | `acusConsumed` | number | ACUs consumed by the session | -| `tags` | json | Tags associated with the session | -| `pullRequests` | json | Pull requests created during the session | +| `tags` | json | Tags associated with the session \(array of strings\) | +| `pullRequests` | json | Pull requests created during the session \(\[\{pr_url, pr_state\}\]\) | | `structuredOutput` | json | Structured output from the session | | `playbookId` | string | Associated playbook ID | +| `isArchived` | boolean | Whether the session is archived | ### `devin_get_session` @@ -81,6 +83,7 @@ Retrieve details of an existing Devin session including status, tags, pull reque | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | | `apiKey` | string | Yes | Devin API key \(service user credential starting with cog_\) | +| `orgId` | string | Yes | Devin organization ID \(prefixed with org-\) | | `sessionId` | string | Yes | The session ID to retrieve | #### Output @@ -95,10 +98,11 @@ Retrieve details of an existing Devin session including status, tags, pull reque | `createdAt` | number | Unix timestamp when the session was created | | `updatedAt` | number | Unix timestamp when the session was last updated | | `acusConsumed` | number | ACUs consumed by the session | -| `tags` | json | Tags associated with the session | -| `pullRequests` | json | Pull requests created during the session | +| `tags` | json | Tags associated with the session \(array of strings\) | +| `pullRequests` | json | Pull requests created during the session \(\[\{pr_url, pr_state\}\]\) | | `structuredOutput` | json | Structured output from the session | | `playbookId` | string | Associated playbook ID | +| `isArchived` | boolean | Whether the session is archived | ### `devin_list_sessions` @@ -109,7 +113,9 @@ List Devin sessions in the organization. Returns up to 100 sessions by default. | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | | `apiKey` | string | Yes | Devin API key \(service user credential starting with cog_\) | +| `orgId` | string | Yes | Devin organization ID \(prefixed with org-\) | | `limit` | number | No | Maximum number of sessions to return \(1-200, default: 100\) | +| `after` | string | No | Pagination cursor \(endCursor from a previous response\) to fetch the next page | #### Output @@ -123,7 +129,14 @@ List Devin sessions in the organization. Returns up to 100 sessions by default. | ↳ `title` | string | Session title | | ↳ `createdAt` | number | Creation timestamp \(Unix\) | | ↳ `updatedAt` | number | Last updated timestamp \(Unix\) | -| ↳ `tags` | json | Session tags | +| ↳ `tags` | json | Session tags \(array of strings\) | +| ↳ `acusConsumed` | number | ACUs consumed by the session | +| ↳ `pullRequests` | json | Pull requests created during the session \(\[\{pr_url, pr_state\}\]\) | +| ↳ `playbookId` | string | Associated playbook ID | +| ↳ `isArchived` | boolean | Whether the session is archived | +| `endCursor` | string | Pagination cursor for the next page, or null if last page | +| `hasNextPage` | boolean | Whether more sessions are available | +| `total` | number | Total number of sessions, if provided | ### `devin_send_message` @@ -134,6 +147,7 @@ Send a message to a Devin session. If the session is suspended, it will be autom | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | | `apiKey` | string | Yes | Devin API key \(service user credential starting with cog_\) | +| `orgId` | string | Yes | Devin organization ID \(prefixed with org-\) | | `sessionId` | string | Yes | The session ID to send the message to | | `message` | string | Yes | The message to send to Devin | @@ -149,9 +163,177 @@ Send a message to a Devin session. If the session is suspended, it will be autom | `createdAt` | number | Unix timestamp when the session was created | | `updatedAt` | number | Unix timestamp when the session was last updated | | `acusConsumed` | number | ACUs consumed by the session | -| `tags` | json | Tags associated with the session | -| `pullRequests` | json | Pull requests created during the session | +| `tags` | json | Tags associated with the session \(array of strings\) | +| `pullRequests` | json | Pull requests created during the session \(\[\{pr_url, pr_state\}\]\) | | `structuredOutput` | json | Structured output from the session | | `playbookId` | string | Associated playbook ID | +| `isArchived` | boolean | Whether the session is archived | + +### `devin_list_session_messages` + +List the messages exchanged in a Devin session, including messages from both the user and Devin. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Devin API key \(service user credential starting with cog_\) | +| `orgId` | string | Yes | Devin organization ID \(prefixed with org-\) | +| `sessionId` | string | Yes | The session ID to list messages for | +| `limit` | number | No | Maximum number of messages to return \(1-200, default: 100\) | +| `after` | string | No | Pagination cursor \(endCursor from a previous response\) to fetch the next page | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `messages` | array | Messages exchanged in the session | +| ↳ `eventId` | string | Unique identifier for the message event | +| ↳ `source` | string | Origin of the message \(devin or user\) | +| ↳ `message` | string | The message content | +| ↳ `createdAt` | number | Unix timestamp when the message was created | +| `endCursor` | string | Pagination cursor for the next page, or null if last page | +| `hasNextPage` | boolean | Whether more messages are available | +| `total` | number | Total number of messages, if provided | + +### `devin_list_session_attachments` + +List the files uploaded to or produced by a Devin session. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Devin API key \(service user credential starting with cog_\) | +| `orgId` | string | Yes | Devin organization ID \(prefixed with org-\) | +| `sessionId` | string | Yes | The session ID to list attachments for | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `attachments` | array | Attachments associated with the session | +| ↳ `attachmentId` | string | Unique identifier for the attachment | +| ↳ `name` | string | Attachment file name | +| ↳ `url` | string | URL to download the attachment | +| ↳ `source` | string | Origin of the attachment \(devin or user\) | +| ↳ `contentType` | string | MIME type of the attachment | + +### `devin_get_session_tags` + +Retrieve the tags currently applied to a Devin session. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Devin API key \(service user credential starting with cog_\) | +| `orgId` | string | Yes | Devin organization ID \(prefixed with org-\) | +| `sessionId` | string | Yes | The session ID to retrieve tags for | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `tags` | json | Tags applied to the session \(array of strings\) | + +### `devin_append_session_tags` + +Add tags to a Devin session without removing existing tags (max 50 tags total). + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Devin API key \(service user credential starting with cog_\) | +| `orgId` | string | Yes | Devin organization ID \(prefixed with org-\) | +| `sessionId` | string | Yes | The session ID to add tags to | +| `tags` | string | Yes | Tags to append to the session \(comma-separated string or array of strings\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `tags` | json | Updated list of tags on the session \(array of strings\) | + +### `devin_replace_session_tags` + +Replace all tags on a Devin session with a new set of tags (max 50 tags). + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Devin API key \(service user credential starting with cog_\) | +| `orgId` | string | Yes | Devin organization ID \(prefixed with org-\) | +| `sessionId` | string | Yes | The session ID to replace tags on | +| `tags` | string | Yes | Tags that will overwrite the existing tags \(comma-separated string or array of strings\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `tags` | json | Updated list of tags on the session \(array of strings\) | + +### `devin_archive_session` + +Archive a Devin session. Archived sessions can still be viewed but cannot be modified or resumed. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Devin API key \(service user credential starting with cog_\) | +| `orgId` | string | Yes | Devin organization ID \(prefixed with org-\) | +| `sessionId` | string | Yes | The session ID to archive | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `sessionId` | string | Unique identifier for the session | +| `url` | string | URL to view the session in the Devin UI | +| `status` | string | Session status \(new, claimed, running, exit, error, suspended, resuming\) | +| `statusDetail` | string | Detailed status \(working, waiting_for_user, waiting_for_approval, finished, inactivity, etc.\) | +| `title` | string | Session title | +| `createdAt` | number | Unix timestamp when the session was created | +| `updatedAt` | number | Unix timestamp when the session was last updated | +| `acusConsumed` | number | ACUs consumed by the session | +| `tags` | json | Tags associated with the session \(array of strings\) | +| `pullRequests` | json | Pull requests created during the session \(\[\{pr_url, pr_state\}\]\) | +| `structuredOutput` | json | Structured output from the session | +| `playbookId` | string | Associated playbook ID | +| `isArchived` | boolean | Whether the session is archived | + +### `devin_terminate_session` + +Terminate a Devin session. Optionally archive the session instead of permanently terminating it. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Devin API key \(service user credential starting with cog_\) | +| `orgId` | string | Yes | Devin organization ID \(prefixed with org-\) | +| `sessionId` | string | Yes | The session ID to terminate | +| `archive` | boolean | No | Archive the session instead of permanently terminating it \(default: false\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `sessionId` | string | Unique identifier for the session | +| `url` | string | URL to view the session in the Devin UI | +| `status` | string | Session status \(new, claimed, running, exit, error, suspended, resuming\) | +| `statusDetail` | string | Detailed status \(working, waiting_for_user, waiting_for_approval, finished, inactivity, etc.\) | +| `title` | string | Session title | +| `createdAt` | number | Unix timestamp when the session was created | +| `updatedAt` | number | Unix timestamp when the session was last updated | +| `acusConsumed` | number | ACUs consumed by the session | +| `tags` | json | Tags associated with the session \(array of strings\) | +| `pullRequests` | json | Pull requests created during the session \(\[\{pr_url, pr_state\}\]\) | +| `structuredOutput` | json | Structured output from the session | +| `playbookId` | string | Associated playbook ID | +| `isArchived` | boolean | Whether the session is archived | diff --git a/apps/docs/content/docs/en/tools/greptile.mdx b/apps/docs/content/docs/en/tools/greptile.mdx index 7132bbb131c..1e3aed3929a 100644 --- a/apps/docs/content/docs/en/tools/greptile.mdx +++ b/apps/docs/content/docs/en/tools/greptile.mdx @@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/sim/app/(landing)/integrations/data/integrations.json b/apps/sim/app/(landing)/integrations/data/integrations.json index fc8e6b61cb1..8d7bec0c5ed 100644 --- a/apps/sim/app/(landing)/integrations/data/integrations.json +++ b/apps/sim/app/(landing)/integrations/data/integrations.json @@ -3052,9 +3052,21 @@ { "name": "Download Artifact", "description": "Download a generated artifact file from a cloud agent." + }, + { + "name": "List Models", + "description": "List the models available for launching cloud agents." + }, + { + "name": "List Repositories", + "description": "List the GitHub repositories accessible to the authenticated user." + }, + { + "name": "Get API Key Info", + "description": "Retrieve details about the API key currently in use." } ], - "operationCount": 9, + "operationCount": 12, "triggers": [], "triggerCount": 0, "authType": "api-key", @@ -3298,9 +3310,37 @@ { "name": "Send Message", "description": "Send a message to a Devin session. If the session is suspended, it will be automatically resumed. Returns the updated session state." + }, + { + "name": "List Session Messages", + "description": "List the messages exchanged in a Devin session, including messages from both the user and Devin." + }, + { + "name": "List Session Attachments", + "description": "List the files uploaded to or produced by a Devin session." + }, + { + "name": "Get Session Tags", + "description": "Retrieve the tags currently applied to a Devin session." + }, + { + "name": "Append Session Tags", + "description": "Add tags to a Devin session without removing existing tags (max 50 tags total)." + }, + { + "name": "Replace Session Tags", + "description": "Replace all tags on a Devin session with a new set of tags (max 50 tags)." + }, + { + "name": "Archive Session", + "description": "Archive a Devin session. Archived sessions can still be viewed but cannot be modified or resumed." + }, + { + "name": "Terminate Session", + "description": "Terminate a Devin session. Optionally archive the session instead of permanently terminating it." } ], - "operationCount": 4, + "operationCount": 11, "triggers": [], "triggerCount": 0, "authType": "api-key", @@ -6470,7 +6510,7 @@ "name": "Greptile", "description": "AI-powered codebase search and Q&A", "longDescription": "Query and search codebases using natural language with Greptile. Get AI-generated answers about your code, find relevant files, and understand complex codebases.", - "bgColor": "#e5e5e5", + "bgColor": "#5DE195", "iconName": "GreptileIcon", "docsUrl": "https://docs.sim.ai/tools/greptile", "operations": [ diff --git a/apps/sim/blocks/blocks/cursor.ts b/apps/sim/blocks/blocks/cursor.ts index b6ef6a52411..c4ef939e766 100644 --- a/apps/sim/blocks/blocks/cursor.ts +++ b/apps/sim/blocks/blocks/cursor.ts @@ -33,6 +33,9 @@ export const CursorBlock: BlockConfig = { { label: 'Delete Agent', id: 'cursor_delete_agent' }, { label: 'List Artifacts', id: 'cursor_list_artifacts' }, { label: 'Download Artifact', id: 'cursor_download_artifact' }, + { label: 'List Models', id: 'cursor_list_models' }, + { label: 'List Repositories', id: 'cursor_list_repositories' }, + { label: 'Get API Key Info', id: 'cursor_get_api_key_info' }, ], value: () => 'cursor_launch_agent', }, @@ -183,6 +186,9 @@ export const CursorBlock: BlockConfig = { 'cursor_delete_agent', 'cursor_list_artifacts', 'cursor_download_artifact', + 'cursor_list_models', + 'cursor_list_repositories', + 'cursor_get_api_key_info', ], config: { tool: (params) => params.operation || 'cursor_launch_agent', @@ -236,6 +242,9 @@ export const CursorV2Block: BlockConfig = { 'cursor_delete_agent_v2', 'cursor_list_artifacts_v2', 'cursor_download_artifact_v2', + 'cursor_list_models_v2', + 'cursor_list_repositories_v2', + 'cursor_get_api_key_info_v2', ], config: { tool: createVersionedToolSelector({ @@ -253,11 +262,19 @@ export const CursorV2Block: BlockConfig = { source: { type: 'json', description: 'Agent source repository info' }, target: { type: 'json', description: 'Agent target branch/PR info' }, summary: { type: 'string', description: 'Agent summary' }, - createdAt: { type: 'string', description: 'Agent creation timestamp' }, + createdAt: { type: 'string', description: 'Creation timestamp (agent or API key)' }, agents: { type: 'json', description: 'Array of agent objects (list operation)' }, nextCursor: { type: 'string', description: 'Pagination cursor (list operation)' }, messages: { type: 'json', description: 'Conversation messages (get conversation operation)' }, artifacts: { type: 'json', description: 'List of artifact files (list artifacts operation)' }, file: { type: 'file', description: 'Downloaded artifact file (download artifact operation)' }, + models: { type: 'json', description: 'Available model names (list models operation)' }, + repositories: { + type: 'json', + description: + 'Accessible repositories [{owner, name, repository}] (list repositories operation)', + }, + apiKeyName: { type: 'string', description: 'API key name (api key info operation)' }, + userEmail: { type: 'string', description: 'Key owner email (api key info operation)' }, }, } diff --git a/apps/sim/blocks/blocks/devin.ts b/apps/sim/blocks/blocks/devin.ts index 291722e7d7d..7460d293155 100644 --- a/apps/sim/blocks/blocks/devin.ts +++ b/apps/sim/blocks/blocks/devin.ts @@ -2,6 +2,14 @@ import { DevinIcon } from '@/components/icons' import type { BlockConfig } from '@/blocks/types' import { AuthMode, IntegrationType } from '@/blocks/types' +const SESSION_OBJECT_OPERATIONS = [ + 'create_session', + 'get_session', + 'send_message', + 'archive_session', + 'terminate_session', +] as const + export const DevinBlock: BlockConfig = { type: 'devin', name: 'Devin', @@ -32,6 +40,13 @@ export const DevinBlock: BlockConfig = { { label: 'Get Session', id: 'get_session' }, { label: 'List Sessions', id: 'list_sessions' }, { label: 'Send Message', id: 'send_message' }, + { label: 'List Session Messages', id: 'list_session_messages' }, + { label: 'List Session Attachments', id: 'list_session_attachments' }, + { label: 'Get Session Tags', id: 'get_session_tags' }, + { label: 'Append Session Tags', id: 'append_session_tags' }, + { label: 'Replace Session Tags', id: 'replace_session_tags' }, + { label: 'Archive Session', id: 'archive_session' }, + { label: 'Terminate Session', id: 'terminate_session' }, ], value: () => 'create_session', }, @@ -43,6 +58,13 @@ export const DevinBlock: BlockConfig = { password: true, required: true, }, + { + id: 'orgId', + title: 'Organization ID', + type: 'short-input', + placeholder: 'Enter your Devin organization ID (org-...)', + required: true, + }, { id: 'prompt', title: 'Prompt', @@ -86,16 +108,19 @@ RULES: title: 'Tags', type: 'short-input', placeholder: 'Comma-separated tags', - condition: { field: 'operation', value: 'create_session' }, - mode: 'advanced', + required: { field: 'operation', value: ['append_session_tags', 'replace_session_tags'] }, + condition: { + field: 'operation', + value: ['create_session', 'append_session_tags', 'replace_session_tags'], + }, }, { id: 'sessionId', title: 'Session ID', type: 'short-input', placeholder: 'Enter session ID', - required: { field: 'operation', value: ['get_session', 'send_message'] }, - condition: { field: 'operation', value: ['get_session', 'send_message'] }, + required: { field: 'operation', value: ['create_session', 'list_sessions'], not: true }, + condition: { field: 'operation', value: ['create_session', 'list_sessions'], not: true }, }, { id: 'message', @@ -109,8 +134,28 @@ RULES: id: 'limit', title: 'Limit', type: 'short-input', - placeholder: 'Number of sessions (1-200, default: 100)', - condition: { field: 'operation', value: 'list_sessions' }, + placeholder: 'Max results (1-200, default: 100)', + condition: { field: 'operation', value: ['list_sessions', 'list_session_messages'] }, + mode: 'advanced', + }, + { + id: 'after', + title: 'After Cursor', + type: 'short-input', + placeholder: 'Pagination cursor from a previous response', + condition: { field: 'operation', value: ['list_sessions', 'list_session_messages'] }, + mode: 'advanced', + }, + { + id: 'terminateArchive', + title: 'Archive Instead of Terminate', + type: 'dropdown', + options: [ + { label: 'No', id: 'false' }, + { label: 'Yes', id: 'true' }, + ], + value: () => 'false', + condition: { field: 'operation', value: 'terminate_session' }, mode: 'advanced', }, ], @@ -120,15 +165,30 @@ RULES: 'devin_get_session', 'devin_list_sessions', 'devin_send_message', + 'devin_list_session_messages', + 'devin_list_session_attachments', + 'devin_get_session_tags', + 'devin_append_session_tags', + 'devin_replace_session_tags', + 'devin_archive_session', + 'devin_terminate_session', ], config: { tool: (params) => `devin_${params.operation}`, params: (params) => { if (params.maxAcuLimit != null && params.maxAcuLimit !== '') { - params.maxAcuLimit = Number(params.maxAcuLimit) + const parsed = Number(params.maxAcuLimit) + params.maxAcuLimit = Number.isFinite(parsed) ? parsed : undefined } if (params.limit != null && params.limit !== '') { - params.limit = Number(params.limit) + const parsed = Number(params.limit) + params.limit = Number.isFinite(parsed) ? parsed : undefined + } + if (params.terminateArchive != null && params.terminateArchive !== '') { + params.archive = + typeof params.terminateArchive === 'boolean' + ? params.terminateArchive + : params.terminateArchive === 'true' } return params }, @@ -139,51 +199,121 @@ RULES: sessionId: { type: 'string', description: 'Session ID' }, message: { type: 'string', description: 'Message to send to the session' }, apiKey: { type: 'string', description: 'Devin API key' }, + orgId: { type: 'string', description: 'Devin organization ID' }, playbookId: { type: 'string', description: 'Playbook ID to guide the session' }, maxAcuLimit: { type: 'number', description: 'Maximum ACU limit' }, - tags: { type: 'string', description: 'Comma-separated tags' }, - limit: { type: 'number', description: 'Number of sessions to return' }, + tags: { type: 'string', description: 'Tags (comma-separated string or array of strings)' }, + limit: { type: 'number', description: 'Maximum number of results to return' }, + after: { type: 'string', description: 'Pagination cursor for the next page' }, + terminateArchive: { + type: 'string', + description: 'Whether to archive instead of terminate the session', + }, }, outputs: { - sessionId: { type: 'string', description: 'Session identifier' }, - url: { type: 'string', description: 'URL to view the session in Devin UI' }, + sessionId: { + type: 'string', + description: 'Session identifier', + condition: { field: 'operation', value: [...SESSION_OBJECT_OPERATIONS] }, + }, + url: { + type: 'string', + description: 'URL to view the session in Devin UI', + condition: { field: 'operation', value: [...SESSION_OBJECT_OPERATIONS] }, + }, status: { type: 'string', description: 'Session status (new, claimed, running, exit, error, suspended, resuming)', + condition: { field: 'operation', value: [...SESSION_OBJECT_OPERATIONS] }, }, statusDetail: { type: 'string', description: 'Detailed status (working, waiting_for_user, finished, etc.)', - condition: { field: 'operation', value: 'list_sessions', not: true }, + condition: { field: 'operation', value: [...SESSION_OBJECT_OPERATIONS] }, + }, + title: { + type: 'string', + description: 'Session title', + condition: { field: 'operation', value: [...SESSION_OBJECT_OPERATIONS] }, + }, + createdAt: { + type: 'number', + description: 'Creation timestamp (Unix)', + condition: { field: 'operation', value: [...SESSION_OBJECT_OPERATIONS] }, + }, + updatedAt: { + type: 'number', + description: 'Last updated timestamp (Unix)', + condition: { field: 'operation', value: [...SESSION_OBJECT_OPERATIONS] }, }, - title: { type: 'string', description: 'Session title' }, - createdAt: { type: 'number', description: 'Creation timestamp (Unix)' }, - updatedAt: { type: 'number', description: 'Last updated timestamp (Unix)' }, acusConsumed: { type: 'number', description: 'ACUs consumed', - condition: { field: 'operation', value: 'list_sessions', not: true }, + condition: { field: 'operation', value: [...SESSION_OBJECT_OPERATIONS] }, + }, + tags: { + type: 'json', + description: 'Session tags (array of strings)', + condition: { + field: 'operation', + value: [ + ...SESSION_OBJECT_OPERATIONS, + 'get_session_tags', + 'append_session_tags', + 'replace_session_tags', + ], + }, }, - tags: { type: 'json', description: 'Session tags' }, pullRequests: { type: 'json', - description: 'Pull requests created during the session', - condition: { field: 'operation', value: 'list_sessions', not: true }, + description: 'Pull requests created during the session ([{pr_url, pr_state}])', + condition: { field: 'operation', value: [...SESSION_OBJECT_OPERATIONS] }, }, structuredOutput: { type: 'json', description: 'Structured output from the session', - condition: { field: 'operation', value: 'list_sessions', not: true }, + condition: { field: 'operation', value: [...SESSION_OBJECT_OPERATIONS] }, }, playbookId: { type: 'string', description: 'Associated playbook ID', - condition: { field: 'operation', value: 'list_sessions', not: true }, + condition: { field: 'operation', value: [...SESSION_OBJECT_OPERATIONS] }, + }, + isArchived: { + type: 'boolean', + description: 'Whether the session is archived', + condition: { field: 'operation', value: [...SESSION_OBJECT_OPERATIONS] }, }, sessions: { type: 'json', - description: 'List of sessions', + description: + 'List of sessions ([{sessionId, url, status, statusDetail, title, tags, acusConsumed, pullRequests, playbookId, isArchived, ...}])', condition: { field: 'operation', value: 'list_sessions' }, }, + messages: { + type: 'json', + description: 'Messages in the session ([{eventId, source, message, createdAt}])', + condition: { field: 'operation', value: 'list_session_messages' }, + }, + attachments: { + type: 'json', + description: 'Session attachments ([{attachmentId, name, url, source, contentType}])', + condition: { field: 'operation', value: 'list_session_attachments' }, + }, + endCursor: { + type: 'string', + description: 'Pagination cursor for the next page, or null if last page', + condition: { field: 'operation', value: ['list_sessions', 'list_session_messages'] }, + }, + hasNextPage: { + type: 'boolean', + description: 'Whether more results are available', + condition: { field: 'operation', value: ['list_sessions', 'list_session_messages'] }, + }, + total: { + type: 'number', + description: 'Total number of results, if provided', + condition: { field: 'operation', value: ['list_sessions', 'list_session_messages'] }, + }, }, } diff --git a/apps/sim/blocks/blocks/greptile.ts b/apps/sim/blocks/blocks/greptile.ts index 76cb142cf3c..83de267de4d 100644 --- a/apps/sim/blocks/blocks/greptile.ts +++ b/apps/sim/blocks/blocks/greptile.ts @@ -14,7 +14,7 @@ export const GreptileBlock: BlockConfig = { category: 'tools', integrationType: IntegrationType.DeveloperTools, tags: ['version-control', 'knowledge-base'], - bgColor: '#e5e5e5', + bgColor: '#5DE195', icon: GreptileIcon, subBlocks: [ { @@ -89,7 +89,7 @@ export const GreptileBlock: BlockConfig = { // type: 'switch', // condition: { field: 'operation', value: 'greptile_search' }, // }, - // Index operation inputs + // Index & Status shared inputs { id: 'remote', title: 'Git Remote', @@ -99,14 +99,14 @@ export const GreptileBlock: BlockConfig = { { label: 'GitLab', id: 'gitlab' }, ], value: () => 'github', - condition: { field: 'operation', value: 'greptile_index_repo' }, + condition: { field: 'operation', value: ['greptile_index_repo', 'greptile_status'] }, }, { id: 'repository', title: 'Repository', type: 'short-input', placeholder: 'owner/repo', - condition: { field: 'operation', value: 'greptile_index_repo' }, + condition: { field: 'operation', value: ['greptile_index_repo', 'greptile_status'] }, required: true, }, { @@ -114,9 +114,10 @@ export const GreptileBlock: BlockConfig = { title: 'Branch', type: 'short-input', placeholder: 'main', - condition: { field: 'operation', value: 'greptile_index_repo' }, + condition: { field: 'operation', value: ['greptile_index_repo', 'greptile_status'] }, required: true, }, + // Index-only inputs { id: 'reload', title: 'Force Re-index', @@ -129,34 +130,6 @@ export const GreptileBlock: BlockConfig = { type: 'switch', condition: { field: 'operation', value: 'greptile_index_repo' }, }, - // Status operation inputs - { - id: 'remote', - title: 'Git Remote', - type: 'dropdown', - options: [ - { label: 'GitHub', id: 'github' }, - { label: 'GitLab', id: 'gitlab' }, - ], - value: () => 'github', - condition: { field: 'operation', value: 'greptile_status' }, - }, - { - id: 'repository', - title: 'Repository', - type: 'short-input', - placeholder: 'owner/repo', - condition: { field: 'operation', value: 'greptile_status' }, - required: true, - }, - { - id: 'branch', - title: 'Branch', - type: 'short-input', - placeholder: 'main', - condition: { field: 'operation', value: 'greptile_status' }, - required: true, - }, // API Keys (common) { id: 'apiKey', diff --git a/apps/sim/tools/cursor/download_artifact.ts b/apps/sim/tools/cursor/download_artifact.ts index 5b891688410..39d3da66928 100644 --- a/apps/sim/tools/cursor/download_artifact.ts +++ b/apps/sim/tools/cursor/download_artifact.ts @@ -59,7 +59,12 @@ export const downloadArtifactTool: ToolConfig 'https://api.cursor.com/v0/me', + method: 'GET', + headers: (params: GetApiKeyInfoParams) => ({ + Authorization: `Basic ${Buffer.from(`${params.apiKey}:`).toString('base64')}`, + }), + }, +} satisfies Pick, 'params' | 'request'> + +export const getApiKeyInfoTool: ToolConfig = { + 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 = { + ...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' }, + }, +} diff --git a/apps/sim/tools/cursor/index.ts b/apps/sim/tools/cursor/index.ts index 80573009eec..5427b8de00e 100644 --- a/apps/sim/tools/cursor/index.ts +++ b/apps/sim/tools/cursor/index.ts @@ -2,10 +2,13 @@ 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 @@ -17,6 +20,9 @@ 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 @@ -27,3 +33,6 @@ 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 diff --git a/apps/sim/tools/cursor/list_models.ts b/apps/sim/tools/cursor/list_models.ts new file mode 100644 index 00000000000..48012d429be --- /dev/null +++ b/apps/sim/tools/cursor/list_models.ts @@ -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, 'params' | 'request'> + +export const listModelsTool: ToolConfig = { + 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 = { + ...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' }, + }, + }, +} diff --git a/apps/sim/tools/cursor/list_repositories.ts b/apps/sim/tools/cursor/list_repositories.ts new file mode 100644 index 00000000000..97ebdb8e5c6 --- /dev/null +++ b/apps/sim/tools/cursor/list_repositories.ts @@ -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, 'params' | 'request'> + +export const listRepositoriesTool: ToolConfig = { + 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' }, + }, + }, + }, + }, +} diff --git a/apps/sim/tools/cursor/types.ts b/apps/sim/tools/cursor/types.ts index f4117e21ccd..2dfcf38fa20 100644 --- a/apps/sim/tools/cursor/types.ts +++ b/apps/sim/tools/cursor/types.ts @@ -44,6 +44,12 @@ 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 @@ -54,14 +60,14 @@ interface AgentTarget { url: string prUrl?: string autoCreatePr: boolean - openAsCursorGithubApp: boolean - skipReviewerRequest: boolean + openAsCursorGithubApp?: boolean + skipReviewerRequest?: boolean } interface AgentMetadata { id: string name: string - status: 'CREATING' | 'RUNNING' | 'FINISHED' | 'STOPPED' | 'FAILED' + status: string source: AgentSource target: AgentTarget summary?: string @@ -150,14 +156,14 @@ export interface DeleteAgentResponse extends ToolResponse { } } -interface GetApiKeyInfoResponse extends ToolResponse { +export interface GetApiKeyInfoResponse extends ToolResponse { output: { content: string metadata: ApiKeyInfoMetadata } } -interface ListModelsResponse extends ToolResponse { +export interface ListModelsResponse extends ToolResponse { output: { content: string metadata: { @@ -166,7 +172,7 @@ interface ListModelsResponse extends ToolResponse { } } -interface ListRepositoriesResponse extends ToolResponse { +export interface ListRepositoriesResponse extends ToolResponse { output: { content: string metadata: { @@ -201,7 +207,12 @@ export interface DownloadArtifactParams extends BaseCursorParams { export interface DownloadArtifactResponse extends ToolResponse { output: { content: string - metadata: Record + metadata: { + name: string + mimeType: string + data: string + size: number + } } } diff --git a/apps/sim/tools/devin/append_session_tags.ts b/apps/sim/tools/devin/append_session_tags.ts new file mode 100644 index 00000000000..ad50cdb83d5 --- /dev/null +++ b/apps/sim/tools/devin/append_session_tags.ts @@ -0,0 +1,70 @@ +import type { ToolConfig } from '@/tools/types' +import type { DevinAppendSessionTagsParams, DevinSessionTagsResponse } from './types' +import { normalizeTags } from './utils' + +export const devinAppendSessionTagsTool: ToolConfig< + DevinAppendSessionTagsParams, + DevinSessionTagsResponse +> = { + id: 'devin_append_session_tags', + name: 'append_session_tags', + description: 'Add tags to a Devin session without removing existing tags (max 50 tags total).', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Devin API key (service user credential starting with cog_)', + }, + orgId: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Devin organization ID (prefixed with org-)', + }, + sessionId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'The session ID to add tags to', + }, + tags: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Tags to append to the session (comma-separated string or array of strings)', + }, + }, + + request: { + url: (params) => + `https://api.devin.ai/v3/organizations/${params.orgId.trim()}/sessions/${params.sessionId.trim()}/tags`, + method: 'POST', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => ({ + tags: normalizeTags(params.tags), + }), + }, + + transformResponse: async (response: Response) => { + const data = await response.json() + return { + success: true, + output: { + tags: data.tags ?? [], + }, + } + }, + + outputs: { + tags: { + type: 'json', + description: 'Updated list of tags on the session (array of strings)', + }, + }, +} diff --git a/apps/sim/tools/devin/archive_session.ts b/apps/sim/tools/devin/archive_session.ts new file mode 100644 index 00000000000..7a4b13c2656 --- /dev/null +++ b/apps/sim/tools/devin/archive_session.ts @@ -0,0 +1,82 @@ +import type { ToolConfig } from '@/tools/types' +import type { DevinArchiveSessionParams, DevinArchiveSessionResponse } from './types' +import { DEVIN_SESSION_OUTPUT_PROPERTIES } from './types' + +export const devinArchiveSessionTool: ToolConfig< + DevinArchiveSessionParams, + DevinArchiveSessionResponse +> = { + id: 'devin_archive_session', + name: 'archive_session', + description: + 'Archive a Devin session. Archived sessions can still be viewed but cannot be modified or resumed.', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Devin API key (service user credential starting with cog_)', + }, + orgId: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Devin organization ID (prefixed with org-)', + }, + sessionId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'The session ID to archive', + }, + }, + + request: { + url: (params) => + `https://api.devin.ai/v3/organizations/${params.orgId.trim()}/sessions/${params.sessionId.trim()}/archive`, + method: 'POST', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response: Response) => { + const data = await response.json() + return { + success: true, + output: { + sessionId: data.session_id ?? null, + url: data.url ?? null, + status: data.status ?? null, + statusDetail: data.status_detail ?? null, + title: data.title ?? null, + createdAt: data.created_at ?? null, + updatedAt: data.updated_at ?? null, + acusConsumed: data.acus_consumed ?? null, + tags: data.tags ?? [], + pullRequests: data.pull_requests ?? [], + structuredOutput: data.structured_output ?? null, + playbookId: data.playbook_id ?? null, + isArchived: data.is_archived ?? false, + }, + } + }, + + outputs: { + sessionId: DEVIN_SESSION_OUTPUT_PROPERTIES.sessionId, + url: DEVIN_SESSION_OUTPUT_PROPERTIES.url, + status: DEVIN_SESSION_OUTPUT_PROPERTIES.status, + statusDetail: DEVIN_SESSION_OUTPUT_PROPERTIES.statusDetail, + title: DEVIN_SESSION_OUTPUT_PROPERTIES.title, + createdAt: DEVIN_SESSION_OUTPUT_PROPERTIES.createdAt, + updatedAt: DEVIN_SESSION_OUTPUT_PROPERTIES.updatedAt, + acusConsumed: DEVIN_SESSION_OUTPUT_PROPERTIES.acusConsumed, + tags: DEVIN_SESSION_OUTPUT_PROPERTIES.tags, + pullRequests: DEVIN_SESSION_OUTPUT_PROPERTIES.pullRequests, + structuredOutput: DEVIN_SESSION_OUTPUT_PROPERTIES.structuredOutput, + playbookId: DEVIN_SESSION_OUTPUT_PROPERTIES.playbookId, + isArchived: DEVIN_SESSION_OUTPUT_PROPERTIES.isArchived, + }, +} diff --git a/apps/sim/tools/devin/create_session.ts b/apps/sim/tools/devin/create_session.ts index 1c99bfba774..72febaa6445 100644 --- a/apps/sim/tools/devin/create_session.ts +++ b/apps/sim/tools/devin/create_session.ts @@ -1,6 +1,7 @@ import type { ToolConfig } from '@/tools/types' import type { DevinCreateSessionParams, DevinCreateSessionResponse } from './types' import { DEVIN_SESSION_OUTPUT_PROPERTIES } from './types' +import { normalizeTags } from './utils' export const devinCreateSessionTool: ToolConfig< DevinCreateSessionParams, @@ -19,6 +20,12 @@ export const devinCreateSessionTool: ToolConfig< visibility: 'user-only', description: 'Devin API key (service user credential starting with cog_)', }, + orgId: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Devin organization ID (prefixed with org-)', + }, prompt: { type: 'string', required: true, @@ -46,7 +53,7 @@ export const devinCreateSessionTool: ToolConfig< }, request: { - url: 'https://api.devin.ai/v3/organizations/sessions', + url: (params) => `https://api.devin.ai/v3/organizations/${params.orgId.trim()}/sessions`, method: 'POST', headers: (params) => ({ Authorization: `Bearer ${params.apiKey}`, @@ -60,9 +67,8 @@ export const devinCreateSessionTool: ToolConfig< if (params.maxAcuLimit != null) { body.max_acu_limit = params.maxAcuLimit } - if (params.tags) { - body.tags = params.tags.split(',').map((t: string) => t.trim()) - } + const tags = normalizeTags(params.tags) + if (tags.length > 0) body.tags = tags return body }, }, @@ -80,10 +86,11 @@ export const devinCreateSessionTool: ToolConfig< createdAt: data.created_at ?? null, updatedAt: data.updated_at ?? null, acusConsumed: data.acus_consumed ?? null, - tags: data.tags ?? null, - pullRequests: data.pull_requests ?? null, + tags: data.tags ?? [], + pullRequests: data.pull_requests ?? [], structuredOutput: data.structured_output ?? null, playbookId: data.playbook_id ?? null, + isArchived: data.is_archived ?? false, }, } }, @@ -101,5 +108,6 @@ export const devinCreateSessionTool: ToolConfig< pullRequests: DEVIN_SESSION_OUTPUT_PROPERTIES.pullRequests, structuredOutput: DEVIN_SESSION_OUTPUT_PROPERTIES.structuredOutput, playbookId: DEVIN_SESSION_OUTPUT_PROPERTIES.playbookId, + isArchived: DEVIN_SESSION_OUTPUT_PROPERTIES.isArchived, }, } diff --git a/apps/sim/tools/devin/get_session.ts b/apps/sim/tools/devin/get_session.ts index 0af5b309bfb..f25d43c1e97 100644 --- a/apps/sim/tools/devin/get_session.ts +++ b/apps/sim/tools/devin/get_session.ts @@ -16,6 +16,12 @@ export const devinGetSessionTool: ToolConfig `https://api.devin.ai/v3/organizations/sessions/${params.sessionId}`, + url: (params) => + `https://api.devin.ai/v3/organizations/${params.orgId.trim()}/sessions/${params.sessionId.trim()}`, method: 'GET', headers: (params) => ({ Authorization: `Bearer ${params.apiKey}`, @@ -45,10 +52,11 @@ export const devinGetSessionTool: ToolConfig = { + id: 'devin_get_session_tags', + name: 'get_session_tags', + description: 'Retrieve the tags currently applied to a Devin session.', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Devin API key (service user credential starting with cog_)', + }, + orgId: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Devin organization ID (prefixed with org-)', + }, + sessionId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'The session ID to retrieve tags for', + }, + }, + + request: { + url: (params) => + `https://api.devin.ai/v3/organizations/${params.orgId.trim()}/sessions/${params.sessionId.trim()}/tags`, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response: Response) => { + const data = await response.json() + return { + success: true, + output: { + tags: data.tags ?? [], + }, + } + }, + + outputs: { + tags: { + type: 'json', + description: 'Tags applied to the session (array of strings)', + }, + }, +} diff --git a/apps/sim/tools/devin/index.ts b/apps/sim/tools/devin/index.ts index be9d1f91db8..9025778b76d 100644 --- a/apps/sim/tools/devin/index.ts +++ b/apps/sim/tools/devin/index.ts @@ -1,4 +1,11 @@ +export { devinAppendSessionTagsTool } from './append_session_tags' +export { devinArchiveSessionTool } from './archive_session' export { devinCreateSessionTool } from './create_session' export { devinGetSessionTool } from './get_session' +export { devinGetSessionTagsTool } from './get_session_tags' +export { devinListSessionAttachmentsTool } from './list_session_attachments' +export { devinListSessionMessagesTool } from './list_session_messages' export { devinListSessionsTool } from './list_sessions' +export { devinReplaceSessionTagsTool } from './replace_session_tags' export { devinSendMessageTool } from './send_message' +export { devinTerminateSessionTool } from './terminate_session' diff --git a/apps/sim/tools/devin/list_session_attachments.ts b/apps/sim/tools/devin/list_session_attachments.ts new file mode 100644 index 00000000000..32b4f0f746a --- /dev/null +++ b/apps/sim/tools/devin/list_session_attachments.ts @@ -0,0 +1,74 @@ +import type { ToolConfig } from '@/tools/types' +import type { + DevinListSessionAttachmentsParams, + DevinListSessionAttachmentsResponse, +} from './types' +import { DEVIN_SESSION_ATTACHMENT_PROPERTIES } from './types' + +export const devinListSessionAttachmentsTool: ToolConfig< + DevinListSessionAttachmentsParams, + DevinListSessionAttachmentsResponse +> = { + id: 'devin_list_session_attachments', + name: 'list_session_attachments', + description: 'List the files uploaded to or produced by a Devin session.', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Devin API key (service user credential starting with cog_)', + }, + orgId: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Devin organization ID (prefixed with org-)', + }, + sessionId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'The session ID to list attachments for', + }, + }, + + request: { + url: (params) => + `https://api.devin.ai/v3/organizations/${params.orgId.trim()}/sessions/${params.sessionId.trim()}/attachments`, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response: Response) => { + const data = await response.json() + const items = Array.isArray(data) ? data : (data.items ?? []) + return { + success: true, + output: { + attachments: items.map((item: Record) => ({ + attachmentId: item.attachment_id ?? null, + name: item.name ?? null, + url: item.url ?? null, + source: item.source ?? null, + contentType: item.content_type ?? null, + })), + }, + } + }, + + outputs: { + attachments: { + type: 'array', + description: 'Attachments associated with the session', + items: { + type: 'object', + properties: DEVIN_SESSION_ATTACHMENT_PROPERTIES, + }, + }, + }, +} diff --git a/apps/sim/tools/devin/list_session_messages.ts b/apps/sim/tools/devin/list_session_messages.ts new file mode 100644 index 00000000000..ca50ccd33f1 --- /dev/null +++ b/apps/sim/tools/devin/list_session_messages.ts @@ -0,0 +1,105 @@ +import type { ToolConfig } from '@/tools/types' +import type { DevinListSessionMessagesParams, DevinListSessionMessagesResponse } from './types' +import { DEVIN_SESSION_MESSAGE_PROPERTIES } from './types' + +export const devinListSessionMessagesTool: ToolConfig< + DevinListSessionMessagesParams, + DevinListSessionMessagesResponse +> = { + id: 'devin_list_session_messages', + name: 'list_session_messages', + description: + 'List the messages exchanged in a Devin session, including messages from both the user and Devin.', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Devin API key (service user credential starting with cog_)', + }, + orgId: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Devin organization ID (prefixed with org-)', + }, + sessionId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'The session ID to list messages for', + }, + limit: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Maximum number of messages to return (1-200, default: 100)', + }, + after: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Pagination cursor (endCursor from a previous response) to fetch the next page', + }, + }, + + request: { + url: (params) => { + const searchParams = new URLSearchParams() + if (params.limit) searchParams.set('first', String(params.limit)) + if (params.after) searchParams.set('after', params.after.trim()) + const qs = searchParams.toString() + return `https://api.devin.ai/v3/organizations/${params.orgId.trim()}/sessions/${params.sessionId.trim()}/messages${qs ? `?${qs}` : ''}` + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response: Response) => { + const data = await response.json() + const items = data.items ?? [] + return { + success: true, + output: { + messages: items.map((item: Record) => ({ + eventId: item.event_id ?? null, + source: item.source ?? null, + message: item.message ?? null, + createdAt: item.created_at ?? null, + })), + endCursor: data.end_cursor ?? null, + hasNextPage: data.has_next_page ?? false, + total: data.total ?? null, + }, + } + }, + + outputs: { + messages: { + type: 'array', + description: 'Messages exchanged in the session', + items: { + type: 'object', + properties: DEVIN_SESSION_MESSAGE_PROPERTIES, + }, + }, + endCursor: { + type: 'string', + description: 'Pagination cursor for the next page, or null if last page', + optional: true, + }, + hasNextPage: { + type: 'boolean', + description: 'Whether more messages are available', + }, + total: { + type: 'number', + description: 'Total number of messages, if provided', + optional: true, + }, + }, +} diff --git a/apps/sim/tools/devin/list_sessions.ts b/apps/sim/tools/devin/list_sessions.ts index 66391e4f34e..90bf6d4a21b 100644 --- a/apps/sim/tools/devin/list_sessions.ts +++ b/apps/sim/tools/devin/list_sessions.ts @@ -16,20 +16,34 @@ export const devinListSessionsTool: ToolConfig { const searchParams = new URLSearchParams() if (params.limit) searchParams.set('first', String(params.limit)) + if (params.after) searchParams.set('after', params.after.trim()) const qs = searchParams.toString() - return `https://api.devin.ai/v3/organizations/sessions${qs ? `?${qs}` : ''}` + return `https://api.devin.ai/v3/organizations/${params.orgId.trim()}/sessions${qs ? `?${qs}` : ''}` }, method: 'GET', headers: (params) => ({ @@ -51,8 +65,15 @@ export const devinListSessionsTool: ToolConfig = { + id: 'devin_replace_session_tags', + name: 'replace_session_tags', + description: 'Replace all tags on a Devin session with a new set of tags (max 50 tags).', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Devin API key (service user credential starting with cog_)', + }, + orgId: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Devin organization ID (prefixed with org-)', + }, + sessionId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'The session ID to replace tags on', + }, + tags: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: + 'Tags that will overwrite the existing tags (comma-separated string or array of strings)', + }, + }, + + request: { + url: (params) => + `https://api.devin.ai/v3/organizations/${params.orgId.trim()}/sessions/${params.sessionId.trim()}/tags`, + method: 'PUT', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => ({ + tags: normalizeTags(params.tags), + }), + }, + + transformResponse: async (response: Response) => { + const data = await response.json() + return { + success: true, + output: { + tags: data.tags ?? [], + }, + } + }, + + outputs: { + tags: { + type: 'json', + description: 'Updated list of tags on the session (array of strings)', + }, + }, +} diff --git a/apps/sim/tools/devin/send_message.ts b/apps/sim/tools/devin/send_message.ts index 13844c47032..c6705b020a3 100644 --- a/apps/sim/tools/devin/send_message.ts +++ b/apps/sim/tools/devin/send_message.ts @@ -16,6 +16,12 @@ export const devinSendMessageTool: ToolConfig `https://api.devin.ai/v3/organizations/sessions/${params.sessionId}/messages`, + url: (params) => + `https://api.devin.ai/v3/organizations/${params.orgId.trim()}/sessions/${params.sessionId.trim()}/messages`, method: 'POST', headers: (params) => ({ Authorization: `Bearer ${params.apiKey}`, @@ -55,10 +62,11 @@ export const devinSendMessageTool: ToolConfig = { + id: 'devin_terminate_session', + name: 'terminate_session', + description: + 'Terminate a Devin session. Optionally archive the session instead of permanently terminating it.', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Devin API key (service user credential starting with cog_)', + }, + orgId: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Devin organization ID (prefixed with org-)', + }, + sessionId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'The session ID to terminate', + }, + archive: { + type: 'boolean', + required: false, + visibility: 'user-or-llm', + description: 'Archive the session instead of permanently terminating it (default: false)', + }, + }, + + request: { + url: (params) => { + const searchParams = new URLSearchParams() + if (params.archive) searchParams.set('archive', 'true') + const qs = searchParams.toString() + return `https://api.devin.ai/v3/organizations/${params.orgId.trim()}/sessions/${params.sessionId.trim()}${qs ? `?${qs}` : ''}` + }, + method: 'DELETE', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response: Response) => { + const data = await response.json() + return { + success: true, + output: { + sessionId: data.session_id ?? null, + url: data.url ?? null, + status: data.status ?? null, + statusDetail: data.status_detail ?? null, + title: data.title ?? null, + createdAt: data.created_at ?? null, + updatedAt: data.updated_at ?? null, + acusConsumed: data.acus_consumed ?? null, + tags: data.tags ?? [], + pullRequests: data.pull_requests ?? [], + structuredOutput: data.structured_output ?? null, + playbookId: data.playbook_id ?? null, + isArchived: data.is_archived ?? false, + }, + } + }, + + outputs: { + sessionId: DEVIN_SESSION_OUTPUT_PROPERTIES.sessionId, + url: DEVIN_SESSION_OUTPUT_PROPERTIES.url, + status: DEVIN_SESSION_OUTPUT_PROPERTIES.status, + statusDetail: DEVIN_SESSION_OUTPUT_PROPERTIES.statusDetail, + title: DEVIN_SESSION_OUTPUT_PROPERTIES.title, + createdAt: DEVIN_SESSION_OUTPUT_PROPERTIES.createdAt, + updatedAt: DEVIN_SESSION_OUTPUT_PROPERTIES.updatedAt, + acusConsumed: DEVIN_SESSION_OUTPUT_PROPERTIES.acusConsumed, + tags: DEVIN_SESSION_OUTPUT_PROPERTIES.tags, + pullRequests: DEVIN_SESSION_OUTPUT_PROPERTIES.pullRequests, + structuredOutput: DEVIN_SESSION_OUTPUT_PROPERTIES.structuredOutput, + playbookId: DEVIN_SESSION_OUTPUT_PROPERTIES.playbookId, + isArchived: DEVIN_SESSION_OUTPUT_PROPERTIES.isArchived, + }, +} diff --git a/apps/sim/tools/devin/types.ts b/apps/sim/tools/devin/types.ts index 7db09ae08af..a1b7c338380 100644 --- a/apps/sim/tools/devin/types.ts +++ b/apps/sim/tools/devin/types.ts @@ -2,28 +2,80 @@ import type { OutputProperty, ToolResponse } from '@/tools/types' export interface DevinCreateSessionParams { apiKey: string + orgId: string prompt: string playbookId?: string maxAcuLimit?: number - tags?: string + tags?: string | string[] } export interface DevinGetSessionParams { apiKey: string + orgId: string sessionId: string } export interface DevinListSessionsParams { apiKey: string + orgId: string limit?: number + after?: string } export interface DevinSendMessageParams { apiKey: string + orgId: string sessionId: string message: string } +export interface DevinListSessionMessagesParams { + apiKey: string + orgId: string + sessionId: string + limit?: number + after?: string +} + +export interface DevinListSessionAttachmentsParams { + apiKey: string + orgId: string + sessionId: string +} + +export interface DevinGetSessionTagsParams { + apiKey: string + orgId: string + sessionId: string +} + +export interface DevinAppendSessionTagsParams { + apiKey: string + orgId: string + sessionId: string + tags: string | string[] +} + +export interface DevinReplaceSessionTagsParams { + apiKey: string + orgId: string + sessionId: string + tags: string | string[] +} + +export interface DevinArchiveSessionParams { + apiKey: string + orgId: string + sessionId: string +} + +export interface DevinTerminateSessionParams { + apiKey: string + orgId: string + sessionId: string + archive?: boolean +} + export const DEVIN_SESSION_OUTPUT_PROPERTIES = { sessionId: { type: 'string', @@ -65,13 +117,11 @@ export const DEVIN_SESSION_OUTPUT_PROPERTIES = { }, tags: { type: 'json', - description: 'Tags associated with the session', - optional: true, + description: 'Tags associated with the session (array of strings)', }, pullRequests: { type: 'json', - description: 'Pull requests created during the session', - optional: true, + description: 'Pull requests created during the session ([{pr_url, pr_state}])', }, structuredOutput: { type: 'json', @@ -83,6 +133,11 @@ export const DEVIN_SESSION_OUTPUT_PROPERTIES = { description: 'Associated playbook ID', optional: true, }, + isArchived: { + type: 'boolean', + description: 'Whether the session is archived', + optional: true, + }, } as const satisfies Record export const DEVIN_SESSION_LIST_ITEM_PROPERTIES = { @@ -120,7 +175,69 @@ export const DEVIN_SESSION_LIST_ITEM_PROPERTIES = { }, tags: { type: 'json', - description: 'Session tags', + description: 'Session tags (array of strings)', + }, + acusConsumed: { + type: 'number', + description: 'ACUs consumed by the session', + optional: true, + }, + pullRequests: { + type: 'json', + description: 'Pull requests created during the session ([{pr_url, pr_state}])', + }, + playbookId: { + type: 'string', + description: 'Associated playbook ID', + optional: true, + }, + isArchived: { + type: 'boolean', + description: 'Whether the session is archived', + optional: true, + }, +} as const satisfies Record + +export const DEVIN_SESSION_MESSAGE_PROPERTIES = { + eventId: { + type: 'string', + description: 'Unique identifier for the message event', + }, + source: { + type: 'string', + description: 'Origin of the message (devin or user)', + }, + message: { + type: 'string', + description: 'The message content', + }, + createdAt: { + type: 'number', + description: 'Unix timestamp when the message was created', + optional: true, + }, +} as const satisfies Record + +export const DEVIN_SESSION_ATTACHMENT_PROPERTIES = { + attachmentId: { + type: 'string', + description: 'Unique identifier for the attachment', + }, + name: { + type: 'string', + description: 'Attachment file name', + }, + url: { + type: 'string', + description: 'URL to download the attachment', + }, + source: { + type: 'string', + description: 'Origin of the attachment (devin or user)', + }, + contentType: { + type: 'string', + description: 'MIME type of the attachment', optional: true, }, } as const satisfies Record @@ -134,10 +251,11 @@ interface DevinSessionOutput { createdAt: number | null updatedAt: number | null acusConsumed: number | null - tags: string[] | null - pullRequests: Array<{ pr_url: string; pr_state: string | null }> | null + tags: string[] + pullRequests: Array<{ pr_url: string; pr_state: string | null }> structuredOutput: Record | null playbookId: string | null + isArchived: boolean } export interface DevinCreateSessionResponse extends ToolResponse { @@ -158,11 +276,58 @@ export interface DevinListSessionsResponse extends ToolResponse { title: string | null createdAt: number | null updatedAt: number | null - tags: string[] | null + tags: string[] + acusConsumed: number | null + pullRequests: Array<{ pr_url: string; pr_state: string | null }> + playbookId: string | null + isArchived: boolean }> + endCursor: string | null + hasNextPage: boolean + total: number | null } } export interface DevinSendMessageResponse extends ToolResponse { output: DevinSessionOutput } + +export interface DevinListSessionMessagesResponse extends ToolResponse { + output: { + messages: Array<{ + eventId: string + source: string + message: string + createdAt: number | null + }> + endCursor: string | null + hasNextPage: boolean + total: number | null + } +} + +export interface DevinListSessionAttachmentsResponse extends ToolResponse { + output: { + attachments: Array<{ + attachmentId: string + name: string + url: string + source: string + contentType: string | null + }> + } +} + +export interface DevinSessionTagsResponse extends ToolResponse { + output: { + tags: string[] + } +} + +export interface DevinArchiveSessionResponse extends ToolResponse { + output: DevinSessionOutput +} + +export interface DevinTerminateSessionResponse extends ToolResponse { + output: DevinSessionOutput +} diff --git a/apps/sim/tools/devin/utils.ts b/apps/sim/tools/devin/utils.ts new file mode 100644 index 00000000000..34863b4f8ea --- /dev/null +++ b/apps/sim/tools/devin/utils.ts @@ -0,0 +1,19 @@ +/** + * Normalize a tags input into a clean string array. + * + * Tags can arrive either as a comma-separated string (typed into the block's + * text input) or as a string array (when wired from another block's JSON + * output, e.g. the tags returned by a get/append/replace tags operation). + */ +export function normalizeTags(input: string | string[] | undefined | null): string[] { + if (Array.isArray(input)) { + return input.map((tag) => String(tag).trim()).filter(Boolean) + } + if (typeof input === 'string') { + return input + .split(',') + .map((tag) => tag.trim()) + .filter(Boolean) + } + return [] +} diff --git a/apps/sim/tools/registry.ts b/apps/sim/tools/registry.ts index d6558b49423..2bf90f1e477 100644 --- a/apps/sim/tools/registry.ts +++ b/apps/sim/tools/registry.ts @@ -435,6 +435,8 @@ import { cursorDownloadArtifactV2Tool, cursorGetAgentTool, cursorGetAgentV2Tool, + cursorGetApiKeyInfoTool, + cursorGetApiKeyInfoV2Tool, cursorGetConversationTool, cursorGetConversationV2Tool, cursorLaunchAgentTool, @@ -443,6 +445,10 @@ import { cursorListAgentsV2Tool, cursorListArtifactsTool, cursorListArtifactsV2Tool, + cursorListModelsTool, + cursorListModelsV2Tool, + cursorListRepositoriesTool, + cursorListRepositoriesV2Tool, cursorStopAgentTool, cursorStopAgentV2Tool, } from '@/tools/cursor' @@ -487,10 +493,17 @@ import { datadogSubmitMetricsTool, } from '@/tools/datadog' import { + devinAppendSessionTagsTool, + devinArchiveSessionTool, devinCreateSessionTool, + devinGetSessionTagsTool, devinGetSessionTool, + devinListSessionAttachmentsTool, + devinListSessionMessagesTool, devinListSessionsTool, + devinReplaceSessionTagsTool, devinSendMessageTool, + devinTerminateSessionTool, } from '@/tools/devin' import { discordAddReactionTool, @@ -4027,6 +4040,13 @@ export const tools: Record = { devin_get_session: devinGetSessionTool, devin_list_sessions: devinListSessionsTool, devin_send_message: devinSendMessageTool, + devin_list_session_messages: devinListSessionMessagesTool, + devin_list_session_attachments: devinListSessionAttachmentsTool, + devin_get_session_tags: devinGetSessionTagsTool, + devin_append_session_tags: devinAppendSessionTagsTool, + devin_replace_session_tags: devinReplaceSessionTagsTool, + devin_archive_session: devinArchiveSessionTool, + devin_terminate_session: devinTerminateSessionTool, dagster_delete_run: dagsterDeleteRunTool, dagster_get_run: dagsterGetRunTool, dagster_get_run_logs: dagsterGetRunLogsTool, @@ -4822,6 +4842,12 @@ export const tools: Record = { cursor_download_artifact_v2: cursorDownloadArtifactV2Tool, cursor_list_artifacts: cursorListArtifactsTool, cursor_list_artifacts_v2: cursorListArtifactsV2Tool, + cursor_list_models: cursorListModelsTool, + cursor_list_models_v2: cursorListModelsV2Tool, + cursor_list_repositories: cursorListRepositoriesTool, + cursor_list_repositories_v2: cursorListRepositoriesV2Tool, + cursor_get_api_key_info: cursorGetApiKeyInfoTool, + cursor_get_api_key_info_v2: cursorGetApiKeyInfoV2Tool, trello_list_lists: trelloListListsTool, trello_list_cards: trelloListCardsTool, trello_create_card: trelloCreateCardTool, diff --git a/bun.lock b/bun.lock index 070992c9a4f..fdee6edfc42 100644 --- a/bun.lock +++ b/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "simstudio",