mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
improvement(integrations): validate and expand devin, cursor, and greptile (#4820)
* improvement(integrations): validate and expand devin, cursor, and greptile - devin: fix missing org_id path segment on all session endpoints, add 7 session sub-resource tools (list messages/attachments, get/append/replace tags, archive, terminate), pagination, and is_archived output - cursor: add get_api_key_info, list_models, list_repositories tools - greptile: align block and docs - normalize array outputs to default [] and tighten types * refactor(cursor): simplify list_repositories v2 array normalization Collapse the redundant `?? []` + `Array.isArray` double-guard into a single Array.isArray check, per PR review feedback. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(devin): scope session-tag mapping to tag ops and normalize array tag inputs - Only map sessionTags into the tools tags param for append/replace operations, preventing stale sessionTags state from clobbering create_session tags - Fall back to a wired tags value when sessionTags is empty for tag operations - Normalize tag inputs (string or wired string[]) via normalizeTags so array values from other blocks no longer throw on .split Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(cursor): restore base64 file data in legacy download_artifact metadata The legacy CursorBlock exposes only content + metadata (no v2 file output), so metadata.data was the only way legacy-block workflows could access downloaded artifact bytes. Restore the base64 data field and document it in the outputs/type instead of dropping it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(devin): coerce terminateArchive to archive flag for boolean-wired input * docs(integrations): regenerate tool docs for new devin and cursor operations --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
911586ad5a
commit
20a8d85e15
@@ -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 |
|
||||
|
||||
|
||||
|
||||
@@ -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 |
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="greptile"
|
||||
color="#e5e5e5"
|
||||
color="#5DE195"
|
||||
/>
|
||||
|
||||
{/* MANUAL-CONTENT-START:intro */}
|
||||
|
||||
@@ -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": [
|
||||
|
||||
@@ -33,6 +33,9 @@ export const CursorBlock: BlockConfig<CursorResponse> = {
|
||||
{ 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<CursorResponse> = {
|
||||
'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<CursorResponse> = {
|
||||
'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<CursorResponse> = {
|
||||
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)' },
|
||||
},
|
||||
}
|
||||
|
||||
+153
-23
@@ -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'] },
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ export const GreptileBlock: BlockConfig<GreptileResponse> = {
|
||||
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<GreptileResponse> = {
|
||||
// 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<GreptileResponse> = {
|
||||
{ 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<GreptileResponse> = {
|
||||
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<GreptileResponse> = {
|
||||
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',
|
||||
|
||||
@@ -59,7 +59,12 @@ export const downloadArtifactTool: ToolConfig<DownloadArtifactParams, DownloadAr
|
||||
success: true,
|
||||
output: {
|
||||
content: `Downloaded artifact: ${data.output.file.name}`,
|
||||
metadata: data.output.file,
|
||||
metadata: {
|
||||
name: data.output.file.name,
|
||||
mimeType: data.output.file.mimeType,
|
||||
data: data.output.file.data,
|
||||
size: data.output.file.size,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
@@ -72,6 +77,7 @@ export const downloadArtifactTool: ToolConfig<DownloadArtifactParams, DownloadAr
|
||||
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' },
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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' },
|
||||
},
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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<string, unknown>
|
||||
metadata: {
|
||||
name: string
|
||||
mimeType: string
|
||||
data: string
|
||||
size: number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -16,6 +16,12 @@ export const devinGetSessionTool: ToolConfig<DevinGetSessionParams, DevinGetSess
|
||||
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,
|
||||
@@ -25,7 +31,8 @@ export const devinGetSessionTool: ToolConfig<DevinGetSessionParams, DevinGetSess
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => `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<DevinGetSessionParams, DevinGetSess
|
||||
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,
|
||||
},
|
||||
}
|
||||
},
|
||||
@@ -66,5 +74,6 @@ export const devinGetSessionTool: ToolConfig<DevinGetSessionParams, DevinGetSess
|
||||
pullRequests: DEVIN_SESSION_OUTPUT_PROPERTIES.pullRequests,
|
||||
structuredOutput: DEVIN_SESSION_OUTPUT_PROPERTIES.structuredOutput,
|
||||
playbookId: DEVIN_SESSION_OUTPUT_PROPERTIES.playbookId,
|
||||
isArchived: DEVIN_SESSION_OUTPUT_PROPERTIES.isArchived,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { DevinGetSessionTagsParams, DevinSessionTagsResponse } from './types'
|
||||
|
||||
export const devinGetSessionTagsTool: ToolConfig<
|
||||
DevinGetSessionTagsParams,
|
||||
DevinSessionTagsResponse
|
||||
> = {
|
||||
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)',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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'
|
||||
|
||||
@@ -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<string, unknown>) => ({
|
||||
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,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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<string, unknown>) => ({
|
||||
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,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -16,20 +16,34 @@ export const devinListSessionsTool: ToolConfig<DevinListSessionsParams, DevinLis
|
||||
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-)',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of sessions 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/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<DevinListSessionsParams, DevinLis
|
||||
title: item.title ?? null,
|
||||
createdAt: item.created_at ?? null,
|
||||
updatedAt: item.updated_at ?? null,
|
||||
tags: item.tags ?? null,
|
||||
tags: item.tags ?? [],
|
||||
acusConsumed: item.acus_consumed ?? null,
|
||||
pullRequests: item.pull_requests ?? [],
|
||||
playbookId: item.playbook_id ?? null,
|
||||
isArchived: item.is_archived ?? false,
|
||||
})),
|
||||
endCursor: data.end_cursor ?? null,
|
||||
hasNextPage: data.has_next_page ?? false,
|
||||
total: data.total ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
@@ -66,5 +87,19 @@ export const devinListSessionsTool: ToolConfig<DevinListSessionsParams, DevinLis
|
||||
properties: DEVIN_SESSION_LIST_ITEM_PROPERTIES,
|
||||
},
|
||||
},
|
||||
endCursor: {
|
||||
type: 'string',
|
||||
description: 'Pagination cursor for the next page, or null if last page',
|
||||
optional: true,
|
||||
},
|
||||
hasNextPage: {
|
||||
type: 'boolean',
|
||||
description: 'Whether more sessions are available',
|
||||
},
|
||||
total: {
|
||||
type: 'number',
|
||||
description: 'Total number of sessions, if provided',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { DevinReplaceSessionTagsParams, DevinSessionTagsResponse } from './types'
|
||||
import { normalizeTags } from './utils'
|
||||
|
||||
export const devinReplaceSessionTagsTool: ToolConfig<
|
||||
DevinReplaceSessionTagsParams,
|
||||
DevinSessionTagsResponse
|
||||
> = {
|
||||
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)',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -16,6 +16,12 @@ export const devinSendMessageTool: ToolConfig<DevinSendMessageParams, DevinSendM
|
||||
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,
|
||||
@@ -31,7 +37,8 @@ export const devinSendMessageTool: ToolConfig<DevinSendMessageParams, DevinSendM
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => `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<DevinSendMessageParams, DevinSendM
|
||||
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,
|
||||
},
|
||||
}
|
||||
},
|
||||
@@ -76,5 +84,6 @@ export const devinSendMessageTool: ToolConfig<DevinSendMessageParams, DevinSendM
|
||||
pullRequests: DEVIN_SESSION_OUTPUT_PROPERTIES.pullRequests,
|
||||
structuredOutput: DEVIN_SESSION_OUTPUT_PROPERTIES.structuredOutput,
|
||||
playbookId: DEVIN_SESSION_OUTPUT_PROPERTIES.playbookId,
|
||||
isArchived: DEVIN_SESSION_OUTPUT_PROPERTIES.isArchived,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { DevinTerminateSessionParams, DevinTerminateSessionResponse } from './types'
|
||||
import { DEVIN_SESSION_OUTPUT_PROPERTIES } from './types'
|
||||
|
||||
export const devinTerminateSessionTool: ToolConfig<
|
||||
DevinTerminateSessionParams,
|
||||
DevinTerminateSessionResponse
|
||||
> = {
|
||||
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,
|
||||
},
|
||||
}
|
||||
@@ -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<string, OutputProperty>
|
||||
|
||||
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<string, OutputProperty>
|
||||
|
||||
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<string, OutputProperty>
|
||||
|
||||
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<string, OutputProperty>
|
||||
@@ -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<string, unknown> | 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
|
||||
}
|
||||
|
||||
@@ -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 []
|
||||
}
|
||||
@@ -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<string, ToolConfig> = {
|
||||
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<string, ToolConfig> = {
|
||||
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,
|
||||
|
||||
Reference in New Issue
Block a user