mirror of
https://github.com/simstudioai/sim.git
synced 2026-10-24 01:23:02 +08:00
* feat(airtable): add delete and upsert record tools * feat(google-docs): add batchUpdate text, table, image, and style tools * feat(whatsapp): add template, media, interactive, reaction, and mark-read tools * feat(microsoft-excel): add clear, format, create-table, sort, and delete-worksheet tools * fix(integrations): address review feedback - google-docs: use camelCase fontSize field mask; normalize string booleans for bold/italic/underline and matchCase - microsoft-excel: escape OData single quotes in worksheet/table keys; validate range for clear/format - airtable: enforce batch limits (delete <=10 ids, upsert <=10 records and 1-3 merge fields) with clear errors * fix(integrations): address round-2 review - airtable: coerce upsert typecast as string-aware boolean (string "false" no longer truthy) - microsoft-excel: format_range surfaces precise partial-state error when fill PATCH fails after font (no atomic font+fill endpoint in Graph) * fix(whatsapp): treat 2xx mark-as-read as success unless body says success:false * fix(integrations): build fix, doc accuracy, and comment cleanup - google-docs: align manualDocumentId condition with the document selector so the documentId canonical group has matching conditions (fixes canonical-pair block test / build) - microsoft-excel: describe fill/font color as hex code only (Graph does not reliably accept named colors) - remove verbose explanatory inline comments from new tools (keep idiomatic section dividers) - regenerate integration docs + integrations.json catalog from the block registry * fix(integrations): harden delete-record id coercion and excel sort-column validation - airtable: coerce recordIds entries via String() so numeric JSON values don't crash on .trim() - microsoft-excel: drop the silent sortColumn default to 0 so invalid input surfaces the tool's clear validation error (both v1 and v2 blocks) * fix(airtable): coerce upsert fieldsToMergeOn entries via String() to handle non-string values
77 lines
2.3 KiB
TypeScript
77 lines
2.3 KiB
TypeScript
import type { ToolConfig } from '@/tools/types'
|
|
import type { WhatsAppMarkReadParams, WhatsAppMarkReadResponse } from '@/tools/whatsapp/types'
|
|
import { buildAuthHeaders, buildMessagesUrl, isRecord } from '@/tools/whatsapp/utils'
|
|
|
|
export const markReadTool: ToolConfig<WhatsAppMarkReadParams, WhatsAppMarkReadResponse> = {
|
|
id: 'whatsapp_mark_read',
|
|
name: 'WhatsApp Mark As Read',
|
|
description: 'Mark a received WhatsApp message as read so the sender sees blue checkmarks.',
|
|
version: '1.0.0',
|
|
|
|
params: {
|
|
messageId: {
|
|
type: 'string',
|
|
required: true,
|
|
visibility: 'user-or-llm',
|
|
description: 'ID (wamid) of the incoming message to mark as read',
|
|
},
|
|
phoneNumberId: {
|
|
type: 'string',
|
|
required: true,
|
|
visibility: 'user-only',
|
|
description: 'WhatsApp Business Phone Number ID (from Meta Business Suite)',
|
|
},
|
|
accessToken: {
|
|
type: 'string',
|
|
required: true,
|
|
visibility: 'user-only',
|
|
description: 'WhatsApp Business API Access Token (from Meta Developer Portal)',
|
|
},
|
|
},
|
|
|
|
request: {
|
|
url: (params) => buildMessagesUrl(params.phoneNumberId),
|
|
method: 'POST',
|
|
headers: (params) => buildAuthHeaders(params.accessToken),
|
|
body: (params) => {
|
|
if (!params.messageId) {
|
|
throw new Error('Message ID is required but was not provided')
|
|
}
|
|
return {
|
|
messaging_product: 'whatsapp',
|
|
status: 'read',
|
|
message_id: params.messageId.trim(),
|
|
}
|
|
},
|
|
},
|
|
|
|
transformResponse: async (response: Response) => {
|
|
const responseText = await response.text()
|
|
const parsed = responseText ? (JSON.parse(responseText) as unknown) : {}
|
|
const data = isRecord(parsed) ? parsed : {}
|
|
const error = isRecord(data.error) ? data.error : undefined
|
|
|
|
if (!response.ok) {
|
|
const errorMessage =
|
|
(typeof error?.message === 'string' ? error.message : undefined) ||
|
|
(typeof error?.error_user_msg === 'string' ? error.error_user_msg : undefined) ||
|
|
`WhatsApp API error (${response.status})`
|
|
throw new Error(errorMessage)
|
|
}
|
|
|
|
return {
|
|
success: true,
|
|
output: {
|
|
success: data.success !== false,
|
|
},
|
|
}
|
|
},
|
|
|
|
outputs: {
|
|
success: {
|
|
type: 'boolean',
|
|
description: 'Whether the message was successfully marked as read',
|
|
},
|
|
},
|
|
}
|