diff --git a/apps/docs/components/icons.tsx b/apps/docs/components/icons.tsx index 8d8d161ecb0..9e68974089e 100644 --- a/apps/docs/components/icons.tsx +++ b/apps/docs/components/icons.tsx @@ -939,6 +939,25 @@ export function GoogleIcon(props: SVGProps) { ) } +export function DevinIcon(props: SVGProps) { + return ( + + + + + + ) +} + export function DiscordIcon(props: SVGProps) { return ( = { confluence_v2: ConfluenceIcon, cursor_v2: CursorIcon, datadog: DatadogIcon, + devin: DevinIcon, discord: DiscordIcon, dropbox: DropboxIcon, dspy: DsPyIcon, diff --git a/apps/docs/content/docs/en/tools/devin.mdx b/apps/docs/content/docs/en/tools/devin.mdx new file mode 100644 index 00000000000..4ea369fcccb --- /dev/null +++ b/apps/docs/content/docs/en/tools/devin.mdx @@ -0,0 +1,157 @@ +--- +title: Devin +description: Autonomous AI software engineer +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[Devin](https://devin.ai/) is an autonomous AI software engineer by Cognition that can independently write, run, debug, and deploy code. + +With Devin, you can: + +- **Automate coding tasks**: Assign software engineering tasks and let Devin autonomously write, test, and iterate on code +- **Manage sessions**: Create, monitor, and interact with Devin sessions to track progress on assigned tasks +- **Guide active work**: Send messages to running sessions to provide additional context, redirect efforts, or answer questions +- **Retrieve structured output**: Poll completed sessions for pull requests, structured results, and detailed status +- **Control costs**: Set ACU (Autonomous Compute Unit) limits to cap spending on long-running tasks +- **Standardize workflows**: Use playbook IDs to apply repeatable task patterns across sessions + +In Sim, the Devin integration enables your agents to programmatically manage Devin sessions as part of their workflows: + +- **Create sessions**: Kick off new Devin sessions with a prompt describing the task, optional playbook, ACU limits, and tags +- **Get session details**: Retrieve the full state of a session including status, pull requests, structured output, and resource consumption +- **List sessions**: Query all sessions in your organization with optional pagination +- **Send messages**: Communicate with active or suspended sessions to provide guidance, and automatically resume suspended sessions + +This allows for powerful automation scenarios such as triggering code generation from upstream events, polling for completion before consuming results, orchestrating multi-step development pipelines, and integrating Devin's output into broader agent workflows. +{/* MANUAL-CONTENT-END */} + + +## Usage Instructions + +Integrate Devin into your workflow. Create sessions to assign coding tasks, send messages to guide active sessions, and retrieve session status and results. Devin autonomously writes, runs, and tests code. + + + +## Tools + +### `devin_create_session` + +Create a new Devin session with a prompt. Devin will autonomously work on the task described in the prompt. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Devin API key \(service user credential starting with cog_\) | +| `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 | +| `tags` | string | No | Comma-separated tags for the session | + +#### 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 | +| `pullRequests` | json | Pull requests created during the session | +| `structuredOutput` | json | Structured output from the session | +| `playbookId` | string | Associated playbook ID | + +### `devin_get_session` + +Retrieve details of an existing Devin session including status, tags, pull requests, and structured output. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Devin API key \(service user credential starting with cog_\) | +| `sessionId` | string | Yes | The session ID to retrieve | + +#### 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 | +| `pullRequests` | json | Pull requests created during the session | +| `structuredOutput` | json | Structured output from the session | +| `playbookId` | string | Associated playbook ID | + +### `devin_list_sessions` + +List Devin sessions in the organization. Returns up to 100 sessions by default. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Devin API key \(service user credential starting with cog_\) | +| `limit` | number | No | Maximum number of sessions to return \(1-200, default: 100\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `sessions` | array | List of Devin sessions | +| ↳ `sessionId` | string | Unique identifier for the session | +| ↳ `url` | string | URL to view the session | +| ↳ `status` | string | Session status | +| ↳ `statusDetail` | string | Detailed status | +| ↳ `title` | string | Session title | +| ↳ `createdAt` | number | Creation timestamp \(Unix\) | +| ↳ `updatedAt` | number | Last updated timestamp \(Unix\) | +| ↳ `tags` | json | Session tags | + +### `devin_send_message` + +Send a message to a Devin session. If the session is suspended, it will be automatically resumed. Returns the updated session state. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Devin API key \(service user credential starting with cog_\) | +| `sessionId` | string | Yes | The session ID to send the message to | +| `message` | string | Yes | The message to send to Devin | + +#### 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 | +| `pullRequests` | json | Pull requests created during the session | +| `structuredOutput` | json | Structured output from the session | +| `playbookId` | string | Associated playbook ID | + + diff --git a/apps/docs/content/docs/en/tools/google_bigquery.mdx b/apps/docs/content/docs/en/tools/google_bigquery.mdx index 4b31096c7a6..38cc4edaad7 100644 --- a/apps/docs/content/docs/en/tools/google_bigquery.mdx +++ b/apps/docs/content/docs/en/tools/google_bigquery.mdx @@ -5,7 +5,7 @@ description: Query, list, and insert data in Google BigQuery import { BlockInfoCard } from "@/components/ui/block-info-card" - @@ -16,6 +16,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" In Sim, the Google BigQuery integration allows your agents to query datasets, list tables, inspect schemas, and insert rows as part of automated workflows. This enables use cases such as automated reporting, data pipeline orchestration, real-time data ingestion, and analytics-driven decision making. By connecting Sim with BigQuery, your agents can pull insights from petabytes of data, write results back to tables, and keep your analytics workflows running without manual intervention. {/* MANUAL-CONTENT-END */} + ## Usage Instructions Connect to Google BigQuery to run SQL queries, list datasets and tables, get table metadata, and insert rows. diff --git a/apps/docs/content/docs/en/tools/google_books.mdx b/apps/docs/content/docs/en/tools/google_books.mdx index d23d424f8b0..8e817dbc0db 100644 --- a/apps/docs/content/docs/en/tools/google_books.mdx +++ b/apps/docs/content/docs/en/tools/google_books.mdx @@ -5,7 +5,7 @@ description: Search and retrieve book information import { BlockInfoCard } from "@/components/ui/block-info-card" - @@ -16,6 +16,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" In Sim, the Google Books integration allows your agents to search for books and retrieve volume details as part of automated workflows. This enables use cases such as content research, reading list curation, bibliographic data enrichment, ISBN lookups, and knowledge gathering from published works. By connecting Sim with Google Books, your agents can discover and analyze book metadata, filter by availability or format, and incorporate literary references into their outputs—all without manual research. {/* MANUAL-CONTENT-END */} + ## Usage Instructions Search for books using the Google Books API. Find volumes by title, author, ISBN, or keywords, and retrieve detailed information about specific books including descriptions, ratings, and publication details. diff --git a/apps/docs/content/docs/en/tools/google_tasks.mdx b/apps/docs/content/docs/en/tools/google_tasks.mdx index 9743de39795..745b04c1e52 100644 --- a/apps/docs/content/docs/en/tools/google_tasks.mdx +++ b/apps/docs/content/docs/en/tools/google_tasks.mdx @@ -5,7 +5,7 @@ description: Manage Google Tasks import { BlockInfoCard } from "@/components/ui/block-info-card" - @@ -16,6 +16,7 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" In Sim, the Google Tasks integration allows your agents to create, read, update, delete, and list tasks and task lists as part of automated workflows. This enables use cases such as automated task creation from incoming data, to-do list management based on workflow triggers, task status tracking, and deadline monitoring. By connecting Sim with Google Tasks, your agents can manage action items programmatically, keep teams organized, and ensure nothing falls through the cracks. {/* MANUAL-CONTENT-END */} + ## Usage Instructions Integrate Google Tasks into your workflow. Create, read, update, delete, and list tasks and task lists. @@ -81,7 +82,24 @@ List all tasks in a Google Tasks list | Parameter | Type | Description | | --------- | ---- | ----------- | -| `tasks` | json | Array of tasks with id, title, notes, status, due, updated, and more | +| `tasks` | array | List of tasks | +| ↳ `id` | string | Task identifier | +| ↳ `title` | string | Title of the task | +| ↳ `notes` | string | Notes/description for the task | +| ↳ `status` | string | Task status: "needsAction" or "completed" | +| ↳ `due` | string | Due date \(RFC 3339 timestamp\) | +| ↳ `completed` | string | Completion date \(RFC 3339 timestamp\) | +| ↳ `updated` | string | Last modification time \(RFC 3339 timestamp\) | +| ↳ `selfLink` | string | URL pointing to this task | +| ↳ `webViewLink` | string | Link to task in Google Tasks UI | +| ↳ `parent` | string | Parent task identifier | +| ↳ `position` | string | Position among sibling tasks \(string-based ordering\) | +| ↳ `hidden` | boolean | Whether the task is hidden | +| ↳ `deleted` | boolean | Whether the task is deleted | +| ↳ `links` | array | Collection of links associated with the task | +| ↳ `type` | string | Link type \(e.g., "email", "generic", "chat_message"\) | +| ↳ `description` | string | Link description | +| ↳ `link` | string | The URL | | `nextPageToken` | string | Token for retrieving the next page of results | ### `google_tasks_get` @@ -170,14 +188,18 @@ Retrieve all task lists for the authenticated user | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `maxResults` | number | No | Maximum number of task lists to return \(default 1000, max 1000\) | +| `maxResults` | number | No | Maximum number of task lists to return \(default 20, max 100\) | | `pageToken` | string | No | Token for pagination | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `taskLists` | json | Array of task lists with id, title, updated, and selfLink | +| `taskLists` | array | List of task lists | +| ↳ `id` | string | Task list identifier | +| ↳ `title` | string | Title of the task list | +| ↳ `updated` | string | Last modification time \(RFC 3339 timestamp\) | +| ↳ `selfLink` | string | URL pointing to this task list | | `nextPageToken` | string | Token for retrieving the next page of results | diff --git a/apps/docs/content/docs/en/tools/meta.json b/apps/docs/content/docs/en/tools/meta.json index cc1a22ca005..a089247e2e7 100644 --- a/apps/docs/content/docs/en/tools/meta.json +++ b/apps/docs/content/docs/en/tools/meta.json @@ -21,6 +21,7 @@ "confluence", "cursor", "datadog", + "devin", "discord", "dropbox", "dspy", diff --git a/apps/sim/blocks/blocks/devin.ts b/apps/sim/blocks/blocks/devin.ts new file mode 100644 index 00000000000..8289fc3476c --- /dev/null +++ b/apps/sim/blocks/blocks/devin.ts @@ -0,0 +1,187 @@ +import { DevinIcon } from '@/components/icons' +import type { BlockConfig } from '@/blocks/types' +import { AuthMode } from '@/blocks/types' + +export const DevinBlock: BlockConfig = { + type: 'devin', + name: 'Devin', + description: 'Autonomous AI software engineer', + longDescription: + 'Integrate Devin into your workflow. Create sessions to assign coding tasks, send messages to guide active sessions, and retrieve session status and results. Devin autonomously writes, runs, and tests code.', + bestPractices: ` + - Write clear, specific prompts describing the task, expected outcome, and any constraints. + - Use playbook IDs to standardize recurring task patterns across sessions. + - Set ACU limits to control cost for long-running tasks. + - Use Get Session to poll for completion status before consuming structured output. + - Send Message auto-resumes suspended sessions — no need to resume separately. + `, + docsLink: 'https://docs.sim.ai/tools/devin', + category: 'tools', + bgColor: '#12141A', + icon: DevinIcon, + authMode: AuthMode.ApiKey, + subBlocks: [ + { + id: 'operation', + title: 'Operation', + type: 'dropdown', + options: [ + { label: 'Create Session', id: 'create_session' }, + { label: 'Get Session', id: 'get_session' }, + { label: 'List Sessions', id: 'list_sessions' }, + { label: 'Send Message', id: 'send_message' }, + ], + value: () => 'create_session', + }, + { + id: 'apiKey', + title: 'API Key', + type: 'short-input', + placeholder: 'Enter your Devin API key (cog_...)', + password: true, + required: true, + }, + { + id: 'prompt', + title: 'Prompt', + type: 'long-input', + placeholder: 'Describe the task for Devin...', + required: { field: 'operation', value: 'create_session' }, + condition: { field: 'operation', value: 'create_session' }, + wandConfig: { + enabled: true, + prompt: `You are an expert at writing clear, actionable prompts for Devin, an autonomous AI software engineer. Generate or refine a task prompt based on the user's request. + +Current prompt: {context} + +RULES: +1. Be specific about the expected outcome and deliverables +2. Include relevant technical context (languages, frameworks, repos) +3. Specify any constraints (don't modify certain files, follow certain patterns) +4. Break complex tasks into clear steps when helpful +5. Return ONLY the prompt text, no markdown formatting or explanations`, + placeholder: 'Describe what you want Devin to do...', + }, + }, + { + id: 'playbookId', + title: 'Playbook ID', + type: 'short-input', + placeholder: 'Optional playbook ID to guide the session', + condition: { field: 'operation', value: 'create_session' }, + mode: 'advanced', + }, + { + id: 'maxAcuLimit', + title: 'Max ACU Limit', + type: 'short-input', + placeholder: 'Maximum ACU budget for this session', + condition: { field: 'operation', value: 'create_session' }, + mode: 'advanced', + }, + { + id: 'tags', + title: 'Tags', + type: 'short-input', + placeholder: 'Comma-separated tags', + condition: { field: 'operation', value: 'create_session' }, + mode: 'advanced', + }, + { + 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'] }, + }, + { + id: 'message', + title: 'Message', + type: 'long-input', + placeholder: 'Enter message to send to Devin...', + required: { field: 'operation', value: 'send_message' }, + condition: { field: 'operation', value: 'send_message' }, + }, + { + id: 'limit', + title: 'Limit', + type: 'short-input', + placeholder: 'Number of sessions (1-200, default: 100)', + condition: { field: 'operation', value: 'list_sessions' }, + mode: 'advanced', + }, + ], + tools: { + access: [ + 'devin_create_session', + 'devin_get_session', + 'devin_list_sessions', + 'devin_send_message', + ], + config: { + tool: (params) => `devin_${params.operation}`, + params: (params) => { + if (params.maxAcuLimit != null && params.maxAcuLimit !== '') { + params.maxAcuLimit = Number(params.maxAcuLimit) + } + if (params.limit != null && params.limit !== '') { + params.limit = Number(params.limit) + } + return params + }, + }, + }, + inputs: { + prompt: { type: 'string', description: 'Task prompt for Devin' }, + sessionId: { type: 'string', description: 'Session ID' }, + message: { type: 'string', description: 'Message to send to the session' }, + apiKey: { type: 'string', description: 'Devin API key' }, + 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' }, + }, + outputs: { + sessionId: { type: 'string', description: 'Session identifier' }, + url: { type: 'string', description: 'URL to view the session in Devin UI' }, + status: { + type: 'string', + description: 'Session status (new, claimed, running, exit, error, suspended, resuming)', + }, + statusDetail: { + type: 'string', + description: 'Detailed status (working, waiting_for_user, finished, etc.)', + condition: { field: 'operation', value: 'list_sessions', not: true }, + }, + 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 }, + }, + tags: { type: 'json', description: 'Session tags' }, + pullRequests: { + type: 'json', + description: 'Pull requests created during the session', + condition: { field: 'operation', value: 'list_sessions', not: true }, + }, + structuredOutput: { + type: 'json', + description: 'Structured output from the session', + condition: { field: 'operation', value: 'list_sessions', not: true }, + }, + playbookId: { + type: 'string', + description: 'Associated playbook ID', + condition: { field: 'operation', value: 'list_sessions', not: true }, + }, + sessions: { + type: 'json', + description: 'List of sessions', + condition: { field: 'operation', value: 'list_sessions' }, + }, + }, +} diff --git a/apps/sim/blocks/registry.ts b/apps/sim/blocks/registry.ts index 8d3ef317f6d..eff25ffb1d7 100644 --- a/apps/sim/blocks/registry.ts +++ b/apps/sim/blocks/registry.ts @@ -23,6 +23,7 @@ import { ConditionBlock } from '@/blocks/blocks/condition' import { ConfluenceBlock, ConfluenceV2Block } from '@/blocks/blocks/confluence' import { CursorBlock, CursorV2Block } from '@/blocks/blocks/cursor' import { DatadogBlock } from '@/blocks/blocks/datadog' +import { DevinBlock } from '@/blocks/blocks/devin' import { DiscordBlock } from '@/blocks/blocks/discord' import { DropboxBlock } from '@/blocks/blocks/dropbox' import { DSPyBlock } from '@/blocks/blocks/dspy' @@ -206,6 +207,7 @@ export const registry: Record = { cursor: CursorBlock, cursor_v2: CursorV2Block, datadog: DatadogBlock, + devin: DevinBlock, discord: DiscordBlock, dropbox: DropboxBlock, dspy: DSPyBlock, diff --git a/apps/sim/components/icons.tsx b/apps/sim/components/icons.tsx index 8d8d161ecb0..9e68974089e 100644 --- a/apps/sim/components/icons.tsx +++ b/apps/sim/components/icons.tsx @@ -939,6 +939,25 @@ export function GoogleIcon(props: SVGProps) { ) } +export function DevinIcon(props: SVGProps) { + return ( + + + + + + ) +} + export function DiscordIcon(props: SVGProps) { return ( = { + id: 'devin_create_session', + name: 'create_session', + description: + 'Create a new Devin session with a prompt. Devin will autonomously work on the task described in the prompt.', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Devin API key (service user credential starting with cog_)', + }, + prompt: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'The task prompt for Devin to work on', + }, + playbookId: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Optional playbook ID to guide the session', + }, + maxAcuLimit: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Maximum ACU limit for the session', + }, + tags: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Comma-separated tags for the session', + }, + }, + + request: { + url: 'https://api.devin.ai/v3/organizations/sessions', + method: 'POST', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => { + const body: Record = { + prompt: params.prompt, + } + if (params.playbookId) body.playbook_id = params.playbookId + if (params.maxAcuLimit != null) { + body.max_acu_limit = params.maxAcuLimit + } + if (params.tags) { + body.tags = params.tags.split(',').map((t: string) => t.trim()) + } + return body + }, + }, + + 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 ?? null, + pullRequests: data.pull_requests ?? null, + structuredOutput: data.structured_output ?? null, + playbookId: data.playbook_id ?? null, + }, + } + }, + + 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, + }, +} diff --git a/apps/sim/tools/devin/get_session.ts b/apps/sim/tools/devin/get_session.ts new file mode 100644 index 00000000000..0af5b309bfb --- /dev/null +++ b/apps/sim/tools/devin/get_session.ts @@ -0,0 +1,70 @@ +import type { ToolConfig } from '@/tools/types' +import type { DevinGetSessionParams, DevinGetSessionResponse } from './types' +import { DEVIN_SESSION_OUTPUT_PROPERTIES } from './types' + +export const devinGetSessionTool: ToolConfig = { + id: 'devin_get_session', + name: 'get_session', + description: + 'Retrieve details of an existing Devin session including status, tags, pull requests, and structured output.', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Devin API key (service user credential starting with cog_)', + }, + sessionId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'The session ID to retrieve', + }, + }, + + request: { + url: (params) => `https://api.devin.ai/v3/organizations/sessions/${params.sessionId}`, + method: 'GET', + 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 ?? null, + pullRequests: data.pull_requests ?? null, + structuredOutput: data.structured_output ?? null, + playbookId: data.playbook_id ?? null, + }, + } + }, + + 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, + }, +} diff --git a/apps/sim/tools/devin/index.ts b/apps/sim/tools/devin/index.ts new file mode 100644 index 00000000000..be9d1f91db8 --- /dev/null +++ b/apps/sim/tools/devin/index.ts @@ -0,0 +1,4 @@ +export { devinCreateSessionTool } from './create_session' +export { devinGetSessionTool } from './get_session' +export { devinListSessionsTool } from './list_sessions' +export { devinSendMessageTool } from './send_message' diff --git a/apps/sim/tools/devin/list_sessions.ts b/apps/sim/tools/devin/list_sessions.ts new file mode 100644 index 00000000000..66391e4f34e --- /dev/null +++ b/apps/sim/tools/devin/list_sessions.ts @@ -0,0 +1,70 @@ +import type { ToolConfig } from '@/tools/types' +import type { DevinListSessionsParams, DevinListSessionsResponse } from './types' +import { DEVIN_SESSION_LIST_ITEM_PROPERTIES } from './types' + +export const devinListSessionsTool: ToolConfig = + { + id: 'devin_list_sessions', + name: 'list_sessions', + description: 'List Devin sessions in the organization. Returns up to 100 sessions by default.', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Devin API key (service user credential starting with cog_)', + }, + limit: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Maximum number of sessions to return (1-200, default: 100)', + }, + }, + + request: { + url: (params) => { + const searchParams = new URLSearchParams() + if (params.limit) searchParams.set('first', String(params.limit)) + const qs = searchParams.toString() + return `https://api.devin.ai/v3/organizations/sessions${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: { + sessions: items.map((item: Record) => ({ + sessionId: item.session_id ?? null, + url: item.url ?? null, + status: item.status ?? null, + statusDetail: item.status_detail ?? null, + title: item.title ?? null, + createdAt: item.created_at ?? null, + updatedAt: item.updated_at ?? null, + tags: item.tags ?? null, + })), + }, + } + }, + + outputs: { + sessions: { + type: 'array', + description: 'List of Devin sessions', + items: { + type: 'object', + properties: DEVIN_SESSION_LIST_ITEM_PROPERTIES, + }, + }, + }, + } diff --git a/apps/sim/tools/devin/send_message.ts b/apps/sim/tools/devin/send_message.ts new file mode 100644 index 00000000000..13844c47032 --- /dev/null +++ b/apps/sim/tools/devin/send_message.ts @@ -0,0 +1,80 @@ +import type { ToolConfig } from '@/tools/types' +import type { DevinSendMessageParams, DevinSendMessageResponse } from './types' +import { DEVIN_SESSION_OUTPUT_PROPERTIES } from './types' + +export const devinSendMessageTool: ToolConfig = { + id: 'devin_send_message', + 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.', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Devin API key (service user credential starting with cog_)', + }, + sessionId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'The session ID to send the message to', + }, + message: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'The message to send to Devin', + }, + }, + + request: { + url: (params) => `https://api.devin.ai/v3/organizations/sessions/${params.sessionId}/messages`, + method: 'POST', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => ({ + message: params.message, + }), + }, + + 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 ?? null, + pullRequests: data.pull_requests ?? null, + structuredOutput: data.structured_output ?? null, + playbookId: data.playbook_id ?? null, + }, + } + }, + + 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, + }, +} diff --git a/apps/sim/tools/devin/types.ts b/apps/sim/tools/devin/types.ts new file mode 100644 index 00000000000..f38653819bb --- /dev/null +++ b/apps/sim/tools/devin/types.ts @@ -0,0 +1,168 @@ +import type { OutputProperty, ToolResponse } from '@/tools/types' + +export interface DevinCreateSessionParams { + apiKey: string + prompt: string + playbookId?: string + maxAcuLimit?: number + tags?: string +} + +export interface DevinGetSessionParams { + apiKey: string + sessionId: string +} + +export interface DevinListSessionsParams { + apiKey: string + limit?: number +} + +export interface DevinSendMessageParams { + apiKey: string + sessionId: string + message: string +} + +export const DEVIN_SESSION_OUTPUT_PROPERTIES = { + sessionId: { + type: 'string', + description: 'Unique identifier for the session', + }, + url: { + type: 'string', + description: 'URL to view the session in the Devin UI', + }, + status: { + type: 'string', + description: 'Session status (new, claimed, running, exit, error, suspended, resuming)', + }, + statusDetail: { + type: 'string', + description: + 'Detailed status (working, waiting_for_user, waiting_for_approval, finished, inactivity, etc.)', + optional: true, + }, + title: { + type: 'string', + description: 'Session title', + optional: true, + }, + createdAt: { + type: 'number', + description: 'Unix timestamp when the session was created', + optional: true, + }, + updatedAt: { + type: 'number', + description: 'Unix timestamp when the session was last updated', + optional: true, + }, + acusConsumed: { + type: 'number', + description: 'ACUs consumed by the session', + optional: true, + }, + tags: { + type: 'json', + description: 'Tags associated with the session', + optional: true, + }, + pullRequests: { + type: 'json', + description: 'Pull requests created during the session', + optional: true, + }, + structuredOutput: { + type: 'json', + description: 'Structured output from the session', + optional: true, + }, + playbookId: { + type: 'string', + description: 'Associated playbook ID', + optional: true, + }, +} as const satisfies Record + +export const DEVIN_SESSION_LIST_ITEM_PROPERTIES = { + sessionId: { + type: 'string', + description: 'Unique identifier for the session', + }, + url: { + type: 'string', + description: 'URL to view the session', + }, + status: { + type: 'string', + description: 'Session status', + }, + statusDetail: { + type: 'string', + description: 'Detailed status', + optional: true, + }, + title: { + type: 'string', + description: 'Session title', + optional: true, + }, + createdAt: { + type: 'number', + description: 'Creation timestamp (Unix)', + optional: true, + }, + updatedAt: { + type: 'number', + description: 'Last updated timestamp (Unix)', + optional: true, + }, + tags: { + type: 'json', + description: 'Session tags', + optional: true, + }, +} as const satisfies Record + +export interface DevinSessionOutput { + sessionId: string + url: string + status: string + statusDetail: string | null + title: string | null + createdAt: number | null + updatedAt: number | null + acusConsumed: number | null + tags: string[] | null + pullRequests: Array<{ pr_url: string; pr_state: string | null }> | null + structuredOutput: Record | null + playbookId: string | null +} + +export interface DevinCreateSessionResponse extends ToolResponse { + output: DevinSessionOutput +} + +export interface DevinGetSessionResponse extends ToolResponse { + output: DevinSessionOutput +} + +export interface DevinListSessionsResponse extends ToolResponse { + output: { + sessions: Array<{ + sessionId: string + url: string + status: string + statusDetail: string | null + title: string | null + createdAt: number | null + updatedAt: number | null + tags: string[] | null + }> + } +} + +export interface DevinSendMessageResponse extends ToolResponse { + output: DevinSessionOutput +} diff --git a/apps/sim/tools/registry.ts b/apps/sim/tools/registry.ts index c6ddacafde9..d8302770c3d 100644 --- a/apps/sim/tools/registry.ts +++ b/apps/sim/tools/registry.ts @@ -262,6 +262,12 @@ import { datadogSendLogsTool, datadogSubmitMetricsTool, } from '@/tools/datadog' +import { + devinCreateSessionTool, + devinGetSessionTool, + devinListSessionsTool, + devinSendMessageTool, +} from '@/tools/devin' import { discordAddReactionTool, discordArchiveThreadTool, @@ -2585,6 +2591,10 @@ export const tools: Record = { dropbox_get_metadata: dropboxGetMetadataTool, dropbox_create_shared_link: dropboxCreateSharedLinkTool, dropbox_search: dropboxSearchTool, + devin_create_session: devinCreateSessionTool, + devin_get_session: devinGetSessionTool, + devin_list_sessions: devinListSessionsTool, + devin_send_message: devinSendMessageTool, duckduckgo_search: duckduckgoSearchTool, dspy_predict: predictTool, dspy_chain_of_thought: chainOfThoughtTool,