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
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:
@@ -0,0 +1,146 @@
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface IntercomAssignConversationParams {
|
||||
accessToken: string
|
||||
conversationId: string
|
||||
admin_id: string
|
||||
assignee_id: string
|
||||
body?: string
|
||||
}
|
||||
|
||||
export interface IntercomAssignConversationV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
conversation: any
|
||||
conversationId: string
|
||||
admin_assignee_id: number | null
|
||||
team_assignee_id: string | null
|
||||
}
|
||||
}
|
||||
|
||||
const assignConversationBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
conversationId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the conversation to assign',
|
||||
},
|
||||
admin_id: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the admin performing the assignment',
|
||||
},
|
||||
assignee_id: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'The ID of the admin or team to assign the conversation to. Set to "0" to unassign.',
|
||||
},
|
||||
body: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Optional message to add when assigning (e.g., "Passing to the support team")',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: IntercomAssignConversationParams) =>
|
||||
buildIntercomUrl(`/conversations/${params.conversationId}/parts`),
|
||||
method: 'POST',
|
||||
headers: (params: IntercomAssignConversationParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
body: (params: IntercomAssignConversationParams) => {
|
||||
const payload: any = {
|
||||
message_type: 'assignment',
|
||||
type: 'admin',
|
||||
admin_id: params.admin_id,
|
||||
assignee_id: params.assignee_id,
|
||||
}
|
||||
|
||||
if (params.body) {
|
||||
payload.body = params.body
|
||||
}
|
||||
|
||||
return payload
|
||||
},
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomAssignConversationParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomAssignConversationV2Tool: ToolConfig<
|
||||
IntercomAssignConversationParams,
|
||||
IntercomAssignConversationV2Response
|
||||
> = {
|
||||
...assignConversationBase,
|
||||
id: 'intercom_assign_conversation_v2',
|
||||
name: 'Assign Conversation in Intercom',
|
||||
description: 'Assign a conversation to an admin or team in Intercom',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'assign_conversation')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
conversation: data,
|
||||
conversationId: data.id,
|
||||
admin_assignee_id: data.admin_assignee_id ?? null,
|
||||
team_assignee_id: data.team_assignee_id ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
conversation: {
|
||||
type: 'object',
|
||||
description: 'The assigned conversation object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the conversation' },
|
||||
type: { type: 'string', description: 'Object type (conversation)' },
|
||||
state: { type: 'string', description: 'State of the conversation' },
|
||||
open: { type: 'boolean', description: 'Whether the conversation is open' },
|
||||
admin_assignee_id: {
|
||||
type: 'number',
|
||||
description: 'ID of the assigned admin',
|
||||
optional: true,
|
||||
},
|
||||
team_assignee_id: {
|
||||
type: 'string',
|
||||
description: 'ID of the assigned team',
|
||||
optional: true,
|
||||
},
|
||||
created_at: { type: 'number', description: 'Unix timestamp when conversation was created' },
|
||||
updated_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when conversation was last updated',
|
||||
},
|
||||
},
|
||||
},
|
||||
conversationId: { type: 'string', description: 'ID of the assigned conversation' },
|
||||
admin_assignee_id: {
|
||||
type: 'number',
|
||||
description: 'ID of the assigned admin',
|
||||
optional: true,
|
||||
},
|
||||
team_assignee_id: { type: 'string', description: 'ID of the assigned team', optional: true },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface IntercomAttachContactToCompanyParams {
|
||||
accessToken: string
|
||||
contactId: string
|
||||
companyId: string
|
||||
}
|
||||
|
||||
export interface IntercomAttachContactToCompanyV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
company: any
|
||||
companyId: string
|
||||
name: string | null
|
||||
}
|
||||
}
|
||||
|
||||
const attachContactToCompanyBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
contactId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the contact to attach to the company',
|
||||
},
|
||||
companyId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the company to attach the contact to',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: IntercomAttachContactToCompanyParams) =>
|
||||
buildIntercomUrl(`/contacts/${params.contactId}/companies`),
|
||||
method: 'POST',
|
||||
headers: (params: IntercomAttachContactToCompanyParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
body: (params: IntercomAttachContactToCompanyParams) => ({
|
||||
id: params.companyId,
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomAttachContactToCompanyParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomAttachContactToCompanyV2Tool: ToolConfig<
|
||||
IntercomAttachContactToCompanyParams,
|
||||
IntercomAttachContactToCompanyV2Response
|
||||
> = {
|
||||
...attachContactToCompanyBase,
|
||||
id: 'intercom_attach_contact_to_company_v2',
|
||||
name: 'Attach Contact to Company in Intercom',
|
||||
description: 'Attach a contact to a company in Intercom',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'attach_contact_to_company')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
company: {
|
||||
id: data.id,
|
||||
type: data.type ?? 'company',
|
||||
company_id: data.company_id ?? null,
|
||||
name: data.name ?? null,
|
||||
created_at: data.created_at ?? null,
|
||||
updated_at: data.updated_at ?? null,
|
||||
user_count: data.user_count ?? null,
|
||||
session_count: data.session_count ?? null,
|
||||
monthly_spend: data.monthly_spend ?? null,
|
||||
plan: data.plan ?? null,
|
||||
},
|
||||
companyId: data.id,
|
||||
name: data.name ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
company: {
|
||||
type: 'object',
|
||||
description: 'The company object the contact was attached to',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the company' },
|
||||
type: { type: 'string', description: 'Object type (company)' },
|
||||
company_id: { type: 'string', description: 'The company_id you defined' },
|
||||
name: { type: 'string', description: 'Name of the company' },
|
||||
created_at: { type: 'number', description: 'Unix timestamp when company was created' },
|
||||
updated_at: { type: 'number', description: 'Unix timestamp when company was updated' },
|
||||
user_count: { type: 'number', description: 'Number of users in the company' },
|
||||
session_count: { type: 'number', description: 'Number of sessions' },
|
||||
monthly_spend: { type: 'number', description: 'Monthly spend amount' },
|
||||
plan: { type: 'object', description: 'Company plan details' },
|
||||
},
|
||||
},
|
||||
companyId: { type: 'string', description: 'ID of the company' },
|
||||
name: { type: 'string', description: 'Name of the company', optional: true },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface IntercomCloseConversationParams {
|
||||
accessToken: string
|
||||
conversationId: string
|
||||
admin_id: string
|
||||
body?: string
|
||||
}
|
||||
|
||||
export interface IntercomCloseConversationV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
conversation: any
|
||||
conversationId: string
|
||||
state: string
|
||||
}
|
||||
}
|
||||
|
||||
const closeConversationBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
conversationId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the conversation to close',
|
||||
},
|
||||
admin_id: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the admin performing the action',
|
||||
},
|
||||
body: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Optional closing message to add to the conversation',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: IntercomCloseConversationParams) =>
|
||||
buildIntercomUrl(`/conversations/${params.conversationId}/parts`),
|
||||
method: 'POST',
|
||||
headers: (params: IntercomCloseConversationParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
body: (params: IntercomCloseConversationParams) => {
|
||||
const payload: any = {
|
||||
message_type: 'close',
|
||||
type: 'admin',
|
||||
admin_id: params.admin_id,
|
||||
}
|
||||
|
||||
if (params.body) {
|
||||
payload.body = params.body
|
||||
}
|
||||
|
||||
return payload
|
||||
},
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomCloseConversationParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomCloseConversationV2Tool: ToolConfig<
|
||||
IntercomCloseConversationParams,
|
||||
IntercomCloseConversationV2Response
|
||||
> = {
|
||||
...closeConversationBase,
|
||||
id: 'intercom_close_conversation_v2',
|
||||
name: 'Close Conversation in Intercom',
|
||||
description: 'Close a conversation in Intercom',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'close_conversation')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
conversation: {
|
||||
id: data.id,
|
||||
type: data.type ?? 'conversation',
|
||||
state: data.state ?? 'closed',
|
||||
open: data.open ?? false,
|
||||
read: data.read ?? false,
|
||||
created_at: data.created_at ?? null,
|
||||
updated_at: data.updated_at ?? null,
|
||||
},
|
||||
conversationId: data.id,
|
||||
state: data.state ?? 'closed',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
conversation: {
|
||||
type: 'object',
|
||||
description: 'The closed conversation object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the conversation' },
|
||||
type: { type: 'string', description: 'Object type (conversation)' },
|
||||
state: { type: 'string', description: 'State of the conversation (closed)' },
|
||||
open: { type: 'boolean', description: 'Whether the conversation is open (false)' },
|
||||
read: { type: 'boolean', description: 'Whether the conversation has been read' },
|
||||
created_at: { type: 'number', description: 'Unix timestamp when conversation was created' },
|
||||
updated_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when conversation was last updated',
|
||||
},
|
||||
},
|
||||
},
|
||||
conversationId: { type: 'string', description: 'ID of the closed conversation' },
|
||||
state: { type: 'string', description: 'State of the conversation (closed)' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,350 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('IntercomCreateCompany')
|
||||
|
||||
export interface IntercomCreateCompanyParams {
|
||||
accessToken: string
|
||||
company_id: string
|
||||
name?: string
|
||||
website?: string
|
||||
plan?: string
|
||||
size?: number
|
||||
industry?: string
|
||||
monthly_spend?: number
|
||||
custom_attributes?: string
|
||||
remote_created_at?: number
|
||||
}
|
||||
|
||||
export interface IntercomCreateCompanyResponse {
|
||||
success: boolean
|
||||
output: {
|
||||
company: {
|
||||
id: string
|
||||
type: string
|
||||
app_id: string
|
||||
company_id: string
|
||||
name?: string
|
||||
website?: string
|
||||
plan: Record<string, any>
|
||||
size?: number
|
||||
industry?: string
|
||||
monthly_spend: number
|
||||
session_count: number
|
||||
user_count: number
|
||||
created_at: number
|
||||
updated_at: number
|
||||
remote_created_at?: number
|
||||
custom_attributes: Record<string, any>
|
||||
tags: {
|
||||
type: string
|
||||
tags: any[]
|
||||
}
|
||||
segments: {
|
||||
type: string
|
||||
segments: any[]
|
||||
}
|
||||
[key: string]: any
|
||||
}
|
||||
metadata: {
|
||||
operation: 'create_company'
|
||||
companyId: string
|
||||
}
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
const createCompanyBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
company_id: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Your unique identifier for the company',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The name of the company',
|
||||
},
|
||||
website: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The company website',
|
||||
},
|
||||
plan: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The company plan name',
|
||||
},
|
||||
size: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The number of employees in the company',
|
||||
},
|
||||
industry: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The industry the company operates in',
|
||||
},
|
||||
monthly_spend: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'How much revenue the company generates for your business. Note: This field truncates floats to whole integers (e.g., 155.98 becomes 155)',
|
||||
},
|
||||
custom_attributes: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Custom attributes as JSON object',
|
||||
},
|
||||
remote_created_at: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The time the company was created by you as a Unix timestamp',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: () => buildIntercomUrl('/companies'),
|
||||
method: 'POST',
|
||||
headers: (params: IntercomCreateCompanyParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
body: (params: IntercomCreateCompanyParams) => {
|
||||
const company: any = {
|
||||
company_id: params.company_id,
|
||||
}
|
||||
|
||||
if (params.name) company.name = params.name
|
||||
if (params.website) company.website = params.website
|
||||
if (params.plan) company.plan = params.plan
|
||||
if (params.size) company.size = params.size
|
||||
if (params.industry) company.industry = params.industry
|
||||
if (params.monthly_spend) company.monthly_spend = params.monthly_spend
|
||||
|
||||
if (params.custom_attributes) {
|
||||
try {
|
||||
company.custom_attributes = JSON.parse(params.custom_attributes)
|
||||
} catch (error) {
|
||||
logger.warn('Failed to parse custom attributes', { error })
|
||||
}
|
||||
}
|
||||
|
||||
if (params.remote_created_at) company.remote_created_at = params.remote_created_at
|
||||
|
||||
return company
|
||||
},
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomCreateCompanyParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomCreateCompanyTool: ToolConfig<
|
||||
IntercomCreateCompanyParams,
|
||||
IntercomCreateCompanyResponse
|
||||
> = {
|
||||
id: 'intercom_create_company',
|
||||
name: 'Create Company in Intercom',
|
||||
description: 'Create or update a company in Intercom',
|
||||
version: '1.0.0',
|
||||
|
||||
...createCompanyBase,
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'create_company')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
company: data,
|
||||
metadata: {
|
||||
operation: 'create_company' as const,
|
||||
companyId: data.id,
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
company: {
|
||||
type: 'object',
|
||||
description: 'Created or updated company object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the company' },
|
||||
type: { type: 'string', description: 'Object type (company)' },
|
||||
app_id: { type: 'string', description: 'Intercom app ID' },
|
||||
company_id: { type: 'string', description: 'Your unique identifier for the company' },
|
||||
name: { type: 'string', description: 'Name of the company' },
|
||||
website: { type: 'string', description: 'Company website URL' },
|
||||
plan: { type: 'object', description: 'Company plan information' },
|
||||
size: { type: 'number', description: 'Number of employees' },
|
||||
industry: { type: 'string', description: 'Industry the company operates in' },
|
||||
monthly_spend: { type: 'number', description: 'Monthly revenue from this company' },
|
||||
session_count: { type: 'number', description: 'Number of sessions' },
|
||||
user_count: { type: 'number', description: 'Number of users in the company' },
|
||||
created_at: { type: 'number', description: 'Unix timestamp when company was created' },
|
||||
updated_at: { type: 'number', description: 'Unix timestamp when company was last updated' },
|
||||
remote_created_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when company was created by you',
|
||||
},
|
||||
custom_attributes: { type: 'object', description: 'Custom attributes set on the company' },
|
||||
tags: {
|
||||
type: 'object',
|
||||
description: 'Tags associated with the company',
|
||||
properties: {
|
||||
type: { type: 'string', description: 'Tag list type' },
|
||||
tags: { type: 'array', description: 'Array of tag objects' },
|
||||
},
|
||||
},
|
||||
segments: {
|
||||
type: 'object',
|
||||
description: 'Segments the company belongs to',
|
||||
properties: {
|
||||
type: { type: 'string', description: 'Segment list type' },
|
||||
segments: { type: 'array', description: 'Array of segment objects' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Operation metadata',
|
||||
properties: {
|
||||
operation: { type: 'string', description: 'The operation performed (create_company)' },
|
||||
companyId: { type: 'string', description: 'ID of the created/updated company' },
|
||||
},
|
||||
},
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
|
||||
interface IntercomCreateCompanyV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
company: {
|
||||
id: string
|
||||
type: string
|
||||
app_id: string
|
||||
company_id: string
|
||||
name?: string
|
||||
website?: string
|
||||
plan: Record<string, any>
|
||||
size?: number
|
||||
industry?: string
|
||||
monthly_spend: number
|
||||
session_count: number
|
||||
user_count: number
|
||||
created_at: number
|
||||
updated_at: number
|
||||
remote_created_at?: number
|
||||
custom_attributes: Record<string, any>
|
||||
tags: {
|
||||
type: string
|
||||
tags: any[]
|
||||
}
|
||||
segments: {
|
||||
type: string
|
||||
segments: any[]
|
||||
}
|
||||
[key: string]: any
|
||||
}
|
||||
companyId: string
|
||||
}
|
||||
}
|
||||
|
||||
export const intercomCreateCompanyV2Tool: ToolConfig<
|
||||
IntercomCreateCompanyParams,
|
||||
IntercomCreateCompanyV2Response
|
||||
> = {
|
||||
...createCompanyBase,
|
||||
id: 'intercom_create_company_v2',
|
||||
name: 'Create Company in Intercom',
|
||||
description: 'Create or update a company in Intercom',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'create_company')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
company: data,
|
||||
companyId: data.id,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
company: {
|
||||
type: 'object',
|
||||
description: 'Created or updated company object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the company' },
|
||||
type: { type: 'string', description: 'Object type (company)' },
|
||||
app_id: { type: 'string', description: 'Intercom app ID' },
|
||||
company_id: { type: 'string', description: 'Your unique identifier for the company' },
|
||||
name: { type: 'string', description: 'Name of the company' },
|
||||
website: { type: 'string', description: 'Company website URL' },
|
||||
plan: { type: 'object', description: 'Company plan information' },
|
||||
size: { type: 'number', description: 'Number of employees' },
|
||||
industry: { type: 'string', description: 'Industry the company operates in' },
|
||||
monthly_spend: { type: 'number', description: 'Monthly revenue from this company' },
|
||||
session_count: { type: 'number', description: 'Number of sessions' },
|
||||
user_count: { type: 'number', description: 'Number of users in the company' },
|
||||
created_at: { type: 'number', description: 'Unix timestamp when company was created' },
|
||||
updated_at: { type: 'number', description: 'Unix timestamp when company was last updated' },
|
||||
remote_created_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when company was created by you',
|
||||
},
|
||||
custom_attributes: { type: 'object', description: 'Custom attributes set on the company' },
|
||||
tags: {
|
||||
type: 'object',
|
||||
description: 'Tags associated with the company',
|
||||
properties: {
|
||||
type: { type: 'string', description: 'Tag list type' },
|
||||
tags: { type: 'array', description: 'Array of tag objects' },
|
||||
},
|
||||
},
|
||||
segments: {
|
||||
type: 'object',
|
||||
description: 'Segments the company belongs to',
|
||||
properties: {
|
||||
type: { type: 'string', description: 'Segment list type' },
|
||||
segments: { type: 'array', description: 'Array of segment objects' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
companyId: { type: 'string', description: 'ID of the created/updated company' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,463 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('IntercomCreateContact')
|
||||
|
||||
export interface IntercomCreateContactParams {
|
||||
accessToken: string
|
||||
role?: 'user' | 'lead'
|
||||
email?: string
|
||||
external_id?: string
|
||||
phone?: string
|
||||
name?: string
|
||||
avatar?: string
|
||||
signed_up_at?: number
|
||||
last_seen_at?: number
|
||||
owner_id?: string
|
||||
unsubscribed_from_emails?: boolean
|
||||
custom_attributes?: string
|
||||
company_id?: string
|
||||
}
|
||||
|
||||
export interface IntercomCreateContactResponse {
|
||||
success: boolean
|
||||
output: {
|
||||
contact: {
|
||||
id: string
|
||||
type: string
|
||||
role: string
|
||||
email: string | null
|
||||
phone: string | null
|
||||
name: string | null
|
||||
avatar: string | null
|
||||
owner_id: string | null
|
||||
external_id: string | null
|
||||
created_at: number
|
||||
updated_at: number
|
||||
signed_up_at: number | null
|
||||
last_seen_at: number | null
|
||||
workspace_id: string
|
||||
custom_attributes: Record<string, any>
|
||||
tags: {
|
||||
type: string
|
||||
url: string
|
||||
data: any[]
|
||||
has_more: boolean
|
||||
total_count: number
|
||||
}
|
||||
notes: {
|
||||
type: string
|
||||
url: string
|
||||
data: any[]
|
||||
has_more: boolean
|
||||
total_count: number
|
||||
}
|
||||
companies: {
|
||||
type: string
|
||||
url: string
|
||||
data: any[]
|
||||
has_more: boolean
|
||||
total_count: number
|
||||
}
|
||||
location: {
|
||||
type: string
|
||||
city: string | null
|
||||
region: string | null
|
||||
country: string | null
|
||||
country_code: string | null
|
||||
continent_code: string | null
|
||||
}
|
||||
social_profiles: {
|
||||
type: string
|
||||
data: any[]
|
||||
}
|
||||
unsubscribed_from_emails: boolean
|
||||
[key: string]: any
|
||||
}
|
||||
metadata: {
|
||||
operation: 'create_contact'
|
||||
contactId: string
|
||||
}
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
const intercomCreateContactBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
role: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
"The role of the contact. Accepts 'user' or 'lead'. Defaults to 'lead' if not specified.",
|
||||
},
|
||||
email: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: "The contact's email address",
|
||||
},
|
||||
external_id: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'A unique identifier for the contact provided by the client',
|
||||
},
|
||||
phone: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: "The contact's phone number",
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: "The contact's name",
|
||||
},
|
||||
avatar: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'An avatar image URL for the contact',
|
||||
},
|
||||
signed_up_at: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The time the user signed up as a Unix timestamp',
|
||||
},
|
||||
last_seen_at: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The time the user was last seen as a Unix timestamp',
|
||||
},
|
||||
owner_id: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The id of an admin that has been assigned account ownership of the contact',
|
||||
},
|
||||
unsubscribed_from_emails: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Whether the contact is unsubscribed from emails',
|
||||
},
|
||||
custom_attributes: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Custom attributes as JSON object (e.g., {"attribute_name": "value"})',
|
||||
},
|
||||
company_id: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Company ID to associate the contact with during creation',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: () => buildIntercomUrl('/contacts'),
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
body: (params) => {
|
||||
const contact: any = {}
|
||||
|
||||
if (params.role) contact.role = params.role
|
||||
if (params.email) contact.email = params.email
|
||||
if (params.external_id) contact.external_id = params.external_id
|
||||
if (params.phone) contact.phone = params.phone
|
||||
if (params.name) contact.name = params.name
|
||||
if (params.avatar) contact.avatar = params.avatar
|
||||
if (params.signed_up_at) contact.signed_up_at = params.signed_up_at
|
||||
if (params.last_seen_at) contact.last_seen_at = params.last_seen_at
|
||||
if (params.owner_id) contact.owner_id = params.owner_id
|
||||
if (params.unsubscribed_from_emails !== undefined)
|
||||
contact.unsubscribed_from_emails = params.unsubscribed_from_emails
|
||||
|
||||
if (params.custom_attributes) {
|
||||
try {
|
||||
contact.custom_attributes = JSON.parse(params.custom_attributes)
|
||||
} catch (error) {
|
||||
logger.warn('Failed to parse custom attributes', { error })
|
||||
}
|
||||
}
|
||||
|
||||
if (params.company_id) contact.company_id = params.company_id
|
||||
|
||||
return contact
|
||||
},
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomCreateContactParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomCreateContactTool: ToolConfig<
|
||||
IntercomCreateContactParams,
|
||||
IntercomCreateContactResponse
|
||||
> = {
|
||||
id: 'intercom_create_contact',
|
||||
name: 'Create Contact in Intercom',
|
||||
description: 'Create a new contact in Intercom with email, external_id, or role',
|
||||
version: '1.0.0',
|
||||
|
||||
...intercomCreateContactBase,
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'create_contact')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
contact: data,
|
||||
metadata: {
|
||||
operation: 'create_contact' as const,
|
||||
contactId: data.id,
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
contact: {
|
||||
type: 'object',
|
||||
description: 'Created contact object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the contact' },
|
||||
type: { type: 'string', description: 'Object type (contact)' },
|
||||
role: { type: 'string', description: 'Role of the contact (user or lead)' },
|
||||
email: { type: 'string', description: 'Email address of the contact', optional: true },
|
||||
phone: { type: 'string', description: 'Phone number of the contact', optional: true },
|
||||
name: { type: 'string', description: 'Name of the contact', optional: true },
|
||||
avatar: { type: 'string', description: 'Avatar URL of the contact', optional: true },
|
||||
owner_id: {
|
||||
type: 'string',
|
||||
description: 'ID of the admin assigned to this contact',
|
||||
optional: true,
|
||||
},
|
||||
external_id: {
|
||||
type: 'string',
|
||||
description: 'External identifier for the contact',
|
||||
optional: true,
|
||||
},
|
||||
created_at: { type: 'number', description: 'Unix timestamp when contact was created' },
|
||||
updated_at: { type: 'number', description: 'Unix timestamp when contact was last updated' },
|
||||
signed_up_at: { type: 'number', description: 'Unix timestamp when user signed up' },
|
||||
last_seen_at: { type: 'number', description: 'Unix timestamp when user was last seen' },
|
||||
workspace_id: { type: 'string', description: 'Workspace ID the contact belongs to' },
|
||||
custom_attributes: { type: 'object', description: 'Custom attributes set on the contact' },
|
||||
tags: {
|
||||
type: 'object',
|
||||
description: 'Tags associated with the contact',
|
||||
properties: {
|
||||
type: { type: 'string', description: 'List type' },
|
||||
url: { type: 'string', description: 'URL to fetch tags' },
|
||||
data: { type: 'array', description: 'Array of tag objects' },
|
||||
has_more: { type: 'boolean', description: 'Whether there are more tags' },
|
||||
total_count: { type: 'number', description: 'Total number of tags' },
|
||||
},
|
||||
},
|
||||
notes: {
|
||||
type: 'object',
|
||||
description: 'Notes associated with the contact',
|
||||
properties: {
|
||||
type: { type: 'string', description: 'List type' },
|
||||
url: { type: 'string', description: 'URL to fetch notes' },
|
||||
data: { type: 'array', description: 'Array of note objects' },
|
||||
has_more: { type: 'boolean', description: 'Whether there are more notes' },
|
||||
total_count: { type: 'number', description: 'Total number of notes' },
|
||||
},
|
||||
},
|
||||
companies: {
|
||||
type: 'object',
|
||||
description: 'Companies associated with the contact',
|
||||
properties: {
|
||||
type: { type: 'string', description: 'List type' },
|
||||
url: { type: 'string', description: 'URL to fetch companies' },
|
||||
data: { type: 'array', description: 'Array of company objects' },
|
||||
has_more: { type: 'boolean', description: 'Whether there are more companies' },
|
||||
total_count: { type: 'number', description: 'Total number of companies' },
|
||||
},
|
||||
},
|
||||
location: {
|
||||
type: 'object',
|
||||
description: 'Location information for the contact',
|
||||
properties: {
|
||||
type: { type: 'string', description: 'Location type' },
|
||||
city: { type: 'string', description: 'City' },
|
||||
region: { type: 'string', description: 'Region/State' },
|
||||
country: { type: 'string', description: 'Country' },
|
||||
country_code: { type: 'string', description: 'Country code' },
|
||||
continent_code: { type: 'string', description: 'Continent code' },
|
||||
},
|
||||
},
|
||||
social_profiles: {
|
||||
type: 'object',
|
||||
description: 'Social profiles of the contact',
|
||||
properties: {
|
||||
type: { type: 'string', description: 'List type' },
|
||||
data: { type: 'array', description: 'Array of social profile objects' },
|
||||
},
|
||||
},
|
||||
unsubscribed_from_emails: {
|
||||
type: 'boolean',
|
||||
description: 'Whether contact is unsubscribed from emails',
|
||||
},
|
||||
},
|
||||
},
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Operation metadata',
|
||||
properties: {
|
||||
operation: { type: 'string', description: 'The operation performed (create_contact)' },
|
||||
contactId: { type: 'string', description: 'ID of the created contact' },
|
||||
},
|
||||
},
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
|
||||
interface IntercomCreateContactV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
contact: IntercomCreateContactResponse['output']['contact']
|
||||
contactId: string
|
||||
}
|
||||
}
|
||||
|
||||
export const intercomCreateContactV2Tool: ToolConfig<
|
||||
IntercomCreateContactParams,
|
||||
IntercomCreateContactV2Response
|
||||
> = {
|
||||
...intercomCreateContactBase,
|
||||
id: 'intercom_create_contact_v2',
|
||||
name: 'Create Contact in Intercom',
|
||||
description:
|
||||
'Create a new contact in Intercom with email, external_id, or role. Returns API-aligned fields only.',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'create_contact')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
contact: data,
|
||||
contactId: data.id,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
contact: {
|
||||
type: 'object',
|
||||
description: 'Created contact object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the contact' },
|
||||
type: { type: 'string', description: 'Object type (contact)' },
|
||||
role: { type: 'string', description: 'Role of the contact (user or lead)' },
|
||||
email: { type: 'string', description: 'Email address of the contact', optional: true },
|
||||
phone: { type: 'string', description: 'Phone number of the contact', optional: true },
|
||||
name: { type: 'string', description: 'Name of the contact', optional: true },
|
||||
avatar: { type: 'string', description: 'Avatar URL of the contact', optional: true },
|
||||
owner_id: {
|
||||
type: 'string',
|
||||
description: 'ID of the admin assigned to this contact',
|
||||
optional: true,
|
||||
},
|
||||
external_id: {
|
||||
type: 'string',
|
||||
description: 'External identifier for the contact',
|
||||
optional: true,
|
||||
},
|
||||
created_at: { type: 'number', description: 'Unix timestamp when contact was created' },
|
||||
updated_at: { type: 'number', description: 'Unix timestamp when contact was last updated' },
|
||||
signed_up_at: { type: 'number', description: 'Unix timestamp when user signed up' },
|
||||
last_seen_at: { type: 'number', description: 'Unix timestamp when user was last seen' },
|
||||
workspace_id: { type: 'string', description: 'Workspace ID the contact belongs to' },
|
||||
custom_attributes: { type: 'object', description: 'Custom attributes set on the contact' },
|
||||
tags: {
|
||||
type: 'object',
|
||||
description: 'Tags associated with the contact',
|
||||
properties: {
|
||||
type: { type: 'string', description: 'List type' },
|
||||
url: { type: 'string', description: 'URL to fetch tags' },
|
||||
data: { type: 'array', description: 'Array of tag objects' },
|
||||
has_more: { type: 'boolean', description: 'Whether there are more tags' },
|
||||
total_count: { type: 'number', description: 'Total number of tags' },
|
||||
},
|
||||
},
|
||||
notes: {
|
||||
type: 'object',
|
||||
description: 'Notes associated with the contact',
|
||||
properties: {
|
||||
type: { type: 'string', description: 'List type' },
|
||||
url: { type: 'string', description: 'URL to fetch notes' },
|
||||
data: { type: 'array', description: 'Array of note objects' },
|
||||
has_more: { type: 'boolean', description: 'Whether there are more notes' },
|
||||
total_count: { type: 'number', description: 'Total number of notes' },
|
||||
},
|
||||
},
|
||||
companies: {
|
||||
type: 'object',
|
||||
description: 'Companies associated with the contact',
|
||||
properties: {
|
||||
type: { type: 'string', description: 'List type' },
|
||||
url: { type: 'string', description: 'URL to fetch companies' },
|
||||
data: { type: 'array', description: 'Array of company objects' },
|
||||
has_more: { type: 'boolean', description: 'Whether there are more companies' },
|
||||
total_count: { type: 'number', description: 'Total number of companies' },
|
||||
},
|
||||
},
|
||||
location: {
|
||||
type: 'object',
|
||||
description: 'Location information for the contact',
|
||||
properties: {
|
||||
type: { type: 'string', description: 'Location type' },
|
||||
city: { type: 'string', description: 'City' },
|
||||
region: { type: 'string', description: 'Region/State' },
|
||||
country: { type: 'string', description: 'Country' },
|
||||
country_code: { type: 'string', description: 'Country code' },
|
||||
continent_code: { type: 'string', description: 'Continent code' },
|
||||
},
|
||||
},
|
||||
social_profiles: {
|
||||
type: 'object',
|
||||
description: 'Social profiles of the contact',
|
||||
properties: {
|
||||
type: { type: 'string', description: 'List type' },
|
||||
data: { type: 'array', description: 'Array of social profile objects' },
|
||||
},
|
||||
},
|
||||
unsubscribed_from_emails: {
|
||||
type: 'boolean',
|
||||
description: 'Whether contact is unsubscribed from emails',
|
||||
},
|
||||
},
|
||||
},
|
||||
contactId: { type: 'string', description: 'ID of the created contact' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('IntercomCreateEvent')
|
||||
|
||||
export interface IntercomCreateEventParams {
|
||||
accessToken: string
|
||||
event_name: string
|
||||
created_at?: number
|
||||
user_id?: string
|
||||
email?: string
|
||||
id?: string
|
||||
metadata?: string
|
||||
}
|
||||
|
||||
export interface IntercomCreateEventV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
accepted: boolean
|
||||
}
|
||||
}
|
||||
|
||||
const createEventBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
event_name: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'The name of the event (e.g., "order-completed"). Use past-tense verb-noun format for readability.',
|
||||
},
|
||||
created_at: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Unix timestamp for when the event occurred. Strongly recommended for uniqueness.',
|
||||
},
|
||||
user_id: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Your identifier for the user (external_id)',
|
||||
},
|
||||
email: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Email address of the user. Use only if your app uses email to uniquely identify users.',
|
||||
},
|
||||
id: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The Intercom contact ID',
|
||||
},
|
||||
metadata: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'JSON object with up to 10 metadata key-value pairs about the event (e.g., {"order_value": 99.99})',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: () => buildIntercomUrl('/events'),
|
||||
method: 'POST',
|
||||
headers: (params: IntercomCreateEventParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
body: (params: IntercomCreateEventParams) => {
|
||||
const payload: any = {
|
||||
event_name: params.event_name,
|
||||
}
|
||||
|
||||
if (params.created_at) {
|
||||
payload.created_at = params.created_at
|
||||
} else {
|
||||
payload.created_at = Math.floor(Date.now() / 1000)
|
||||
}
|
||||
|
||||
if (params.user_id) {
|
||||
payload.user_id = params.user_id
|
||||
}
|
||||
|
||||
if (params.email) {
|
||||
payload.email = params.email
|
||||
}
|
||||
|
||||
if (params.id) {
|
||||
payload.id = params.id
|
||||
}
|
||||
|
||||
if (params.metadata) {
|
||||
try {
|
||||
payload.metadata = JSON.parse(params.metadata)
|
||||
} catch (error) {
|
||||
logger.warn('Failed to parse metadata, ignoring', { error })
|
||||
}
|
||||
}
|
||||
|
||||
return payload
|
||||
},
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomCreateEventParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomCreateEventV2Tool: ToolConfig<
|
||||
IntercomCreateEventParams,
|
||||
IntercomCreateEventV2Response
|
||||
> = {
|
||||
...createEventBase,
|
||||
id: 'intercom_create_event_v2',
|
||||
name: 'Create Event in Intercom',
|
||||
description: 'Track a custom event for a contact in Intercom',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'create_event')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
accepted: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
accepted: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the event was accepted (202 Accepted)',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface IntercomCreateMessageParams {
|
||||
accessToken: string
|
||||
message_type: 'inapp' | 'email'
|
||||
template: 'plain' | 'personal'
|
||||
subject?: string
|
||||
body: string
|
||||
from_type: string
|
||||
from_id: string
|
||||
to_type: string
|
||||
to_id: string
|
||||
created_at?: number
|
||||
}
|
||||
|
||||
export interface IntercomCreateMessageResponse {
|
||||
success: boolean
|
||||
output: {
|
||||
message: any
|
||||
metadata: {
|
||||
operation: 'create_message'
|
||||
messageId: string
|
||||
}
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
export interface IntercomCreateMessageV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
message: any
|
||||
messageId: string
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
const createMessageBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
message_type: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Message type: "inapp" for in-app messages or "email" for email messages',
|
||||
},
|
||||
template: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Message template style: "plain" for plain text or "personal" for personalized style',
|
||||
},
|
||||
subject: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The subject of the message (for email type)',
|
||||
},
|
||||
body: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The body of the message',
|
||||
},
|
||||
from_type: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Sender type: "admin"',
|
||||
},
|
||||
from_id: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the admin sending the message',
|
||||
},
|
||||
to_type: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Recipient type: "contact"',
|
||||
},
|
||||
to_id: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the contact receiving the message',
|
||||
},
|
||||
created_at: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Unix timestamp for when the message was created. If not provided, current time is used.',
|
||||
},
|
||||
},
|
||||
request: {
|
||||
url: () => buildIntercomUrl('/messages'),
|
||||
method: 'POST',
|
||||
headers: (params: IntercomCreateMessageParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
body: (params: IntercomCreateMessageParams) => {
|
||||
// Map "inapp" to "in_app" as required by Intercom API
|
||||
const apiMessageType = params.message_type === 'inapp' ? 'in_app' : params.message_type
|
||||
|
||||
const message: any = {
|
||||
message_type: apiMessageType,
|
||||
template: params.template,
|
||||
body: params.body,
|
||||
from: {
|
||||
type: params.from_type,
|
||||
id: params.from_id,
|
||||
},
|
||||
to: {
|
||||
type: params.to_type,
|
||||
id: params.to_id,
|
||||
},
|
||||
}
|
||||
|
||||
if (params.subject && params.message_type === 'email') {
|
||||
message.subject = params.subject
|
||||
}
|
||||
|
||||
if (params.created_at) message.created_at = params.created_at
|
||||
|
||||
return message
|
||||
},
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomCreateMessageParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomCreateMessageTool: ToolConfig<
|
||||
IntercomCreateMessageParams,
|
||||
IntercomCreateMessageResponse
|
||||
> = {
|
||||
id: 'intercom_create_message',
|
||||
name: 'Create Message in Intercom',
|
||||
description: 'Create and send a new admin-initiated message in Intercom',
|
||||
version: '1.0.0',
|
||||
|
||||
...createMessageBase,
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'create_message')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
message: data,
|
||||
metadata: {
|
||||
operation: 'create_message' as const,
|
||||
messageId: data.id,
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
message: {
|
||||
type: 'object',
|
||||
description: 'Created message object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the message' },
|
||||
type: { type: 'string', description: 'Object type (message)' },
|
||||
created_at: { type: 'number', description: 'Unix timestamp when message was created' },
|
||||
body: { type: 'string', description: 'Body of the message' },
|
||||
message_type: { type: 'string', description: 'Type of the message (in_app or email)' },
|
||||
conversation_id: { type: 'string', description: 'ID of the conversation created' },
|
||||
owner: { type: 'object', description: 'Owner of the message' },
|
||||
},
|
||||
},
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Operation metadata',
|
||||
properties: {
|
||||
operation: { type: 'string', description: 'The operation performed (create_message)' },
|
||||
messageId: { type: 'string', description: 'ID of the created message' },
|
||||
},
|
||||
},
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
|
||||
export const intercomCreateMessageV2Tool: ToolConfig<
|
||||
IntercomCreateMessageParams,
|
||||
IntercomCreateMessageV2Response
|
||||
> = {
|
||||
...createMessageBase,
|
||||
id: 'intercom_create_message_v2',
|
||||
name: 'Create Message in Intercom',
|
||||
description:
|
||||
'Create and send a new admin-initiated message in Intercom. Returns API-aligned fields only.',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'create_message')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
message: data,
|
||||
messageId: data.id,
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
message: {
|
||||
type: 'object',
|
||||
description: 'Created message object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the message' },
|
||||
type: { type: 'string', description: 'Object type (message)' },
|
||||
created_at: { type: 'number', description: 'Unix timestamp when message was created' },
|
||||
body: { type: 'string', description: 'Body of the message' },
|
||||
message_type: { type: 'string', description: 'Type of the message (in_app or email)' },
|
||||
conversation_id: { type: 'string', description: 'ID of the conversation created' },
|
||||
owner: { type: 'object', description: 'Owner of the message' },
|
||||
},
|
||||
},
|
||||
messageId: { type: 'string', description: 'ID of the created message' },
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface IntercomCreateNoteParams {
|
||||
accessToken: string
|
||||
contactId: string
|
||||
body: string
|
||||
admin_id?: string
|
||||
}
|
||||
|
||||
export interface IntercomCreateNoteV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
id: string
|
||||
body: string
|
||||
created_at: number
|
||||
type: string
|
||||
author: any | null
|
||||
contact: any | null
|
||||
}
|
||||
}
|
||||
|
||||
const createNoteBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
contactId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the contact to add the note to',
|
||||
},
|
||||
body: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The text content of the note',
|
||||
},
|
||||
admin_id: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the admin creating the note',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: IntercomCreateNoteParams) =>
|
||||
buildIntercomUrl(`/contacts/${params.contactId}/notes`),
|
||||
method: 'POST',
|
||||
headers: (params: IntercomCreateNoteParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
body: (params: IntercomCreateNoteParams) => {
|
||||
const payload: any = {
|
||||
body: params.body,
|
||||
}
|
||||
|
||||
if (params.admin_id) {
|
||||
payload.admin_id = params.admin_id
|
||||
}
|
||||
|
||||
return payload
|
||||
},
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomCreateNoteParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomCreateNoteV2Tool: ToolConfig<
|
||||
IntercomCreateNoteParams,
|
||||
IntercomCreateNoteV2Response
|
||||
> = {
|
||||
...createNoteBase,
|
||||
id: 'intercom_create_note_v2',
|
||||
name: 'Create Note in Intercom',
|
||||
description: 'Add a note to a specific contact',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'create_note')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
body: data.body,
|
||||
created_at: data.created_at,
|
||||
type: data.type ?? 'note',
|
||||
author: data.author ?? null,
|
||||
contact: data.contact ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Unique identifier for the note' },
|
||||
body: { type: 'string', description: 'The text content of the note' },
|
||||
created_at: { type: 'number', description: 'Unix timestamp when the note was created' },
|
||||
type: { type: 'string', description: 'Object type (note)' },
|
||||
author: {
|
||||
type: 'object',
|
||||
description: 'The admin who created the note',
|
||||
optional: true,
|
||||
properties: {
|
||||
type: { type: 'string', description: 'Author type (admin)' },
|
||||
id: { type: 'string', description: 'Author ID' },
|
||||
name: { type: 'string', description: 'Author name' },
|
||||
email: { type: 'string', description: 'Author email' },
|
||||
},
|
||||
},
|
||||
contact: {
|
||||
type: 'object',
|
||||
description: 'The contact the note was created for',
|
||||
optional: true,
|
||||
properties: {
|
||||
type: { type: 'string', description: 'Contact type' },
|
||||
id: { type: 'string', description: 'Contact ID' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface IntercomCreateTagParams {
|
||||
accessToken: string
|
||||
name: string
|
||||
id?: string
|
||||
}
|
||||
|
||||
export interface IntercomCreateTagV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
id: string
|
||||
name: string
|
||||
type: string
|
||||
}
|
||||
}
|
||||
|
||||
const createTagBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'The name of the tag. Will create a new tag if not found, or update the name if id is provided.',
|
||||
},
|
||||
id: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of an existing tag to update. Omit to create a new tag.',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: () => buildIntercomUrl('/tags'),
|
||||
method: 'POST',
|
||||
headers: (params: IntercomCreateTagParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
body: (params: IntercomCreateTagParams) => {
|
||||
const payload: any = {
|
||||
name: params.name,
|
||||
}
|
||||
|
||||
if (params.id) {
|
||||
payload.id = params.id
|
||||
}
|
||||
|
||||
return payload
|
||||
},
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomCreateTagParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomCreateTagV2Tool: ToolConfig<
|
||||
IntercomCreateTagParams,
|
||||
IntercomCreateTagV2Response
|
||||
> = {
|
||||
...createTagBase,
|
||||
id: 'intercom_create_tag_v2',
|
||||
name: 'Create Tag in Intercom',
|
||||
description: 'Create a new tag or update an existing tag name',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'create_tag')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
type: data.type ?? 'tag',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Unique identifier for the tag' },
|
||||
name: { type: 'string', description: 'Name of the tag' },
|
||||
type: { type: 'string', description: 'Object type (tag)' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('IntercomCreateTicket')
|
||||
|
||||
export interface IntercomCreateTicketParams {
|
||||
accessToken: string
|
||||
ticket_type_id: string
|
||||
contacts: string
|
||||
ticket_attributes: string
|
||||
company_id?: string
|
||||
created_at?: number
|
||||
conversation_to_link_id?: string
|
||||
disable_notifications?: boolean
|
||||
}
|
||||
|
||||
export interface IntercomCreateTicketResponse {
|
||||
success: boolean
|
||||
output: {
|
||||
ticket: any
|
||||
metadata: {
|
||||
operation: 'create_ticket'
|
||||
ticketId: string
|
||||
}
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
export interface IntercomCreateTicketV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
ticket: any
|
||||
ticketId: string
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
const createTicketBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
ticket_type_id: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the ticket type',
|
||||
},
|
||||
contacts: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'JSON array of contact identifiers (e.g., [{"id": "contact_id"}])',
|
||||
},
|
||||
ticket_attributes: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'JSON object with ticket attributes including _default_title_ and _default_description_',
|
||||
},
|
||||
company_id: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Company ID to associate the ticket with',
|
||||
},
|
||||
created_at: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Unix timestamp for when the ticket was created. If not provided, current time is used.',
|
||||
},
|
||||
conversation_to_link_id: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'ID of an existing conversation to link to this ticket',
|
||||
},
|
||||
disable_notifications: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'When true, suppresses notifications when the ticket is created',
|
||||
},
|
||||
},
|
||||
request: {
|
||||
url: () => buildIntercomUrl('/tickets'),
|
||||
method: 'POST',
|
||||
headers: (params: IntercomCreateTicketParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
body: (params: IntercomCreateTicketParams) => {
|
||||
const ticket: any = {
|
||||
ticket_type_id: params.ticket_type_id,
|
||||
}
|
||||
|
||||
try {
|
||||
ticket.contacts = JSON.parse(params.contacts)
|
||||
} catch (error) {
|
||||
logger.warn('Failed to parse contacts, using as single contact ID', { error })
|
||||
ticket.contacts = [{ id: params.contacts }]
|
||||
}
|
||||
|
||||
try {
|
||||
ticket.ticket_attributes = JSON.parse(params.ticket_attributes)
|
||||
} catch (error) {
|
||||
logger.error('Failed to parse ticket attributes', { error })
|
||||
throw new Error('ticket_attributes must be a valid JSON object')
|
||||
}
|
||||
|
||||
if (params.company_id) ticket.company_id = params.company_id
|
||||
if (params.created_at) ticket.created_at = params.created_at
|
||||
if (params.conversation_to_link_id)
|
||||
ticket.conversation_to_link_id = params.conversation_to_link_id
|
||||
if (params.disable_notifications !== undefined)
|
||||
ticket.disable_notifications = params.disable_notifications
|
||||
|
||||
return ticket
|
||||
},
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomCreateTicketParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomCreateTicketTool: ToolConfig<
|
||||
IntercomCreateTicketParams,
|
||||
IntercomCreateTicketResponse
|
||||
> = {
|
||||
id: 'intercom_create_ticket',
|
||||
name: 'Create Ticket in Intercom',
|
||||
description: 'Create a new ticket in Intercom',
|
||||
version: '1.0.0',
|
||||
|
||||
...createTicketBase,
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'create_ticket')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
ticket: data,
|
||||
metadata: {
|
||||
operation: 'create_ticket' as const,
|
||||
ticketId: data.id,
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
ticket: {
|
||||
type: 'object',
|
||||
description: 'Created ticket object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the ticket' },
|
||||
type: { type: 'string', description: 'Object type (ticket)' },
|
||||
ticket_id: { type: 'string', description: 'Ticket ID' },
|
||||
ticket_type: { type: 'object', description: 'Type of the ticket', optional: true },
|
||||
ticket_attributes: { type: 'object', description: 'Attributes of the ticket' },
|
||||
ticket_state: { type: 'string', description: 'State of the ticket' },
|
||||
ticket_state_internal_label: {
|
||||
type: 'string',
|
||||
description: 'Internal label for ticket state',
|
||||
},
|
||||
ticket_state_external_label: {
|
||||
type: 'string',
|
||||
description: 'External label for ticket state',
|
||||
},
|
||||
created_at: { type: 'number', description: 'Unix timestamp when ticket was created' },
|
||||
updated_at: { type: 'number', description: 'Unix timestamp when ticket was last updated' },
|
||||
contacts: { type: 'object', description: 'Contacts associated with the ticket' },
|
||||
admin_assignee_id: { type: 'string', description: 'ID of assigned admin' },
|
||||
team_assignee_id: { type: 'string', description: 'ID of assigned team' },
|
||||
is_shared: { type: 'boolean', description: 'Whether the ticket is shared' },
|
||||
open: { type: 'boolean', description: 'Whether the ticket is open' },
|
||||
},
|
||||
},
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Operation metadata',
|
||||
properties: {
|
||||
operation: { type: 'string', description: 'The operation performed (create_ticket)' },
|
||||
ticketId: { type: 'string', description: 'ID of the created ticket' },
|
||||
},
|
||||
},
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
|
||||
export const intercomCreateTicketV2Tool: ToolConfig<
|
||||
IntercomCreateTicketParams,
|
||||
IntercomCreateTicketV2Response
|
||||
> = {
|
||||
...createTicketBase,
|
||||
id: 'intercom_create_ticket_v2',
|
||||
name: 'Create Ticket in Intercom',
|
||||
description: 'Create a new ticket in Intercom. Returns API-aligned fields only.',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'create_ticket')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
ticket: data,
|
||||
ticketId: data.id,
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
ticket: {
|
||||
type: 'object',
|
||||
description: 'Created ticket object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the ticket' },
|
||||
type: { type: 'string', description: 'Object type (ticket)' },
|
||||
ticket_id: { type: 'string', description: 'Ticket ID' },
|
||||
ticket_type: { type: 'object', description: 'Type of the ticket', optional: true },
|
||||
ticket_attributes: { type: 'object', description: 'Attributes of the ticket' },
|
||||
ticket_state: { type: 'string', description: 'State of the ticket' },
|
||||
ticket_state_internal_label: {
|
||||
type: 'string',
|
||||
description: 'Internal label for ticket state',
|
||||
},
|
||||
ticket_state_external_label: {
|
||||
type: 'string',
|
||||
description: 'External label for ticket state',
|
||||
},
|
||||
created_at: { type: 'number', description: 'Unix timestamp when ticket was created' },
|
||||
updated_at: { type: 'number', description: 'Unix timestamp when ticket was last updated' },
|
||||
contacts: { type: 'object', description: 'Contacts associated with the ticket' },
|
||||
admin_assignee_id: { type: 'string', description: 'ID of assigned admin' },
|
||||
team_assignee_id: { type: 'string', description: 'ID of assigned team' },
|
||||
is_shared: { type: 'boolean', description: 'Whether the ticket is shared' },
|
||||
open: { type: 'boolean', description: 'Whether the ticket is open' },
|
||||
},
|
||||
},
|
||||
ticketId: { type: 'string', description: 'ID of the created ticket' },
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface IntercomDeleteContactParams {
|
||||
accessToken: string
|
||||
contactId: string
|
||||
}
|
||||
|
||||
export interface IntercomDeleteContactResponse {
|
||||
success: boolean
|
||||
output: {
|
||||
id: string
|
||||
deleted: boolean
|
||||
metadata: {
|
||||
operation: 'delete_contact'
|
||||
}
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
const intercomDeleteContactBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
contactId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Contact ID to delete',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: IntercomDeleteContactParams) => buildIntercomUrl(`/contacts/${params.contactId}`),
|
||||
method: 'DELETE',
|
||||
headers: (params: IntercomDeleteContactParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomDeleteContactParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomDeleteContactTool: ToolConfig<
|
||||
IntercomDeleteContactParams,
|
||||
IntercomDeleteContactResponse
|
||||
> = {
|
||||
id: 'intercom_delete_contact',
|
||||
name: 'Delete Contact from Intercom',
|
||||
description: 'Delete a contact from Intercom by ID',
|
||||
version: '1.0.0',
|
||||
|
||||
...intercomDeleteContactBase,
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'delete_contact')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
deleted: true,
|
||||
metadata: {
|
||||
operation: 'delete_contact' as const,
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'ID of deleted contact' },
|
||||
deleted: { type: 'boolean', description: 'Whether the contact was deleted' },
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Operation metadata',
|
||||
properties: {
|
||||
operation: { type: 'string', description: 'The operation performed (delete_contact)' },
|
||||
},
|
||||
},
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
|
||||
interface IntercomDeleteContactV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
id: string
|
||||
deleted: boolean
|
||||
}
|
||||
}
|
||||
|
||||
export const intercomDeleteContactV2Tool: ToolConfig<
|
||||
IntercomDeleteContactParams,
|
||||
IntercomDeleteContactV2Response
|
||||
> = {
|
||||
...intercomDeleteContactBase,
|
||||
id: 'intercom_delete_contact_v2',
|
||||
name: 'Delete Contact from Intercom',
|
||||
description: 'Delete a contact from Intercom by ID. Returns API-aligned fields only.',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'delete_contact')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
deleted: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'ID of deleted contact' },
|
||||
deleted: { type: 'boolean', description: 'Whether the contact was deleted' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface IntercomDetachContactFromCompanyParams {
|
||||
accessToken: string
|
||||
contactId: string
|
||||
companyId: string
|
||||
}
|
||||
|
||||
export interface IntercomDetachContactFromCompanyV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
company: any
|
||||
companyId: string
|
||||
name: string | null
|
||||
}
|
||||
}
|
||||
|
||||
const detachContactFromCompanyBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
contactId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the contact to detach from the company',
|
||||
},
|
||||
companyId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the company to detach the contact from',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: IntercomDetachContactFromCompanyParams) =>
|
||||
buildIntercomUrl(`/contacts/${params.contactId}/companies/${params.companyId}`),
|
||||
method: 'DELETE',
|
||||
headers: (params: IntercomDetachContactFromCompanyParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomDetachContactFromCompanyParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomDetachContactFromCompanyV2Tool: ToolConfig<
|
||||
IntercomDetachContactFromCompanyParams,
|
||||
IntercomDetachContactFromCompanyV2Response
|
||||
> = {
|
||||
...detachContactFromCompanyBase,
|
||||
id: 'intercom_detach_contact_from_company_v2',
|
||||
name: 'Detach Contact from Company in Intercom',
|
||||
description: 'Remove a contact from a company in Intercom',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'detach_contact_from_company')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
company: {
|
||||
id: data.id,
|
||||
type: data.type ?? 'company',
|
||||
company_id: data.company_id ?? null,
|
||||
name: data.name ?? null,
|
||||
},
|
||||
companyId: data.id,
|
||||
name: data.name ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
company: {
|
||||
type: 'object',
|
||||
description: 'The company object the contact was detached from',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the company' },
|
||||
type: { type: 'string', description: 'Object type (company)' },
|
||||
company_id: { type: 'string', description: 'The company_id you defined' },
|
||||
name: { type: 'string', description: 'Name of the company' },
|
||||
},
|
||||
},
|
||||
companyId: { type: 'string', description: 'ID of the company' },
|
||||
name: { type: 'string', description: 'Name of the company', optional: true },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface IntercomGetCompanyParams {
|
||||
accessToken: string
|
||||
companyId: string
|
||||
}
|
||||
|
||||
export interface IntercomGetCompanyResponse {
|
||||
success: boolean
|
||||
output: {
|
||||
company: any
|
||||
metadata: {
|
||||
operation: 'get_company'
|
||||
}
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
const getCompanyBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
companyId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Company ID to retrieve',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: IntercomGetCompanyParams) => buildIntercomUrl(`/companies/${params.companyId}`),
|
||||
method: 'GET',
|
||||
headers: (params: IntercomGetCompanyParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomGetCompanyParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomGetCompanyTool: ToolConfig<
|
||||
IntercomGetCompanyParams,
|
||||
IntercomGetCompanyResponse
|
||||
> = {
|
||||
id: 'intercom_get_company',
|
||||
name: 'Get Company from Intercom',
|
||||
description: 'Retrieve a single company by ID from Intercom',
|
||||
version: '1.0.0',
|
||||
|
||||
...getCompanyBase,
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'get_company')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
company: data,
|
||||
metadata: {
|
||||
operation: 'get_company' as const,
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
company: {
|
||||
type: 'object',
|
||||
description: 'Company object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the company' },
|
||||
type: { type: 'string', description: 'Object type (company)' },
|
||||
app_id: { type: 'string', description: 'Intercom app ID' },
|
||||
company_id: { type: 'string', description: 'Your unique identifier for the company' },
|
||||
name: { type: 'string', description: 'Name of the company' },
|
||||
website: { type: 'string', description: 'Company website URL' },
|
||||
plan: { type: 'object', description: 'Company plan information' },
|
||||
size: { type: 'number', description: 'Number of employees' },
|
||||
industry: { type: 'string', description: 'Industry the company operates in' },
|
||||
monthly_spend: { type: 'number', description: 'Monthly revenue from this company' },
|
||||
session_count: { type: 'number', description: 'Number of sessions' },
|
||||
user_count: { type: 'number', description: 'Number of users in the company' },
|
||||
created_at: { type: 'number', description: 'Unix timestamp when company was created' },
|
||||
updated_at: { type: 'number', description: 'Unix timestamp when company was last updated' },
|
||||
custom_attributes: { type: 'object', description: 'Custom attributes set on the company' },
|
||||
tags: { type: 'object', description: 'Tags associated with the company' },
|
||||
segments: { type: 'object', description: 'Segments the company belongs to' },
|
||||
},
|
||||
},
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Operation metadata',
|
||||
properties: {
|
||||
operation: { type: 'string', description: 'The operation performed (get_company)' },
|
||||
},
|
||||
},
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
|
||||
interface IntercomGetCompanyV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
company: any
|
||||
}
|
||||
}
|
||||
|
||||
export const intercomGetCompanyV2Tool: ToolConfig<
|
||||
IntercomGetCompanyParams,
|
||||
IntercomGetCompanyV2Response
|
||||
> = {
|
||||
...getCompanyBase,
|
||||
id: 'intercom_get_company_v2',
|
||||
name: 'Get Company from Intercom',
|
||||
description: 'Retrieve a single company by ID from Intercom',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'get_company')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
company: data,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
company: {
|
||||
type: 'object',
|
||||
description: 'Company object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the company' },
|
||||
type: { type: 'string', description: 'Object type (company)' },
|
||||
app_id: { type: 'string', description: 'Intercom app ID' },
|
||||
company_id: { type: 'string', description: 'Your unique identifier for the company' },
|
||||
name: { type: 'string', description: 'Name of the company' },
|
||||
website: { type: 'string', description: 'Company website URL' },
|
||||
plan: { type: 'object', description: 'Company plan information' },
|
||||
size: { type: 'number', description: 'Number of employees' },
|
||||
industry: { type: 'string', description: 'Industry the company operates in' },
|
||||
monthly_spend: { type: 'number', description: 'Monthly revenue from this company' },
|
||||
session_count: { type: 'number', description: 'Number of sessions' },
|
||||
user_count: { type: 'number', description: 'Number of users in the company' },
|
||||
created_at: { type: 'number', description: 'Unix timestamp when company was created' },
|
||||
updated_at: { type: 'number', description: 'Unix timestamp when company was last updated' },
|
||||
custom_attributes: { type: 'object', description: 'Custom attributes set on the company' },
|
||||
tags: { type: 'object', description: 'Tags associated with the company' },
|
||||
segments: { type: 'object', description: 'Segments the company belongs to' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
import {
|
||||
buildIntercomUrl,
|
||||
handleIntercomError,
|
||||
INTERCOM_CONTACT_OUTPUT_PROPERTIES,
|
||||
} from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface IntercomGetContactParams {
|
||||
accessToken: string
|
||||
contactId: string
|
||||
}
|
||||
|
||||
export interface IntercomGetContactResponse {
|
||||
success: boolean
|
||||
output: {
|
||||
contact: any
|
||||
metadata: {
|
||||
operation: 'get_contact'
|
||||
}
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
const intercomGetContactBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
contactId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Contact ID to retrieve',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: IntercomGetContactParams) => buildIntercomUrl(`/contacts/${params.contactId}`),
|
||||
method: 'GET',
|
||||
headers: (params: IntercomGetContactParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomGetContactParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomGetContactTool: ToolConfig<
|
||||
IntercomGetContactParams,
|
||||
IntercomGetContactResponse
|
||||
> = {
|
||||
id: 'intercom_get_contact',
|
||||
name: 'Get Single Contact from Intercom',
|
||||
description: 'Get a single contact by ID from Intercom',
|
||||
version: '1.0.0',
|
||||
|
||||
...intercomGetContactBase,
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'get_contact')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
contact: data,
|
||||
metadata: {
|
||||
operation: 'get_contact' as const,
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
contact: {
|
||||
type: 'object',
|
||||
description: 'Contact object',
|
||||
properties: INTERCOM_CONTACT_OUTPUT_PROPERTIES,
|
||||
},
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Operation metadata',
|
||||
properties: {
|
||||
operation: { type: 'string', description: 'The operation performed (get_contact)' },
|
||||
},
|
||||
},
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
|
||||
interface IntercomGetContactV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
contact: any
|
||||
}
|
||||
}
|
||||
|
||||
export const intercomGetContactV2Tool: ToolConfig<
|
||||
IntercomGetContactParams,
|
||||
IntercomGetContactV2Response
|
||||
> = {
|
||||
...intercomGetContactBase,
|
||||
id: 'intercom_get_contact_v2',
|
||||
name: 'Get Single Contact from Intercom',
|
||||
description: 'Get a single contact by ID from Intercom. Returns API-aligned fields only.',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'get_contact')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
contact: data,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
contact: {
|
||||
type: 'object',
|
||||
description: 'Contact object',
|
||||
properties: INTERCOM_CONTACT_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface IntercomGetConversationParams {
|
||||
accessToken: string
|
||||
conversationId: string
|
||||
display_as?: string
|
||||
include_translations?: boolean
|
||||
}
|
||||
|
||||
export interface IntercomGetConversationResponse {
|
||||
success: boolean
|
||||
output: {
|
||||
conversation: any
|
||||
metadata: {
|
||||
operation: 'get_conversation'
|
||||
}
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
const getConversationBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
conversationId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Conversation ID to retrieve',
|
||||
},
|
||||
display_as: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Set to "plaintext" to retrieve messages in plain text',
|
||||
},
|
||||
include_translations: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'When true, conversation parts will be translated to the detected language of the conversation',
|
||||
},
|
||||
},
|
||||
request: {
|
||||
url: (params: IntercomGetConversationParams) => {
|
||||
const url = buildIntercomUrl(`/conversations/${params.conversationId}`)
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.display_as) queryParams.append('display_as', params.display_as)
|
||||
if (params.include_translations !== undefined)
|
||||
queryParams.append('include_translations', String(params.include_translations))
|
||||
|
||||
const queryString = queryParams.toString()
|
||||
return queryString ? `${url}?${queryString}` : url
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params: IntercomGetConversationParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomGetConversationParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomGetConversationTool: ToolConfig<
|
||||
IntercomGetConversationParams,
|
||||
IntercomGetConversationResponse
|
||||
> = {
|
||||
id: 'intercom_get_conversation',
|
||||
name: 'Get Conversation from Intercom',
|
||||
description: 'Retrieve a single conversation by ID from Intercom',
|
||||
version: '1.0.0',
|
||||
|
||||
...getConversationBase,
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'get_conversation')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
conversation: data,
|
||||
metadata: {
|
||||
operation: 'get_conversation' as const,
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
conversation: {
|
||||
type: 'object',
|
||||
description: 'Conversation object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the conversation' },
|
||||
type: { type: 'string', description: 'Object type (conversation)' },
|
||||
title: { type: 'string', description: 'Title of the conversation', optional: true },
|
||||
created_at: { type: 'number', description: 'Unix timestamp when conversation was created' },
|
||||
updated_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when conversation was last updated',
|
||||
},
|
||||
waiting_since: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when waiting for reply',
|
||||
optional: true,
|
||||
},
|
||||
snoozed_until: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when snooze ends',
|
||||
optional: true,
|
||||
},
|
||||
open: { type: 'boolean', description: 'Whether the conversation is open' },
|
||||
state: { type: 'string', description: 'State of the conversation' },
|
||||
read: { type: 'boolean', description: 'Whether the conversation has been read' },
|
||||
priority: { type: 'string', description: 'Priority of the conversation' },
|
||||
admin_assignee_id: { type: 'number', description: 'ID of assigned admin', optional: true },
|
||||
team_assignee_id: { type: 'string', description: 'ID of assigned team', optional: true },
|
||||
tags: { type: 'object', description: 'Tags on the conversation' },
|
||||
source: { type: 'object', description: 'Source of the conversation' },
|
||||
contacts: { type: 'object', description: 'Contacts in the conversation' },
|
||||
teammates: { type: 'object', description: 'Teammates in the conversation' },
|
||||
conversation_parts: { type: 'object', description: 'Parts of the conversation' },
|
||||
statistics: { type: 'object', description: 'Conversation statistics' },
|
||||
},
|
||||
},
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Operation metadata',
|
||||
properties: {
|
||||
operation: { type: 'string', description: 'The operation performed (get_conversation)' },
|
||||
},
|
||||
},
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
|
||||
interface IntercomGetConversationV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
conversation: any
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
export const intercomGetConversationV2Tool: ToolConfig<
|
||||
IntercomGetConversationParams,
|
||||
IntercomGetConversationV2Response
|
||||
> = {
|
||||
...getConversationBase,
|
||||
id: 'intercom_get_conversation_v2',
|
||||
name: 'Get Conversation from Intercom',
|
||||
description: 'Retrieve a single conversation by ID from Intercom',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'get_conversation')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
conversation: data,
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
conversation: {
|
||||
type: 'object',
|
||||
description: 'Conversation object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the conversation' },
|
||||
type: { type: 'string', description: 'Object type (conversation)' },
|
||||
title: { type: 'string', description: 'Title of the conversation', optional: true },
|
||||
created_at: { type: 'number', description: 'Unix timestamp when conversation was created' },
|
||||
updated_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when conversation was last updated',
|
||||
},
|
||||
waiting_since: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when waiting for reply',
|
||||
optional: true,
|
||||
},
|
||||
snoozed_until: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when snooze ends',
|
||||
optional: true,
|
||||
},
|
||||
open: { type: 'boolean', description: 'Whether the conversation is open' },
|
||||
state: { type: 'string', description: 'State of the conversation' },
|
||||
read: { type: 'boolean', description: 'Whether the conversation has been read' },
|
||||
priority: { type: 'string', description: 'Priority of the conversation' },
|
||||
admin_assignee_id: { type: 'number', description: 'ID of assigned admin', optional: true },
|
||||
team_assignee_id: { type: 'string', description: 'ID of assigned team', optional: true },
|
||||
tags: { type: 'object', description: 'Tags on the conversation' },
|
||||
source: { type: 'object', description: 'Source of the conversation' },
|
||||
contacts: { type: 'object', description: 'Contacts in the conversation' },
|
||||
teammates: { type: 'object', description: 'Teammates in the conversation' },
|
||||
conversation_parts: { type: 'object', description: 'Parts of the conversation' },
|
||||
statistics: { type: 'object', description: 'Conversation statistics' },
|
||||
},
|
||||
},
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface IntercomGetTicketParams {
|
||||
accessToken: string
|
||||
ticketId: string
|
||||
}
|
||||
|
||||
export interface IntercomGetTicketResponse {
|
||||
success: boolean
|
||||
output: {
|
||||
ticket: any
|
||||
metadata: {
|
||||
operation: 'get_ticket'
|
||||
}
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
export interface IntercomGetTicketV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
ticket: any
|
||||
ticketId: string
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
const getTicketBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
ticketId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Ticket ID to retrieve',
|
||||
},
|
||||
},
|
||||
request: {
|
||||
url: (params: IntercomGetTicketParams) => buildIntercomUrl(`/tickets/${params.ticketId}`),
|
||||
method: 'GET',
|
||||
headers: (params: IntercomGetTicketParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomGetTicketParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomGetTicketTool: ToolConfig<IntercomGetTicketParams, IntercomGetTicketResponse> =
|
||||
{
|
||||
id: 'intercom_get_ticket',
|
||||
name: 'Get Ticket from Intercom',
|
||||
description: 'Retrieve a single ticket by ID from Intercom',
|
||||
version: '1.0.0',
|
||||
|
||||
...getTicketBase,
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'get_ticket')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
ticket: data,
|
||||
metadata: {
|
||||
operation: 'get_ticket' as const,
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
ticket: {
|
||||
type: 'object',
|
||||
description: 'Ticket object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the ticket' },
|
||||
type: { type: 'string', description: 'Object type (ticket)' },
|
||||
ticket_id: { type: 'string', description: 'Ticket ID' },
|
||||
ticket_type: { type: 'object', description: 'Type of the ticket', optional: true },
|
||||
ticket_attributes: { type: 'object', description: 'Attributes of the ticket' },
|
||||
ticket_state: { type: 'string', description: 'State of the ticket' },
|
||||
ticket_state_internal_label: {
|
||||
type: 'string',
|
||||
description: 'Internal label for ticket state',
|
||||
},
|
||||
ticket_state_external_label: {
|
||||
type: 'string',
|
||||
description: 'External label for ticket state',
|
||||
},
|
||||
created_at: { type: 'number', description: 'Unix timestamp when ticket was created' },
|
||||
updated_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when ticket was last updated',
|
||||
},
|
||||
contacts: { type: 'object', description: 'Contacts associated with the ticket' },
|
||||
admin_assignee_id: { type: 'string', description: 'ID of assigned admin' },
|
||||
team_assignee_id: { type: 'string', description: 'ID of assigned team' },
|
||||
is_shared: { type: 'boolean', description: 'Whether the ticket is shared' },
|
||||
open: { type: 'boolean', description: 'Whether the ticket is open' },
|
||||
},
|
||||
},
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Operation metadata',
|
||||
properties: {
|
||||
operation: { type: 'string', description: 'The operation performed (get_ticket)' },
|
||||
},
|
||||
},
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
|
||||
export const intercomGetTicketV2Tool: ToolConfig<
|
||||
IntercomGetTicketParams,
|
||||
IntercomGetTicketV2Response
|
||||
> = {
|
||||
...getTicketBase,
|
||||
id: 'intercom_get_ticket_v2',
|
||||
name: 'Get Ticket from Intercom',
|
||||
description: 'Retrieve a single ticket by ID from Intercom. Returns API-aligned fields only.',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'get_ticket')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
ticket: data,
|
||||
ticketId: data.id,
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
ticket: {
|
||||
type: 'object',
|
||||
description: 'Ticket object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the ticket' },
|
||||
type: { type: 'string', description: 'Object type (ticket)' },
|
||||
ticket_id: { type: 'string', description: 'Ticket ID' },
|
||||
ticket_type: { type: 'object', description: 'Type of the ticket', optional: true },
|
||||
ticket_attributes: { type: 'object', description: 'Attributes of the ticket' },
|
||||
ticket_state: { type: 'string', description: 'State of the ticket' },
|
||||
ticket_state_internal_label: {
|
||||
type: 'string',
|
||||
description: 'Internal label for ticket state',
|
||||
},
|
||||
ticket_state_external_label: {
|
||||
type: 'string',
|
||||
description: 'External label for ticket state',
|
||||
},
|
||||
created_at: { type: 'number', description: 'Unix timestamp when ticket was created' },
|
||||
updated_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when ticket was last updated',
|
||||
},
|
||||
contacts: { type: 'object', description: 'Contacts associated with the ticket' },
|
||||
admin_assignee_id: { type: 'string', description: 'ID of assigned admin' },
|
||||
team_assignee_id: { type: 'string', description: 'ID of assigned team' },
|
||||
is_shared: { type: 'boolean', description: 'Whether the ticket is shared' },
|
||||
open: { type: 'boolean', description: 'Whether the ticket is open' },
|
||||
},
|
||||
},
|
||||
ticketId: { type: 'string', description: 'ID of the retrieved ticket' },
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
export { intercomAssignConversationV2Tool } from './assign_conversation'
|
||||
export { intercomAttachContactToCompanyV2Tool } from './attach_contact_to_company'
|
||||
export { intercomCloseConversationV2Tool } from './close_conversation'
|
||||
export { intercomCreateCompanyTool, intercomCreateCompanyV2Tool } from './create_company'
|
||||
export { intercomCreateContactTool, intercomCreateContactV2Tool } from './create_contact'
|
||||
export { intercomCreateEventV2Tool } from './create_event'
|
||||
export { intercomCreateMessageTool, intercomCreateMessageV2Tool } from './create_message'
|
||||
export { intercomCreateNoteV2Tool } from './create_note'
|
||||
export { intercomCreateTagV2Tool } from './create_tag'
|
||||
export { intercomCreateTicketTool, intercomCreateTicketV2Tool } from './create_ticket'
|
||||
export { intercomDeleteContactTool, intercomDeleteContactV2Tool } from './delete_contact'
|
||||
export { intercomDetachContactFromCompanyV2Tool } from './detach_contact_from_company'
|
||||
export { intercomGetCompanyTool, intercomGetCompanyV2Tool } from './get_company'
|
||||
export { intercomGetContactTool, intercomGetContactV2Tool } from './get_contact'
|
||||
export { intercomGetConversationTool, intercomGetConversationV2Tool } from './get_conversation'
|
||||
export { intercomGetTicketTool, intercomGetTicketV2Tool } from './get_ticket'
|
||||
export { intercomListAdminsV2Tool } from './list_admins'
|
||||
export { intercomListCompaniesTool, intercomListCompaniesV2Tool } from './list_companies'
|
||||
export { intercomListContactsTool, intercomListContactsV2Tool } from './list_contacts'
|
||||
export {
|
||||
intercomListConversationsTool,
|
||||
intercomListConversationsV2Tool,
|
||||
} from './list_conversations'
|
||||
export { intercomListTagsV2Tool } from './list_tags'
|
||||
export { intercomOpenConversationV2Tool } from './open_conversation'
|
||||
export {
|
||||
intercomReplyConversationTool,
|
||||
intercomReplyConversationV2Tool,
|
||||
} from './reply_conversation'
|
||||
export { intercomSearchContactsTool, intercomSearchContactsV2Tool } from './search_contacts'
|
||||
export {
|
||||
intercomSearchConversationsTool,
|
||||
intercomSearchConversationsV2Tool,
|
||||
} from './search_conversations'
|
||||
export { intercomSnoozeConversationV2Tool } from './snooze_conversation'
|
||||
export { intercomTagContactV2Tool } from './tag_contact'
|
||||
export { intercomTagConversationV2Tool } from './tag_conversation'
|
||||
export { intercomUntagContactV2Tool } from './untag_contact'
|
||||
export { intercomUpdateContactTool, intercomUpdateContactV2Tool } from './update_contact'
|
||||
export { intercomUpdateTicketV2Tool } from './update_ticket'
|
||||
@@ -0,0 +1,125 @@
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface IntercomListAdminsParams {
|
||||
accessToken: string
|
||||
}
|
||||
|
||||
interface IntercomAdmin {
|
||||
type: string
|
||||
id: string
|
||||
name: string
|
||||
email: string
|
||||
job_title: string | null
|
||||
away_mode_enabled: boolean
|
||||
away_mode_reassign: boolean
|
||||
has_inbox_seat: boolean
|
||||
team_ids: number[]
|
||||
avatar: {
|
||||
type: string
|
||||
image_url: string | null
|
||||
} | null
|
||||
email_verified: boolean | null
|
||||
}
|
||||
|
||||
export interface IntercomListAdminsV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
admins: IntercomAdmin[]
|
||||
type: string
|
||||
}
|
||||
}
|
||||
|
||||
const listAdminsBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: () => buildIntercomUrl('/admins'),
|
||||
method: 'GET',
|
||||
headers: (params: IntercomListAdminsParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomListAdminsParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomListAdminsV2Tool: ToolConfig<
|
||||
IntercomListAdminsParams,
|
||||
IntercomListAdminsV2Response
|
||||
> = {
|
||||
...listAdminsBase,
|
||||
id: 'intercom_list_admins_v2',
|
||||
name: 'List Admins from Intercom',
|
||||
description: 'Fetch a list of all admins for the workspace',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'list_admins')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
admins: data.admins ?? [],
|
||||
type: data.type ?? 'admin.list',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
admins: {
|
||||
type: 'array',
|
||||
description: 'Array of admin objects',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the admin' },
|
||||
type: { type: 'string', description: 'Object type (admin)' },
|
||||
name: { type: 'string', description: 'Name of the admin' },
|
||||
email: { type: 'string', description: 'Email of the admin' },
|
||||
job_title: { type: 'string', description: 'Job title of the admin', optional: true },
|
||||
away_mode_enabled: {
|
||||
type: 'boolean',
|
||||
description: 'Whether admin is in away mode',
|
||||
},
|
||||
away_mode_reassign: {
|
||||
type: 'boolean',
|
||||
description: 'Whether to reassign conversations when away',
|
||||
},
|
||||
has_inbox_seat: {
|
||||
type: 'boolean',
|
||||
description: 'Whether admin has a paid inbox seat',
|
||||
},
|
||||
team_ids: {
|
||||
type: 'array',
|
||||
description: 'List of team IDs the admin belongs to',
|
||||
},
|
||||
avatar: {
|
||||
type: 'object',
|
||||
description: 'Avatar information',
|
||||
optional: true,
|
||||
},
|
||||
email_verified: {
|
||||
type: 'boolean',
|
||||
description: 'Whether email is verified',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
type: { type: 'string', description: 'Object type (admin.list)' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface IntercomListCompaniesParams {
|
||||
accessToken: string
|
||||
per_page?: number
|
||||
page?: number
|
||||
starting_after?: string
|
||||
}
|
||||
|
||||
export interface IntercomListCompaniesResponse {
|
||||
success: boolean
|
||||
output: {
|
||||
companies: any[]
|
||||
pages?: any
|
||||
metadata: {
|
||||
operation: 'list_companies'
|
||||
total_count?: number
|
||||
}
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
const listCompaniesBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
per_page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of results per page',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number',
|
||||
},
|
||||
starting_after: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Cursor for pagination (preferred over page-based pagination)',
|
||||
},
|
||||
},
|
||||
request: {
|
||||
url: (params: IntercomListCompaniesParams) => {
|
||||
const url = buildIntercomUrl('/companies/list')
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.per_page) queryParams.append('per_page', params.per_page.toString())
|
||||
if (params.page) queryParams.append('page', params.page.toString())
|
||||
if (params.starting_after) queryParams.append('starting_after', params.starting_after)
|
||||
|
||||
const queryString = queryParams.toString()
|
||||
return queryString ? `${url}?${queryString}` : url
|
||||
},
|
||||
method: 'POST',
|
||||
headers: (params: IntercomListCompaniesParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomListCompaniesParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomListCompaniesTool: ToolConfig<
|
||||
IntercomListCompaniesParams,
|
||||
IntercomListCompaniesResponse
|
||||
> = {
|
||||
id: 'intercom_list_companies',
|
||||
name: 'List Companies from Intercom',
|
||||
description:
|
||||
'List all companies from Intercom with pagination support. Note: This endpoint has a limit of 10,000 companies that can be returned using pagination. For datasets larger than 10,000 companies, use the Scroll API instead.',
|
||||
version: '1.0.0',
|
||||
|
||||
...listCompaniesBase,
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'list_companies')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
companies: data.data || data.companies || [],
|
||||
pages: data.pages,
|
||||
metadata: {
|
||||
operation: 'list_companies' as const,
|
||||
total_count: data.total_count,
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
companies: {
|
||||
type: 'array',
|
||||
description: 'Array of company objects',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the company' },
|
||||
type: { type: 'string', description: 'Object type (company)' },
|
||||
app_id: { type: 'string', description: 'Intercom app ID' },
|
||||
company_id: { type: 'string', description: 'Your unique identifier for the company' },
|
||||
name: { type: 'string', description: 'Name of the company' },
|
||||
website: { type: 'string', description: 'Company website URL' },
|
||||
plan: { type: 'object', description: 'Company plan information' },
|
||||
monthly_spend: { type: 'number', description: 'Monthly revenue from this company' },
|
||||
session_count: { type: 'number', description: 'Number of sessions' },
|
||||
user_count: { type: 'number', description: 'Number of users in the company' },
|
||||
created_at: { type: 'number', description: 'Unix timestamp when company was created' },
|
||||
updated_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when company was last updated',
|
||||
},
|
||||
custom_attributes: {
|
||||
type: 'object',
|
||||
description: 'Custom attributes set on the company',
|
||||
},
|
||||
tags: { type: 'object', description: 'Tags associated with the company' },
|
||||
segments: { type: 'object', description: 'Segments the company belongs to' },
|
||||
},
|
||||
},
|
||||
},
|
||||
pages: {
|
||||
type: 'object',
|
||||
description: 'Pagination information',
|
||||
properties: {
|
||||
type: { type: 'string', description: 'Pages type identifier' },
|
||||
page: { type: 'number', description: 'Current page number' },
|
||||
per_page: { type: 'number', description: 'Number of results per page' },
|
||||
total_pages: { type: 'number', description: 'Total number of pages' },
|
||||
},
|
||||
},
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Operation metadata',
|
||||
properties: {
|
||||
operation: { type: 'string', description: 'The operation performed (list_companies)' },
|
||||
total_count: { type: 'number', description: 'Total number of companies' },
|
||||
},
|
||||
},
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
|
||||
interface IntercomListCompaniesV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
companies: any[]
|
||||
pages?: any
|
||||
total_count?: number
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
export const intercomListCompaniesV2Tool: ToolConfig<
|
||||
IntercomListCompaniesParams,
|
||||
IntercomListCompaniesV2Response
|
||||
> = {
|
||||
...listCompaniesBase,
|
||||
id: 'intercom_list_companies_v2',
|
||||
name: 'List Companies from Intercom',
|
||||
description:
|
||||
'List all companies from Intercom with pagination support. Note: This endpoint has a limit of 10,000 companies that can be returned using pagination. For datasets larger than 10,000 companies, use the Scroll API instead.',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'list_companies')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
companies: data.data || data.companies || [],
|
||||
pages: data.pages,
|
||||
total_count: data.total_count,
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
companies: {
|
||||
type: 'array',
|
||||
description: 'Array of company objects',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the company' },
|
||||
type: { type: 'string', description: 'Object type (company)' },
|
||||
app_id: { type: 'string', description: 'Intercom app ID' },
|
||||
company_id: { type: 'string', description: 'Your unique identifier for the company' },
|
||||
name: { type: 'string', description: 'Name of the company' },
|
||||
website: { type: 'string', description: 'Company website URL' },
|
||||
plan: { type: 'object', description: 'Company plan information' },
|
||||
monthly_spend: { type: 'number', description: 'Monthly revenue from this company' },
|
||||
session_count: { type: 'number', description: 'Number of sessions' },
|
||||
user_count: { type: 'number', description: 'Number of users in the company' },
|
||||
created_at: { type: 'number', description: 'Unix timestamp when company was created' },
|
||||
updated_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when company was last updated',
|
||||
},
|
||||
custom_attributes: {
|
||||
type: 'object',
|
||||
description: 'Custom attributes set on the company',
|
||||
},
|
||||
tags: { type: 'object', description: 'Tags associated with the company' },
|
||||
segments: { type: 'object', description: 'Segments the company belongs to' },
|
||||
},
|
||||
},
|
||||
},
|
||||
pages: {
|
||||
type: 'object',
|
||||
description: 'Pagination information',
|
||||
properties: {
|
||||
type: { type: 'string', description: 'Pages type identifier' },
|
||||
page: { type: 'number', description: 'Current page number' },
|
||||
per_page: { type: 'number', description: 'Number of results per page' },
|
||||
total_pages: { type: 'number', description: 'Total number of pages' },
|
||||
},
|
||||
},
|
||||
total_count: { type: 'number', description: 'Total number of companies' },
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,234 @@
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface IntercomListContactsParams {
|
||||
accessToken: string
|
||||
per_page?: number
|
||||
starting_after?: string
|
||||
}
|
||||
|
||||
export interface IntercomListContactsResponse {
|
||||
success: boolean
|
||||
output: {
|
||||
contacts: any[]
|
||||
pages?: any
|
||||
metadata: {
|
||||
operation: 'list_contacts'
|
||||
total_count?: number
|
||||
}
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
const listContactsBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
per_page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of results per page (max: 150)',
|
||||
},
|
||||
starting_after: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Cursor for pagination - ID to start after',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: IntercomListContactsParams) => {
|
||||
const url = buildIntercomUrl('/contacts')
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.per_page) queryParams.append('per_page', params.per_page.toString())
|
||||
if (params.starting_after) queryParams.append('starting_after', params.starting_after)
|
||||
|
||||
const queryString = queryParams.toString()
|
||||
return queryString ? `${url}?${queryString}` : url
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params: IntercomListContactsParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomListContactsParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomListContactsTool: ToolConfig<
|
||||
IntercomListContactsParams,
|
||||
IntercomListContactsResponse
|
||||
> = {
|
||||
id: 'intercom_list_contacts',
|
||||
name: 'List Contacts from Intercom',
|
||||
description: 'List all contacts from Intercom with pagination support',
|
||||
version: '1.0.0',
|
||||
|
||||
...listContactsBase,
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'list_contacts')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
contacts: data.data || [],
|
||||
pages: data.pages,
|
||||
metadata: {
|
||||
operation: 'list_contacts' as const,
|
||||
total_count: data.total_count,
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
contacts: {
|
||||
type: 'array',
|
||||
description: 'Array of contact objects',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the contact' },
|
||||
type: { type: 'string', description: 'Object type (contact)' },
|
||||
role: { type: 'string', description: 'Role of the contact (user or lead)' },
|
||||
email: { type: 'string', description: 'Email address of the contact' },
|
||||
phone: { type: 'string', description: 'Phone number of the contact' },
|
||||
name: { type: 'string', description: 'Name of the contact' },
|
||||
external_id: { type: 'string', description: 'External identifier for the contact' },
|
||||
created_at: { type: 'number', description: 'Unix timestamp when contact was created' },
|
||||
updated_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when contact was last updated',
|
||||
},
|
||||
workspace_id: { type: 'string', description: 'Workspace ID the contact belongs to' },
|
||||
custom_attributes: {
|
||||
type: 'object',
|
||||
description: 'Custom attributes set on the contact',
|
||||
},
|
||||
tags: { type: 'object', description: 'Tags associated with the contact' },
|
||||
companies: { type: 'object', description: 'Companies associated with the contact' },
|
||||
},
|
||||
},
|
||||
},
|
||||
pages: {
|
||||
type: 'object',
|
||||
description: 'Pagination information',
|
||||
properties: {
|
||||
type: { type: 'string', description: 'Pages type identifier' },
|
||||
page: { type: 'number', description: 'Current page number' },
|
||||
per_page: { type: 'number', description: 'Number of results per page' },
|
||||
total_pages: { type: 'number', description: 'Total number of pages' },
|
||||
},
|
||||
},
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Operation metadata',
|
||||
properties: {
|
||||
operation: { type: 'string', description: 'The operation performed (list_contacts)' },
|
||||
total_count: { type: 'number', description: 'Total number of contacts' },
|
||||
},
|
||||
},
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
|
||||
interface IntercomListContactsV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
contacts: any[]
|
||||
pages?: any
|
||||
total_count?: number
|
||||
}
|
||||
}
|
||||
|
||||
export const intercomListContactsV2Tool: ToolConfig<
|
||||
IntercomListContactsParams,
|
||||
IntercomListContactsV2Response
|
||||
> = {
|
||||
...listContactsBase,
|
||||
id: 'intercom_list_contacts_v2',
|
||||
name: 'List Contacts from Intercom',
|
||||
description: 'List all contacts from Intercom with pagination support',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'list_contacts')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
contacts: data.data ?? null,
|
||||
pages: data.pages ?? null,
|
||||
total_count: data.total_count ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
contacts: {
|
||||
type: 'array',
|
||||
description: 'Array of contact objects',
|
||||
optional: true,
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the contact' },
|
||||
type: { type: 'string', description: 'Object type (contact)' },
|
||||
role: { type: 'string', description: 'Role of the contact (user or lead)' },
|
||||
email: { type: 'string', description: 'Email address of the contact', optional: true },
|
||||
phone: { type: 'string', description: 'Phone number of the contact', optional: true },
|
||||
name: { type: 'string', description: 'Name of the contact', optional: true },
|
||||
external_id: {
|
||||
type: 'string',
|
||||
description: 'External identifier for the contact',
|
||||
optional: true,
|
||||
},
|
||||
created_at: { type: 'number', description: 'Unix timestamp when contact was created' },
|
||||
updated_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when contact was last updated',
|
||||
},
|
||||
workspace_id: { type: 'string', description: 'Workspace ID the contact belongs to' },
|
||||
custom_attributes: {
|
||||
type: 'object',
|
||||
description: 'Custom attributes set on the contact',
|
||||
},
|
||||
tags: { type: 'object', description: 'Tags associated with the contact', optional: true },
|
||||
companies: { type: 'object', description: 'Companies associated with the contact' },
|
||||
},
|
||||
},
|
||||
},
|
||||
pages: {
|
||||
type: 'object',
|
||||
description: 'Pagination information',
|
||||
optional: true,
|
||||
properties: {
|
||||
type: { type: 'string', description: 'Pages type identifier' },
|
||||
page: { type: 'number', description: 'Current page number' },
|
||||
per_page: { type: 'number', description: 'Number of results per page' },
|
||||
total_pages: { type: 'number', description: 'Total number of pages' },
|
||||
},
|
||||
},
|
||||
total_count: { type: 'number', description: 'Total number of contacts', optional: true },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface IntercomListConversationsParams {
|
||||
accessToken: string
|
||||
per_page?: number
|
||||
starting_after?: string
|
||||
sort?: string
|
||||
order?: 'asc' | 'desc'
|
||||
}
|
||||
|
||||
export interface IntercomListConversationsResponse {
|
||||
success: boolean
|
||||
output: {
|
||||
conversations: any[]
|
||||
pages?: any
|
||||
metadata: {
|
||||
operation: 'list_conversations'
|
||||
total_count?: number
|
||||
}
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
const listConversationsBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
per_page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of results per page (max: 150)',
|
||||
},
|
||||
starting_after: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Cursor for pagination',
|
||||
},
|
||||
sort: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Field to sort by (e.g., "waiting_since", "updated_at", "created_at")',
|
||||
},
|
||||
order: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Sort order: "asc" (ascending) or "desc" (descending)',
|
||||
},
|
||||
},
|
||||
request: {
|
||||
url: (params: IntercomListConversationsParams) => {
|
||||
const url = buildIntercomUrl('/conversations')
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.per_page) queryParams.append('per_page', params.per_page.toString())
|
||||
if (params.starting_after) queryParams.append('starting_after', params.starting_after)
|
||||
if (params.sort) queryParams.append('sort', params.sort)
|
||||
if (params.order) queryParams.append('order', params.order)
|
||||
|
||||
const queryString = queryParams.toString()
|
||||
return queryString ? `${url}?${queryString}` : url
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params: IntercomListConversationsParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomListConversationsParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomListConversationsTool: ToolConfig<
|
||||
IntercomListConversationsParams,
|
||||
IntercomListConversationsResponse
|
||||
> = {
|
||||
id: 'intercom_list_conversations',
|
||||
name: 'List Conversations from Intercom',
|
||||
description: 'List all conversations from Intercom with pagination support',
|
||||
version: '1.0.0',
|
||||
|
||||
...listConversationsBase,
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'list_conversations')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
conversations: data.conversations || [],
|
||||
pages: data.pages,
|
||||
metadata: {
|
||||
operation: 'list_conversations' as const,
|
||||
total_count: data.total_count,
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
conversations: {
|
||||
type: 'array',
|
||||
description: 'Array of conversation objects',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the conversation' },
|
||||
type: { type: 'string', description: 'Object type (conversation)' },
|
||||
title: { type: 'string', description: 'Title of the conversation' },
|
||||
created_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when conversation was created',
|
||||
},
|
||||
updated_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when conversation was last updated',
|
||||
},
|
||||
waiting_since: { type: 'number', description: 'Unix timestamp when waiting for reply' },
|
||||
open: { type: 'boolean', description: 'Whether the conversation is open' },
|
||||
state: { type: 'string', description: 'State of the conversation' },
|
||||
read: { type: 'boolean', description: 'Whether the conversation has been read' },
|
||||
priority: { type: 'string', description: 'Priority of the conversation' },
|
||||
admin_assignee_id: { type: 'number', description: 'ID of assigned admin' },
|
||||
team_assignee_id: { type: 'string', description: 'ID of assigned team' },
|
||||
tags: { type: 'object', description: 'Tags on the conversation' },
|
||||
source: { type: 'object', description: 'Source of the conversation' },
|
||||
contacts: { type: 'object', description: 'Contacts in the conversation' },
|
||||
},
|
||||
},
|
||||
},
|
||||
pages: {
|
||||
type: 'object',
|
||||
description: 'Pagination information',
|
||||
properties: {
|
||||
type: { type: 'string', description: 'Pages type identifier' },
|
||||
page: { type: 'number', description: 'Current page number' },
|
||||
per_page: { type: 'number', description: 'Number of results per page' },
|
||||
total_pages: { type: 'number', description: 'Total number of pages' },
|
||||
},
|
||||
},
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Operation metadata',
|
||||
properties: {
|
||||
operation: { type: 'string', description: 'The operation performed (list_conversations)' },
|
||||
total_count: { type: 'number', description: 'Total number of conversations' },
|
||||
},
|
||||
},
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
|
||||
interface IntercomListConversationsV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
conversations: any[]
|
||||
pages?: any
|
||||
total_count?: number
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
export const intercomListConversationsV2Tool: ToolConfig<
|
||||
IntercomListConversationsParams,
|
||||
IntercomListConversationsV2Response
|
||||
> = {
|
||||
...listConversationsBase,
|
||||
id: 'intercom_list_conversations_v2',
|
||||
name: 'List Conversations from Intercom',
|
||||
description: 'List all conversations from Intercom with pagination support',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'list_conversations')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
conversations: data.conversations ?? null,
|
||||
pages: data.pages ?? null,
|
||||
total_count: data.total_count ?? null,
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
conversations: {
|
||||
type: 'array',
|
||||
description: 'Array of conversation objects',
|
||||
optional: true,
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the conversation' },
|
||||
type: { type: 'string', description: 'Object type (conversation)' },
|
||||
title: { type: 'string', description: 'Title of the conversation', optional: true },
|
||||
created_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when conversation was created',
|
||||
},
|
||||
updated_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when conversation was last updated',
|
||||
},
|
||||
waiting_since: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when waiting for reply',
|
||||
optional: true,
|
||||
},
|
||||
open: { type: 'boolean', description: 'Whether the conversation is open' },
|
||||
state: { type: 'string', description: 'State of the conversation' },
|
||||
read: { type: 'boolean', description: 'Whether the conversation has been read' },
|
||||
priority: { type: 'string', description: 'Priority of the conversation' },
|
||||
admin_assignee_id: {
|
||||
type: 'number',
|
||||
description: 'ID of assigned admin',
|
||||
optional: true,
|
||||
},
|
||||
team_assignee_id: { type: 'string', description: 'ID of assigned team', optional: true },
|
||||
tags: { type: 'object', description: 'Tags on the conversation' },
|
||||
source: { type: 'object', description: 'Source of the conversation' },
|
||||
contacts: { type: 'object', description: 'Contacts in the conversation' },
|
||||
},
|
||||
},
|
||||
},
|
||||
pages: {
|
||||
type: 'object',
|
||||
description: 'Pagination information',
|
||||
optional: true,
|
||||
properties: {
|
||||
type: { type: 'string', description: 'Pages type identifier' },
|
||||
page: { type: 'number', description: 'Current page number' },
|
||||
per_page: { type: 'number', description: 'Number of results per page' },
|
||||
total_pages: { type: 'number', description: 'Total number of pages' },
|
||||
},
|
||||
},
|
||||
total_count: { type: 'number', description: 'Total number of conversations', optional: true },
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface IntercomListTagsParams {
|
||||
accessToken: string
|
||||
}
|
||||
|
||||
interface IntercomTag {
|
||||
type: string
|
||||
id: string
|
||||
name: string
|
||||
}
|
||||
|
||||
export interface IntercomListTagsV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
tags: IntercomTag[]
|
||||
type: string
|
||||
}
|
||||
}
|
||||
|
||||
const listTagsBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: () => buildIntercomUrl('/tags'),
|
||||
method: 'GET',
|
||||
headers: (params: IntercomListTagsParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomListTagsParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomListTagsV2Tool: ToolConfig<
|
||||
IntercomListTagsParams,
|
||||
IntercomListTagsV2Response
|
||||
> = {
|
||||
...listTagsBase,
|
||||
id: 'intercom_list_tags_v2',
|
||||
name: 'List Tags from Intercom',
|
||||
description: 'Fetch a list of all tags in the workspace',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'list_tags')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
tags: data.tags ?? [],
|
||||
type: data.type ?? 'tag.list',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
tags: {
|
||||
type: 'array',
|
||||
description: 'Array of tag objects',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the tag' },
|
||||
type: { type: 'string', description: 'Object type (tag)' },
|
||||
name: { type: 'string', description: 'Name of the tag' },
|
||||
},
|
||||
},
|
||||
},
|
||||
type: { type: 'string', description: 'Object type (list)' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface IntercomOpenConversationParams {
|
||||
accessToken: string
|
||||
conversationId: string
|
||||
admin_id: string
|
||||
}
|
||||
|
||||
export interface IntercomOpenConversationV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
conversation: any
|
||||
conversationId: string
|
||||
state: string
|
||||
}
|
||||
}
|
||||
|
||||
const openConversationBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
conversationId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the conversation to open',
|
||||
},
|
||||
admin_id: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the admin performing the action',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: IntercomOpenConversationParams) =>
|
||||
buildIntercomUrl(`/conversations/${params.conversationId}/parts`),
|
||||
method: 'POST',
|
||||
headers: (params: IntercomOpenConversationParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
body: (params: IntercomOpenConversationParams) => ({
|
||||
message_type: 'open',
|
||||
type: 'admin',
|
||||
admin_id: params.admin_id,
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomOpenConversationParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomOpenConversationV2Tool: ToolConfig<
|
||||
IntercomOpenConversationParams,
|
||||
IntercomOpenConversationV2Response
|
||||
> = {
|
||||
...openConversationBase,
|
||||
id: 'intercom_open_conversation_v2',
|
||||
name: 'Open Conversation in Intercom',
|
||||
description: 'Open a closed or snoozed conversation in Intercom',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'open_conversation')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
conversation: {
|
||||
id: data.id,
|
||||
type: data.type ?? 'conversation',
|
||||
state: data.state ?? 'open',
|
||||
open: data.open ?? true,
|
||||
read: data.read ?? false,
|
||||
created_at: data.created_at ?? null,
|
||||
updated_at: data.updated_at ?? null,
|
||||
},
|
||||
conversationId: data.id,
|
||||
state: data.state ?? 'open',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
conversation: {
|
||||
type: 'object',
|
||||
description: 'The opened conversation object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the conversation' },
|
||||
type: { type: 'string', description: 'Object type (conversation)' },
|
||||
state: { type: 'string', description: 'State of the conversation (open)' },
|
||||
open: { type: 'boolean', description: 'Whether the conversation is open (true)' },
|
||||
read: { type: 'boolean', description: 'Whether the conversation has been read' },
|
||||
created_at: { type: 'number', description: 'Unix timestamp when conversation was created' },
|
||||
updated_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when conversation was last updated',
|
||||
},
|
||||
},
|
||||
},
|
||||
conversationId: { type: 'string', description: 'ID of the opened conversation' },
|
||||
state: { type: 'string', description: 'State of the conversation (open)' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface IntercomReplyConversationParams {
|
||||
accessToken: string
|
||||
conversationId: string
|
||||
message_type: string
|
||||
body: string
|
||||
admin_id?: string
|
||||
attachment_urls?: string
|
||||
created_at?: number
|
||||
}
|
||||
|
||||
export interface IntercomReplyConversationResponse {
|
||||
success: boolean
|
||||
output: {
|
||||
conversation: any
|
||||
metadata: {
|
||||
operation: 'reply_conversation'
|
||||
conversationId: string
|
||||
}
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
const replyConversationBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
conversationId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Conversation ID to reply to',
|
||||
},
|
||||
message_type: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Message type: "comment" or "note"',
|
||||
},
|
||||
body: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The text body of the reply',
|
||||
},
|
||||
admin_id: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'The ID of the admin authoring the reply. If not provided, a default admin (Operator/Fin) will be used.',
|
||||
},
|
||||
attachment_urls: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated list of image URLs (max 10)',
|
||||
},
|
||||
created_at: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Unix timestamp for when the reply was created. If not provided, current time is used.',
|
||||
},
|
||||
},
|
||||
request: {
|
||||
url: (params: IntercomReplyConversationParams) =>
|
||||
buildIntercomUrl(`/conversations/${params.conversationId}/reply`),
|
||||
method: 'POST',
|
||||
headers: (params: IntercomReplyConversationParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
body: (params: IntercomReplyConversationParams) => {
|
||||
const reply: any = {
|
||||
message_type: params.message_type,
|
||||
type: 'admin',
|
||||
body: params.body,
|
||||
}
|
||||
|
||||
if (params.admin_id) reply.admin_id = params.admin_id
|
||||
|
||||
if (params.attachment_urls) {
|
||||
reply.attachment_urls = params.attachment_urls
|
||||
.split(',')
|
||||
.map((url) => url.trim())
|
||||
.slice(0, 10)
|
||||
}
|
||||
|
||||
if (params.created_at) reply.created_at = params.created_at
|
||||
|
||||
return reply
|
||||
},
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomReplyConversationParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomReplyConversationTool: ToolConfig<
|
||||
IntercomReplyConversationParams,
|
||||
IntercomReplyConversationResponse
|
||||
> = {
|
||||
id: 'intercom_reply_conversation',
|
||||
name: 'Reply to Conversation in Intercom',
|
||||
description: 'Reply to a conversation as an admin in Intercom',
|
||||
version: '1.0.0',
|
||||
|
||||
...replyConversationBase,
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'reply_conversation')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
conversation: data,
|
||||
metadata: {
|
||||
operation: 'reply_conversation' as const,
|
||||
conversationId: data.id,
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
conversation: {
|
||||
type: 'object',
|
||||
description: 'Updated conversation object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the conversation' },
|
||||
type: { type: 'string', description: 'Object type (conversation)' },
|
||||
title: { type: 'string', description: 'Title of the conversation', optional: true },
|
||||
created_at: { type: 'number', description: 'Unix timestamp when conversation was created' },
|
||||
updated_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when conversation was last updated',
|
||||
},
|
||||
waiting_since: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when waiting for reply',
|
||||
optional: true,
|
||||
},
|
||||
open: { type: 'boolean', description: 'Whether the conversation is open' },
|
||||
state: { type: 'string', description: 'State of the conversation' },
|
||||
read: { type: 'boolean', description: 'Whether the conversation has been read' },
|
||||
priority: { type: 'string', description: 'Priority of the conversation' },
|
||||
admin_assignee_id: { type: 'number', description: 'ID of assigned admin', optional: true },
|
||||
team_assignee_id: { type: 'string', description: 'ID of assigned team', optional: true },
|
||||
tags: { type: 'object', description: 'Tags on the conversation' },
|
||||
source: { type: 'object', description: 'Source of the conversation' },
|
||||
contacts: { type: 'object', description: 'Contacts in the conversation' },
|
||||
conversation_parts: { type: 'object', description: 'Parts of the conversation' },
|
||||
},
|
||||
},
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Operation metadata',
|
||||
properties: {
|
||||
operation: { type: 'string', description: 'The operation performed (reply_conversation)' },
|
||||
conversationId: { type: 'string', description: 'ID of the conversation' },
|
||||
},
|
||||
},
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
|
||||
interface IntercomReplyConversationV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
conversation: any
|
||||
conversationId: string
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
export const intercomReplyConversationV2Tool: ToolConfig<
|
||||
IntercomReplyConversationParams,
|
||||
IntercomReplyConversationV2Response
|
||||
> = {
|
||||
...replyConversationBase,
|
||||
id: 'intercom_reply_conversation_v2',
|
||||
name: 'Reply to Conversation in Intercom',
|
||||
description: 'Reply to a conversation as an admin in Intercom',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'reply_conversation')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
conversation: data,
|
||||
conversationId: data.id,
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
conversation: {
|
||||
type: 'object',
|
||||
description: 'Updated conversation object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the conversation' },
|
||||
type: { type: 'string', description: 'Object type (conversation)' },
|
||||
title: { type: 'string', description: 'Title of the conversation', optional: true },
|
||||
created_at: { type: 'number', description: 'Unix timestamp when conversation was created' },
|
||||
updated_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when conversation was last updated',
|
||||
},
|
||||
waiting_since: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when waiting for reply',
|
||||
optional: true,
|
||||
},
|
||||
open: { type: 'boolean', description: 'Whether the conversation is open' },
|
||||
state: { type: 'string', description: 'State of the conversation' },
|
||||
read: { type: 'boolean', description: 'Whether the conversation has been read' },
|
||||
priority: { type: 'string', description: 'Priority of the conversation' },
|
||||
admin_assignee_id: { type: 'number', description: 'ID of assigned admin', optional: true },
|
||||
team_assignee_id: { type: 'string', description: 'ID of assigned team', optional: true },
|
||||
tags: { type: 'object', description: 'Tags on the conversation' },
|
||||
source: { type: 'object', description: 'Source of the conversation' },
|
||||
contacts: { type: 'object', description: 'Contacts in the conversation' },
|
||||
conversation_parts: { type: 'object', description: 'Parts of the conversation' },
|
||||
},
|
||||
},
|
||||
conversationId: { type: 'string', description: 'ID of the conversation' },
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,425 @@
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface IntercomSearchContactsParams {
|
||||
accessToken: string
|
||||
query: string
|
||||
per_page?: number
|
||||
starting_after?: string
|
||||
sort_field?: string
|
||||
sort_order?: 'ascending' | 'descending'
|
||||
}
|
||||
|
||||
export interface IntercomSearchContactsResponse {
|
||||
success: boolean
|
||||
output: {
|
||||
contacts: Array<{
|
||||
id: string
|
||||
type: string
|
||||
role: string
|
||||
email: string | null
|
||||
phone: string | null
|
||||
name: string | null
|
||||
avatar: string | null
|
||||
owner_id: string | null
|
||||
external_id: string | null
|
||||
created_at: number
|
||||
updated_at: number
|
||||
signed_up_at: number | null
|
||||
last_seen_at: number | null
|
||||
workspace_id: string
|
||||
custom_attributes: Record<string, any>
|
||||
tags: {
|
||||
type: string
|
||||
url: string
|
||||
data: any[]
|
||||
has_more: boolean
|
||||
total_count: number
|
||||
}
|
||||
notes: {
|
||||
type: string
|
||||
url: string
|
||||
data: any[]
|
||||
has_more: boolean
|
||||
total_count: number
|
||||
}
|
||||
companies: {
|
||||
type: string
|
||||
url: string
|
||||
data: any[]
|
||||
has_more: boolean
|
||||
total_count: number
|
||||
}
|
||||
location: {
|
||||
type: string
|
||||
city: string | null
|
||||
region: string | null
|
||||
country: string | null
|
||||
country_code: string | null
|
||||
continent_code: string | null
|
||||
}
|
||||
social_profiles: {
|
||||
type: string
|
||||
data: any[]
|
||||
}
|
||||
unsubscribed_from_emails: boolean
|
||||
[key: string]: any
|
||||
}>
|
||||
pages: {
|
||||
type: string
|
||||
page: number
|
||||
per_page: number
|
||||
total_pages: number
|
||||
}
|
||||
metadata: {
|
||||
operation: 'search_contacts'
|
||||
total_count: number
|
||||
}
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
const searchContactsBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
query: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Search query (e.g., {"field":"email","operator":"=","value":"user@example.com"})',
|
||||
},
|
||||
per_page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of results per page (max: 150)',
|
||||
},
|
||||
starting_after: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Cursor for pagination',
|
||||
},
|
||||
sort_field: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Field to sort by (e.g., "name", "created_at", "last_seen_at")',
|
||||
},
|
||||
sort_order: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Sort order: "ascending" or "descending"',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: () => buildIntercomUrl('/contacts/search'),
|
||||
method: 'POST',
|
||||
headers: (params: IntercomSearchContactsParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
body: (params: IntercomSearchContactsParams) => {
|
||||
let query
|
||||
try {
|
||||
query = JSON.parse(params.query)
|
||||
} catch (error) {
|
||||
// If not JSON, treat as simple text search
|
||||
query = {
|
||||
field: 'name',
|
||||
operator: '~',
|
||||
value: params.query,
|
||||
}
|
||||
}
|
||||
|
||||
const body: any = { query }
|
||||
|
||||
if (params.per_page) body.pagination = { per_page: params.per_page }
|
||||
if (params.starting_after)
|
||||
body.pagination = { ...body.pagination, starting_after: params.starting_after }
|
||||
|
||||
if (params.sort_field) {
|
||||
body.sort = {
|
||||
field: params.sort_field,
|
||||
order: params.sort_order || 'descending',
|
||||
}
|
||||
}
|
||||
|
||||
return body
|
||||
},
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomSearchContactsParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomSearchContactsTool: ToolConfig<
|
||||
IntercomSearchContactsParams,
|
||||
IntercomSearchContactsResponse
|
||||
> = {
|
||||
id: 'intercom_search_contacts',
|
||||
name: 'Search Contacts in Intercom',
|
||||
description: 'Search for contacts in Intercom using a query',
|
||||
version: '1.0.0',
|
||||
|
||||
...searchContactsBase,
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'search_contacts')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
contacts: data.data || [],
|
||||
pages: data.pages,
|
||||
metadata: {
|
||||
operation: 'search_contacts' as const,
|
||||
total_count: data.total_count,
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
contacts: {
|
||||
type: 'array',
|
||||
description: 'Array of matching contact objects',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the contact' },
|
||||
type: { type: 'string', description: 'Object type (contact)' },
|
||||
role: { type: 'string', description: 'Role of the contact (user or lead)' },
|
||||
email: { type: 'string', description: 'Email address of the contact' },
|
||||
phone: { type: 'string', description: 'Phone number of the contact' },
|
||||
name: { type: 'string', description: 'Name of the contact' },
|
||||
avatar: { type: 'string', description: 'Avatar URL of the contact' },
|
||||
owner_id: { type: 'string', description: 'ID of the admin assigned to this contact' },
|
||||
external_id: { type: 'string', description: 'External identifier for the contact' },
|
||||
created_at: { type: 'number', description: 'Unix timestamp when contact was created' },
|
||||
updated_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when contact was last updated',
|
||||
},
|
||||
signed_up_at: { type: 'number', description: 'Unix timestamp when user signed up' },
|
||||
last_seen_at: { type: 'number', description: 'Unix timestamp when user was last seen' },
|
||||
workspace_id: { type: 'string', description: 'Workspace ID the contact belongs to' },
|
||||
custom_attributes: {
|
||||
type: 'object',
|
||||
description: 'Custom attributes set on the contact',
|
||||
},
|
||||
tags: { type: 'object', description: 'Tags associated with the contact' },
|
||||
notes: { type: 'object', description: 'Notes associated with the contact' },
|
||||
companies: { type: 'object', description: 'Companies associated with the contact' },
|
||||
location: { type: 'object', description: 'Location information for the contact' },
|
||||
social_profiles: { type: 'object', description: 'Social profiles of the contact' },
|
||||
unsubscribed_from_emails: {
|
||||
type: 'boolean',
|
||||
description: 'Whether contact is unsubscribed from emails',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
pages: {
|
||||
type: 'object',
|
||||
description: 'Pagination information',
|
||||
properties: {
|
||||
type: { type: 'string', description: 'Pages type identifier' },
|
||||
page: { type: 'number', description: 'Current page number' },
|
||||
per_page: { type: 'number', description: 'Number of results per page' },
|
||||
total_pages: { type: 'number', description: 'Total number of pages' },
|
||||
},
|
||||
},
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Operation metadata',
|
||||
properties: {
|
||||
operation: { type: 'string', description: 'The operation performed (search_contacts)' },
|
||||
total_count: { type: 'number', description: 'Total number of matching contacts' },
|
||||
},
|
||||
},
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
|
||||
interface IntercomSearchContactsV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
contacts: Array<{
|
||||
id: string
|
||||
type: string
|
||||
role: string
|
||||
email: string | null
|
||||
phone: string | null
|
||||
name: string | null
|
||||
avatar: string | null
|
||||
owner_id: string | null
|
||||
external_id: string | null
|
||||
created_at: number
|
||||
updated_at: number
|
||||
signed_up_at: number | null
|
||||
last_seen_at: number | null
|
||||
workspace_id: string
|
||||
custom_attributes: Record<string, any>
|
||||
tags: {
|
||||
type: string
|
||||
url: string
|
||||
data: any[]
|
||||
has_more: boolean
|
||||
total_count: number
|
||||
}
|
||||
notes: {
|
||||
type: string
|
||||
url: string
|
||||
data: any[]
|
||||
has_more: boolean
|
||||
total_count: number
|
||||
}
|
||||
companies: {
|
||||
type: string
|
||||
url: string
|
||||
data: any[]
|
||||
has_more: boolean
|
||||
total_count: number
|
||||
}
|
||||
location: {
|
||||
type: string
|
||||
city: string | null
|
||||
region: string | null
|
||||
country: string | null
|
||||
country_code: string | null
|
||||
continent_code: string | null
|
||||
}
|
||||
social_profiles: {
|
||||
type: string
|
||||
data: any[]
|
||||
}
|
||||
unsubscribed_from_emails: boolean
|
||||
[key: string]: any
|
||||
}>
|
||||
pages: {
|
||||
type: string
|
||||
page: number
|
||||
per_page: number
|
||||
total_pages: number
|
||||
}
|
||||
total_count: number
|
||||
}
|
||||
}
|
||||
|
||||
export const intercomSearchContactsV2Tool: ToolConfig<
|
||||
IntercomSearchContactsParams,
|
||||
IntercomSearchContactsV2Response
|
||||
> = {
|
||||
...searchContactsBase,
|
||||
id: 'intercom_search_contacts_v2',
|
||||
name: 'Search Contacts in Intercom',
|
||||
description: 'Search for contacts in Intercom using a query',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'search_contacts')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
contacts: data.data ?? null,
|
||||
pages: data.pages ?? null,
|
||||
total_count: data.total_count ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
contacts: {
|
||||
type: 'array',
|
||||
description: 'Array of matching contact objects',
|
||||
optional: true,
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the contact' },
|
||||
type: { type: 'string', description: 'Object type (contact)' },
|
||||
role: { type: 'string', description: 'Role of the contact (user or lead)' },
|
||||
email: { type: 'string', description: 'Email address of the contact', optional: true },
|
||||
phone: { type: 'string', description: 'Phone number of the contact', optional: true },
|
||||
name: { type: 'string', description: 'Name of the contact', optional: true },
|
||||
avatar: { type: 'string', description: 'Avatar URL of the contact', optional: true },
|
||||
owner_id: {
|
||||
type: 'string',
|
||||
description: 'ID of the admin assigned to this contact',
|
||||
optional: true,
|
||||
},
|
||||
external_id: {
|
||||
type: 'string',
|
||||
description: 'External identifier for the contact',
|
||||
optional: true,
|
||||
},
|
||||
created_at: { type: 'number', description: 'Unix timestamp when contact was created' },
|
||||
updated_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when contact was last updated',
|
||||
},
|
||||
signed_up_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when user signed up',
|
||||
optional: true,
|
||||
},
|
||||
last_seen_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when user was last seen',
|
||||
optional: true,
|
||||
},
|
||||
workspace_id: { type: 'string', description: 'Workspace ID the contact belongs to' },
|
||||
custom_attributes: {
|
||||
type: 'object',
|
||||
description: 'Custom attributes set on the contact',
|
||||
},
|
||||
tags: { type: 'object', description: 'Tags associated with the contact', optional: true },
|
||||
notes: { type: 'object', description: 'Notes associated with the contact' },
|
||||
companies: { type: 'object', description: 'Companies associated with the contact' },
|
||||
location: { type: 'object', description: 'Location information for the contact' },
|
||||
social_profiles: { type: 'object', description: 'Social profiles of the contact' },
|
||||
unsubscribed_from_emails: {
|
||||
type: 'boolean',
|
||||
description: 'Whether contact is unsubscribed from emails',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
pages: {
|
||||
type: 'object',
|
||||
description: 'Pagination information',
|
||||
optional: true,
|
||||
properties: {
|
||||
type: { type: 'string', description: 'Pages type identifier' },
|
||||
page: { type: 'number', description: 'Current page number' },
|
||||
per_page: { type: 'number', description: 'Number of results per page' },
|
||||
total_pages: { type: 'number', description: 'Total number of pages' },
|
||||
},
|
||||
},
|
||||
total_count: {
|
||||
type: 'number',
|
||||
description: 'Total number of matching contacts',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,295 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('IntercomSearchConversations')
|
||||
|
||||
export interface IntercomSearchConversationsParams {
|
||||
accessToken: string
|
||||
query: string
|
||||
per_page?: number
|
||||
starting_after?: string
|
||||
sort_field?: string
|
||||
sort_order?: 'ascending' | 'descending'
|
||||
}
|
||||
|
||||
export interface IntercomSearchConversationsResponse {
|
||||
success: boolean
|
||||
output: {
|
||||
conversations: any[]
|
||||
pages?: any
|
||||
metadata: {
|
||||
operation: 'search_conversations'
|
||||
total_count?: number
|
||||
}
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
export interface IntercomSearchConversationsV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
conversations: any[]
|
||||
pages?: any
|
||||
total_count?: number
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
const searchConversationsBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
query: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Search query as JSON object',
|
||||
},
|
||||
per_page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of results per page (max: 150)',
|
||||
},
|
||||
starting_after: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Cursor for pagination',
|
||||
},
|
||||
sort_field: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Field to sort by (e.g., "created_at", "updated_at")',
|
||||
},
|
||||
sort_order: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Sort order: "ascending" or "descending"',
|
||||
},
|
||||
},
|
||||
request: {
|
||||
url: () => buildIntercomUrl('/conversations/search'),
|
||||
method: 'POST',
|
||||
headers: (params: IntercomSearchConversationsParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
body: (params: IntercomSearchConversationsParams) => {
|
||||
let query
|
||||
try {
|
||||
query = JSON.parse(params.query)
|
||||
} catch (error) {
|
||||
logger.warn('Failed to parse search query, using default', { error })
|
||||
query = {
|
||||
field: 'updated_at',
|
||||
operator: '>',
|
||||
value: Math.floor(Date.now() / 1000) - 86400, // Last 24 hours
|
||||
}
|
||||
}
|
||||
|
||||
const body: any = { query }
|
||||
|
||||
if (params.per_page) body.pagination = { per_page: params.per_page }
|
||||
if (params.starting_after)
|
||||
body.pagination = { ...body.pagination, starting_after: params.starting_after }
|
||||
|
||||
if (params.sort_field) {
|
||||
body.sort = {
|
||||
field: params.sort_field,
|
||||
order: params.sort_order || 'descending',
|
||||
}
|
||||
}
|
||||
|
||||
return body
|
||||
},
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomSearchConversationsParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomSearchConversationsTool: ToolConfig<
|
||||
IntercomSearchConversationsParams,
|
||||
IntercomSearchConversationsResponse
|
||||
> = {
|
||||
id: 'intercom_search_conversations',
|
||||
name: 'Search Conversations in Intercom',
|
||||
description: 'Search for conversations in Intercom using a query',
|
||||
version: '1.0.0',
|
||||
|
||||
...searchConversationsBase,
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'search_conversations')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
conversations: data.conversations || [],
|
||||
pages: data.pages,
|
||||
metadata: {
|
||||
operation: 'search_conversations' as const,
|
||||
total_count: data.total_count,
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
conversations: {
|
||||
type: 'array',
|
||||
description: 'Array of matching conversation objects',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the conversation' },
|
||||
type: { type: 'string', description: 'Object type (conversation)' },
|
||||
title: { type: 'string', description: 'Title of the conversation' },
|
||||
created_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when conversation was created',
|
||||
},
|
||||
updated_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when conversation was last updated',
|
||||
},
|
||||
waiting_since: { type: 'number', description: 'Unix timestamp when waiting for reply' },
|
||||
open: { type: 'boolean', description: 'Whether the conversation is open' },
|
||||
state: { type: 'string', description: 'State of the conversation' },
|
||||
read: { type: 'boolean', description: 'Whether the conversation has been read' },
|
||||
priority: { type: 'string', description: 'Priority of the conversation' },
|
||||
admin_assignee_id: { type: 'number', description: 'ID of assigned admin' },
|
||||
team_assignee_id: { type: 'string', description: 'ID of assigned team' },
|
||||
tags: { type: 'object', description: 'Tags on the conversation' },
|
||||
source: { type: 'object', description: 'Source of the conversation' },
|
||||
contacts: { type: 'object', description: 'Contacts in the conversation' },
|
||||
},
|
||||
},
|
||||
},
|
||||
pages: {
|
||||
type: 'object',
|
||||
description: 'Pagination information',
|
||||
properties: {
|
||||
type: { type: 'string', description: 'Pages type identifier' },
|
||||
page: { type: 'number', description: 'Current page number' },
|
||||
per_page: { type: 'number', description: 'Number of results per page' },
|
||||
total_pages: { type: 'number', description: 'Total number of pages' },
|
||||
},
|
||||
},
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Operation metadata',
|
||||
properties: {
|
||||
operation: {
|
||||
type: 'string',
|
||||
description: 'The operation performed (search_conversations)',
|
||||
},
|
||||
total_count: { type: 'number', description: 'Total number of matching conversations' },
|
||||
},
|
||||
},
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
|
||||
export const intercomSearchConversationsV2Tool: ToolConfig<
|
||||
IntercomSearchConversationsParams,
|
||||
IntercomSearchConversationsV2Response
|
||||
> = {
|
||||
...searchConversationsBase,
|
||||
id: 'intercom_search_conversations_v2',
|
||||
name: 'Search Conversations in Intercom',
|
||||
description:
|
||||
'Search for conversations in Intercom using a query. Returns API-aligned fields only.',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'search_conversations')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
conversations: data.conversations ?? null,
|
||||
pages: data.pages ?? null,
|
||||
total_count: data.total_count ?? null,
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
conversations: {
|
||||
type: 'array',
|
||||
description: 'Array of matching conversation objects',
|
||||
optional: true,
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the conversation' },
|
||||
type: { type: 'string', description: 'Object type (conversation)' },
|
||||
title: { type: 'string', description: 'Title of the conversation', optional: true },
|
||||
created_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when conversation was created',
|
||||
},
|
||||
updated_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when conversation was last updated',
|
||||
},
|
||||
waiting_since: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when waiting for reply',
|
||||
optional: true,
|
||||
},
|
||||
open: { type: 'boolean', description: 'Whether the conversation is open' },
|
||||
state: { type: 'string', description: 'State of the conversation' },
|
||||
read: { type: 'boolean', description: 'Whether the conversation has been read' },
|
||||
priority: { type: 'string', description: 'Priority of the conversation' },
|
||||
admin_assignee_id: {
|
||||
type: 'number',
|
||||
description: 'ID of assigned admin',
|
||||
optional: true,
|
||||
},
|
||||
team_assignee_id: { type: 'string', description: 'ID of assigned team', optional: true },
|
||||
tags: { type: 'object', description: 'Tags on the conversation' },
|
||||
source: { type: 'object', description: 'Source of the conversation' },
|
||||
contacts: { type: 'object', description: 'Contacts in the conversation' },
|
||||
},
|
||||
},
|
||||
},
|
||||
pages: {
|
||||
type: 'object',
|
||||
description: 'Pagination information',
|
||||
optional: true,
|
||||
properties: {
|
||||
type: { type: 'string', description: 'Pages type identifier' },
|
||||
page: { type: 'number', description: 'Current page number' },
|
||||
per_page: { type: 'number', description: 'Number of results per page' },
|
||||
total_pages: { type: 'number', description: 'Total number of pages' },
|
||||
},
|
||||
},
|
||||
total_count: {
|
||||
type: 'number',
|
||||
description: 'Total number of matching conversations',
|
||||
optional: true,
|
||||
},
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface IntercomSnoozeConversationParams {
|
||||
accessToken: string
|
||||
conversationId: string
|
||||
admin_id: string
|
||||
snoozed_until: number
|
||||
}
|
||||
|
||||
export interface IntercomSnoozeConversationV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
conversation: any
|
||||
conversationId: string
|
||||
state: string
|
||||
snoozed_until: number | null
|
||||
}
|
||||
}
|
||||
|
||||
const snoozeConversationBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
conversationId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the conversation to snooze',
|
||||
},
|
||||
admin_id: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the admin performing the action',
|
||||
},
|
||||
snoozed_until: {
|
||||
type: 'number',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Unix timestamp for when the conversation should reopen',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: IntercomSnoozeConversationParams) =>
|
||||
buildIntercomUrl(`/conversations/${params.conversationId}/reply`),
|
||||
method: 'POST',
|
||||
headers: (params: IntercomSnoozeConversationParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
body: (params: IntercomSnoozeConversationParams) => ({
|
||||
message_type: 'snoozed',
|
||||
admin_id: params.admin_id,
|
||||
snoozed_until: params.snoozed_until,
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomSnoozeConversationParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomSnoozeConversationV2Tool: ToolConfig<
|
||||
IntercomSnoozeConversationParams,
|
||||
IntercomSnoozeConversationV2Response
|
||||
> = {
|
||||
...snoozeConversationBase,
|
||||
id: 'intercom_snooze_conversation_v2',
|
||||
name: 'Snooze Conversation in Intercom',
|
||||
description: 'Snooze a conversation to reopen at a future time',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'snooze_conversation')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
conversation: data,
|
||||
conversationId: data.id,
|
||||
state: data.state ?? 'snoozed',
|
||||
snoozed_until: data.snoozed_until ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
conversation: {
|
||||
type: 'object',
|
||||
description: 'The snoozed conversation object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the conversation' },
|
||||
type: { type: 'string', description: 'Object type (conversation)' },
|
||||
state: { type: 'string', description: 'State of the conversation (snoozed)' },
|
||||
open: { type: 'boolean', description: 'Whether the conversation is open' },
|
||||
snoozed_until: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when conversation will reopen',
|
||||
optional: true,
|
||||
},
|
||||
created_at: { type: 'number', description: 'Unix timestamp when conversation was created' },
|
||||
updated_at: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when conversation was last updated',
|
||||
},
|
||||
},
|
||||
},
|
||||
conversationId: { type: 'string', description: 'ID of the snoozed conversation' },
|
||||
state: { type: 'string', description: 'State of the conversation (snoozed)' },
|
||||
snoozed_until: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when conversation will reopen',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface IntercomTagContactParams {
|
||||
accessToken: string
|
||||
contactId: string
|
||||
tagId: string
|
||||
}
|
||||
|
||||
export interface IntercomTagContactV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
id: string
|
||||
name: string
|
||||
type: string
|
||||
}
|
||||
}
|
||||
|
||||
const tagContactBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
contactId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the contact to tag',
|
||||
},
|
||||
tagId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the tag to apply',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: IntercomTagContactParams) =>
|
||||
buildIntercomUrl(`/contacts/${params.contactId}/tags`),
|
||||
method: 'POST',
|
||||
headers: (params: IntercomTagContactParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
body: (params: IntercomTagContactParams) => ({
|
||||
id: params.tagId,
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomTagContactParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomTagContactV2Tool: ToolConfig<
|
||||
IntercomTagContactParams,
|
||||
IntercomTagContactV2Response
|
||||
> = {
|
||||
...tagContactBase,
|
||||
id: 'intercom_tag_contact_v2',
|
||||
name: 'Tag Contact in Intercom',
|
||||
description: 'Add a tag to a specific contact',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'tag_contact')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
type: data.type ?? 'tag',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Unique identifier for the tag' },
|
||||
name: { type: 'string', description: 'Name of the tag' },
|
||||
type: { type: 'string', description: 'Object type (tag)' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface IntercomTagConversationParams {
|
||||
accessToken: string
|
||||
conversationId: string
|
||||
tagId: string
|
||||
admin_id: string
|
||||
}
|
||||
|
||||
export interface IntercomTagConversationV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
id: string
|
||||
name: string
|
||||
type: string
|
||||
}
|
||||
}
|
||||
|
||||
const tagConversationBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
conversationId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the conversation to tag',
|
||||
},
|
||||
tagId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the tag to apply',
|
||||
},
|
||||
admin_id: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the admin applying the tag',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: IntercomTagConversationParams) =>
|
||||
buildIntercomUrl(`/conversations/${params.conversationId}/tags`),
|
||||
method: 'POST',
|
||||
headers: (params: IntercomTagConversationParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
body: (params: IntercomTagConversationParams) => ({
|
||||
id: params.tagId,
|
||||
admin_id: params.admin_id,
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomTagConversationParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomTagConversationV2Tool: ToolConfig<
|
||||
IntercomTagConversationParams,
|
||||
IntercomTagConversationV2Response
|
||||
> = {
|
||||
...tagConversationBase,
|
||||
id: 'intercom_tag_conversation_v2',
|
||||
name: 'Tag Conversation in Intercom',
|
||||
description: 'Add a tag to a specific conversation',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'tag_conversation')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
type: data.type ?? 'tag',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Unique identifier for the tag' },
|
||||
name: { type: 'string', description: 'Name of the tag' },
|
||||
type: { type: 'string', description: 'Object type (tag)' },
|
||||
},
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,87 @@
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export interface IntercomUntagContactParams {
|
||||
accessToken: string
|
||||
contactId: string
|
||||
tagId: string
|
||||
}
|
||||
|
||||
export interface IntercomUntagContactV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
id: string
|
||||
name: string
|
||||
type: string
|
||||
}
|
||||
}
|
||||
|
||||
const untagContactBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
contactId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the contact to untag',
|
||||
},
|
||||
tagId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the tag to remove',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: IntercomUntagContactParams) =>
|
||||
buildIntercomUrl(`/contacts/${params.contactId}/tags/${params.tagId}`),
|
||||
method: 'DELETE',
|
||||
headers: (params: IntercomUntagContactParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomUntagContactParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomUntagContactV2Tool: ToolConfig<
|
||||
IntercomUntagContactParams,
|
||||
IntercomUntagContactV2Response
|
||||
> = {
|
||||
...untagContactBase,
|
||||
id: 'intercom_untag_contact_v2',
|
||||
name: 'Untag Contact in Intercom',
|
||||
description: 'Remove a tag from a specific contact',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'untag_contact')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
type: data.type ?? 'tag',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Unique identifier for the tag that was removed' },
|
||||
name: { type: 'string', description: 'Name of the tag that was removed' },
|
||||
type: { type: 'string', description: 'Object type (tag)' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,317 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('IntercomUpdateContact')
|
||||
|
||||
export interface IntercomUpdateContactParams {
|
||||
accessToken: string
|
||||
contactId: string
|
||||
role?: 'user' | 'lead'
|
||||
external_id?: string
|
||||
email?: string
|
||||
phone?: string
|
||||
name?: string
|
||||
avatar?: string
|
||||
signed_up_at?: number
|
||||
last_seen_at?: number
|
||||
owner_id?: string
|
||||
unsubscribed_from_emails?: boolean
|
||||
custom_attributes?: string
|
||||
company_id?: string
|
||||
}
|
||||
|
||||
export interface IntercomUpdateContactResponse {
|
||||
success: boolean
|
||||
output: {
|
||||
contact: any
|
||||
metadata: {
|
||||
operation: 'update_contact'
|
||||
contactId: string
|
||||
}
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
const intercomUpdateContactBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
contactId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Contact ID to update',
|
||||
},
|
||||
role: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: "The role of the contact. Accepts 'user' or 'lead'.",
|
||||
},
|
||||
external_id: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'A unique identifier for the contact provided by the client',
|
||||
},
|
||||
email: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: "The contact's email address",
|
||||
},
|
||||
phone: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: "The contact's phone number",
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: "The contact's name",
|
||||
},
|
||||
avatar: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'An avatar image URL for the contact',
|
||||
},
|
||||
signed_up_at: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The time the user signed up as a Unix timestamp',
|
||||
},
|
||||
last_seen_at: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The time the user was last seen as a Unix timestamp',
|
||||
},
|
||||
owner_id: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The id of an admin that has been assigned account ownership of the contact',
|
||||
},
|
||||
unsubscribed_from_emails: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Whether the contact is unsubscribed from emails',
|
||||
},
|
||||
custom_attributes: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Custom attributes as JSON object (e.g., {"attribute_name": "value"})',
|
||||
},
|
||||
company_id: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Company ID to associate the contact with',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => buildIntercomUrl(`/contacts/${params.contactId}`),
|
||||
method: 'PUT',
|
||||
headers: (params) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
body: (params) => {
|
||||
const contact: any = {}
|
||||
|
||||
if (params.role) contact.role = params.role
|
||||
if (params.external_id) contact.external_id = params.external_id
|
||||
if (params.email) contact.email = params.email
|
||||
if (params.phone) contact.phone = params.phone
|
||||
if (params.name) contact.name = params.name
|
||||
if (params.avatar) contact.avatar = params.avatar
|
||||
if (params.signed_up_at) contact.signed_up_at = params.signed_up_at
|
||||
if (params.last_seen_at) contact.last_seen_at = params.last_seen_at
|
||||
if (params.owner_id) contact.owner_id = params.owner_id
|
||||
if (params.unsubscribed_from_emails !== undefined)
|
||||
contact.unsubscribed_from_emails = params.unsubscribed_from_emails
|
||||
|
||||
if (params.custom_attributes) {
|
||||
try {
|
||||
contact.custom_attributes = JSON.parse(params.custom_attributes)
|
||||
} catch (error) {
|
||||
logger.warn('Failed to parse custom attributes', { error })
|
||||
}
|
||||
}
|
||||
|
||||
if (params.company_id) contact.company_id = params.company_id
|
||||
|
||||
return contact
|
||||
},
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomUpdateContactParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomUpdateContactTool: ToolConfig<
|
||||
IntercomUpdateContactParams,
|
||||
IntercomUpdateContactResponse
|
||||
> = {
|
||||
id: 'intercom_update_contact',
|
||||
name: 'Update Contact in Intercom',
|
||||
description: 'Update an existing contact in Intercom',
|
||||
version: '1.0.0',
|
||||
|
||||
...intercomUpdateContactBase,
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'update_contact')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
contact: data,
|
||||
metadata: {
|
||||
operation: 'update_contact' as const,
|
||||
contactId: data.id,
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
contact: {
|
||||
type: 'object',
|
||||
description: 'Updated contact object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the contact' },
|
||||
type: { type: 'string', description: 'Object type (contact)' },
|
||||
role: { type: 'string', description: 'Role of the contact (user or lead)' },
|
||||
email: { type: 'string', description: 'Email address of the contact', optional: true },
|
||||
phone: { type: 'string', description: 'Phone number of the contact', optional: true },
|
||||
name: { type: 'string', description: 'Name of the contact', optional: true },
|
||||
avatar: { type: 'string', description: 'Avatar URL of the contact', optional: true },
|
||||
owner_id: {
|
||||
type: 'string',
|
||||
description: 'ID of the admin assigned to this contact',
|
||||
optional: true,
|
||||
},
|
||||
external_id: {
|
||||
type: 'string',
|
||||
description: 'External identifier for the contact',
|
||||
optional: true,
|
||||
},
|
||||
created_at: { type: 'number', description: 'Unix timestamp when contact was created' },
|
||||
updated_at: { type: 'number', description: 'Unix timestamp when contact was last updated' },
|
||||
workspace_id: { type: 'string', description: 'Workspace ID the contact belongs to' },
|
||||
custom_attributes: { type: 'object', description: 'Custom attributes set on the contact' },
|
||||
tags: { type: 'object', description: 'Tags associated with the contact' },
|
||||
notes: { type: 'object', description: 'Notes associated with the contact' },
|
||||
companies: { type: 'object', description: 'Companies associated with the contact' },
|
||||
location: { type: 'object', description: 'Location information for the contact' },
|
||||
social_profiles: { type: 'object', description: 'Social profiles of the contact' },
|
||||
unsubscribed_from_emails: {
|
||||
type: 'boolean',
|
||||
description: 'Whether contact is unsubscribed from emails',
|
||||
},
|
||||
},
|
||||
},
|
||||
metadata: {
|
||||
type: 'object',
|
||||
description: 'Operation metadata',
|
||||
properties: {
|
||||
operation: { type: 'string', description: 'The operation performed (update_contact)' },
|
||||
contactId: { type: 'string', description: 'ID of the updated contact' },
|
||||
},
|
||||
},
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
}
|
||||
|
||||
interface IntercomUpdateContactV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
contact: any
|
||||
contactId: string
|
||||
}
|
||||
}
|
||||
|
||||
export const intercomUpdateContactV2Tool: ToolConfig<
|
||||
IntercomUpdateContactParams,
|
||||
IntercomUpdateContactV2Response
|
||||
> = {
|
||||
...intercomUpdateContactBase,
|
||||
id: 'intercom_update_contact_v2',
|
||||
name: 'Update Contact in Intercom',
|
||||
description: 'Update an existing contact in Intercom. Returns API-aligned fields only.',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'update_contact')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
contact: data,
|
||||
contactId: data.id,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
contact: {
|
||||
type: 'object',
|
||||
description: 'Updated contact object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the contact' },
|
||||
type: { type: 'string', description: 'Object type (contact)' },
|
||||
role: { type: 'string', description: 'Role of the contact (user or lead)' },
|
||||
email: { type: 'string', description: 'Email address of the contact', optional: true },
|
||||
phone: { type: 'string', description: 'Phone number of the contact', optional: true },
|
||||
name: { type: 'string', description: 'Name of the contact', optional: true },
|
||||
avatar: { type: 'string', description: 'Avatar URL of the contact', optional: true },
|
||||
owner_id: {
|
||||
type: 'string',
|
||||
description: 'ID of the admin assigned to this contact',
|
||||
optional: true,
|
||||
},
|
||||
external_id: {
|
||||
type: 'string',
|
||||
description: 'External identifier for the contact',
|
||||
optional: true,
|
||||
},
|
||||
created_at: { type: 'number', description: 'Unix timestamp when contact was created' },
|
||||
updated_at: { type: 'number', description: 'Unix timestamp when contact was last updated' },
|
||||
workspace_id: { type: 'string', description: 'Workspace ID the contact belongs to' },
|
||||
custom_attributes: { type: 'object', description: 'Custom attributes set on the contact' },
|
||||
tags: { type: 'object', description: 'Tags associated with the contact' },
|
||||
notes: { type: 'object', description: 'Notes associated with the contact' },
|
||||
companies: { type: 'object', description: 'Companies associated with the contact' },
|
||||
location: { type: 'object', description: 'Location information for the contact' },
|
||||
social_profiles: { type: 'object', description: 'Social profiles of the contact' },
|
||||
unsubscribed_from_emails: {
|
||||
type: 'boolean',
|
||||
description: 'Whether contact is unsubscribed from emails',
|
||||
},
|
||||
},
|
||||
},
|
||||
contactId: { type: 'string', description: 'ID of the updated contact' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { buildIntercomUrl, handleIntercomError } from '@/tools/intercom/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('IntercomUpdateTicket')
|
||||
|
||||
export interface IntercomUpdateTicketParams {
|
||||
accessToken: string
|
||||
ticketId: string
|
||||
ticket_attributes?: string
|
||||
open?: boolean
|
||||
is_shared?: boolean
|
||||
snoozed_until?: number
|
||||
admin_id?: string
|
||||
assignee_id?: string
|
||||
}
|
||||
|
||||
export interface IntercomUpdateTicketV2Response {
|
||||
success: boolean
|
||||
output: {
|
||||
ticket: any
|
||||
ticketId: string
|
||||
ticket_state: string
|
||||
}
|
||||
}
|
||||
|
||||
const updateTicketBase = {
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Intercom API access token',
|
||||
},
|
||||
ticketId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the ticket to update',
|
||||
},
|
||||
ticket_attributes: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'JSON object with ticket attributes (e.g., {"_default_title_":"New Title","_default_description_":"Updated description"})',
|
||||
},
|
||||
open: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Set to false to close the ticket, true to keep it open',
|
||||
},
|
||||
is_shared: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Whether the ticket is visible to users',
|
||||
},
|
||||
snoozed_until: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Unix timestamp for when the ticket should reopen',
|
||||
},
|
||||
admin_id: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'The ID of the admin performing the update (needed for workflows and attribution)',
|
||||
},
|
||||
assignee_id: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the admin or team to assign the ticket to. Set to "0" to unassign.',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: IntercomUpdateTicketParams) => buildIntercomUrl(`/tickets/${params.ticketId}`),
|
||||
method: 'PUT',
|
||||
headers: (params: IntercomUpdateTicketParams) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Intercom-Version': '2.14',
|
||||
}),
|
||||
body: (params: IntercomUpdateTicketParams) => {
|
||||
const payload: any = {}
|
||||
|
||||
if (params.ticket_attributes) {
|
||||
try {
|
||||
payload.ticket_attributes = JSON.parse(params.ticket_attributes)
|
||||
} catch (error) {
|
||||
logger.error('Failed to parse ticket_attributes', { error })
|
||||
throw new Error('ticket_attributes must be a valid JSON object')
|
||||
}
|
||||
}
|
||||
|
||||
if (params.open !== undefined) {
|
||||
payload.open = params.open
|
||||
}
|
||||
|
||||
if (params.is_shared !== undefined) {
|
||||
payload.is_shared = params.is_shared
|
||||
}
|
||||
|
||||
if (params.snoozed_until !== undefined) {
|
||||
payload.snoozed_until = params.snoozed_until
|
||||
}
|
||||
|
||||
if (params.admin_id) {
|
||||
payload.admin_id = params.admin_id
|
||||
}
|
||||
|
||||
if (params.assignee_id) {
|
||||
payload.assignee_id = params.assignee_id
|
||||
}
|
||||
|
||||
return payload
|
||||
},
|
||||
},
|
||||
} satisfies Pick<ToolConfig<IntercomUpdateTicketParams, any>, 'params' | 'request'>
|
||||
|
||||
export const intercomUpdateTicketV2Tool: ToolConfig<
|
||||
IntercomUpdateTicketParams,
|
||||
IntercomUpdateTicketV2Response
|
||||
> = {
|
||||
...updateTicketBase,
|
||||
id: 'intercom_update_ticket_v2',
|
||||
name: 'Update Ticket in Intercom',
|
||||
description: 'Update a ticket in Intercom (change state, assignment, attributes)',
|
||||
version: '2.0.0',
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
handleIntercomError(data, response.status, 'update_ticket')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
ticket: {
|
||||
id: data.id,
|
||||
type: data.type ?? 'ticket',
|
||||
ticket_id: data.ticket_id ?? null,
|
||||
ticket_state: data.ticket_state ?? null,
|
||||
ticket_attributes: data.ticket_attributes ?? null,
|
||||
open: data.open ?? null,
|
||||
is_shared: data.is_shared ?? null,
|
||||
snoozed_until: data.snoozed_until ?? null,
|
||||
admin_assignee_id: data.admin_assignee_id ?? null,
|
||||
team_assignee_id: data.team_assignee_id ?? null,
|
||||
created_at: data.created_at ?? null,
|
||||
updated_at: data.updated_at ?? null,
|
||||
},
|
||||
ticketId: data.id,
|
||||
ticket_state: data.ticket_state ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
ticket: {
|
||||
type: 'object',
|
||||
description: 'The updated ticket object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Unique identifier for the ticket' },
|
||||
type: { type: 'string', description: 'Object type (ticket)' },
|
||||
ticket_id: { type: 'string', description: 'Ticket ID shown in Intercom UI' },
|
||||
ticket_state: { type: 'string', description: 'State of the ticket' },
|
||||
ticket_attributes: { type: 'object', description: 'Attributes of the ticket' },
|
||||
open: { type: 'boolean', description: 'Whether the ticket is open' },
|
||||
is_shared: { type: 'boolean', description: 'Whether the ticket is visible to users' },
|
||||
snoozed_until: {
|
||||
type: 'number',
|
||||
description: 'Unix timestamp when ticket will reopen',
|
||||
optional: true,
|
||||
},
|
||||
admin_assignee_id: { type: 'string', description: 'ID of assigned admin', optional: true },
|
||||
team_assignee_id: { type: 'string', description: 'ID of assigned team', optional: true },
|
||||
created_at: { type: 'number', description: 'Unix timestamp when ticket was created' },
|
||||
updated_at: { type: 'number', description: 'Unix timestamp when ticket was last updated' },
|
||||
},
|
||||
},
|
||||
ticketId: { type: 'string', description: 'ID of the updated ticket' },
|
||||
ticket_state: { type: 'string', description: 'Current state of the ticket' },
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user