fix(tools): fixed tool outputs (#2534)

* fixed typeform

* fixed supabase tools

* salesforce fix

* removed comments

* pinecone fix

* fixed intercom

* regex constant

* removed fallback logic
This commit is contained in:
Adam Gough
2025-12-26 12:46:39 -08:00
committed by GitHub
parent 1f0e3f2be6
commit 27ec4120bc
31 changed files with 1362 additions and 230 deletions

View File

@@ -10,6 +10,8 @@ export const dynamic = 'force-dynamic'
const logger = createLogger('OAuthTokenAPI')
const SALESFORCE_INSTANCE_URL_REGEX = /__sf_instance__:([^\s]+)/
const tokenRequestSchema = z.object({
credentialId: z
.string({ required_error: 'Credential ID is required' })
@@ -78,10 +80,20 @@ export async function POST(request: NextRequest) {
try {
// Refresh the token if needed
const { accessToken } = await refreshTokenIfNeeded(requestId, credential, credentialId)
let instanceUrl: string | undefined
if (credential.providerId === 'salesforce' && credential.scope) {
const instanceMatch = credential.scope.match(SALESFORCE_INSTANCE_URL_REGEX)
if (instanceMatch) {
instanceUrl = instanceMatch[1]
}
}
return NextResponse.json(
{
accessToken,
idToken: credential.idToken || undefined,
...(instanceUrl && { instanceUrl }),
},
{ status: 200 }
)
@@ -147,10 +159,21 @@ export async function GET(request: NextRequest) {
try {
const { accessToken } = await refreshTokenIfNeeded(requestId, credential, credentialId)
// For Salesforce, extract instanceUrl from the scope field
let instanceUrl: string | undefined
if (credential.providerId === 'salesforce' && credential.scope) {
const instanceMatch = credential.scope.match(SALESFORCE_INSTANCE_URL_REGEX)
if (instanceMatch) {
instanceUrl = instanceMatch[1]
}
}
return NextResponse.json(
{
accessToken,
idToken: credential.idToken || undefined,
...(instanceUrl && { instanceUrl }),
},
{ status: 200 }
)

View File

@@ -264,7 +264,7 @@ export const PineconeBlock: BlockConfig<PineconeResponse> = {
outputs: {
matches: { type: 'json', description: 'Search matches' },
upsertedCount: { type: 'number', description: 'Upserted count' },
statusText: { type: 'string', description: 'Status of the upsert operation' },
data: { type: 'json', description: 'Response data' },
model: { type: 'string', description: 'Model information' },
vector_type: { type: 'string', description: 'Vector type' },

View File

@@ -596,13 +596,20 @@ Return ONLY the PostgREST filter expression - no explanations, no markdown, no e
},
// Storage Upload fields
{
id: 'path',
title: 'File Path',
id: 'fileName',
title: 'File Name',
type: 'short-input',
placeholder: 'folder/file.jpg',
placeholder: 'myfile.pdf',
condition: { field: 'operation', value: 'storage_upload' },
required: true,
},
{
id: 'path',
title: 'Folder Path (optional)',
type: 'short-input',
placeholder: 'folder/subfolder/',
condition: { field: 'operation', value: 'storage_upload' },
},
{
id: 'fileContent',
title: 'File Content',
@@ -1065,10 +1072,10 @@ Return ONLY the PostgREST filter expression - no explanations, no markdown, no e
countType: { type: 'string', description: 'Count type: exact, planned, or estimated' },
// Storage operation inputs
bucket: { type: 'string', description: 'Storage bucket name' },
path: { type: 'string', description: 'File path in storage' },
path: { type: 'string', description: 'File or folder path in storage' },
fileContent: { type: 'string', description: 'File content (base64 for binary)' },
contentType: { type: 'string', description: 'MIME type of the file' },
fileName: { type: 'string', description: 'Optional filename override for downloaded file' },
fileName: { type: 'string', description: 'File name for upload or download override' },
upsert: { type: 'boolean', description: 'Whether to overwrite existing file' },
download: { type: 'boolean', description: 'Whether to force download' },
paths: { type: 'array', description: 'Array of file paths' },

View File

@@ -199,10 +199,76 @@ export const TypeformBlock: BlockConfig<TypeformResponse> = {
{
id: 'operations',
title: 'JSON Patch Operations',
type: 'long-input',
placeholder: 'JSON array of patch operations (RFC 6902)',
type: 'code',
language: 'json',
placeholder: '[{"op": "replace", "path": "/title", "value": "New Title"}]',
condition: { field: 'operation', value: 'typeform_update_form' },
required: true,
wandConfig: {
enabled: true,
maintainHistory: true,
prompt: `You are an expert at creating JSON Patch operations (RFC 6902) for Typeform forms.
Generate ONLY the JSON array of patch operations based on the user's request.
The output MUST be a valid JSON array, starting with [ and ending with ].
Current operations: {context}
### JSON PATCH OPERATIONS
Each operation is an object with:
- "op": The operation type ("add", "remove", "replace", "move", "copy", "test")
- "path": JSON pointer to the target location (e.g., "/title", "/fields/0", "/settings/language")
- "value": The new value (required for "add", "replace", "copy", "test")
- "from": Source path (required for "move" and "copy")
### COMMON TYPEFORM PATHS
- /title - Form title
- /settings/language - Form language (e.g., "en", "es", "fr")
- /settings/is_public - Whether form is public (true/false)
- /settings/show_progress_bar - Show progress bar (true/false)
- /fields - Array of form fields
- /fields/- - Add to end of fields array
- /fields/0 - First field
- /welcome_screens - Array of welcome screens
- /thankyou_screens - Array of thank you screens
- /theme/href - Theme URL reference
### FIELD OBJECT STRUCTURE
{
"type": "short_text" | "long_text" | "email" | "number" | "multiple_choice" | "yes_no" | "rating" | "date" | "dropdown" | "file_upload",
"title": "Question text",
"ref": "unique_reference_id",
"properties": { ... },
"validations": { "required": true/false }
}
### EXAMPLES
**Change form title:**
[{"op": "replace", "path": "/title", "value": "My Updated Form"}]
**Add a new text field:**
[{"op": "add", "path": "/fields/-", "value": {"type": "short_text", "title": "What is your name?", "ref": "name_field", "validations": {"required": true}}}]
**Add multiple choice field:**
[{"op": "add", "path": "/fields/-", "value": {"type": "multiple_choice", "title": "Select your favorite color", "ref": "color_field", "properties": {"choices": [{"label": "Red"}, {"label": "Blue"}, {"label": "Green"}]}}}]
**Remove first field:**
[{"op": "remove", "path": "/fields/0"}]
**Update form settings:**
[{"op": "replace", "path": "/settings/language", "value": "es"}, {"op": "replace", "path": "/settings/is_public", "value": false}]
**Multiple operations:**
[
{"op": "replace", "path": "/title", "value": "Customer Feedback Form"},
{"op": "add", "path": "/fields/-", "value": {"type": "rating", "title": "Rate your experience", "ref": "rating_field", "properties": {"steps": 5}}},
{"op": "replace", "path": "/settings/show_progress_bar", "value": true}
]
Do not include any explanations, markdown formatting, or other text outside the JSON array.`,
placeholder: 'Describe how you want to update the form...',
generationType: 'json-object',
},
},
...getTrigger('typeform_webhook').subBlocks,
],
@@ -322,6 +388,9 @@ export const TypeformBlock: BlockConfig<TypeformResponse> = {
fields: { type: 'json', description: 'Form fields array' },
welcome_screens: { type: 'json', description: 'Welcome screens array' },
thankyou_screens: { type: 'json', description: 'Thank you screens array' },
created_at: { type: 'string', description: 'Form creation timestamp' },
last_updated_at: { type: 'string', description: 'Form last update timestamp' },
published_at: { type: 'string', description: 'Form publication timestamp' },
_links: { type: 'json', description: 'Related resource links' },
// Delete form outputs
deleted: { type: 'boolean', description: 'Whether the form was deleted' },

View File

@@ -120,6 +120,35 @@ export const auth = betterAuth({
})
if (existing) {
let scopeToStore = account.scope
if (account.providerId === 'salesforce' && account.accessToken) {
try {
const response = await fetch(
'https://login.salesforce.com/services/oauth2/userinfo',
{
headers: {
Authorization: `Bearer ${account.accessToken}`,
},
}
)
if (response.ok) {
const data = await response.json()
if (data.profile) {
const match = data.profile.match(/^(https:\/\/[^/]+)/)
if (match && match[1] !== 'https://login.salesforce.com') {
const instanceUrl = match[1]
scopeToStore = `__sf_instance__:${instanceUrl} ${account.scope}`
}
}
}
} catch (error) {
logger.error('Failed to fetch Salesforce instance URL', { error })
}
}
await db
.update(schema.account)
.set({
@@ -129,7 +158,7 @@ export const auth = betterAuth({
idToken: account.idToken,
accessTokenExpiresAt: account.accessTokenExpiresAt,
refreshTokenExpiresAt: account.refreshTokenExpiresAt,
scope: account.scope,
scope: scopeToStore,
updatedAt: new Date(),
})
.where(eq(schema.account.id, existing.id))
@@ -140,24 +169,45 @@ export const auth = betterAuth({
return { data: account }
},
after: async (account) => {
// Salesforce doesn't return expires_in in its token response (unlike other OAuth providers).
// We set a default 2-hour expiration so token refresh logic works correctly.
if (account.providerId === 'salesforce' && !account.accessTokenExpiresAt) {
const twoHoursFromNow = new Date(Date.now() + 2 * 60 * 60 * 1000)
try {
await db
.update(schema.account)
.set({ accessTokenExpiresAt: twoHoursFromNow })
.where(eq(schema.account.id, account.id))
logger.info(
'[databaseHooks.account.create.after] Set default expiration for Salesforce token',
{ accountId: account.id, expiresAt: twoHoursFromNow }
)
} catch (error) {
logger.error(
'[databaseHooks.account.create.after] Failed to set Salesforce token expiration',
{ accountId: account.id, error }
)
if (account.providerId === 'salesforce') {
const updates: {
accessTokenExpiresAt?: Date
scope?: string
} = {}
if (!account.accessTokenExpiresAt) {
updates.accessTokenExpiresAt = new Date(Date.now() + 2 * 60 * 60 * 1000)
}
if (account.accessToken) {
try {
const response = await fetch(
'https://login.salesforce.com/services/oauth2/userinfo',
{
headers: {
Authorization: `Bearer ${account.accessToken}`,
},
}
)
if (response.ok) {
const data = await response.json()
if (data.profile) {
const match = data.profile.match(/^(https:\/\/[^/]+)/)
if (match && match[1] !== 'https://login.salesforce.com') {
const instanceUrl = match[1]
updates.scope = `__sf_instance__:${instanceUrl} ${account.scope}`
}
}
}
} catch (error) {
logger.error('Failed to fetch Salesforce instance URL', { error })
}
}
if (Object.keys(updates).length > 0) {
await db.update(schema.account).set(updates).where(eq(schema.account.id, account.id))
}
}
},
@@ -928,8 +978,6 @@ export const auth = betterAuth({
redirectURI: `${getBaseUrl()}/api/auth/oauth2/callback/salesforce`,
getUserInfo: async (tokens) => {
try {
logger.info('Fetching Salesforce user profile')
const response = await fetch(
'https://login.salesforce.com/services/oauth2/userinfo',
{

View File

@@ -26,3 +26,318 @@ export const mockHttpResponses = {
status: 401,
},
}
// Gmail Mock Data
export const mockGmailResponses = {
// List messages response
messageList: {
messages: [
{ id: 'msg1', threadId: 'thread1' },
{ id: 'msg2', threadId: 'thread2' },
{ id: 'msg3', threadId: 'thread3' },
],
nextPageToken: 'token123',
},
// Empty list response
emptyList: {
messages: [],
resultSizeEstimate: 0,
},
// Single message response
singleMessage: {
id: 'msg1',
threadId: 'thread1',
labelIds: ['INBOX', 'UNREAD'],
snippet: 'This is a snippet preview of the email...',
payload: {
headers: [
{ name: 'From', value: 'sender@example.com' },
{ name: 'To', value: 'recipient@example.com' },
{ name: 'Subject', value: 'Test Email Subject' },
{ name: 'Date', value: 'Mon, 15 Mar 2025 10:30:00 -0800' },
],
mimeType: 'multipart/alternative',
parts: [
{
mimeType: 'text/plain',
body: {
data: Buffer.from('This is the plain text content of the email').toString('base64'),
},
},
{
mimeType: 'text/html',
body: {
data: Buffer.from('<div>This is the HTML content of the email</div>').toString(
'base64'
),
},
},
],
},
},
}
// Google Drive Mock Data
export const mockDriveResponses = {
// List files response
fileList: {
files: [
{ id: 'file1', name: 'Document1.docx', mimeType: 'application/vnd.google-apps.document' },
{
id: 'file2',
name: 'Spreadsheet.xlsx',
mimeType: 'application/vnd.google-apps.spreadsheet',
},
{
id: 'file3',
name: 'Presentation.pptx',
mimeType: 'application/vnd.google-apps.presentation',
},
],
nextPageToken: 'drive-page-token',
},
// Empty file list
emptyFileList: {
files: [],
},
// Single file metadata
fileMetadata: {
id: 'file1',
name: 'Document1.docx',
mimeType: 'application/vnd.google-apps.document',
webViewLink: 'https://docs.google.com/document/d/123/edit',
createdTime: '2025-03-15T12:00:00Z',
modifiedTime: '2025-03-16T10:15:00Z',
owners: [{ displayName: 'Test User', emailAddress: 'user@example.com' }],
size: '12345',
},
}
// Google Sheets Mock Data
export const mockSheetsResponses = {
// Read range response
rangeData: {
range: 'Sheet1!A1:D5',
majorDimension: 'ROWS',
values: [
['Header1', 'Header2', 'Header3', 'Header4'],
['Row1Col1', 'Row1Col2', 'Row1Col3', 'Row1Col4'],
['Row2Col1', 'Row2Col2', 'Row2Col3', 'Row2Col4'],
['Row3Col1', 'Row3Col2', 'Row3Col3', 'Row3Col4'],
['Row4Col1', 'Row4Col2', 'Row4Col3', 'Row4Col4'],
],
},
// Empty range
emptyRange: {
range: 'Sheet1!A1:D5',
majorDimension: 'ROWS',
values: [],
},
// Update range response
updateResponse: {
spreadsheetId: 'spreadsheet123',
updatedRange: 'Sheet1!A1:D5',
updatedRows: 5,
updatedColumns: 4,
updatedCells: 20,
},
}
// Pinecone Mock Data
export const mockPineconeResponses = {
// Vector embedding
embedding: {
embedding: Array(1536)
.fill(0)
.map(() => Math.random() * 2 - 1),
metadata: { text: 'Sample text for embedding', id: 'embed-123' },
},
// Search results
searchResults: {
matches: [
{ id: 'doc1', score: 0.92, metadata: { text: 'Matching text 1' } },
{ id: 'doc2', score: 0.85, metadata: { text: 'Matching text 2' } },
{ id: 'doc3', score: 0.78, metadata: { text: 'Matching text 3' } },
],
},
// Upsert response
upsertResponse: {
statusText: 'Created',
},
}
// GitHub Mock Data
export const mockGitHubResponses = {
// Repository info
repoInfo: {
id: 12345,
name: 'test-repo',
full_name: 'user/test-repo',
description: 'A test repository',
html_url: 'https://github.com/user/test-repo',
owner: {
login: 'user',
id: 54321,
avatar_url: 'https://avatars.githubusercontent.com/u/54321',
},
private: false,
fork: false,
created_at: '2025-01-01T00:00:00Z',
updated_at: '2025-03-15T10:00:00Z',
pushed_at: '2025-03-15T09:00:00Z',
default_branch: 'main',
open_issues_count: 5,
watchers_count: 10,
forks_count: 3,
stargazers_count: 15,
language: 'TypeScript',
},
// PR creation response
prResponse: {
id: 12345,
number: 42,
title: 'Test PR Title',
body: 'Test PR description',
html_url: 'https://github.com/user/test-repo/pull/42',
state: 'open',
user: {
login: 'user',
id: 54321,
},
created_at: '2025-03-15T10:00:00Z',
updated_at: '2025-03-15T10:05:00Z',
},
}
// Serper Search Mock Data
export const mockSerperResponses = {
// Search results
searchResults: {
searchParameters: {
q: 'test query',
gl: 'us',
hl: 'en',
},
organic: [
{
title: 'Test Result 1',
link: 'https://example.com/1',
snippet: 'This is a snippet for the first test result.',
position: 1,
},
{
title: 'Test Result 2',
link: 'https://example.com/2',
snippet: 'This is a snippet for the second test result.',
position: 2,
},
{
title: 'Test Result 3',
link: 'https://example.com/3',
snippet: 'This is a snippet for the third test result.',
position: 3,
},
],
knowledgeGraph: {
title: 'Test Knowledge Graph',
type: 'Test Type',
description: 'This is a test knowledge graph result',
},
},
}
// Slack Mock Data
export const mockSlackResponses = {
// Message post response
messageResponse: {
ok: true,
channel: 'C1234567890',
ts: '1627385301.000700',
message: {
text: 'This is a test message',
user: 'U1234567890',
ts: '1627385301.000700',
team: 'T1234567890',
},
},
// Error response
errorResponse: {
ok: false,
error: 'channel_not_found',
},
}
// Tavily Mock Data
export const mockTavilyResponses = {
// Search results
searchResults: {
results: [
{
title: 'Test Article 1',
url: 'https://example.com/article1',
content: 'This is the content of test article 1.',
score: 0.95,
},
{
title: 'Test Article 2',
url: 'https://example.com/article2',
content: 'This is the content of test article 2.',
score: 0.87,
},
{
title: 'Test Article 3',
url: 'https://example.com/article3',
content: 'This is the content of test article 3.',
score: 0.72,
},
],
query: 'test query',
search_id: 'search-123',
},
}
// Supabase Mock Data
export const mockSupabaseResponses = {
// Query response
queryResponse: {
data: [
{ id: 1, name: 'Item 1', description: 'Description 1' },
{ id: 2, name: 'Item 2', description: 'Description 2' },
{ id: 3, name: 'Item 3', description: 'Description 3' },
],
error: null,
},
// Insert response
insertResponse: {
data: [{ id: 4, name: 'Item 4', description: 'Description 4' }],
error: null,
},
// Update response
updateResponse: {
data: [{ id: 1, name: 'Updated Item 1', description: 'Updated Description 1' }],
error: null,
},
// Error response
errorResponse: {
data: null,
error: {
message: 'Database error',
details: 'Error details',
hint: 'Error hint',
code: 'DB_ERROR',
},
},
}

View File

@@ -305,10 +305,11 @@ export async function executeTool(
if (data.idToken) {
contextParams.idToken = data.idToken
}
if (data.instanceUrl) {
contextParams.instanceUrl = data.instanceUrl
}
logger.info(
`[${requestId}] Successfully got access token for ${toolId}, length: ${data.accessToken?.length || 0}`
)
logger.info(`[${requestId}] Successfully got access token for ${toolId}`)
// Preserve credential for downstream transforms while removing it from request payload
// so we don't leak it to external services.
@@ -747,6 +748,8 @@ async function handleInternalRequest(
url: fullUrl,
json: () => response.json(),
text: () => response.text(),
arrayBuffer: () => response.arrayBuffer(),
blob: () => response.blob(),
} as Response
const data = await tool.transformResponse(mockResponse, params)

View File

@@ -20,7 +20,33 @@ export interface IntercomCreateCompanyParams {
export interface IntercomCreateCompanyResponse {
success: boolean
output: {
company: any
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
@@ -159,15 +185,55 @@ export const intercomCreateCompanyTool: ToolConfig<
},
outputs: {
success: { type: 'boolean', description: 'Operation success status' },
output: {
company: {
type: 'object',
description: 'Created or updated company data',
description: 'Created or updated company object',
properties: {
company: { type: 'object', description: 'Company object' },
metadata: { type: 'object', description: 'Operation metadata' },
success: { type: 'boolean', description: 'Operation success' },
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' },
},
}

View File

@@ -23,7 +23,58 @@ export interface IntercomCreateContactParams {
export interface IntercomCreateContactResponse {
success: boolean
output: {
contact: any
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
@@ -182,15 +233,92 @@ export const intercomCreateContactTool: ToolConfig<
},
outputs: {
success: { type: 'boolean', description: 'Operation success status' },
output: {
contact: {
type: 'object',
description: 'Created contact data',
description: 'Created contact object',
properties: {
contact: { type: 'object', description: 'Created contact object' },
metadata: { type: 'object', description: 'Operation metadata' },
success: { type: 'boolean', description: 'Operation success' },
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',
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' },
},
}

View File

@@ -161,15 +161,27 @@ export const intercomCreateMessageTool: ToolConfig<
},
outputs: {
success: { type: 'boolean', description: 'Operation success status' },
output: {
message: {
type: 'object',
description: 'Created message data',
description: 'Created message object',
properties: {
message: { type: 'object', description: 'Created message object' },
metadata: { type: 'object', description: 'Operation metadata' },
success: { type: 'boolean', description: 'Operation success' },
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' },
},
}

View File

@@ -149,15 +149,41 @@ export const intercomCreateTicketTool: ToolConfig<
},
outputs: {
success: { type: 'boolean', description: 'Operation success status' },
output: {
ticket: {
type: 'object',
description: 'Created ticket data',
description: 'Created ticket object',
properties: {
ticket: { type: 'object', description: 'Created ticket object' },
metadata: { type: 'object', description: 'Operation metadata' },
success: { type: 'boolean', description: 'Operation success' },
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' },
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' },
},
}

View File

@@ -77,16 +77,15 @@ export const intercomDeleteContactTool: ToolConfig<
},
outputs: {
success: { type: 'boolean', description: 'Operation success status' },
output: {
id: { type: 'string', description: 'ID of deleted contact' },
deleted: { type: 'boolean', description: 'Whether the contact was deleted' },
metadata: {
type: 'object',
description: 'Deletion result',
description: 'Operation metadata',
properties: {
id: { type: 'string', description: 'ID of deleted contact' },
deleted: { type: 'boolean', description: 'Deletion status' },
metadata: { type: 'object', description: 'Operation metadata' },
success: { type: 'boolean', description: 'Operation success' },
operation: { type: 'string', description: 'The operation performed (delete_contact)' },
},
},
success: { type: 'boolean', description: 'Operation success status' },
},
}

View File

@@ -76,15 +76,36 @@ export const intercomGetCompanyTool: ToolConfig<
},
outputs: {
success: { type: 'boolean', description: 'Operation success status' },
output: {
company: {
type: 'object',
description: 'Company data',
description: 'Company object',
properties: {
company: { type: 'object', description: 'Company object' },
metadata: { type: 'object', description: 'Operation metadata' },
success: { type: 'boolean', description: 'Operation success' },
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' },
},
}

View File

@@ -76,15 +76,41 @@ export const intercomGetContactTool: ToolConfig<
},
outputs: {
success: { type: 'boolean', description: 'Operation success status' },
output: {
contact: {
type: 'object',
description: 'Contact data',
description: 'Contact object',
properties: {
contact: { type: 'object', description: 'Contact object' },
metadata: { type: 'object', description: 'Operation metadata' },
success: { type: 'boolean', description: 'Operation success' },
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' },
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 (get_contact)' },
},
},
success: { type: 'boolean', description: 'Operation success status' },
},
}

View File

@@ -101,15 +101,41 @@ export const intercomGetConversationTool: ToolConfig<
},
outputs: {
success: { type: 'boolean', description: 'Operation success status' },
output: {
conversation: {
type: 'object',
description: 'Conversation data',
description: 'Conversation object',
properties: {
conversation: { type: 'object', description: 'Conversation object' },
metadata: { type: 'object', description: 'Operation metadata' },
success: { type: 'boolean', description: 'Operation success' },
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' },
snoozed_until: { type: 'number', description: 'Unix timestamp when snooze ends' },
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' },
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' },
},
}

View File

@@ -74,15 +74,43 @@ export const intercomGetTicketTool: ToolConfig<IntercomGetTicketParams, Intercom
},
outputs: {
success: { type: 'boolean', description: 'Operation success status' },
output: {
ticket: {
type: 'object',
description: 'Ticket data',
description: 'Ticket object',
properties: {
ticket: { type: 'object', description: 'Ticket object' },
metadata: { type: 'object', description: 'Operation metadata' },
success: { type: 'boolean', description: 'Operation success' },
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' },
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' },
},
}

View File

@@ -105,16 +105,54 @@ export const intercomListCompaniesTool: ToolConfig<
},
outputs: {
success: { type: 'boolean', description: 'Operation success status' },
output: {
type: 'object',
description: 'List of companies',
properties: {
companies: { type: 'array', description: 'Array of company objects' },
pages: { type: 'object', description: 'Pagination information' },
metadata: { type: 'object', description: 'Operation metadata' },
success: { type: 'boolean', description: 'Operation success' },
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' },
},
}

View File

@@ -96,16 +96,52 @@ export const intercomListContactsTool: ToolConfig<
},
outputs: {
success: { type: 'boolean', description: 'Operation success status' },
output: {
type: 'object',
description: 'List of contacts',
properties: {
contacts: { type: 'array', description: 'Array of contact objects' },
pages: { type: 'object', description: 'Pagination information' },
metadata: { type: 'object', description: 'Operation metadata' },
success: { type: 'boolean', description: 'Operation success' },
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' },
},
}

View File

@@ -112,16 +112,54 @@ export const intercomListConversationsTool: ToolConfig<
},
outputs: {
success: { type: 'boolean', description: 'Operation success status' },
output: {
type: 'object',
description: 'List of conversations',
properties: {
conversations: { type: 'array', description: 'Array of conversation objects' },
pages: { type: 'object', description: 'Pagination information' },
metadata: { type: 'object', description: 'Operation metadata' },
success: { type: 'boolean', description: 'Operation success' },
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' },
},
}

View File

@@ -134,15 +134,39 @@ export const intercomReplyConversationTool: ToolConfig<
},
outputs: {
success: { type: 'boolean', description: 'Operation success status' },
output: {
conversation: {
type: 'object',
description: 'Updated conversation with reply',
description: 'Updated conversation object',
properties: {
conversation: { type: 'object', description: 'Updated conversation object' },
metadata: { type: 'object', description: 'Operation metadata' },
success: { type: 'boolean', description: 'Operation success' },
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' },
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' },
},
}

View File

@@ -16,11 +16,67 @@ export interface IntercomSearchContactsParams {
export interface IntercomSearchContactsResponse {
success: boolean
output: {
contacts: any[]
pages?: any
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
total_count: number
}
success: boolean
}
@@ -137,16 +193,63 @@ export const intercomSearchContactsTool: ToolConfig<
},
outputs: {
success: { type: 'boolean', description: 'Operation success status' },
output: {
type: 'object',
description: 'Search results',
properties: {
contacts: { type: 'array', description: 'Array of matching contact objects' },
pages: { type: 'object', description: 'Pagination information' },
metadata: { type: 'object', description: 'Operation metadata' },
success: { type: 'boolean', description: 'Operation success' },
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' },
},
}

View File

@@ -136,16 +136,57 @@ export const intercomSearchConversationsTool: ToolConfig<
},
outputs: {
success: { type: 'boolean', description: 'Operation success status' },
output: {
type: 'object',
description: 'Search results',
properties: {
conversations: { type: 'array', description: 'Array of matching conversation objects' },
pages: { type: 'object', description: 'Pagination information' },
metadata: { type: 'object', description: 'Operation metadata' },
success: { type: 'boolean', description: 'Operation success' },
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' },
},
}

View File

@@ -188,15 +188,42 @@ export const intercomUpdateContactTool: ToolConfig<
},
outputs: {
success: { type: 'boolean', description: 'Operation success status' },
output: {
contact: {
type: 'object',
description: 'Updated contact data',
description: 'Updated contact object',
properties: {
contact: { type: 'object', description: 'Updated contact object' },
metadata: { type: 'object', description: 'Operation metadata' },
success: { type: 'boolean', description: 'Operation success' },
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' },
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' },
},
}

View File

@@ -18,7 +18,7 @@ export interface PineconeMatchResponse {
export interface PineconeResponse extends ToolResponse {
output: {
matches?: PineconeMatchResponse[]
upsertedCount?: number
statusText?: string
data?: Array<{
values: number[]
vector_type: 'dense' | 'sparse'

View File

@@ -71,22 +71,11 @@ export const upsertTextTool: ToolConfig<PineconeUpsertTextParams, PineconeRespon
},
transformResponse: async (response) => {
// Handle empty response (201 Created)
if (response.status === 201) {
return {
success: true,
output: {
statusText: 'Created',
},
}
}
// Handle response with content
const data = await response.json()
// Pinecone upsert returns 201 Created with empty body on success
return {
success: true,
success: response.status === 201,
output: {
upsertedCount: data.upsertedCount || 0,
statusText: response.status === 201 ? 'Created' : response.statusText,
},
}
},
@@ -96,9 +85,5 @@ export const upsertTextTool: ToolConfig<PineconeUpsertTextParams, PineconeRespon
type: 'string',
description: 'Status of the upsert operation',
},
upsertedCount: {
type: 'number',
description: 'Number of records successfully upserted',
},
},
}

View File

@@ -26,11 +26,17 @@ export const storageUploadTool: ToolConfig<
visibility: 'user-or-llm',
description: 'The name of the storage bucket',
},
path: {
fileName: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The path where the file will be stored (e.g., "folder/file.jpg")',
description: 'The name of the file (e.g., "document.pdf", "image.jpg")',
},
path: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Optional folder path (e.g., "folder/subfolder/")',
},
fileContent: {
type: 'string',
@@ -60,7 +66,14 @@ export const storageUploadTool: ToolConfig<
request: {
url: (params) => {
return `https://${params.projectId}.supabase.co/storage/v1/object/${params.bucket}/${params.path}`
// Combine folder path and fileName, ensuring proper formatting
let fullPath = params.fileName
if (params.path) {
// Ensure path ends with / and doesn't have double slashes
const folderPath = params.path.endsWith('/') ? params.path : `${params.path}/`
fullPath = `${folderPath}${params.fileName}`
}
return `https://${params.projectId}.supabase.co/storage/v1/object/${params.bucket}/${fullPath}`
},
method: 'POST',
headers: (params) => {

View File

@@ -132,7 +132,8 @@ export interface SupabaseStorageUploadParams {
apiKey: string
projectId: string
bucket: string
path: string
fileName: string
path?: string
fileContent: string
contentType?: string
upsert?: boolean

View File

@@ -98,7 +98,12 @@ export const createFormTool: ToolConfig<TypeformCreateFormParams, TypeformCreate
return {
success: true,
output: data,
output: {
...data,
welcome_screens: data.welcome_screens || [],
thankyou_screens: data.thankyou_screens || [],
fields: data.fields || [],
},
}
},
@@ -115,9 +120,29 @@ export const createFormTool: ToolConfig<TypeformCreateFormParams, TypeformCreate
type: 'string',
description: 'Form type',
},
settings: {
type: 'object',
description: 'Form settings object',
},
theme: {
type: 'object',
description: 'Theme reference',
},
workspace: {
type: 'object',
description: 'Workspace reference',
},
fields: {
type: 'array',
description: 'Array of created form fields',
description: 'Array of created form fields (empty if none added)',
},
welcome_screens: {
type: 'array',
description: 'Array of welcome screens (empty if none configured)',
},
thankyou_screens: {
type: 'array',
description: 'Array of thank you screens',
},
_links: {
type: 'object',

View File

@@ -37,7 +37,12 @@ export const getFormTool: ToolConfig<TypeformGetFormParams, TypeformGetFormRespo
return {
success: true,
output: data,
output: {
...data,
welcome_screens: data.welcome_screens || [],
thankyou_screens: data.thankyou_screens || [],
fields: data.fields || [],
},
}
},
@@ -72,12 +77,24 @@ export const getFormTool: ToolConfig<TypeformGetFormParams, TypeformGetFormRespo
},
welcome_screens: {
type: 'array',
description: 'Array of welcome screens',
description: 'Array of welcome screens (empty if none configured)',
},
thankyou_screens: {
type: 'array',
description: 'Array of thank you screens',
},
created_at: {
type: 'string',
description: 'Form creation timestamp (ISO 8601 format)',
},
last_updated_at: {
type: 'string',
description: 'Form last update timestamp (ISO 8601 format)',
},
published_at: {
type: 'string',
description: 'Form publication timestamp (ISO 8601 format)',
},
_links: {
type: 'object',
description: 'Related resource links including public form URL',

View File

@@ -221,20 +221,7 @@ export interface TypeformUpdateFormParams {
export interface TypeformUpdateFormResponse extends ToolResponse {
output: {
id: string
title: string
type: string
created_at: string
last_updated_at: string
settings: Record<string, any>
theme: Record<string, any>
workspace?: {
href: string
}
fields: Array<Record<string, any>>
thankyou_screens?: Array<Record<string, any>>
_links: Record<string, any>
[key: string]: any
message: string
}
}

View File

@@ -44,54 +44,54 @@ export const updateFormTool: ToolConfig<TypeformUpdateFormParams, TypeformUpdate
},
transformResponse: async (response: Response) => {
const data = await response.json()
// Check if response has content
const text = await response.text()
// Handle empty responses
if (!text || text.trim() === '') {
if (response.ok) {
// Success with no content (e.g., 204 No Content)
return {
success: true,
output: {
message: 'Form updated successfully',
},
}
}
throw new Error(`Request failed with status ${response.status}: ${response.statusText}`)
}
// Try to parse as JSON
let data: any
try {
data = JSON.parse(text)
} catch {
// If response is not OK and not JSON, throw with the raw text
if (!response.ok) {
throw new Error(`Request failed with status ${response.status}: ${text.slice(0, 200)}`)
}
throw new Error(`Invalid JSON response: ${text.slice(0, 200)}`)
}
// Handle error responses from Typeform API
if (!response.ok) {
const errorMessage = data.description || data.message || data.error || JSON.stringify(data)
throw new Error(`Typeform API error (${response.status}): ${errorMessage}`)
}
// Return simple success message (Typeform PATCH returns minimal/no content on success)
return {
success: true,
output: data,
output: {
message: 'Form updated successfully',
},
}
},
outputs: {
id: {
message: {
type: 'string',
description: 'Updated form unique identifier',
},
title: {
type: 'string',
description: 'Form title',
},
type: {
type: 'string',
description: 'Form type',
},
settings: {
type: 'object',
description: 'Form settings',
},
theme: {
type: 'object',
description: 'Theme reference',
},
workspace: {
type: 'object',
description: 'Workspace reference',
},
fields: {
type: 'array',
description: 'Array of form fields',
},
welcome_screens: {
type: 'array',
description: 'Array of welcome screens',
},
thankyou_screens: {
type: 'array',
description: 'Array of thank you screens',
},
_links: {
type: 'object',
description: 'Related resource links',
description: 'Success confirmation message',
},
},
}