chore: import upstream snapshot with attribution
Publish CLI Package / publish-npm (push) Waiting to run
Publish Python SDK / publish-pypi (push) Waiting to run
Publish TypeScript SDK / publish-npm (push) Waiting to run
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:20:55 +08:00
commit d25d482dc2
13754 changed files with 4996608 additions and 0 deletions
+135
View File
@@ -0,0 +1,135 @@
import { createLogger } from '@sim/logger'
import type {
PipedriveCreateActivityParams,
PipedriveCreateActivityResponse,
} from '@/tools/pipedrive/types'
import type { ToolConfig } from '@/tools/types'
const logger = createLogger('PipedriveCreateActivity')
export const pipedriveCreateActivityTool: ToolConfig<
PipedriveCreateActivityParams,
PipedriveCreateActivityResponse
> = {
id: 'pipedrive_create_activity',
name: 'Create Activity in Pipedrive',
description: 'Create a new activity (task) in Pipedrive',
version: '1.0.0',
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'The access token for the Pipedrive API',
},
subject: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The subject/title of the activity (e.g., "Follow up call with John")',
},
type: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Activity type: call, meeting, task, deadline, email, lunch',
},
due_date: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Due date in YYYY-MM-DD format (e.g., "2025-03-15")',
},
due_time: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Due time in HH:MM format (e.g., "14:30")',
},
duration: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Duration in HH:MM format (e.g., "01:00" for 1 hour)',
},
deal_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'ID of the deal to associate with (e.g., "123")',
},
person_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'ID of the person to associate with (e.g., "456")',
},
org_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'ID of the organization to associate with (e.g., "789")',
},
note: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Notes for the activity',
},
},
request: {
url: () => 'https://api.pipedrive.com/v1/activities',
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
throw new Error('Access token is required')
}
return {
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
}
},
body: (params) => {
const body: Record<string, any> = {
subject: params.subject,
type: params.type,
due_date: params.due_date,
}
if (params.due_time) body.due_time = params.due_time
if (params.duration) body.duration = params.duration
if (params.deal_id) body.deal_id = Number(params.deal_id)
if (params.person_id) body.person_id = Number(params.person_id)
if (params.org_id) body.org_id = Number(params.org_id)
if (params.note) body.note = params.note
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!data.success) {
logger.error('Pipedrive API request failed', { data })
throw new Error(data.error || 'Failed to create activity in Pipedrive')
}
return {
success: true,
output: {
activity: data.data ?? null,
success: true,
},
}
},
outputs: {
activity: { type: 'object', description: 'The created activity object', optional: true },
success: { type: 'boolean', description: 'Operation success status' },
},
}
+135
View File
@@ -0,0 +1,135 @@
import { createLogger } from '@sim/logger'
import type {
PipedriveCreateDealParams,
PipedriveCreateDealResponse,
} from '@/tools/pipedrive/types'
import type { ToolConfig } from '@/tools/types'
const logger = createLogger('PipedriveCreateDeal')
export const pipedriveCreateDealTool: ToolConfig<
PipedriveCreateDealParams,
PipedriveCreateDealResponse
> = {
id: 'pipedrive_create_deal',
name: 'Create Deal in Pipedrive',
description: 'Create a new deal in Pipedrive',
version: '1.0.0',
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'The access token for the Pipedrive API',
},
title: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The title of the deal (e.g., "Enterprise Software License")',
},
value: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'The monetary value of the deal (e.g., "5000")',
},
currency: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Currency code (e.g., "USD", "EUR", "GBP")',
},
person_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'ID of the person this deal is associated with (e.g., "456")',
},
org_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'ID of the organization this deal is associated with (e.g., "789")',
},
pipeline_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'ID of the pipeline this deal should be placed in (e.g., "1")',
},
stage_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'ID of the stage this deal should be placed in (e.g., "2")',
},
status: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Status of the deal: open, won, lost',
},
expected_close_date: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Expected close date in YYYY-MM-DD format (e.g., "2025-06-30")',
},
},
request: {
url: () => 'https://api.pipedrive.com/api/v2/deals',
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
throw new Error('Access token is required')
}
return {
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
}
},
body: (params) => {
const body: Record<string, any> = {
title: params.title,
}
if (params.value) body.value = Number(params.value)
if (params.currency) body.currency = params.currency
if (params.person_id) body.person_id = Number(params.person_id)
if (params.org_id) body.org_id = Number(params.org_id)
if (params.pipeline_id) body.pipeline_id = Number(params.pipeline_id)
if (params.stage_id) body.stage_id = Number(params.stage_id)
if (params.status) body.status = params.status
if (params.expected_close_date) body.expected_close_date = params.expected_close_date
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!data.success) {
logger.error('Pipedrive API request failed', { data })
throw new Error(data.error || 'Failed to create deal in Pipedrive')
}
return {
success: true,
output: {
deal: data.data ?? null,
success: true,
},
}
},
outputs: {
deal: { type: 'object', description: 'The created deal object', optional: true },
success: { type: 'boolean', description: 'Operation success status' },
},
}
+144
View File
@@ -0,0 +1,144 @@
import { createLogger } from '@sim/logger'
import type {
PipedriveCreateLeadParams,
PipedriveCreateLeadResponse,
} from '@/tools/pipedrive/types'
import type { ToolConfig } from '@/tools/types'
const logger = createLogger('PipedriveCreateLead')
export const pipedriveCreateLeadTool: ToolConfig<
PipedriveCreateLeadParams,
PipedriveCreateLeadResponse
> = {
id: 'pipedrive_create_lead',
name: 'Create Lead in Pipedrive',
description: 'Create a new lead in Pipedrive',
version: '1.0.0',
oauth: {
required: true,
provider: 'pipedrive',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'The access token for the Pipedrive API',
},
title: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The name of the lead (e.g., "Acme Corp - Website Redesign")',
},
person_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'ID of the person (REQUIRED unless organization_id is provided) (e.g., "456")',
},
organization_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'ID of the organization (REQUIRED unless person_id is provided) (e.g., "789")',
},
owner_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'ID of the user who will own the lead (e.g., "123")',
},
value_amount: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Potential value amount (e.g., "10000")',
},
value_currency: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Currency code (e.g., "USD", "EUR", "GBP")',
},
expected_close_date: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Expected close date in YYYY-MM-DD format (e.g., "2025-04-15")',
},
visible_to: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Visibility: 1 (Owner & followers), 3 (Entire company)',
},
},
request: {
url: () => 'https://api.pipedrive.com/v1/leads',
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
throw new Error('Access token is required')
}
return {
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
}
},
body: (params) => {
if (!params.person_id && !params.organization_id) {
throw new Error('Either person_id or organization_id is required to create a lead')
}
const body: Record<string, any> = {
title: params.title,
}
if (params.person_id) body.person_id = Number(params.person_id)
if (params.organization_id) body.organization_id = Number(params.organization_id)
if (params.owner_id) body.owner_id = Number(params.owner_id)
// Build value object if both amount and currency are provided
if (params.value_amount && params.value_currency) {
body.value = {
amount: Number(params.value_amount),
currency: params.value_currency,
}
}
if (params.expected_close_date) body.expected_close_date = params.expected_close_date
if (params.visible_to) body.visible_to = Number(params.visible_to)
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!data.success) {
logger.error('Pipedrive API request failed', { data })
throw new Error(data.error || 'Failed to create lead in Pipedrive')
}
return {
success: true,
output: {
lead: data.data ?? null,
success: true,
},
}
},
outputs: {
lead: { type: 'object', description: 'The created lead object', optional: true },
success: { type: 'boolean', description: 'Operation success status' },
},
}
+100
View File
@@ -0,0 +1,100 @@
import { createLogger } from '@sim/logger'
import type {
PipedriveCreateProjectParams,
PipedriveCreateProjectResponse,
} from '@/tools/pipedrive/types'
import type { ToolConfig } from '@/tools/types'
const logger = createLogger('PipedriveCreateProject')
export const pipedriveCreateProjectTool: ToolConfig<
PipedriveCreateProjectParams,
PipedriveCreateProjectResponse
> = {
id: 'pipedrive_create_project',
name: 'Create Project in Pipedrive',
description: 'Create a new project in Pipedrive',
version: '1.0.0',
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'The access token for the Pipedrive API',
},
title: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The title of the project (e.g., "Q2 Marketing Campaign")',
},
description: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Description of the project',
},
start_date: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Project start date in YYYY-MM-DD format (e.g., "2025-04-01")',
},
end_date: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Project end date in YYYY-MM-DD format (e.g., "2025-06-30")',
},
},
request: {
url: () => 'https://api.pipedrive.com/v1/projects',
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
throw new Error('Access token is required')
}
return {
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
}
},
body: (params) => {
const body: Record<string, any> = {
title: params.title,
}
if (params.description) body.description = params.description
if (params.start_date) body.start_date = params.start_date
if (params.end_date) body.end_date = params.end_date
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!data.success) {
logger.error('Pipedrive API request failed', { data })
throw new Error(data.error || 'Failed to create project in Pipedrive')
}
return {
success: true,
output: {
project: data.data ?? null,
success: true,
},
}
},
outputs: {
project: { type: 'object', description: 'The created project object', optional: true },
success: { type: 'boolean', description: 'Operation success status' },
},
}
+75
View File
@@ -0,0 +1,75 @@
import { createLogger } from '@sim/logger'
import type {
PipedriveDeleteLeadParams,
PipedriveDeleteLeadResponse,
} from '@/tools/pipedrive/types'
import type { ToolConfig } from '@/tools/types'
const logger = createLogger('PipedriveDeleteLead')
export const pipedriveDeleteLeadTool: ToolConfig<
PipedriveDeleteLeadParams,
PipedriveDeleteLeadResponse
> = {
id: 'pipedrive_delete_lead',
name: 'Delete Lead from Pipedrive',
description: 'Delete a specific lead from Pipedrive',
version: '1.0.0',
oauth: {
required: true,
provider: 'pipedrive',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'The access token for the Pipedrive API',
},
lead_id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the lead to delete (e.g., "abc123-def456-ghi789")',
},
},
request: {
url: (params) => `https://api.pipedrive.com/v1/leads/${params.lead_id}`,
method: 'DELETE',
headers: (params) => {
if (!params.accessToken) {
throw new Error('Access token is required')
}
return {
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
}
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!data.success) {
logger.error('Pipedrive API request failed', { data })
throw new Error(data.error || 'Failed to delete lead from Pipedrive')
}
return {
success: true,
output: {
data: data.data ?? null,
success: true,
},
}
},
outputs: {
data: { type: 'object', description: 'Deletion confirmation data', optional: true },
success: { type: 'boolean', description: 'Operation success status' },
},
}
+132
View File
@@ -0,0 +1,132 @@
import { createLogger } from '@sim/logger'
import type {
PipedriveGetActivitiesParams,
PipedriveGetActivitiesResponse,
} from '@/tools/pipedrive/types'
import { PIPEDRIVE_ACTIVITY_OUTPUT_PROPERTIES } from '@/tools/pipedrive/types'
import type { ToolConfig } from '@/tools/types'
const logger = createLogger('PipedriveGetActivities')
export const pipedriveGetActivitiesTool: ToolConfig<
PipedriveGetActivitiesParams,
PipedriveGetActivitiesResponse
> = {
id: 'pipedrive_get_activities',
name: 'Get Activities from Pipedrive',
description: 'Retrieve activities (tasks) from Pipedrive with optional filters',
version: '1.0.0',
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'The access token for the Pipedrive API',
},
user_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter activities by user ID (e.g., "123")',
},
type: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter by activity type (call, meeting, task, deadline, email, lunch)',
},
done: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter by completion status: 0 for not done, 1 for done',
},
limit: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Number of results to return (e.g., "50", default: 100, max: 500)',
},
start: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Pagination start offset (0-based index of the first item to return)',
},
},
request: {
url: (params) => {
const baseUrl = 'https://api.pipedrive.com/v1/activities'
const queryParams = new URLSearchParams()
if (params.user_id) queryParams.append('user_id', params.user_id)
if (params.type) queryParams.append('type', params.type)
if (params.done) queryParams.append('done', params.done)
if (params.limit) queryParams.append('limit', params.limit)
if (params.start) queryParams.append('start', params.start)
const queryString = queryParams.toString()
return queryString ? `${baseUrl}?${queryString}` : baseUrl
},
method: 'GET',
headers: (params) => {
if (!params.accessToken) {
throw new Error('Access token is required')
}
return {
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
}
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!data.success) {
logger.error('Pipedrive API request failed', { data })
throw new Error(data.error || 'Failed to fetch activities from Pipedrive')
}
const activities = data.data || []
const hasMore = data.additional_data?.pagination?.more_items_in_collection || false
const nextStart = data.additional_data?.pagination?.next_start ?? null
return {
success: true,
output: {
activities,
total_items: activities.length,
has_more: hasMore,
next_start: nextStart,
success: true,
},
}
},
outputs: {
activities: {
type: 'array',
description: 'Array of activity objects from Pipedrive',
items: {
type: 'object',
properties: PIPEDRIVE_ACTIVITY_OUTPUT_PROPERTIES,
},
},
total_items: { type: 'number', description: 'Total number of activities returned' },
has_more: {
type: 'boolean',
description: 'Whether more activities are available',
optional: true,
},
next_start: {
type: 'number',
description: 'Offset for fetching the next page',
optional: true,
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
+150
View File
@@ -0,0 +1,150 @@
import { createLogger } from '@sim/logger'
import type {
PipedriveGetAllDealsParams,
PipedriveGetAllDealsResponse,
} from '@/tools/pipedrive/types'
import {
PIPEDRIVE_DEAL_OUTPUT_PROPERTIES,
PIPEDRIVE_METADATA_OUTPUT_PROPERTIES,
} from '@/tools/pipedrive/types'
import type { ToolConfig } from '@/tools/types'
const logger = createLogger('PipedriveGetAllDeals')
export const pipedriveGetAllDealsTool: ToolConfig<
PipedriveGetAllDealsParams,
PipedriveGetAllDealsResponse
> = {
id: 'pipedrive_get_all_deals',
name: 'Get All Deals from Pipedrive',
description: 'Retrieve all deals from Pipedrive with optional filters',
version: '1.0.0',
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'The access token for the Pipedrive API',
},
status: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'Only fetch deals with a specific status. Values: open, won, lost. If omitted, all not deleted deals are returned',
},
person_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'If supplied, only deals linked to the specified person are returned (e.g., "456")',
},
org_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'If supplied, only deals linked to the specified organization are returned (e.g., "789")',
},
pipeline_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'If supplied, only deals in the specified pipeline are returned (e.g., "1")',
},
updated_since: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'If set, only deals updated after this time are returned. Format: 2025-01-01T10:20:00Z',
},
limit: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Number of results to return (e.g., "50", default: 100, max: 500)',
},
cursor: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'For pagination, the marker representing the first item on the next page',
},
},
request: {
url: (params) => {
const baseUrl = 'https://api.pipedrive.com/api/v2/deals'
const queryParams = new URLSearchParams()
// Add optional parameters to query string if they exist
if (params.status) queryParams.append('status', params.status)
if (params.person_id) queryParams.append('person_id', params.person_id)
if (params.org_id) queryParams.append('org_id', params.org_id)
if (params.pipeline_id) queryParams.append('pipeline_id', params.pipeline_id)
if (params.updated_since) queryParams.append('updated_since', params.updated_since)
if (params.limit) queryParams.append('limit', params.limit)
if (params.cursor) queryParams.append('cursor', params.cursor)
const queryString = queryParams.toString()
return queryString ? `${baseUrl}?${queryString}` : baseUrl
},
method: 'GET',
headers: (params) => {
if (!params.accessToken) {
throw new Error('Access token is required')
}
return {
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
}
},
},
transformResponse: async (response: Response, params?: PipedriveGetAllDealsParams) => {
const data = await response.json()
if (!data.success) {
logger.error('Pipedrive API request failed', { data })
throw new Error(data.error || 'Failed to fetch deals from Pipedrive')
}
const deals = data.data || []
const nextCursor = data.additional_data?.next_cursor ?? null
const hasMore = nextCursor !== null
return {
success: true,
output: {
deals,
metadata: {
total_items: deals.length,
has_more: hasMore,
next_cursor: nextCursor,
},
success: true,
},
}
},
outputs: {
deals: {
type: 'array',
description: 'Array of deal objects from Pipedrive',
items: {
type: 'object',
properties: PIPEDRIVE_DEAL_OUTPUT_PROPERTIES,
},
},
metadata: {
type: 'object',
description: 'Pagination metadata for the response',
properties: PIPEDRIVE_METADATA_OUTPUT_PROPERTIES,
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
+64
View File
@@ -0,0 +1,64 @@
import { createLogger } from '@sim/logger'
import type { PipedriveGetDealParams, PipedriveGetDealResponse } from '@/tools/pipedrive/types'
import type { ToolConfig } from '@/tools/types'
const logger = createLogger('PipedriveGetDeal')
export const pipedriveGetDealTool: ToolConfig<PipedriveGetDealParams, PipedriveGetDealResponse> = {
id: 'pipedrive_get_deal',
name: 'Get Deal Details from Pipedrive',
description: 'Retrieve detailed information about a specific deal',
version: '1.0.0',
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'The access token for the Pipedrive API',
},
deal_id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the deal to retrieve (e.g., "123")',
},
},
request: {
url: (params) => `https://api.pipedrive.com/api/v2/deals/${params.deal_id}`,
method: 'GET',
headers: (params) => {
if (!params.accessToken) {
throw new Error('Access token is required')
}
return {
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
}
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!data.success) {
logger.error('Pipedrive API request failed', { data })
throw new Error(data.error || 'Failed to fetch deal from Pipedrive')
}
return {
success: true,
output: {
deal: data.data ?? null,
success: true,
},
}
},
outputs: {
deal: { type: 'object', description: 'Deal object with full details', optional: true },
success: { type: 'boolean', description: 'Operation success status' },
},
}
+87
View File
@@ -0,0 +1,87 @@
import type { PipedriveGetFilesParams, PipedriveGetFilesResponse } from '@/tools/pipedrive/types'
import { PIPEDRIVE_FILE_OUTPUT_PROPERTIES } from '@/tools/pipedrive/types'
import type { ToolConfig } from '@/tools/types'
export const pipedriveGetFilesTool: ToolConfig<PipedriveGetFilesParams, PipedriveGetFilesResponse> =
{
id: 'pipedrive_get_files',
name: 'Get Files from Pipedrive',
description: 'Retrieve files from Pipedrive with optional filters',
version: '1.0.0',
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'The access token for the Pipedrive API',
},
sort: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Sort files by field (supported: "id", "update_time")',
},
limit: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Number of results to return (e.g., "50", default: 100, max: 100)',
},
start: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Pagination start offset (0-based index of the first item to return)',
},
downloadFiles: {
type: 'boolean',
required: false,
visibility: 'user-or-llm',
description: 'Download file contents into file outputs',
},
},
request: {
url: '/api/tools/pipedrive/get-files',
method: 'POST',
headers: () => ({
'Content-Type': 'application/json',
}),
body: (params) => ({
accessToken: params.accessToken,
sort: params.sort,
limit: params.limit,
start: params.start,
downloadFiles: params.downloadFiles,
}),
},
outputs: {
files: {
type: 'array',
description: 'Array of file objects from Pipedrive',
items: {
type: 'object',
properties: PIPEDRIVE_FILE_OUTPUT_PROPERTIES,
},
},
downloadedFiles: {
type: 'file[]',
description: 'Downloaded files from Pipedrive',
optional: true,
},
total_items: { type: 'number', description: 'Total number of files returned' },
has_more: {
type: 'boolean',
description: 'Whether more files are available',
optional: true,
},
next_start: {
type: 'number',
description: 'Offset for fetching the next page',
optional: true,
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
+180
View File
@@ -0,0 +1,180 @@
import { createLogger } from '@sim/logger'
import type { PipedriveGetLeadsParams, PipedriveGetLeadsResponse } from '@/tools/pipedrive/types'
import { PIPEDRIVE_LEAD_OUTPUT_PROPERTIES } from '@/tools/pipedrive/types'
import type { ToolConfig } from '@/tools/types'
const logger = createLogger('PipedriveGetLeads')
export const pipedriveGetLeadsTool: ToolConfig<PipedriveGetLeadsParams, PipedriveGetLeadsResponse> =
{
id: 'pipedrive_get_leads',
name: 'Get Leads from Pipedrive',
description: 'Retrieve all leads or a specific lead from Pipedrive',
version: '1.0.0',
oauth: {
required: true,
provider: 'pipedrive',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'The access token for the Pipedrive API',
},
lead_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Optional: ID of a specific lead to retrieve (e.g., "abc123-def456-ghi789")',
},
archived: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Get archived leads instead of active ones (e.g., "true" or "false")',
},
owner_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter by owner user ID (e.g., "123")',
},
person_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter by person ID (e.g., "456")',
},
organization_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter by organization ID (e.g., "789")',
},
limit: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Number of results to return (e.g., "50", default: 100, max: 500)',
},
start: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Pagination start offset (0-based index of the first item to return)',
},
},
request: {
url: (params) => {
// If lead_id is provided, get specific lead
if (params.lead_id) {
return `https://api.pipedrive.com/v1/leads/${params.lead_id}`
}
// Get archived or active leads with optional filters
const baseUrl =
params.archived === 'true'
? 'https://api.pipedrive.com/v1/leads/archived'
: 'https://api.pipedrive.com/v1/leads'
const queryParams = new URLSearchParams()
if (params.owner_id) queryParams.append('owner_id', params.owner_id)
if (params.person_id) queryParams.append('person_id', params.person_id)
if (params.organization_id) queryParams.append('organization_id', params.organization_id)
if (params.limit) queryParams.append('limit', params.limit)
if (params.start) queryParams.append('start', params.start)
const queryString = queryParams.toString()
return queryString ? `${baseUrl}?${queryString}` : baseUrl
},
method: 'GET',
headers: (params) => {
if (!params.accessToken) {
throw new Error('Access token is required')
}
return {
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
}
},
},
transformResponse: async (response: Response, params) => {
const data = await response.json()
if (!data.success) {
logger.error('Pipedrive API request failed', { data })
throw new Error(data.error || 'Failed to fetch lead(s) from Pipedrive')
}
// If lead_id was provided, return single lead
if (params?.lead_id) {
return {
success: true,
output: {
lead: data.data ?? null,
success: true,
},
}
}
// Otherwise, return list of leads
const leads = data.data || []
// Leads endpoint puts pagination fields directly on additional_data (no .pagination wrapper)
const hasMore = data.additional_data?.more_items_in_collection || false
const currentStart = data.additional_data?.start ?? 0
const currentLimit = data.additional_data?.limit ?? leads.length
const nextStart = hasMore ? currentStart + currentLimit : null
return {
success: true,
output: {
leads,
total_items: leads.length,
has_more: hasMore,
next_start: nextStart,
success: true,
},
}
},
outputs: {
leads: {
type: 'array',
description: 'Array of lead objects (when listing all)',
optional: true,
items: {
type: 'object',
properties: PIPEDRIVE_LEAD_OUTPUT_PROPERTIES,
},
},
lead: {
type: 'object',
description: 'Single lead object (when lead_id is provided)',
optional: true,
properties: PIPEDRIVE_LEAD_OUTPUT_PROPERTIES,
},
total_items: {
type: 'number',
description: 'Total number of leads returned',
optional: true,
},
has_more: {
type: 'boolean',
description: 'Whether more leads are available',
optional: true,
},
next_start: {
type: 'number',
description: 'Offset for fetching the next page',
optional: true,
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
@@ -0,0 +1,115 @@
import { createLogger } from '@sim/logger'
import type {
PipedriveGetMailMessagesParams,
PipedriveGetMailMessagesResponse,
} from '@/tools/pipedrive/types'
import type { ToolConfig } from '@/tools/types'
const logger = createLogger('PipedriveGetMailMessages')
export const pipedriveGetMailMessagesTool: ToolConfig<
PipedriveGetMailMessagesParams,
PipedriveGetMailMessagesResponse
> = {
id: 'pipedrive_get_mail_messages',
name: 'Get Mail Threads from Pipedrive',
description: 'Retrieve mail threads from Pipedrive mailbox',
version: '1.0.0',
oauth: {
required: true,
provider: 'pipedrive',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'The access token for the Pipedrive API',
},
folder: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter by folder: inbox, drafts, sent, archive (default: inbox)',
},
limit: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Number of results to return (e.g., "25", default: 50)',
},
start: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Pagination start offset (0-based index of the first item to return)',
},
},
request: {
url: (params) => {
const baseUrl = 'https://api.pipedrive.com/v1/mailbox/mailThreads'
const queryParams = new URLSearchParams()
if (params.folder) queryParams.append('folder', params.folder)
if (params.limit) queryParams.append('limit', params.limit)
if (params.start) queryParams.append('start', params.start)
const queryString = queryParams.toString()
return queryString ? `${baseUrl}?${queryString}` : baseUrl
},
method: 'GET',
headers: (params) => {
if (!params.accessToken) {
throw new Error('Access token is required')
}
return {
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
}
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!data.success) {
logger.error('Pipedrive API request failed', { data })
throw new Error(data.error || 'Failed to fetch mail threads from Pipedrive')
}
const threads = data.data || []
const hasMore = data.additional_data?.pagination?.more_items_in_collection || false
const nextStart = data.additional_data?.pagination?.next_start ?? null
return {
success: true,
output: {
messages: threads,
total_items: threads.length,
has_more: hasMore,
next_start: nextStart,
success: true,
},
}
},
outputs: {
messages: { type: 'array', description: 'Array of mail thread objects from Pipedrive mailbox' },
total_items: { type: 'number', description: 'Total number of mail threads returned' },
has_more: {
type: 'boolean',
description: 'Whether more messages are available',
optional: true,
},
next_start: {
type: 'number',
description: 'Offset for fetching the next page',
optional: true,
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
@@ -0,0 +1,86 @@
import { createLogger } from '@sim/logger'
import type {
PipedriveGetMailThreadParams,
PipedriveGetMailThreadResponse,
} from '@/tools/pipedrive/types'
import type { ToolConfig } from '@/tools/types'
const logger = createLogger('PipedriveGetMailThread')
export const pipedriveGetMailThreadTool: ToolConfig<
PipedriveGetMailThreadParams,
PipedriveGetMailThreadResponse
> = {
id: 'pipedrive_get_mail_thread',
name: 'Get Mail Thread Messages from Pipedrive',
description: 'Retrieve all messages from a specific mail thread',
version: '1.0.0',
oauth: {
required: true,
provider: 'pipedrive',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'The access token for the Pipedrive API',
},
thread_id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the mail thread (e.g., "12345")',
},
},
request: {
url: (params) =>
`https://api.pipedrive.com/v1/mailbox/mailThreads/${params.thread_id}/mailMessages`,
method: 'GET',
headers: (params) => {
if (!params.accessToken) {
throw new Error('Access token is required')
}
return {
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
}
},
},
transformResponse: async (response: Response, params) => {
const data = await response.json()
if (!data.success) {
logger.error('Pipedrive API request failed', { data })
throw new Error(data.error || 'Failed to fetch mail thread from Pipedrive')
}
const messages = data.data || []
return {
success: true,
output: {
messages,
metadata: {
thread_id: params?.thread_id || '',
total_items: messages.length,
},
success: true,
},
}
},
outputs: {
messages: { type: 'array', description: 'Array of mail message objects from the thread' },
metadata: {
type: 'object',
description: 'Thread and pagination metadata',
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
@@ -0,0 +1,112 @@
import { createLogger } from '@sim/logger'
import type {
PipedriveGetPipelineDealsParams,
PipedriveGetPipelineDealsResponse,
} from '@/tools/pipedrive/types'
import type { ToolConfig } from '@/tools/types'
const logger = createLogger('PipedriveGetPipelineDeals')
export const pipedriveGetPipelineDealsTool: ToolConfig<
PipedriveGetPipelineDealsParams,
PipedriveGetPipelineDealsResponse
> = {
id: 'pipedrive_get_pipeline_deals',
name: 'Get Pipeline Deals from Pipedrive',
description: 'Retrieve all deals in a specific pipeline',
version: '1.0.0',
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'The access token for the Pipedrive API',
},
pipeline_id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the pipeline (e.g., "1")',
},
stage_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter by specific stage within the pipeline (e.g., "2")',
},
limit: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Number of results to return (e.g., "50", default: 100, max: 500)',
},
start: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Pagination start offset (0-based index of the first item to return)',
},
},
request: {
url: (params) => {
const baseUrl = `https://api.pipedrive.com/v1/pipelines/${params.pipeline_id}/deals`
const queryParams = new URLSearchParams()
if (params.stage_id) queryParams.append('stage_id', params.stage_id)
if (params.limit) queryParams.append('limit', params.limit)
if (params.start) queryParams.append('start', params.start)
const queryString = queryParams.toString()
return queryString ? `${baseUrl}?${queryString}` : baseUrl
},
method: 'GET',
headers: (params) => {
if (!params.accessToken) {
throw new Error('Access token is required')
}
return {
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
}
},
},
transformResponse: async (response: Response, params) => {
const data = await response.json()
if (!data.success) {
logger.error('Pipedrive API request failed', { data })
throw new Error(data.error || 'Failed to fetch pipeline deals from Pipedrive')
}
const deals = data.data || []
const hasMore = data.additional_data?.pagination?.more_items_in_collection || false
const nextStart = data.additional_data?.pagination?.next_start ?? null
return {
success: true,
output: {
deals,
metadata: {
pipeline_id: params?.pipeline_id || '',
total_items: deals.length,
has_more: hasMore,
next_start: nextStart,
},
success: true,
},
}
},
outputs: {
deals: { type: 'array', description: 'Array of deal objects from the pipeline' },
metadata: {
type: 'object',
description: 'Pipeline and pagination metadata',
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
+125
View File
@@ -0,0 +1,125 @@
import { createLogger } from '@sim/logger'
import type {
PipedriveGetPipelinesParams,
PipedriveGetPipelinesResponse,
} from '@/tools/pipedrive/types'
import { PIPEDRIVE_PIPELINE_OUTPUT_PROPERTIES } from '@/tools/pipedrive/types'
import type { ToolConfig } from '@/tools/types'
const logger = createLogger('PipedriveGetPipelines')
export const pipedriveGetPipelinesTool: ToolConfig<
PipedriveGetPipelinesParams,
PipedriveGetPipelinesResponse
> = {
id: 'pipedrive_get_pipelines',
name: 'Get Pipelines from Pipedrive',
description: 'Retrieve all pipelines from Pipedrive',
version: '1.0.0',
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'The access token for the Pipedrive API',
},
sort_by: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Field to sort by: id, update_time, add_time (default: id)',
},
sort_direction: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Sorting direction: asc, desc (default: asc)',
},
limit: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Number of results to return (e.g., "50", default: 100, max: 500)',
},
start: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Pagination start offset (0-based index of the first item to return)',
},
},
request: {
url: (params) => {
const baseUrl = 'https://api.pipedrive.com/v1/pipelines'
const queryParams = new URLSearchParams()
if (params.sort_by) queryParams.append('sort_by', params.sort_by)
if (params.sort_direction) queryParams.append('sort_direction', params.sort_direction)
if (params.limit) queryParams.append('limit', params.limit)
if (params.start) queryParams.append('start', params.start)
const queryString = queryParams.toString()
return queryString ? `${baseUrl}?${queryString}` : baseUrl
},
method: 'GET',
headers: (params) => {
if (!params.accessToken) {
throw new Error('Access token is required')
}
return {
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
}
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!data.success) {
logger.error('Pipedrive API request failed', { data })
throw new Error(data.error || 'Failed to fetch pipelines from Pipedrive')
}
const pipelines = data.data || []
const hasMore = data.additional_data?.pagination?.more_items_in_collection || false
const nextStart = data.additional_data?.pagination?.next_start ?? null
return {
success: true,
output: {
pipelines,
total_items: pipelines.length,
has_more: hasMore,
next_start: nextStart,
success: true,
},
}
},
outputs: {
pipelines: {
type: 'array',
description: 'Array of pipeline objects from Pipedrive',
items: {
type: 'object',
properties: PIPEDRIVE_PIPELINE_OUTPUT_PROPERTIES,
},
},
total_items: { type: 'number', description: 'Total number of pipelines returned' },
has_more: {
type: 'boolean',
description: 'Whether more pipelines are available',
optional: true,
},
next_start: {
type: 'number',
description: 'Offset for fetching the next page',
optional: true,
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
+148
View File
@@ -0,0 +1,148 @@
import { createLogger } from '@sim/logger'
import type {
PipedriveGetProjectsParams,
PipedriveGetProjectsResponse,
} from '@/tools/pipedrive/types'
import type { ToolConfig } from '@/tools/types'
const logger = createLogger('PipedriveGetProjects')
export const pipedriveGetProjectsTool: ToolConfig<
PipedriveGetProjectsParams,
PipedriveGetProjectsResponse
> = {
id: 'pipedrive_get_projects',
name: 'Get Projects from Pipedrive',
description: 'Retrieve all projects or a specific project from Pipedrive',
version: '1.0.0',
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'The access token for the Pipedrive API',
},
project_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Optional: ID of a specific project to retrieve (e.g., "123")',
},
status: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter by project status: open, completed, deleted (only for listing all)',
},
limit: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'Number of results to return (e.g., "50", default: 100, max: 500, only for listing all)',
},
cursor: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'For pagination, the marker representing the first item on the next page',
},
},
request: {
url: (params) => {
// If project_id is provided, get specific project
if (params.project_id) {
return `https://api.pipedrive.com/v1/projects/${params.project_id}`
}
// Otherwise, get all projects with optional filters
const baseUrl = 'https://api.pipedrive.com/v1/projects'
const queryParams = new URLSearchParams()
if (params.status) queryParams.append('status', params.status)
if (params.limit) queryParams.append('limit', params.limit)
if (params.cursor) queryParams.append('cursor', params.cursor)
const queryString = queryParams.toString()
return queryString ? `${baseUrl}?${queryString}` : baseUrl
},
method: 'GET',
headers: (params) => {
if (!params.accessToken) {
throw new Error('Access token is required')
}
return {
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
}
},
},
transformResponse: async (response: Response, params) => {
const data = await response.json()
if (!data.success) {
logger.error('Pipedrive API request failed', { data })
throw new Error(data.error || 'Failed to fetch project(s) from Pipedrive')
}
// If project_id was provided, return single project
if (params?.project_id) {
return {
success: true,
output: {
project: data.data ?? null,
success: true,
},
}
}
// Otherwise, return list of projects
const projects = data.data || []
const nextCursor = data.additional_data?.next_cursor ?? null
const hasMore = nextCursor !== null
return {
success: true,
output: {
projects,
total_items: projects.length,
has_more: hasMore,
next_cursor: nextCursor,
success: true,
},
}
},
outputs: {
projects: {
type: 'array',
description: 'Array of project objects (when listing all)',
optional: true,
},
project: {
type: 'object',
description: 'Single project object (when project_id is provided)',
optional: true,
},
total_items: {
type: 'number',
description: 'Total number of projects returned',
optional: true,
},
has_more: {
type: 'boolean',
description: 'Whether more projects are available',
optional: true,
},
next_cursor: {
type: 'string',
description: 'Cursor for fetching the next page',
optional: true,
},
success: { type: 'boolean', description: 'Operation success status' },
},
}
+26
View File
@@ -0,0 +1,26 @@
// Deal operations
export { pipedriveCreateActivityTool } from '@/tools/pipedrive/create_activity'
export { pipedriveCreateDealTool } from '@/tools/pipedrive/create_deal'
export { pipedriveCreateLeadTool } from '@/tools/pipedrive/create_lead'
export { pipedriveCreateProjectTool } from '@/tools/pipedrive/create_project'
export { pipedriveDeleteLeadTool } from '@/tools/pipedrive/delete_lead'
// Activity operations
export { pipedriveGetActivitiesTool } from '@/tools/pipedrive/get_activities'
export { pipedriveGetAllDealsTool } from '@/tools/pipedrive/get_all_deals'
export { pipedriveGetDealTool } from '@/tools/pipedrive/get_deal'
// File operations
export { pipedriveGetFilesTool } from '@/tools/pipedrive/get_files'
// Lead operations
export { pipedriveGetLeadsTool } from '@/tools/pipedrive/get_leads'
// Mail operations
export { pipedriveGetMailMessagesTool } from '@/tools/pipedrive/get_mail_messages'
export { pipedriveGetMailThreadTool } from '@/tools/pipedrive/get_mail_thread'
export { pipedriveGetPipelineDealsTool } from '@/tools/pipedrive/get_pipeline_deals'
// Pipeline operations
export { pipedriveGetPipelinesTool } from '@/tools/pipedrive/get_pipelines'
// Project operations
export { pipedriveGetProjectsTool } from '@/tools/pipedrive/get_projects'
export { pipedriveUpdateActivityTool } from '@/tools/pipedrive/update_activity'
export { pipedriveUpdateDealTool } from '@/tools/pipedrive/update_deal'
export { pipedriveUpdateLeadTool } from '@/tools/pipedrive/update_lead'
+758
View File
@@ -0,0 +1,758 @@
import type { OutputProperty, ToolFileData, ToolResponse } from '@/tools/types'
/**
* Output property definitions for Pipedrive API responses.
* @see https://developers.pipedrive.com/docs/api/v1
*/
/**
* Output definition for lead value objects.
* @see https://developers.pipedrive.com/docs/api/v1/Leads
*/
export const PIPEDRIVE_LEAD_VALUE_OUTPUT_PROPERTIES = {
amount: { type: 'number', description: 'Value amount' },
currency: { type: 'string', description: 'Currency code (e.g., USD, EUR)' },
} as const satisfies Record<string, OutputProperty>
/**
* Output definition for lead objects.
* @see https://developers.pipedrive.com/docs/api/v1/Leads
*/
export const PIPEDRIVE_LEAD_OUTPUT_PROPERTIES = {
id: { type: 'string', description: 'Lead ID (UUID)' },
title: { type: 'string', description: 'Lead title' },
person_id: { type: 'number', description: 'ID of the associated person', optional: true },
organization_id: {
type: 'number',
description: 'ID of the associated organization',
optional: true,
},
owner_id: { type: 'number', description: 'ID of the lead owner' },
value: {
type: 'object',
description: 'Lead value',
optional: true,
properties: PIPEDRIVE_LEAD_VALUE_OUTPUT_PROPERTIES,
},
expected_close_date: {
type: 'string',
description: 'Expected close date (YYYY-MM-DD)',
optional: true,
},
is_archived: { type: 'boolean', description: 'Whether the lead is archived' },
was_seen: { type: 'boolean', description: 'Whether the lead was seen' },
add_time: { type: 'string', description: 'When the lead was created (ISO 8601)' },
update_time: { type: 'string', description: 'When the lead was last updated (ISO 8601)' },
} as const satisfies Record<string, OutputProperty>
/**
* Complete lead output definition
*/
export const PIPEDRIVE_LEAD_OUTPUT: OutputProperty = {
type: 'object',
description: 'Pipedrive lead object',
properties: PIPEDRIVE_LEAD_OUTPUT_PROPERTIES,
}
/**
* Output definition for deal objects.
* @see https://developers.pipedrive.com/docs/api/v1/Deals
*/
export const PIPEDRIVE_DEAL_OUTPUT_PROPERTIES = {
id: { type: 'number', description: 'Deal ID' },
title: { type: 'string', description: 'Deal title' },
value: { type: 'number', description: 'Deal value' },
currency: { type: 'string', description: 'Currency code' },
status: { type: 'string', description: 'Deal status (open, won, lost, deleted)' },
stage_id: { type: 'number', description: 'Pipeline stage ID' },
pipeline_id: { type: 'number', description: 'Pipeline ID' },
person_id: { type: 'number', description: 'Associated person ID', optional: true },
org_id: { type: 'number', description: 'Associated organization ID', optional: true },
owner_id: { type: 'number', description: 'Deal owner user ID' },
add_time: { type: 'string', description: 'When the deal was created (ISO 8601)' },
update_time: { type: 'string', description: 'When the deal was last updated (ISO 8601)' },
won_time: { type: 'string', description: 'When the deal was won', optional: true },
lost_time: { type: 'string', description: 'When the deal was lost', optional: true },
close_time: { type: 'string', description: 'When the deal was closed', optional: true },
expected_close_date: { type: 'string', description: 'Expected close date', optional: true },
} as const satisfies Record<string, OutputProperty>
/**
* Complete deal output definition
*/
export const PIPEDRIVE_DEAL_OUTPUT: OutputProperty = {
type: 'object',
description: 'Pipedrive deal object',
properties: PIPEDRIVE_DEAL_OUTPUT_PROPERTIES,
}
/**
* Output definition for activity objects.
* @see https://developers.pipedrive.com/docs/api/v1/Activities
*/
export const PIPEDRIVE_ACTIVITY_OUTPUT_PROPERTIES = {
id: { type: 'number', description: 'Activity ID' },
subject: { type: 'string', description: 'Activity subject' },
type: { type: 'string', description: 'Activity type (call, meeting, task, etc.)' },
due_date: { type: 'string', description: 'Due date (YYYY-MM-DD)' },
due_time: { type: 'string', description: 'Due time (HH:MM)' },
duration: { type: 'string', description: 'Duration (HH:MM)' },
deal_id: { type: 'number', description: 'Associated deal ID', optional: true },
person_id: { type: 'number', description: 'Associated person ID', optional: true },
org_id: { type: 'number', description: 'Associated organization ID', optional: true },
done: { type: 'boolean', description: 'Whether the activity is done' },
note: { type: 'string', description: 'Activity note' },
add_time: { type: 'string', description: 'When the activity was created' },
update_time: { type: 'string', description: 'When the activity was last updated' },
} as const satisfies Record<string, OutputProperty>
/**
* Complete activity output definition
*/
export const PIPEDRIVE_ACTIVITY_OUTPUT: OutputProperty = {
type: 'object',
description: 'Pipedrive activity object',
properties: PIPEDRIVE_ACTIVITY_OUTPUT_PROPERTIES,
}
/**
* Output definition for file objects.
* @see https://developers.pipedrive.com/docs/api/v1/Files
*/
export const PIPEDRIVE_FILE_OUTPUT_PROPERTIES = {
id: { type: 'number', description: 'File ID' },
name: { type: 'string', description: 'File name' },
file_type: { type: 'string', description: 'File type/extension' },
file_size: { type: 'number', description: 'File size in bytes' },
add_time: { type: 'string', description: 'When the file was uploaded' },
update_time: { type: 'string', description: 'When the file was last updated' },
deal_id: { type: 'number', description: 'Associated deal ID', optional: true },
person_id: { type: 'number', description: 'Associated person ID', optional: true },
org_id: { type: 'number', description: 'Associated organization ID', optional: true },
url: { type: 'string', description: 'File download URL' },
} as const satisfies Record<string, OutputProperty>
/**
* Complete file output definition
*/
export const PIPEDRIVE_FILE_OUTPUT: OutputProperty = {
type: 'object',
description: 'Pipedrive file object',
properties: PIPEDRIVE_FILE_OUTPUT_PROPERTIES,
}
/**
* Output definition for pipeline objects.
* @see https://developers.pipedrive.com/docs/api/v1/Pipelines
*/
export const PIPEDRIVE_PIPELINE_OUTPUT_PROPERTIES = {
id: { type: 'number', description: 'Pipeline ID' },
name: { type: 'string', description: 'Pipeline name' },
url_title: { type: 'string', description: 'URL-friendly title' },
order_nr: { type: 'number', description: 'Pipeline order number' },
active: { type: 'boolean', description: 'Whether the pipeline is active' },
deal_probability: { type: 'boolean', description: 'Whether deal probability is enabled' },
add_time: { type: 'string', description: 'When the pipeline was created' },
update_time: { type: 'string', description: 'When the pipeline was last updated' },
} as const satisfies Record<string, OutputProperty>
/**
* Complete pipeline output definition
*/
export const PIPEDRIVE_PIPELINE_OUTPUT: OutputProperty = {
type: 'object',
description: 'Pipedrive pipeline object',
properties: PIPEDRIVE_PIPELINE_OUTPUT_PROPERTIES,
}
/**
* Output definition for project objects.
* @see https://developers.pipedrive.com/docs/api/v1/Projects
*/
export const PIPEDRIVE_PROJECT_OUTPUT_PROPERTIES = {
id: { type: 'number', description: 'Project ID' },
title: { type: 'string', description: 'Project title' },
description: { type: 'string', description: 'Project description', optional: true },
status: { type: 'string', description: 'Project status' },
owner_id: { type: 'number', description: 'Project owner user ID' },
start_date: { type: 'string', description: 'Project start date', optional: true },
end_date: { type: 'string', description: 'Project end date', optional: true },
add_time: { type: 'string', description: 'When the project was created' },
update_time: { type: 'string', description: 'When the project was last updated' },
} as const satisfies Record<string, OutputProperty>
/**
* Complete project output definition
*/
export const PIPEDRIVE_PROJECT_OUTPUT: OutputProperty = {
type: 'object',
description: 'Pipedrive project object',
properties: PIPEDRIVE_PROJECT_OUTPUT_PROPERTIES,
}
/**
* Output definition for mail message objects.
* @see https://developers.pipedrive.com/docs/api/v1/Mailbox
*/
export const PIPEDRIVE_MAIL_MESSAGE_OUTPUT_PROPERTIES = {
id: { type: 'number', description: 'Message ID' },
subject: { type: 'string', description: 'Email subject' },
snippet: { type: 'string', description: 'Email snippet/preview' },
mail_thread_id: { type: 'number', description: 'Mail thread ID' },
from_address: { type: 'string', description: 'Sender email address' },
to_addresses: {
type: 'array',
description: 'Recipient email addresses',
items: { type: 'string', description: 'Email address' },
},
cc_addresses: {
type: 'array',
description: 'CC email addresses',
optional: true,
items: { type: 'string', description: 'Email address' },
},
bcc_addresses: {
type: 'array',
description: 'BCC email addresses',
optional: true,
items: { type: 'string', description: 'Email address' },
},
timestamp: { type: 'string', description: 'Message timestamp' },
item_type: { type: 'string', description: 'Item type' },
deal_id: { type: 'number', description: 'Associated deal ID', optional: true },
person_id: { type: 'number', description: 'Associated person ID', optional: true },
org_id: { type: 'number', description: 'Associated organization ID', optional: true },
} as const satisfies Record<string, OutputProperty>
/**
* Complete mail message output definition
*/
export const PIPEDRIVE_MAIL_MESSAGE_OUTPUT: OutputProperty = {
type: 'object',
description: 'Pipedrive mail message object',
properties: PIPEDRIVE_MAIL_MESSAGE_OUTPUT_PROPERTIES,
}
/**
* List metadata output properties
*/
export const PIPEDRIVE_METADATA_OUTPUT_PROPERTIES = {
total_items: { type: 'number', description: 'Total number of items' },
has_more: { type: 'boolean', description: 'Whether more items are available', optional: true },
next_cursor: {
type: 'string',
description: 'Cursor for fetching the next page (v2 endpoints)',
optional: true,
},
next_start: {
type: 'number',
description: 'Offset for fetching the next page (v1 endpoints)',
optional: true,
},
} as const satisfies Record<string, OutputProperty>
// Common Pipedrive types
interface PipedriveLead {
id: string
title: string
person_id?: number
organization_id?: number
owner_id: number
value?: {
amount: number
currency: string
}
expected_close_date?: string
is_archived: boolean
was_seen: boolean
add_time: string
update_time: string
}
interface PipedriveDeal {
id: number
title: string
value: number
currency: string
status: string
stage_id: number
pipeline_id: number
person_id?: number
org_id?: number
owner_id: number
add_time: string
update_time: string
won_time?: string
lost_time?: string
close_time?: string
expected_close_date?: string
}
interface PipedriveActivity {
id: number
subject: string
type: string
due_date: string
due_time: string
duration: string
deal_id?: number
person_id?: number
org_id?: number
done: boolean
note: string
add_time: string
update_time: string
}
interface PipedriveFile {
id: number
name: string
file_type: string
file_size: number
add_time: string
update_time: string
deal_id?: number
person_id?: number
org_id?: number
url: string
}
interface PipedrivePipeline {
id: number
name: string
url_title: string
order_nr: number
active: boolean
deal_probability: boolean
add_time: string
update_time: string
}
interface PipedriveProject {
id: number
title: string
description?: string
status: string
owner_id: number
start_date?: string
end_date?: string
add_time: string
update_time: string
}
interface PipedriveMailMessage {
id: number
subject: string
snippet: string
mail_thread_id: number
from_address: string
to_addresses: string[]
cc_addresses?: string[]
bcc_addresses?: string[]
timestamp: string
item_type: string
deal_id?: number
person_id?: number
org_id?: number
}
// GET All Deals
export interface PipedriveGetAllDealsParams {
accessToken: string
status?: string
person_id?: string
org_id?: string
pipeline_id?: string
updated_since?: string
limit?: string
cursor?: string
}
interface PipedriveGetAllDealsOutput {
deals: PipedriveDeal[]
metadata: {
total_items: number
has_more: boolean
next_cursor?: string
}
success: boolean
}
export interface PipedriveGetAllDealsResponse extends ToolResponse {
output: PipedriveGetAllDealsOutput
}
// GET Deal
export interface PipedriveGetDealParams {
accessToken: string
deal_id: string
}
interface PipedriveGetDealOutput {
deal: PipedriveDeal
success: boolean
}
export interface PipedriveGetDealResponse extends ToolResponse {
output: PipedriveGetDealOutput
}
// CREATE Deal
export interface PipedriveCreateDealParams {
accessToken: string
title: string
value?: string
currency?: string
person_id?: string
org_id?: string
pipeline_id?: string
stage_id?: string
status?: string
expected_close_date?: string
}
interface PipedriveCreateDealOutput {
deal: PipedriveDeal
success: boolean
}
export interface PipedriveCreateDealResponse extends ToolResponse {
output: PipedriveCreateDealOutput
}
// UPDATE Deal
export interface PipedriveUpdateDealParams {
accessToken: string
deal_id: string
title?: string
value?: string
status?: string
stage_id?: string
expected_close_date?: string
}
interface PipedriveUpdateDealOutput {
deal: PipedriveDeal
success: boolean
}
export interface PipedriveUpdateDealResponse extends ToolResponse {
output: PipedriveUpdateDealOutput
}
// GET Files
export interface PipedriveGetFilesParams {
accessToken: string
sort?: string
limit?: string
start?: string
downloadFiles?: boolean
}
interface PipedriveGetFilesOutput {
files: PipedriveFile[]
downloadedFiles?: ToolFileData[]
total_items: number
has_more?: boolean
next_start?: number
success: boolean
}
export interface PipedriveGetFilesResponse extends ToolResponse {
output: PipedriveGetFilesOutput
}
export interface PipedriveGetMailMessagesParams {
accessToken: string
folder?: string
limit?: string
start?: string
}
interface PipedriveGetMailMessagesOutput {
messages: PipedriveMailMessage[]
total_items: number
has_more?: boolean
next_start?: number
success: boolean
}
export interface PipedriveGetMailMessagesResponse extends ToolResponse {
output: PipedriveGetMailMessagesOutput
}
// GET Mail Thread
export interface PipedriveGetMailThreadParams {
accessToken: string
thread_id: string
}
interface PipedriveGetMailThreadOutput {
messages: PipedriveMailMessage[]
metadata: {
thread_id: string
total_items: number
}
success: boolean
}
export interface PipedriveGetMailThreadResponse extends ToolResponse {
output: PipedriveGetMailThreadOutput
}
// GET All Pipelines
export interface PipedriveGetPipelinesParams {
accessToken: string
sort_by?: string
sort_direction?: string
limit?: string
start?: string
}
interface PipedriveGetPipelinesOutput {
pipelines: PipedrivePipeline[]
total_items: number
has_more?: boolean
next_start?: number
success: boolean
}
export interface PipedriveGetPipelinesResponse extends ToolResponse {
output: PipedriveGetPipelinesOutput
}
// GET Pipeline Deals
export interface PipedriveGetPipelineDealsParams {
accessToken: string
pipeline_id: string
stage_id?: string
limit?: string
start?: string
}
interface PipedriveGetPipelineDealsOutput {
deals: PipedriveDeal[]
metadata: {
pipeline_id: string
total_items: number
has_more?: boolean
next_start?: number
}
success: boolean
}
export interface PipedriveGetPipelineDealsResponse extends ToolResponse {
output: PipedriveGetPipelineDealsOutput
}
// GET All Projects (or single project if project_id provided)
export interface PipedriveGetProjectsParams {
accessToken: string
project_id?: string
status?: string
limit?: string
cursor?: string
}
interface PipedriveGetProjectsOutput {
projects?: PipedriveProject[]
project?: PipedriveProject
total_items?: number
has_more?: boolean
next_cursor?: string
success: boolean
}
export interface PipedriveGetProjectsResponse extends ToolResponse {
output: PipedriveGetProjectsOutput
}
// CREATE Project
export interface PipedriveCreateProjectParams {
accessToken: string
title: string
description?: string
start_date?: string
end_date?: string
}
interface PipedriveCreateProjectOutput {
project: PipedriveProject
success: boolean
}
export interface PipedriveCreateProjectResponse extends ToolResponse {
output: PipedriveCreateProjectOutput
}
// GET All Activities
export interface PipedriveGetActivitiesParams {
accessToken: string
user_id?: string
type?: string
done?: string
limit?: string
start?: string
}
interface PipedriveGetActivitiesOutput {
activities: PipedriveActivity[]
total_items: number
has_more?: boolean
next_start?: number
success: boolean
}
export interface PipedriveGetActivitiesResponse extends ToolResponse {
output: PipedriveGetActivitiesOutput
}
// CREATE Activity
export interface PipedriveCreateActivityParams {
accessToken: string
subject: string
type: string
due_date: string
due_time?: string
duration?: string
deal_id?: string
person_id?: string
org_id?: string
note?: string
}
interface PipedriveCreateActivityOutput {
activity: PipedriveActivity
success: boolean
}
export interface PipedriveCreateActivityResponse extends ToolResponse {
output: PipedriveCreateActivityOutput
}
// UPDATE Activity
export interface PipedriveUpdateActivityParams {
accessToken: string
activity_id: string
subject?: string
due_date?: string
due_time?: string
duration?: string
done?: string
note?: string
}
interface PipedriveUpdateActivityOutput {
activity: PipedriveActivity
success: boolean
}
export interface PipedriveUpdateActivityResponse extends ToolResponse {
output: PipedriveUpdateActivityOutput
}
// GET Leads
export interface PipedriveGetLeadsParams {
accessToken: string
lead_id?: string
archived?: string
owner_id?: string
person_id?: string
organization_id?: string
limit?: string
start?: string
}
interface PipedriveGetLeadsOutput {
leads?: PipedriveLead[]
lead?: PipedriveLead
total_items?: number
has_more?: boolean
next_start?: number
success: boolean
}
export interface PipedriveGetLeadsResponse extends ToolResponse {
output: PipedriveGetLeadsOutput
}
// CREATE Lead
export interface PipedriveCreateLeadParams {
accessToken: string
title: string
person_id?: string
organization_id?: string
owner_id?: string
value_amount?: string
value_currency?: string
expected_close_date?: string
visible_to?: string
}
interface PipedriveCreateLeadOutput {
lead: PipedriveLead
success: boolean
}
export interface PipedriveCreateLeadResponse extends ToolResponse {
output: PipedriveCreateLeadOutput
}
// UPDATE Lead
export interface PipedriveUpdateLeadParams {
accessToken: string
lead_id: string
title?: string
person_id?: string
organization_id?: string
owner_id?: string
value_amount?: string
value_currency?: string
expected_close_date?: string
is_archived?: string
}
interface PipedriveUpdateLeadOutput {
lead: PipedriveLead
success: boolean
}
export interface PipedriveUpdateLeadResponse extends ToolResponse {
output: PipedriveUpdateLeadOutput
}
// DELETE Lead
export interface PipedriveDeleteLeadParams {
accessToken: string
lead_id: string
}
interface PipedriveDeleteLeadOutput {
data: any
success: boolean
}
export interface PipedriveDeleteLeadResponse extends ToolResponse {
output: PipedriveDeleteLeadOutput
}
// Union type of all responses
export type PipedriveResponse =
| PipedriveGetAllDealsResponse
| PipedriveGetDealResponse
| PipedriveCreateDealResponse
| PipedriveUpdateDealResponse
| PipedriveGetFilesResponse
| PipedriveGetMailMessagesResponse
| PipedriveGetMailThreadResponse
| PipedriveGetPipelinesResponse
| PipedriveGetPipelineDealsResponse
| PipedriveGetProjectsResponse
| PipedriveCreateProjectResponse
| PipedriveGetActivitiesResponse
| PipedriveCreateActivityResponse
| PipedriveUpdateActivityResponse
| PipedriveGetLeadsResponse
| PipedriveCreateLeadResponse
| PipedriveUpdateLeadResponse
| PipedriveDeleteLeadResponse
+119
View File
@@ -0,0 +1,119 @@
import { createLogger } from '@sim/logger'
import type {
PipedriveUpdateActivityParams,
PipedriveUpdateActivityResponse,
} from '@/tools/pipedrive/types'
import type { ToolConfig } from '@/tools/types'
const logger = createLogger('PipedriveUpdateActivity')
export const pipedriveUpdateActivityTool: ToolConfig<
PipedriveUpdateActivityParams,
PipedriveUpdateActivityResponse
> = {
id: 'pipedrive_update_activity',
name: 'Update Activity in Pipedrive',
description: 'Update an existing activity (task) in Pipedrive',
version: '1.0.0',
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'The access token for the Pipedrive API',
},
activity_id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the activity to update (e.g., "12345")',
},
subject: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New subject/title for the activity (e.g., "Updated meeting with client")',
},
due_date: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New due date in YYYY-MM-DD format (e.g., "2025-03-20")',
},
due_time: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New due time in HH:MM format (e.g., "15:00")',
},
duration: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New duration in HH:MM format (e.g., "00:30" for 30 minutes)',
},
done: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Mark as done: 0 for not done, 1 for done',
},
note: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New notes for the activity',
},
},
request: {
url: (params) => `https://api.pipedrive.com/v1/activities/${params.activity_id}`,
method: 'PUT',
headers: (params) => {
if (!params.accessToken) {
throw new Error('Access token is required')
}
return {
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
}
},
body: (params) => {
const body: Record<string, any> = {}
if (params.subject) body.subject = params.subject
if (params.due_date) body.due_date = params.due_date
if (params.due_time) body.due_time = params.due_time
if (params.duration) body.duration = params.duration
if (params.done !== undefined) body.done = params.done === '1' ? 1 : 0
if (params.note) body.note = params.note
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!data.success) {
logger.error('Pipedrive API request failed', { data })
throw new Error(data.error || 'Failed to update activity in Pipedrive')
}
return {
success: true,
output: {
activity: data.data ?? null,
success: true,
},
}
},
outputs: {
activity: { type: 'object', description: 'The updated activity object', optional: true },
success: { type: 'boolean', description: 'Operation success status' },
},
}
+112
View File
@@ -0,0 +1,112 @@
import { createLogger } from '@sim/logger'
import type {
PipedriveUpdateDealParams,
PipedriveUpdateDealResponse,
} from '@/tools/pipedrive/types'
import type { ToolConfig } from '@/tools/types'
const logger = createLogger('PipedriveUpdateDeal')
export const pipedriveUpdateDealTool: ToolConfig<
PipedriveUpdateDealParams,
PipedriveUpdateDealResponse
> = {
id: 'pipedrive_update_deal',
name: 'Update Deal in Pipedrive',
description: 'Update an existing deal in Pipedrive',
version: '1.0.0',
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'The access token for the Pipedrive API',
},
deal_id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the deal to update (e.g., "123")',
},
title: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New title for the deal (e.g., "Updated Enterprise License")',
},
value: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New monetary value for the deal (e.g., "7500")',
},
status: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New status: open, won, lost',
},
stage_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New stage ID for the deal (e.g., "3")',
},
expected_close_date: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New expected close date in YYYY-MM-DD format (e.g., "2025-07-15")',
},
},
request: {
url: (params) => `https://api.pipedrive.com/api/v2/deals/${params.deal_id}`,
method: 'PATCH',
headers: (params) => {
if (!params.accessToken) {
throw new Error('Access token is required')
}
return {
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
}
},
body: (params) => {
const body: Record<string, any> = {}
if (params.title) body.title = params.title
if (params.value) body.value = Number(params.value)
if (params.status) body.status = params.status
if (params.stage_id) body.stage_id = Number(params.stage_id)
if (params.expected_close_date) body.expected_close_date = params.expected_close_date
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!data.success) {
logger.error('Pipedrive API request failed', { data })
throw new Error(data.error || 'Failed to update deal in Pipedrive')
}
return {
success: true,
output: {
deal: data.data ?? null,
success: true,
},
}
},
outputs: {
deal: { type: 'object', description: 'The updated deal object', optional: true },
success: { type: 'boolean', description: 'Operation success status' },
},
}
+145
View File
@@ -0,0 +1,145 @@
import { createLogger } from '@sim/logger'
import type {
PipedriveUpdateLeadParams,
PipedriveUpdateLeadResponse,
} from '@/tools/pipedrive/types'
import type { ToolConfig } from '@/tools/types'
const logger = createLogger('PipedriveUpdateLead')
export const pipedriveUpdateLeadTool: ToolConfig<
PipedriveUpdateLeadParams,
PipedriveUpdateLeadResponse
> = {
id: 'pipedrive_update_lead',
name: 'Update Lead in Pipedrive',
description: 'Update an existing lead in Pipedrive',
version: '1.0.0',
oauth: {
required: true,
provider: 'pipedrive',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'The access token for the Pipedrive API',
},
lead_id: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the lead to update (e.g., "abc123-def456-ghi789")',
},
title: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New name for the lead (e.g., "Updated Lead - Premium Package")',
},
person_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New person ID (e.g., "456")',
},
organization_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New organization ID (e.g., "789")',
},
owner_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New owner user ID (e.g., "123")',
},
value_amount: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New value amount (e.g., "15000")',
},
value_currency: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New currency code (e.g., "USD", "EUR", "GBP")',
},
expected_close_date: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'New expected close date in YYYY-MM-DD format (e.g., "2025-05-01")',
},
is_archived: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Archive the lead: true or false',
},
},
request: {
url: (params) => `https://api.pipedrive.com/v1/leads/${params.lead_id}`,
method: 'PATCH',
headers: (params) => {
if (!params.accessToken) {
throw new Error('Access token is required')
}
return {
Authorization: `Bearer ${params.accessToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
}
},
body: (params) => {
const body: Record<string, any> = {}
if (params.title) body.title = params.title
if (params.person_id) body.person_id = Number(params.person_id)
if (params.organization_id) body.organization_id = Number(params.organization_id)
if (params.owner_id) body.owner_id = Number(params.owner_id)
// Build value object if both amount and currency are provided
if (params.value_amount && params.value_currency) {
body.value = {
amount: Number(params.value_amount),
currency: params.value_currency,
}
}
if (params.expected_close_date) body.expected_close_date = params.expected_close_date
if (params.is_archived) body.is_archived = params.is_archived === 'true'
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!data.success) {
logger.error('Pipedrive API request failed', { data })
throw new Error(data.error || 'Failed to update lead in Pipedrive')
}
return {
success: true,
output: {
lead: data.data ?? null,
success: true,
},
}
},
outputs: {
lead: { type: 'object', description: 'The updated lead object', optional: true },
success: { type: 'boolean', description: 'Operation success status' },
},
}