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,221 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ZoomCreateMeetingParams, ZoomCreateMeetingResponse } from '@/tools/zoom/types'
|
||||
import { MEETING_OUTPUT_PROPERTIES } from '@/tools/zoom/types'
|
||||
|
||||
export const zoomCreateMeetingTool: ToolConfig<ZoomCreateMeetingParams, ZoomCreateMeetingResponse> =
|
||||
{
|
||||
id: 'zoom_create_meeting',
|
||||
name: 'Zoom Create Meeting',
|
||||
description: 'Create a new Zoom meeting',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zoom',
|
||||
requiredScopes: ['meeting:write:meeting'],
|
||||
},
|
||||
|
||||
params: {
|
||||
userId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'The user ID or email address (e.g., "me", "user@example.com", or "AbcDefGHi"). Use "me" for the authenticated user.',
|
||||
},
|
||||
topic: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Meeting topic (e.g., "Weekly Team Standup" or "Project Review")',
|
||||
},
|
||||
type: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Meeting type: 1=instant, 2=scheduled, 3=recurring no fixed time, 8=recurring fixed time',
|
||||
},
|
||||
startTime: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Meeting start time in ISO 8601 format (e.g., 2025-06-03T10:00:00Z)',
|
||||
},
|
||||
duration: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Meeting duration in minutes (e.g., 30, 60, 90)',
|
||||
},
|
||||
timezone: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Timezone for the meeting (e.g., America/Los_Angeles)',
|
||||
},
|
||||
password: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Meeting password',
|
||||
},
|
||||
agenda: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Meeting agenda or description text',
|
||||
},
|
||||
hostVideo: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Start with host video on',
|
||||
},
|
||||
participantVideo: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Start with participant video on',
|
||||
},
|
||||
joinBeforeHost: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Allow participants to join before host',
|
||||
},
|
||||
muteUponEntry: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Mute participants upon entry',
|
||||
},
|
||||
waitingRoom: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Enable waiting room',
|
||||
},
|
||||
autoRecording: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Auto recording setting: local, cloud, or none',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => `https://api.zoom.us/v2/users/${encodeURIComponent(params.userId)}/meetings`,
|
||||
method: 'POST',
|
||||
headers: (params) => {
|
||||
if (!params.accessToken) {
|
||||
throw new Error('Missing access token for Zoom API request')
|
||||
}
|
||||
return {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}
|
||||
},
|
||||
body: (params) => {
|
||||
if (!params.topic || !params.topic.trim()) {
|
||||
throw new Error('Topic is required to create a Zoom meeting')
|
||||
}
|
||||
|
||||
const body: Record<string, any> = {
|
||||
topic: params.topic,
|
||||
type: params.type || 2, // Default to scheduled meeting
|
||||
}
|
||||
|
||||
if (params.startTime) {
|
||||
body.start_time = params.startTime
|
||||
}
|
||||
if (params.duration != null) {
|
||||
body.duration = params.duration
|
||||
}
|
||||
if (params.timezone) {
|
||||
body.timezone = params.timezone
|
||||
}
|
||||
if (params.password) {
|
||||
body.password = params.password
|
||||
}
|
||||
if (params.agenda) {
|
||||
body.agenda = params.agenda
|
||||
}
|
||||
|
||||
// Build settings object
|
||||
const settings: Record<string, any> = {}
|
||||
if (params.hostVideo != null) {
|
||||
settings.host_video = params.hostVideo
|
||||
}
|
||||
if (params.participantVideo != null) {
|
||||
settings.participant_video = params.participantVideo
|
||||
}
|
||||
if (params.joinBeforeHost != null) {
|
||||
settings.join_before_host = params.joinBeforeHost
|
||||
}
|
||||
if (params.muteUponEntry != null) {
|
||||
settings.mute_upon_entry = params.muteUponEntry
|
||||
}
|
||||
if (params.waitingRoom != null) {
|
||||
settings.waiting_room = params.waitingRoom
|
||||
}
|
||||
if (params.autoRecording) {
|
||||
settings.auto_recording = params.autoRecording
|
||||
}
|
||||
|
||||
if (Object.keys(settings).length > 0) {
|
||||
body.settings = settings
|
||||
}
|
||||
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}))
|
||||
return {
|
||||
success: false,
|
||||
error: errorData.message || `Zoom API error: ${response.status} ${response.statusText}`,
|
||||
output: { meeting: {} as any },
|
||||
}
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
meeting: {
|
||||
id: data.id,
|
||||
uuid: data.uuid,
|
||||
host_id: data.host_id,
|
||||
host_email: data.host_email,
|
||||
topic: data.topic,
|
||||
type: data.type,
|
||||
status: data.status,
|
||||
start_time: data.start_time,
|
||||
duration: data.duration,
|
||||
timezone: data.timezone,
|
||||
agenda: data.agenda,
|
||||
created_at: data.created_at,
|
||||
start_url: data.start_url,
|
||||
join_url: data.join_url,
|
||||
password: data.password,
|
||||
h323_password: data.h323_password,
|
||||
pstn_password: data.pstn_password,
|
||||
encrypted_password: data.encrypted_password,
|
||||
settings: data.settings,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
meeting: {
|
||||
type: 'object',
|
||||
description: 'The created meeting with all its properties',
|
||||
properties: MEETING_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ZoomDeleteMeetingParams, ZoomDeleteMeetingResponse } from '@/tools/zoom/types'
|
||||
|
||||
export const zoomDeleteMeetingTool: ToolConfig<ZoomDeleteMeetingParams, ZoomDeleteMeetingResponse> =
|
||||
{
|
||||
id: 'zoom_delete_meeting',
|
||||
name: 'Zoom Delete Meeting',
|
||||
description: 'Delete or cancel a Zoom meeting',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zoom',
|
||||
requiredScopes: ['meeting:delete:meeting'],
|
||||
},
|
||||
|
||||
params: {
|
||||
meetingId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The meeting ID to delete (e.g., "1234567890" or "85746065432")',
|
||||
},
|
||||
occurrenceId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Occurrence ID for deleting a specific occurrence of a recurring meeting',
|
||||
},
|
||||
scheduleForReminder: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Send cancellation reminder email to registrants',
|
||||
},
|
||||
cancelMeetingReminder: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Send cancellation email to registrants and alternative hosts',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const baseUrl = `https://api.zoom.us/v2/meetings/${encodeURIComponent(params.meetingId)}`
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.occurrenceId) {
|
||||
queryParams.append('occurrence_id', params.occurrenceId)
|
||||
}
|
||||
if (params.scheduleForReminder != null) {
|
||||
queryParams.append('schedule_for_reminder', String(params.scheduleForReminder))
|
||||
}
|
||||
if (params.cancelMeetingReminder != null) {
|
||||
queryParams.append('cancel_meeting_reminder', String(params.cancelMeetingReminder))
|
||||
}
|
||||
|
||||
const queryString = queryParams.toString()
|
||||
return queryString ? `${baseUrl}?${queryString}` : baseUrl
|
||||
},
|
||||
method: 'DELETE',
|
||||
headers: (params) => {
|
||||
if (!params.accessToken) {
|
||||
throw new Error('Missing access token for Zoom API request')
|
||||
}
|
||||
return {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}))
|
||||
return {
|
||||
success: false,
|
||||
error: errorData.message || `Zoom API error: ${response.status} ${response.statusText}`,
|
||||
output: { success: false },
|
||||
}
|
||||
}
|
||||
|
||||
// Zoom returns 204 No Content on successful deletion
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
success: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the meeting was deleted successfully',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ZoomDeleteRecordingParams, ZoomDeleteRecordingResponse } from '@/tools/zoom/types'
|
||||
|
||||
export const zoomDeleteRecordingTool: ToolConfig<
|
||||
ZoomDeleteRecordingParams,
|
||||
ZoomDeleteRecordingResponse
|
||||
> = {
|
||||
id: 'zoom_delete_recording',
|
||||
name: 'Zoom Delete Recording',
|
||||
description: 'Delete cloud recordings for a Zoom meeting',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zoom',
|
||||
requiredScopes: ['cloud_recording:delete:recording_file'],
|
||||
},
|
||||
|
||||
params: {
|
||||
meetingId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'The meeting ID or meeting UUID (e.g., "1234567890" or "4444AAABBBccccc12345==")',
|
||||
},
|
||||
recordingId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Specific recording file ID to delete. If not provided, deletes all recordings.',
|
||||
},
|
||||
action: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Delete action: "trash" (move to trash) or "delete" (permanently delete)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
let baseUrl = `https://api.zoom.us/v2/meetings/${encodeURIComponent(params.meetingId)}/recordings`
|
||||
|
||||
if (params.recordingId) {
|
||||
baseUrl += `/${encodeURIComponent(params.recordingId)}`
|
||||
}
|
||||
|
||||
const queryParams = new URLSearchParams()
|
||||
if (params.action) {
|
||||
queryParams.append('action', params.action)
|
||||
}
|
||||
|
||||
const queryString = queryParams.toString()
|
||||
return queryString ? `${baseUrl}?${queryString}` : baseUrl
|
||||
},
|
||||
method: 'DELETE',
|
||||
headers: (params) => {
|
||||
if (!params.accessToken) {
|
||||
throw new Error('Missing access token for Zoom API request')
|
||||
}
|
||||
return {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}))
|
||||
return {
|
||||
success: false,
|
||||
error: errorData.message || `Zoom API error: ${response.status} ${response.statusText}`,
|
||||
output: { success: false },
|
||||
}
|
||||
}
|
||||
|
||||
// Zoom returns 204 No Content on successful deletion
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
success: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the recording was deleted successfully',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ZoomGetMeetingParams, ZoomGetMeetingResponse } from '@/tools/zoom/types'
|
||||
import { MEETING_OUTPUT_PROPERTIES } from '@/tools/zoom/types'
|
||||
|
||||
export const zoomGetMeetingTool: ToolConfig<ZoomGetMeetingParams, ZoomGetMeetingResponse> = {
|
||||
id: 'zoom_get_meeting',
|
||||
name: 'Zoom Get Meeting',
|
||||
description: 'Get details of a specific Zoom meeting',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zoom',
|
||||
requiredScopes: ['meeting:read:meeting'],
|
||||
},
|
||||
|
||||
params: {
|
||||
meetingId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The meeting ID (e.g., "1234567890" or "85746065432")',
|
||||
},
|
||||
occurrenceId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Occurrence ID for recurring meetings',
|
||||
},
|
||||
showPreviousOccurrences: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Show previous occurrences for recurring meetings',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const baseUrl = `https://api.zoom.us/v2/meetings/${encodeURIComponent(params.meetingId)}`
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.occurrenceId) {
|
||||
queryParams.append('occurrence_id', params.occurrenceId)
|
||||
}
|
||||
if (params.showPreviousOccurrences != null) {
|
||||
queryParams.append('show_previous_occurrences', String(params.showPreviousOccurrences))
|
||||
}
|
||||
|
||||
const queryString = queryParams.toString()
|
||||
return queryString ? `${baseUrl}?${queryString}` : baseUrl
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => {
|
||||
if (!params.accessToken) {
|
||||
throw new Error('Missing access token for Zoom API request')
|
||||
}
|
||||
return {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}))
|
||||
return {
|
||||
success: false,
|
||||
error: errorData.message || `Zoom API error: ${response.status} ${response.statusText}`,
|
||||
output: { meeting: {} as any },
|
||||
}
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
meeting: {
|
||||
id: data.id,
|
||||
uuid: data.uuid,
|
||||
host_id: data.host_id,
|
||||
host_email: data.host_email,
|
||||
topic: data.topic,
|
||||
type: data.type,
|
||||
status: data.status,
|
||||
start_time: data.start_time,
|
||||
duration: data.duration,
|
||||
timezone: data.timezone,
|
||||
agenda: data.agenda,
|
||||
created_at: data.created_at,
|
||||
start_url: data.start_url,
|
||||
join_url: data.join_url,
|
||||
password: data.password,
|
||||
h323_password: data.h323_password,
|
||||
pstn_password: data.pstn_password,
|
||||
encrypted_password: data.encrypted_password,
|
||||
settings: data.settings,
|
||||
recurrence: data.recurrence,
|
||||
occurrences: data.occurrences,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
meeting: {
|
||||
type: 'object',
|
||||
description: 'The meeting details',
|
||||
properties: MEETING_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type {
|
||||
ZoomGetMeetingInvitationParams,
|
||||
ZoomGetMeetingInvitationResponse,
|
||||
} from '@/tools/zoom/types'
|
||||
|
||||
export const zoomGetMeetingInvitationTool: ToolConfig<
|
||||
ZoomGetMeetingInvitationParams,
|
||||
ZoomGetMeetingInvitationResponse
|
||||
> = {
|
||||
id: 'zoom_get_meeting_invitation',
|
||||
name: 'Zoom Get Meeting Invitation',
|
||||
description: 'Get the meeting invitation text for a Zoom meeting',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zoom',
|
||||
requiredScopes: ['meeting:read:invitation'],
|
||||
},
|
||||
|
||||
params: {
|
||||
meetingId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The meeting ID (e.g., "1234567890" or "85746065432")',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`https://api.zoom.us/v2/meetings/${encodeURIComponent(params.meetingId)}/invitation`,
|
||||
method: 'GET',
|
||||
headers: (params) => {
|
||||
if (!params.accessToken) {
|
||||
throw new Error('Missing access token for Zoom API request')
|
||||
}
|
||||
return {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}))
|
||||
return {
|
||||
success: false,
|
||||
error: errorData.message || `Zoom API error: ${response.status} ${response.statusText}`,
|
||||
output: { invitation: '' },
|
||||
}
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
invitation: data.invitation || '',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
invitation: {
|
||||
type: 'string',
|
||||
description: 'The meeting invitation text',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type {
|
||||
ZoomGetMeetingRecordingsParams,
|
||||
ZoomGetMeetingRecordingsResponse,
|
||||
} from '@/tools/zoom/types'
|
||||
import { RECORDING_OUTPUT_PROPERTIES } from '@/tools/zoom/types'
|
||||
|
||||
export const zoomGetMeetingRecordingsTool: ToolConfig<
|
||||
ZoomGetMeetingRecordingsParams,
|
||||
ZoomGetMeetingRecordingsResponse
|
||||
> = {
|
||||
id: 'zoom_get_meeting_recordings',
|
||||
name: 'Zoom Get Meeting Recordings',
|
||||
description: 'Get all recordings for a specific Zoom meeting',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zoom',
|
||||
requiredScopes: ['cloud_recording:read:list_recording_files'],
|
||||
},
|
||||
|
||||
params: {
|
||||
meetingId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'The meeting ID or meeting UUID (e.g., "1234567890" or "4444AAABBBccccc12345==")',
|
||||
},
|
||||
includeFolderItems: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Include items within a folder',
|
||||
},
|
||||
ttl: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Time to live for download URLs in seconds (max 604800)',
|
||||
},
|
||||
downloadFiles: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Download recording files into file outputs',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: '/api/tools/zoom/get-recordings',
|
||||
method: 'POST',
|
||||
headers: () => ({
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params) => ({
|
||||
accessToken: params.accessToken,
|
||||
meetingId: params.meetingId,
|
||||
includeFolderItems: params.includeFolderItems,
|
||||
ttl: params.ttl,
|
||||
downloadFiles: params.downloadFiles,
|
||||
}),
|
||||
},
|
||||
|
||||
outputs: {
|
||||
recording: {
|
||||
type: 'object',
|
||||
description: 'The meeting recording with all files',
|
||||
properties: RECORDING_OUTPUT_PROPERTIES,
|
||||
},
|
||||
files: {
|
||||
type: 'file[]',
|
||||
description: 'Downloaded recording files',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// Zoom tools exports
|
||||
export { zoomCreateMeetingTool } from './create_meeting'
|
||||
export { zoomDeleteMeetingTool } from './delete_meeting'
|
||||
export { zoomDeleteRecordingTool } from './delete_recording'
|
||||
export { zoomGetMeetingTool } from './get_meeting'
|
||||
export { zoomGetMeetingInvitationTool } from './get_meeting_invitation'
|
||||
export { zoomGetMeetingRecordingsTool } from './get_meeting_recordings'
|
||||
export { zoomListMeetingsTool } from './list_meetings'
|
||||
export { zoomListPastParticipantsTool } from './list_past_participants'
|
||||
export { zoomListRecordingsTool } from './list_recordings'
|
||||
export { zoomUpdateMeetingTool } from './update_meeting'
|
||||
@@ -0,0 +1,141 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ZoomListMeetingsParams, ZoomListMeetingsResponse } from '@/tools/zoom/types'
|
||||
import {
|
||||
MEETING_LIST_ITEM_OUTPUT_PROPERTIES,
|
||||
MEETING_PAGE_INFO_OUTPUT_PROPERTIES,
|
||||
} from '@/tools/zoom/types'
|
||||
|
||||
export const zoomListMeetingsTool: ToolConfig<ZoomListMeetingsParams, ZoomListMeetingsResponse> = {
|
||||
id: 'zoom_list_meetings',
|
||||
name: 'Zoom List Meetings',
|
||||
description: 'List all meetings for a Zoom user',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zoom',
|
||||
requiredScopes: ['meeting:read:list_meetings'],
|
||||
},
|
||||
|
||||
params: {
|
||||
userId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'The user ID or email address (e.g., "me", "user@example.com", or "AbcDefGHi"). Use "me" for the authenticated user.',
|
||||
},
|
||||
type: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Meeting type filter: scheduled, live, upcoming, upcoming_meetings, or previous_meetings',
|
||||
},
|
||||
pageSize: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of records per page, 1-300 (e.g., 30, 50, 100)',
|
||||
},
|
||||
nextPageToken: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Token for pagination to get next page of results',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const baseUrl = `https://api.zoom.us/v2/users/${encodeURIComponent(params.userId)}/meetings`
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.type) {
|
||||
queryParams.append('type', params.type)
|
||||
}
|
||||
if (params.pageSize) {
|
||||
queryParams.append('page_size', String(params.pageSize))
|
||||
}
|
||||
if (params.nextPageToken) {
|
||||
queryParams.append('next_page_token', params.nextPageToken)
|
||||
}
|
||||
|
||||
const queryString = queryParams.toString()
|
||||
return queryString ? `${baseUrl}?${queryString}` : baseUrl
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => {
|
||||
if (!params.accessToken) {
|
||||
throw new Error('Missing access token for Zoom API request')
|
||||
}
|
||||
return {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}))
|
||||
return {
|
||||
success: false,
|
||||
error: errorData.message || `Zoom API error: ${response.status} ${response.statusText}`,
|
||||
output: {
|
||||
meetings: [],
|
||||
pageInfo: {
|
||||
pageCount: 0,
|
||||
pageNumber: 0,
|
||||
pageSize: 0,
|
||||
totalRecords: 0,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
meetings: (data.meetings || []).map((meeting: any) => ({
|
||||
id: meeting.id,
|
||||
uuid: meeting.uuid,
|
||||
host_id: meeting.host_id,
|
||||
topic: meeting.topic,
|
||||
type: meeting.type,
|
||||
start_time: meeting.start_time,
|
||||
duration: meeting.duration,
|
||||
timezone: meeting.timezone,
|
||||
agenda: meeting.agenda,
|
||||
created_at: meeting.created_at,
|
||||
join_url: meeting.join_url,
|
||||
})),
|
||||
pageInfo: {
|
||||
pageCount: data.page_count || 0,
|
||||
pageNumber: data.page_number || 0,
|
||||
pageSize: data.page_size || 0,
|
||||
totalRecords: data.total_records || 0,
|
||||
nextPageToken: data.next_page_token,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
meetings: {
|
||||
type: 'array',
|
||||
description: 'List of meetings',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: MEETING_LIST_ITEM_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
pageInfo: {
|
||||
type: 'object',
|
||||
description: 'Pagination information',
|
||||
properties: MEETING_PAGE_INFO_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type {
|
||||
ZoomListPastParticipantsParams,
|
||||
ZoomListPastParticipantsResponse,
|
||||
} from '@/tools/zoom/types'
|
||||
import {
|
||||
PARTICIPANT_OUTPUT_PROPERTIES,
|
||||
PARTICIPANT_PAGE_INFO_OUTPUT_PROPERTIES,
|
||||
} from '@/tools/zoom/types'
|
||||
|
||||
export const zoomListPastParticipantsTool: ToolConfig<
|
||||
ZoomListPastParticipantsParams,
|
||||
ZoomListPastParticipantsResponse
|
||||
> = {
|
||||
id: 'zoom_list_past_participants',
|
||||
name: 'Zoom List Past Participants',
|
||||
description: 'List participants from a past Zoom meeting',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zoom',
|
||||
requiredScopes: ['meeting:read:list_past_participants'],
|
||||
},
|
||||
|
||||
params: {
|
||||
meetingId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The past meeting ID or UUID (e.g., "1234567890" or "4444AAABBBccccc12345==")',
|
||||
},
|
||||
pageSize: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of records per page, 1-300 (e.g., 30, 50, 100)',
|
||||
},
|
||||
nextPageToken: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Token for pagination to get next page of results',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const baseUrl = `https://api.zoom.us/v2/past_meetings/${encodeURIComponent(params.meetingId)}/participants`
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.pageSize) {
|
||||
queryParams.append('page_size', String(params.pageSize))
|
||||
}
|
||||
if (params.nextPageToken) {
|
||||
queryParams.append('next_page_token', params.nextPageToken)
|
||||
}
|
||||
|
||||
const queryString = queryParams.toString()
|
||||
return queryString ? `${baseUrl}?${queryString}` : baseUrl
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => {
|
||||
if (!params.accessToken) {
|
||||
throw new Error('Missing access token for Zoom API request')
|
||||
}
|
||||
return {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}))
|
||||
return {
|
||||
success: false,
|
||||
error: errorData.message || `Zoom API error: ${response.status} ${response.statusText}`,
|
||||
output: {
|
||||
participants: [],
|
||||
pageInfo: {
|
||||
pageSize: 0,
|
||||
totalRecords: 0,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
participants: (data.participants || []).map((participant: any) => ({
|
||||
id: participant.id,
|
||||
user_id: participant.user_id,
|
||||
name: participant.name,
|
||||
user_email: participant.user_email,
|
||||
join_time: participant.join_time,
|
||||
leave_time: participant.leave_time,
|
||||
duration: participant.duration,
|
||||
attentiveness_score: participant.attentiveness_score,
|
||||
failover: participant.failover,
|
||||
status: participant.status,
|
||||
})),
|
||||
pageInfo: {
|
||||
pageSize: data.page_size || 0,
|
||||
totalRecords: data.total_records || 0,
|
||||
nextPageToken: data.next_page_token,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
participants: {
|
||||
type: 'array',
|
||||
description: 'List of meeting participants',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: PARTICIPANT_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
pageInfo: {
|
||||
type: 'object',
|
||||
description: 'Pagination information',
|
||||
properties: PARTICIPANT_PAGE_INFO_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ZoomListRecordingsParams, ZoomListRecordingsResponse } from '@/tools/zoom/types'
|
||||
import {
|
||||
RECORDING_OUTPUT_PROPERTIES,
|
||||
RECORDING_PAGE_INFO_OUTPUT_PROPERTIES,
|
||||
} from '@/tools/zoom/types'
|
||||
|
||||
export const zoomListRecordingsTool: ToolConfig<
|
||||
ZoomListRecordingsParams,
|
||||
ZoomListRecordingsResponse
|
||||
> = {
|
||||
id: 'zoom_list_recordings',
|
||||
name: 'Zoom List Recordings',
|
||||
description: 'List all cloud recordings for a Zoom user',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zoom',
|
||||
requiredScopes: ['cloud_recording:read:list_user_recordings'],
|
||||
},
|
||||
|
||||
params: {
|
||||
userId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'The user ID or email address (e.g., "me", "user@example.com", or "AbcDefGHi"). Use "me" for the authenticated user.',
|
||||
},
|
||||
from: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Start date in yyyy-mm-dd format (within last 6 months)',
|
||||
},
|
||||
to: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'End date in yyyy-mm-dd format',
|
||||
},
|
||||
pageSize: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of records per page, 1-300 (e.g., 30, 50, 100)',
|
||||
},
|
||||
nextPageToken: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Token for pagination to get next page of results',
|
||||
},
|
||||
trash: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Set to true to list recordings from trash',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const baseUrl = `https://api.zoom.us/v2/users/${encodeURIComponent(params.userId)}/recordings`
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.from) {
|
||||
queryParams.append('from', params.from)
|
||||
}
|
||||
if (params.to) {
|
||||
queryParams.append('to', params.to)
|
||||
}
|
||||
if (params.pageSize) {
|
||||
queryParams.append('page_size', String(params.pageSize))
|
||||
}
|
||||
if (params.nextPageToken) {
|
||||
queryParams.append('next_page_token', params.nextPageToken)
|
||||
}
|
||||
if (params.trash) {
|
||||
queryParams.append('trash', 'true')
|
||||
}
|
||||
|
||||
const queryString = queryParams.toString()
|
||||
return queryString ? `${baseUrl}?${queryString}` : baseUrl
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => {
|
||||
if (!params.accessToken) {
|
||||
throw new Error('Missing access token for Zoom API request')
|
||||
}
|
||||
return {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}))
|
||||
return {
|
||||
success: false,
|
||||
error: errorData.message || `Zoom API error: ${response.status} ${response.statusText}`,
|
||||
output: {
|
||||
recordings: [],
|
||||
pageInfo: {
|
||||
from: '',
|
||||
to: '',
|
||||
pageSize: 0,
|
||||
totalRecords: 0,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
recordings: (data.meetings || []).map((recording: any) => ({
|
||||
uuid: recording.uuid,
|
||||
id: recording.id,
|
||||
account_id: recording.account_id,
|
||||
host_id: recording.host_id,
|
||||
topic: recording.topic,
|
||||
type: recording.type,
|
||||
start_time: recording.start_time,
|
||||
duration: recording.duration,
|
||||
total_size: recording.total_size,
|
||||
recording_count: recording.recording_count,
|
||||
share_url: recording.share_url,
|
||||
recording_files: recording.recording_files || [],
|
||||
})),
|
||||
pageInfo: {
|
||||
from: data.from || '',
|
||||
to: data.to || '',
|
||||
pageSize: data.page_size || 0,
|
||||
totalRecords: data.total_records || 0,
|
||||
nextPageToken: data.next_page_token,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
recordings: {
|
||||
type: 'array',
|
||||
description: 'List of recordings',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: RECORDING_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
pageInfo: {
|
||||
type: 'object',
|
||||
description: 'Pagination information',
|
||||
properties: RECORDING_PAGE_INFO_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,625 @@
|
||||
// Common types for Zoom tools
|
||||
import type { OutputProperty, ToolFileData, ToolResponse } from '@/tools/types'
|
||||
|
||||
/**
|
||||
* Shared output property definitions for Zoom API responses.
|
||||
* These are reusable across all Zoom tools to ensure consistency.
|
||||
* Based on the official Zoom API documentation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Output definition for meeting settings objects
|
||||
* @see https://developers.zoom.us/docs/api/rest/reference/zoom-api/methods/#operation/meetingCreate
|
||||
*/
|
||||
export const MEETING_SETTINGS_OUTPUT_PROPERTIES = {
|
||||
host_video: { type: 'boolean', description: 'Start with host video on' },
|
||||
participant_video: { type: 'boolean', description: 'Start with participant video on' },
|
||||
join_before_host: { type: 'boolean', description: 'Allow participants to join before host' },
|
||||
mute_upon_entry: { type: 'boolean', description: 'Mute participants upon entry' },
|
||||
watermark: { type: 'boolean', description: 'Add watermark when viewing shared screen' },
|
||||
audio: { type: 'string', description: 'Audio options: both, telephony, or voip' },
|
||||
auto_recording: { type: 'string', description: 'Auto recording: local, cloud, or none' },
|
||||
waiting_room: { type: 'boolean', description: 'Enable waiting room' },
|
||||
meeting_authentication: { type: 'boolean', description: 'Require meeting authentication' },
|
||||
approval_type: { type: 'number', description: 'Approval type: 0=auto, 1=manual, 2=none' },
|
||||
} as const satisfies Record<string, OutputProperty>
|
||||
|
||||
/**
|
||||
* Complete meeting settings object output definition
|
||||
*/
|
||||
export const MEETING_SETTINGS_OUTPUT: OutputProperty = {
|
||||
type: 'object',
|
||||
description: 'Meeting settings',
|
||||
properties: MEETING_SETTINGS_OUTPUT_PROPERTIES,
|
||||
}
|
||||
|
||||
/**
|
||||
* Output definition for recurrence objects in recurring meetings
|
||||
* @see https://developers.zoom.us/docs/api/rest/reference/zoom-api/methods/#operation/meetingCreate
|
||||
*/
|
||||
export const RECURRENCE_OUTPUT_PROPERTIES = {
|
||||
type: { type: 'number', description: 'Recurrence type: 1=daily, 2=weekly, 3=monthly' },
|
||||
repeat_interval: { type: 'number', description: 'Interval between recurring meetings' },
|
||||
weekly_days: {
|
||||
type: 'string',
|
||||
description: 'Days of week for weekly recurrence (1-7, comma-separated)',
|
||||
},
|
||||
monthly_day: { type: 'number', description: 'Day of month for monthly recurrence' },
|
||||
monthly_week: { type: 'number', description: 'Week of month for monthly recurrence' },
|
||||
monthly_week_day: { type: 'number', description: 'Day of week for monthly recurrence' },
|
||||
end_times: { type: 'number', description: 'Number of occurrences' },
|
||||
end_date_time: { type: 'string', description: 'End date time in ISO 8601 format' },
|
||||
} as const satisfies Record<string, OutputProperty>
|
||||
|
||||
/**
|
||||
* Complete recurrence object output definition
|
||||
*/
|
||||
export const RECURRENCE_OUTPUT: OutputProperty = {
|
||||
type: 'object',
|
||||
description: 'Recurrence settings for recurring meetings',
|
||||
properties: RECURRENCE_OUTPUT_PROPERTIES,
|
||||
}
|
||||
|
||||
/**
|
||||
* Output definition for occurrence objects in recurring meetings
|
||||
* @see https://developers.zoom.us/docs/api/rest/reference/zoom-api/methods/#operation/meeting
|
||||
*/
|
||||
export const OCCURRENCE_OUTPUT_PROPERTIES = {
|
||||
occurrence_id: { type: 'string', description: 'Occurrence ID' },
|
||||
start_time: { type: 'string', description: 'Start time in ISO 8601 format' },
|
||||
duration: { type: 'number', description: 'Duration in minutes' },
|
||||
status: { type: 'string', description: 'Occurrence status' },
|
||||
} as const satisfies Record<string, OutputProperty>
|
||||
|
||||
/**
|
||||
* Complete occurrences array output definition
|
||||
*/
|
||||
export const OCCURRENCES_OUTPUT: OutputProperty = {
|
||||
type: 'array',
|
||||
description: 'Meeting occurrences for recurring meetings',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: OCCURRENCE_OUTPUT_PROPERTIES,
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Common meeting output properties shared across meeting tools
|
||||
* @see https://developers.zoom.us/docs/api/rest/reference/zoom-api/methods/#operation/meetingCreate
|
||||
* @see https://developers.zoom.us/docs/api/rest/reference/zoom-api/methods/#operation/meeting
|
||||
*/
|
||||
export const MEETING_OUTPUT_PROPERTIES = {
|
||||
id: { type: 'number', description: 'Meeting ID' },
|
||||
uuid: { type: 'string', description: 'Meeting UUID' },
|
||||
host_id: { type: 'string', description: 'Host user ID' },
|
||||
host_email: { type: 'string', description: 'Host email address' },
|
||||
topic: { type: 'string', description: 'Meeting topic' },
|
||||
type: {
|
||||
type: 'number',
|
||||
description:
|
||||
'Meeting type: 1=instant, 2=scheduled, 3=recurring no fixed time, 8=recurring fixed time',
|
||||
},
|
||||
status: { type: 'string', description: 'Meeting status (e.g., waiting, started)' },
|
||||
start_time: { type: 'string', description: 'Start time in ISO 8601 format' },
|
||||
duration: { type: 'number', description: 'Duration in minutes' },
|
||||
timezone: { type: 'string', description: 'Timezone (e.g., America/Los_Angeles)' },
|
||||
agenda: { type: 'string', description: 'Meeting agenda' },
|
||||
created_at: { type: 'string', description: 'Creation timestamp in ISO 8601 format' },
|
||||
start_url: { type: 'string', description: 'URL for host to start the meeting' },
|
||||
join_url: { type: 'string', description: 'URL for participants to join the meeting' },
|
||||
password: { type: 'string', description: 'Meeting password' },
|
||||
h323_password: { type: 'string', description: 'H.323/SIP room system password' },
|
||||
pstn_password: { type: 'string', description: 'PSTN password for phone dial-in' },
|
||||
encrypted_password: { type: 'string', description: 'Encrypted password for joining' },
|
||||
settings: MEETING_SETTINGS_OUTPUT,
|
||||
recurrence: RECURRENCE_OUTPUT,
|
||||
occurrences: OCCURRENCES_OUTPUT,
|
||||
} as const satisfies Record<string, OutputProperty>
|
||||
|
||||
/**
|
||||
* Output definition for meeting object (used in create/get meeting responses)
|
||||
*/
|
||||
export const MEETING_OUTPUT: OutputProperty = {
|
||||
type: 'object',
|
||||
description: 'Meeting object with all properties',
|
||||
properties: MEETING_OUTPUT_PROPERTIES,
|
||||
}
|
||||
|
||||
/**
|
||||
* Meeting list item output properties (subset returned in list responses)
|
||||
* @see https://developers.zoom.us/docs/api/rest/reference/zoom-api/methods/#operation/meetings
|
||||
*/
|
||||
export const MEETING_LIST_ITEM_OUTPUT_PROPERTIES = {
|
||||
id: { type: 'number', description: 'Meeting ID' },
|
||||
uuid: { type: 'string', description: 'Meeting UUID' },
|
||||
host_id: { type: 'string', description: 'Host user ID' },
|
||||
topic: { type: 'string', description: 'Meeting topic' },
|
||||
type: { type: 'number', description: 'Meeting type' },
|
||||
start_time: { type: 'string', description: 'Start time in ISO 8601 format' },
|
||||
duration: { type: 'number', description: 'Duration in minutes' },
|
||||
timezone: { type: 'string', description: 'Timezone' },
|
||||
agenda: { type: 'string', description: 'Meeting agenda' },
|
||||
created_at: { type: 'string', description: 'Creation timestamp' },
|
||||
join_url: { type: 'string', description: 'URL for participants to join' },
|
||||
} as const satisfies Record<string, OutputProperty>
|
||||
|
||||
/**
|
||||
* Output definition for meetings array in list responses
|
||||
*/
|
||||
export const MEETINGS_ARRAY_OUTPUT: OutputProperty = {
|
||||
type: 'array',
|
||||
description: 'List of meetings',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: MEETING_LIST_ITEM_OUTPUT_PROPERTIES,
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Pagination output properties for meeting list endpoints
|
||||
* @see https://developers.zoom.us/docs/api/rest/reference/zoom-api/methods/#operation/meetings
|
||||
*/
|
||||
export const MEETING_PAGE_INFO_OUTPUT_PROPERTIES = {
|
||||
pageCount: { type: 'number', description: 'Total number of pages' },
|
||||
pageNumber: { type: 'number', description: 'Current page number' },
|
||||
pageSize: { type: 'number', description: 'Number of records per page' },
|
||||
totalRecords: { type: 'number', description: 'Total number of records' },
|
||||
nextPageToken: { type: 'string', description: 'Token for next page of results' },
|
||||
} as const satisfies Record<string, OutputProperty>
|
||||
|
||||
/**
|
||||
* Complete page info output definition for meeting lists
|
||||
*/
|
||||
export const MEETING_PAGE_INFO_OUTPUT: OutputProperty = {
|
||||
type: 'object',
|
||||
description: 'Pagination information',
|
||||
properties: MEETING_PAGE_INFO_OUTPUT_PROPERTIES,
|
||||
}
|
||||
|
||||
/**
|
||||
* Output definition for recording file objects
|
||||
* @see https://developers.zoom.us/docs/api/rest/reference/zoom-api/methods/#operation/recordingGet
|
||||
*/
|
||||
export const RECORDING_FILE_OUTPUT_PROPERTIES = {
|
||||
id: { type: 'string', description: 'Recording file ID' },
|
||||
meeting_id: { type: 'string', description: 'Meeting ID associated with the recording' },
|
||||
recording_start: { type: 'string', description: 'Start time of the recording' },
|
||||
recording_end: { type: 'string', description: 'End time of the recording' },
|
||||
file_type: { type: 'string', description: 'Type of recording file (MP4, M4A, etc.)' },
|
||||
file_extension: { type: 'string', description: 'File extension' },
|
||||
file_size: { type: 'number', description: 'File size in bytes' },
|
||||
play_url: { type: 'string', description: 'URL to play the recording' },
|
||||
download_url: { type: 'string', description: 'URL to download the recording' },
|
||||
status: { type: 'string', description: 'Recording status' },
|
||||
recording_type: {
|
||||
type: 'string',
|
||||
description: 'Type of recording (shared_screen, audio_only, etc.)',
|
||||
},
|
||||
} as const satisfies Record<string, OutputProperty>
|
||||
|
||||
/**
|
||||
* Complete recording files array output definition
|
||||
*/
|
||||
export const RECORDING_FILES_OUTPUT: OutputProperty = {
|
||||
type: 'array',
|
||||
description: 'List of recording files',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: RECORDING_FILE_OUTPUT_PROPERTIES,
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Output definition for recording objects
|
||||
* @see https://developers.zoom.us/docs/api/rest/reference/zoom-api/methods/#operation/recordingGet
|
||||
* @see https://developers.zoom.us/docs/api/rest/reference/zoom-api/methods/#operation/recordingsList
|
||||
*/
|
||||
export const RECORDING_OUTPUT_PROPERTIES = {
|
||||
uuid: { type: 'string', description: 'Meeting UUID' },
|
||||
id: { type: 'number', description: 'Meeting ID' },
|
||||
account_id: { type: 'string', description: 'Account ID' },
|
||||
host_id: { type: 'string', description: 'Host user ID' },
|
||||
topic: { type: 'string', description: 'Meeting topic' },
|
||||
type: { type: 'number', description: 'Meeting type' },
|
||||
start_time: { type: 'string', description: 'Meeting start time' },
|
||||
duration: { type: 'number', description: 'Meeting duration in minutes' },
|
||||
total_size: { type: 'number', description: 'Total size of all recordings in bytes' },
|
||||
recording_count: { type: 'number', description: 'Number of recording files' },
|
||||
share_url: { type: 'string', description: 'URL to share recordings' },
|
||||
recording_files: RECORDING_FILES_OUTPUT,
|
||||
} as const satisfies Record<string, OutputProperty>
|
||||
|
||||
/**
|
||||
* Complete recording object output definition
|
||||
*/
|
||||
export const RECORDING_OUTPUT: OutputProperty = {
|
||||
type: 'object',
|
||||
description: 'Recording object with all files',
|
||||
properties: RECORDING_OUTPUT_PROPERTIES,
|
||||
}
|
||||
|
||||
/**
|
||||
* Output definition for recordings array in list responses
|
||||
*/
|
||||
export const RECORDINGS_ARRAY_OUTPUT: OutputProperty = {
|
||||
type: 'array',
|
||||
description: 'List of recordings',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: RECORDING_OUTPUT_PROPERTIES,
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Pagination output properties for recording list endpoints
|
||||
* @see https://developers.zoom.us/docs/api/rest/reference/zoom-api/methods/#operation/recordingsList
|
||||
*/
|
||||
export const RECORDING_PAGE_INFO_OUTPUT_PROPERTIES = {
|
||||
from: { type: 'string', description: 'Start date of query range' },
|
||||
to: { type: 'string', description: 'End date of query range' },
|
||||
pageSize: { type: 'number', description: 'Number of records per page' },
|
||||
totalRecords: { type: 'number', description: 'Total number of records' },
|
||||
nextPageToken: { type: 'string', description: 'Token for next page of results' },
|
||||
} as const satisfies Record<string, OutputProperty>
|
||||
|
||||
/**
|
||||
* Complete page info output definition for recording lists
|
||||
*/
|
||||
export const RECORDING_PAGE_INFO_OUTPUT: OutputProperty = {
|
||||
type: 'object',
|
||||
description: 'Pagination information',
|
||||
properties: RECORDING_PAGE_INFO_OUTPUT_PROPERTIES,
|
||||
}
|
||||
|
||||
/**
|
||||
* Output definition for participant objects
|
||||
* @see https://developers.zoom.us/docs/api/rest/reference/zoom-api/methods/#operation/pastMeetingParticipants
|
||||
*/
|
||||
export const PARTICIPANT_OUTPUT_PROPERTIES = {
|
||||
id: { type: 'string', description: 'Participant unique identifier' },
|
||||
user_id: { type: 'string', description: 'User ID if registered Zoom user' },
|
||||
name: { type: 'string', description: 'Participant display name' },
|
||||
user_email: { type: 'string', description: 'Participant email address' },
|
||||
join_time: { type: 'string', description: 'Time when participant joined (ISO 8601)' },
|
||||
leave_time: { type: 'string', description: 'Time when participant left (ISO 8601)' },
|
||||
duration: { type: 'number', description: 'Duration in seconds participant was in meeting' },
|
||||
attentiveness_score: { type: 'string', description: 'Attentiveness score (deprecated)' },
|
||||
failover: {
|
||||
type: 'boolean',
|
||||
description: 'Whether participant failed over to another data center',
|
||||
},
|
||||
status: { type: 'string', description: 'Participant status' },
|
||||
} as const satisfies Record<string, OutputProperty>
|
||||
|
||||
/**
|
||||
* Complete participants array output definition
|
||||
*/
|
||||
export const PARTICIPANTS_ARRAY_OUTPUT: OutputProperty = {
|
||||
type: 'array',
|
||||
description: 'List of meeting participants',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: PARTICIPANT_OUTPUT_PROPERTIES,
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Pagination output properties for participant list endpoints
|
||||
* @see https://developers.zoom.us/docs/api/rest/reference/zoom-api/methods/#operation/pastMeetingParticipants
|
||||
*/
|
||||
export const PARTICIPANT_PAGE_INFO_OUTPUT_PROPERTIES = {
|
||||
pageSize: { type: 'number', description: 'Number of records per page' },
|
||||
totalRecords: { type: 'number', description: 'Total number of records' },
|
||||
nextPageToken: { type: 'string', description: 'Token for next page of results' },
|
||||
} as const satisfies Record<string, OutputProperty>
|
||||
|
||||
/**
|
||||
* Complete page info output definition for participant lists
|
||||
*/
|
||||
export const PARTICIPANT_PAGE_INFO_OUTPUT: OutputProperty = {
|
||||
type: 'object',
|
||||
description: 'Pagination information',
|
||||
properties: PARTICIPANT_PAGE_INFO_OUTPUT_PROPERTIES,
|
||||
}
|
||||
|
||||
// Common parameters for all Zoom tools
|
||||
interface ZoomBaseParams {
|
||||
accessToken: string
|
||||
}
|
||||
|
||||
// Meeting types
|
||||
export type ZoomMeetingType = 1 | 2 | 3 | 8 // 1=instant, 2=scheduled, 3=recurring no fixed time, 8=recurring fixed time
|
||||
|
||||
interface ZoomMeetingSettings {
|
||||
host_video?: boolean
|
||||
participant_video?: boolean
|
||||
join_before_host?: boolean
|
||||
mute_upon_entry?: boolean
|
||||
watermark?: boolean
|
||||
audio?: 'both' | 'telephony' | 'voip'
|
||||
auto_recording?: 'local' | 'cloud' | 'none'
|
||||
waiting_room?: boolean
|
||||
meeting_authentication?: boolean
|
||||
approval_type?: 0 | 1 | 2 // 0=auto, 1=manual, 2=none
|
||||
}
|
||||
|
||||
interface ZoomMeeting {
|
||||
id: number
|
||||
uuid: string
|
||||
host_id: string
|
||||
host_email?: string
|
||||
topic: string
|
||||
type: ZoomMeetingType
|
||||
status?: string
|
||||
start_time?: string
|
||||
duration?: number
|
||||
timezone?: string
|
||||
agenda?: string
|
||||
created_at?: string
|
||||
start_url?: string
|
||||
join_url: string
|
||||
password?: string
|
||||
h323_password?: string
|
||||
pstn_password?: string
|
||||
encrypted_password?: string
|
||||
settings?: ZoomMeetingSettings
|
||||
recurrence?: {
|
||||
type: number
|
||||
repeat_interval?: number
|
||||
weekly_days?: string
|
||||
monthly_day?: number
|
||||
monthly_week?: number
|
||||
monthly_week_day?: number
|
||||
end_times?: number
|
||||
end_date_time?: string
|
||||
}
|
||||
occurrences?: Array<{
|
||||
occurrence_id: string
|
||||
start_time: string
|
||||
duration: number
|
||||
status: string
|
||||
}>
|
||||
}
|
||||
|
||||
interface ZoomMeetingListResponse {
|
||||
page_count: number
|
||||
page_number: number
|
||||
page_size: number
|
||||
total_records: number
|
||||
next_page_token?: string
|
||||
meetings: ZoomMeeting[]
|
||||
}
|
||||
|
||||
// Create Meeting tool types
|
||||
export interface ZoomCreateMeetingParams extends ZoomBaseParams {
|
||||
userId: string
|
||||
topic: string
|
||||
type?: ZoomMeetingType
|
||||
startTime?: string
|
||||
duration?: number
|
||||
timezone?: string
|
||||
password?: string
|
||||
agenda?: string
|
||||
hostVideo?: boolean
|
||||
participantVideo?: boolean
|
||||
joinBeforeHost?: boolean
|
||||
muteUponEntry?: boolean
|
||||
waitingRoom?: boolean
|
||||
autoRecording?: 'local' | 'cloud' | 'none'
|
||||
}
|
||||
|
||||
export interface ZoomCreateMeetingResponse extends ToolResponse {
|
||||
output: {
|
||||
meeting: ZoomMeeting
|
||||
}
|
||||
}
|
||||
|
||||
// List Meetings tool types
|
||||
export interface ZoomListMeetingsParams extends ZoomBaseParams {
|
||||
userId: string
|
||||
type?: 'scheduled' | 'live' | 'upcoming' | 'upcoming_meetings' | 'previous_meetings'
|
||||
pageSize?: number
|
||||
nextPageToken?: string
|
||||
}
|
||||
|
||||
export interface ZoomListMeetingsResponse extends ToolResponse {
|
||||
output: {
|
||||
meetings: ZoomMeeting[]
|
||||
pageInfo: {
|
||||
pageCount: number
|
||||
pageNumber: number
|
||||
pageSize: number
|
||||
totalRecords: number
|
||||
nextPageToken?: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get Meeting tool types
|
||||
export interface ZoomGetMeetingParams extends ZoomBaseParams {
|
||||
meetingId: string
|
||||
occurrenceId?: string
|
||||
showPreviousOccurrences?: boolean
|
||||
}
|
||||
|
||||
export interface ZoomGetMeetingResponse extends ToolResponse {
|
||||
output: {
|
||||
meeting: ZoomMeeting
|
||||
}
|
||||
}
|
||||
|
||||
// Update Meeting tool types
|
||||
export interface ZoomUpdateMeetingParams extends ZoomBaseParams {
|
||||
meetingId: string
|
||||
topic?: string
|
||||
type?: ZoomMeetingType
|
||||
startTime?: string
|
||||
duration?: number
|
||||
timezone?: string
|
||||
password?: string
|
||||
agenda?: string
|
||||
hostVideo?: boolean
|
||||
participantVideo?: boolean
|
||||
joinBeforeHost?: boolean
|
||||
muteUponEntry?: boolean
|
||||
waitingRoom?: boolean
|
||||
autoRecording?: 'local' | 'cloud' | 'none'
|
||||
}
|
||||
|
||||
export interface ZoomUpdateMeetingResponse extends ToolResponse {
|
||||
output: {
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
// Delete Meeting tool types
|
||||
export interface ZoomDeleteMeetingParams extends ZoomBaseParams {
|
||||
meetingId: string
|
||||
occurrenceId?: string
|
||||
scheduleForReminder?: boolean
|
||||
cancelMeetingReminder?: boolean
|
||||
}
|
||||
|
||||
export interface ZoomDeleteMeetingResponse extends ToolResponse {
|
||||
output: {
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
// Get Meeting Invitation tool types
|
||||
export interface ZoomGetMeetingInvitationParams extends ZoomBaseParams {
|
||||
meetingId: string
|
||||
}
|
||||
|
||||
export interface ZoomGetMeetingInvitationResponse extends ToolResponse {
|
||||
output: {
|
||||
invitation: string
|
||||
}
|
||||
}
|
||||
|
||||
// Recording types
|
||||
interface ZoomRecordingFile {
|
||||
id: string
|
||||
meeting_id: string
|
||||
recording_start: string
|
||||
recording_end: string
|
||||
file_type: string
|
||||
file_extension: string
|
||||
file_size: number
|
||||
play_url?: string
|
||||
download_url?: string
|
||||
status: string
|
||||
recording_type: string
|
||||
}
|
||||
|
||||
interface ZoomRecording {
|
||||
uuid: string
|
||||
id: number
|
||||
account_id: string
|
||||
host_id: string
|
||||
topic: string
|
||||
type: number
|
||||
start_time: string
|
||||
duration: number
|
||||
total_size: number
|
||||
recording_count: number
|
||||
share_url?: string
|
||||
recording_files: ZoomRecordingFile[]
|
||||
}
|
||||
|
||||
// List Recordings tool types
|
||||
export interface ZoomListRecordingsParams extends ZoomBaseParams {
|
||||
userId: string
|
||||
from?: string
|
||||
to?: string
|
||||
pageSize?: number
|
||||
nextPageToken?: string
|
||||
trash?: boolean
|
||||
trashType?: 'meeting_recordings' | 'recording_file'
|
||||
}
|
||||
|
||||
export interface ZoomListRecordingsResponse extends ToolResponse {
|
||||
output: {
|
||||
recordings: ZoomRecording[]
|
||||
pageInfo: {
|
||||
from: string
|
||||
to: string
|
||||
pageSize: number
|
||||
totalRecords: number
|
||||
nextPageToken?: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get Meeting Recordings tool types
|
||||
export interface ZoomGetMeetingRecordingsParams extends ZoomBaseParams {
|
||||
meetingId: string
|
||||
includeFolderItems?: boolean
|
||||
ttl?: number
|
||||
downloadFiles?: boolean
|
||||
}
|
||||
|
||||
export interface ZoomGetMeetingRecordingsResponse extends ToolResponse {
|
||||
output: {
|
||||
recording: ZoomRecording
|
||||
files?: ToolFileData[]
|
||||
}
|
||||
}
|
||||
|
||||
// Delete Recording tool types
|
||||
export interface ZoomDeleteRecordingParams extends ZoomBaseParams {
|
||||
meetingId: string
|
||||
recordingId?: string
|
||||
action?: 'trash' | 'delete'
|
||||
}
|
||||
|
||||
export interface ZoomDeleteRecordingResponse extends ToolResponse {
|
||||
output: {
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
// Participant types
|
||||
interface ZoomParticipant {
|
||||
id: string
|
||||
user_id?: string
|
||||
name: string
|
||||
user_email?: string
|
||||
join_time: string
|
||||
leave_time?: string
|
||||
duration: number
|
||||
attentiveness_score?: string
|
||||
failover?: boolean
|
||||
status?: string
|
||||
}
|
||||
|
||||
// List Past Participants tool types
|
||||
export interface ZoomListPastParticipantsParams extends ZoomBaseParams {
|
||||
meetingId: string
|
||||
pageSize?: number
|
||||
nextPageToken?: string
|
||||
}
|
||||
|
||||
export interface ZoomListPastParticipantsResponse extends ToolResponse {
|
||||
output: {
|
||||
participants: ZoomParticipant[]
|
||||
pageInfo: {
|
||||
pageSize: number
|
||||
totalRecords: number
|
||||
nextPageToken?: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Combined response type for block
|
||||
export type ZoomResponse =
|
||||
| ZoomCreateMeetingResponse
|
||||
| ZoomListMeetingsResponse
|
||||
| ZoomGetMeetingResponse
|
||||
| ZoomUpdateMeetingResponse
|
||||
| ZoomDeleteMeetingResponse
|
||||
| ZoomGetMeetingInvitationResponse
|
||||
| ZoomListRecordingsResponse
|
||||
| ZoomGetMeetingRecordingsResponse
|
||||
| ZoomDeleteRecordingResponse
|
||||
| ZoomListPastParticipantsResponse
|
||||
@@ -0,0 +1,196 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type { ZoomUpdateMeetingParams, ZoomUpdateMeetingResponse } from '@/tools/zoom/types'
|
||||
|
||||
export const zoomUpdateMeetingTool: ToolConfig<ZoomUpdateMeetingParams, ZoomUpdateMeetingResponse> =
|
||||
{
|
||||
id: 'zoom_update_meeting',
|
||||
name: 'Zoom Update Meeting',
|
||||
description: 'Update an existing Zoom meeting',
|
||||
version: '1.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'zoom',
|
||||
requiredScopes: ['meeting:update:meeting'],
|
||||
},
|
||||
|
||||
params: {
|
||||
meetingId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The meeting ID to update (e.g., "1234567890" or "85746065432")',
|
||||
},
|
||||
topic: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Meeting topic (e.g., "Weekly Team Standup" or "Project Review")',
|
||||
},
|
||||
type: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Meeting type: 1=instant, 2=scheduled, 3=recurring no fixed time, 8=recurring fixed time',
|
||||
},
|
||||
startTime: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Meeting start time in ISO 8601 format (e.g., 2025-06-03T10:00:00Z)',
|
||||
},
|
||||
duration: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Meeting duration in minutes (e.g., 30, 60, 90)',
|
||||
},
|
||||
timezone: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Timezone for the meeting (e.g., America/Los_Angeles)',
|
||||
},
|
||||
password: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Meeting password',
|
||||
},
|
||||
agenda: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Meeting agenda or description text',
|
||||
},
|
||||
hostVideo: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Start with host video on',
|
||||
},
|
||||
participantVideo: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Start with participant video on',
|
||||
},
|
||||
joinBeforeHost: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Allow participants to join before host',
|
||||
},
|
||||
muteUponEntry: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Mute participants upon entry',
|
||||
},
|
||||
waitingRoom: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Enable waiting room',
|
||||
},
|
||||
autoRecording: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Auto recording setting: local, cloud, or none',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => `https://api.zoom.us/v2/meetings/${encodeURIComponent(params.meetingId)}`,
|
||||
method: 'PATCH',
|
||||
headers: (params) => {
|
||||
if (!params.accessToken) {
|
||||
throw new Error('Missing access token for Zoom API request')
|
||||
}
|
||||
return {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}
|
||||
},
|
||||
body: (params) => {
|
||||
const body: Record<string, any> = {}
|
||||
|
||||
if (params.topic) {
|
||||
body.topic = params.topic
|
||||
}
|
||||
if (params.type != null) {
|
||||
body.type = params.type
|
||||
}
|
||||
if (params.startTime) {
|
||||
body.start_time = params.startTime
|
||||
}
|
||||
if (params.duration != null) {
|
||||
body.duration = params.duration
|
||||
}
|
||||
if (params.timezone) {
|
||||
body.timezone = params.timezone
|
||||
}
|
||||
if (params.password) {
|
||||
body.password = params.password
|
||||
}
|
||||
if (params.agenda) {
|
||||
body.agenda = params.agenda
|
||||
}
|
||||
|
||||
// Build settings object
|
||||
const settings: Record<string, any> = {}
|
||||
if (params.hostVideo != null) {
|
||||
settings.host_video = params.hostVideo
|
||||
}
|
||||
if (params.participantVideo != null) {
|
||||
settings.participant_video = params.participantVideo
|
||||
}
|
||||
if (params.joinBeforeHost != null) {
|
||||
settings.join_before_host = params.joinBeforeHost
|
||||
}
|
||||
if (params.muteUponEntry != null) {
|
||||
settings.mute_upon_entry = params.muteUponEntry
|
||||
}
|
||||
if (params.waitingRoom != null) {
|
||||
settings.waiting_room = params.waitingRoom
|
||||
}
|
||||
if (params.autoRecording) {
|
||||
settings.auto_recording = params.autoRecording
|
||||
}
|
||||
|
||||
if (Object.keys(settings).length > 0) {
|
||||
body.settings = settings
|
||||
}
|
||||
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}))
|
||||
return {
|
||||
success: false,
|
||||
error: errorData.message || `Zoom API error: ${response.status} ${response.statusText}`,
|
||||
output: { success: false },
|
||||
}
|
||||
}
|
||||
|
||||
// Zoom returns 204 No Content on successful update
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
success: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the meeting was updated successfully',
|
||||
},
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user