chore: import upstream snapshot with attribution
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) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
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) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
import type { ThriveAddUsersResponse, ThriveAudienceManagersParams } from '@/tools/thrive/types'
|
||||
import { THRIVE_ADD_USERS_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import {
|
||||
getThriveBaseUrl,
|
||||
getThriveHeaders,
|
||||
parseThriveArray,
|
||||
parseThriveResponse,
|
||||
} from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const addAudienceManagersTool: ToolConfig<
|
||||
ThriveAudienceManagersParams,
|
||||
ThriveAddUsersResponse
|
||||
> = {
|
||||
id: 'thrive_add_audience_managers',
|
||||
name: 'Thrive Add Audience Managers',
|
||||
description: 'Add managers to a Thrive audience with their permissions.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
audienceId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The audience id or audience reference',
|
||||
},
|
||||
managers: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'JSON array of manager objects (1-100). Each: {"reference":"user@example.com","permissions":{"audienceManager":{"manageContent":true,"assignments":true},"peopleManager":{"canViewLearnPage":true,"insights":false,"manage":false},"administrator":{"canAddAudienceManagers":false}}}',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/audiences/${encodeURIComponent(params.audienceId)}/managers`,
|
||||
method: 'POST',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
body: (params) => JSON.stringify(parseThriveArray(params.managers, 'managers')),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveAddUsersResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to add audience managers')
|
||||
return {
|
||||
success: true,
|
||||
output: { result: { success: data?.success ?? null, failure: data?.failure } },
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
result: {
|
||||
type: 'object',
|
||||
description:
|
||||
'The add/replace result, with successfully and unsuccessfully processed entities',
|
||||
properties: THRIVE_ADD_USERS_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
import type { ThriveAddUsersResponse, ThriveAudienceUsersParams } from '@/tools/thrive/types'
|
||||
import { THRIVE_ADD_USERS_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import {
|
||||
getThriveBaseUrl,
|
||||
getThriveHeaders,
|
||||
parseThriveArray,
|
||||
parseThriveResponse,
|
||||
} from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const addAudienceMembersTool: ToolConfig<ThriveAudienceUsersParams, ThriveAddUsersResponse> =
|
||||
{
|
||||
id: 'thrive_add_audience_members',
|
||||
name: 'Thrive Add Audience Members',
|
||||
description: 'Add members to a Thrive audience by email, ref, or id.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
audienceId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The audience id or audience reference',
|
||||
},
|
||||
users: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'JSON array of user emails/refs/ids to add (1-100). Example: ["user@example.com"]',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/audiences/${encodeURIComponent(params.audienceId)}/members`,
|
||||
method: 'POST',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
body: (params) => JSON.stringify(parseThriveArray<string>(params.users, 'users')),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveAddUsersResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to add audience members')
|
||||
return {
|
||||
success: true,
|
||||
output: { result: { success: data?.success ?? null, failure: data?.failure } },
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
result: {
|
||||
type: 'object',
|
||||
description:
|
||||
'The add/replace result, with successfully and unsuccessfully processed entities',
|
||||
properties: THRIVE_ADD_USERS_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import type { ThriveAddUserTagsParams, ThriveMessageResponse } from '@/tools/thrive/types'
|
||||
import {
|
||||
getThriveBaseUrl,
|
||||
getThriveHeaders,
|
||||
parseThriveArray,
|
||||
parseThriveResponse,
|
||||
} from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const addUserTagsTool: ToolConfig<ThriveAddUserTagsParams, ThriveMessageResponse> = {
|
||||
id: 'thrive_add_user_tags',
|
||||
name: 'Thrive Add User Tags',
|
||||
description: 'Add one or more tags to a learner in Thrive.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
userId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The learner ID',
|
||||
},
|
||||
tags: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'JSON array of tag names to add (1-100). Example: ["leadership"]',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/users/${encodeURIComponent(params.userId)}/tags`,
|
||||
method: 'POST',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
body: (params) => ({ tags: parseThriveArray<string>(params.tags, 'tags') }),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveMessageResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to add tags to learner')
|
||||
return {
|
||||
success: true,
|
||||
output: { status: data?.status ?? null, message: data?.message ?? null },
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
status: { type: 'number', description: 'The HTTP status code of the operation' },
|
||||
message: { type: 'string', description: 'A human-readable result message' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
import type { ThriveAssignmentResponse, ThriveCreateAssignmentParams } from '@/tools/thrive/types'
|
||||
import { THRIVE_ASSIGNMENT_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import {
|
||||
getThriveBaseUrl,
|
||||
getThriveHeaders,
|
||||
parseThriveArray,
|
||||
parseThriveResponse,
|
||||
} from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const createAssignmentTool: ToolConfig<
|
||||
ThriveCreateAssignmentParams,
|
||||
ThriveAssignmentResponse
|
||||
> = {
|
||||
id: 'thrive_create_assignment',
|
||||
name: 'Thrive Create Assignment',
|
||||
description: 'Create a compliance assignment in Thrive for an audience and content item.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
audienceId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The audience ID',
|
||||
},
|
||||
contentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The content ID for the primary content',
|
||||
},
|
||||
alternativeContentIds: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'JSON array of content IDs that can also complete the assignment',
|
||||
},
|
||||
hideAlternativeContent: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Whether to hide the alternative content',
|
||||
},
|
||||
completionPeriod: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The number of days required to complete the assignment (default 30)',
|
||||
},
|
||||
recurrence: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The number of days until the assignment will reoccur',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => `${getThriveBaseUrl(params.host, 'v1')}/assignments`,
|
||||
method: 'POST',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
body: (params) => {
|
||||
const body: Record<string, any> = {
|
||||
audienceId: params.audienceId,
|
||||
contentId: params.contentId,
|
||||
}
|
||||
if (params.alternativeContentIds) {
|
||||
body.alternativeContentIds = parseThriveArray<string>(
|
||||
params.alternativeContentIds,
|
||||
'alternativeContentIds'
|
||||
)
|
||||
}
|
||||
if (params.hideAlternativeContent !== undefined) {
|
||||
body.hideAlternativeContent = params.hideAlternativeContent
|
||||
}
|
||||
if (params.completionPeriod !== undefined) body.completionPeriod = params.completionPeriod
|
||||
if (params.recurrence !== undefined) body.recurrence = params.recurrence
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveAssignmentResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to create assignment')
|
||||
return { success: true, output: { assignment: data ?? null } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
assignment: {
|
||||
type: 'object',
|
||||
description: 'The created assignment',
|
||||
properties: THRIVE_ASSIGNMENT_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
import type { ThriveAudienceResponse, ThriveCreateAudienceParams } from '@/tools/thrive/types'
|
||||
import { THRIVE_AUDIENCE_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import { getThriveBaseUrl, getThriveHeaders, parseThriveResponse } from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const createAudienceTool: ToolConfig<ThriveCreateAudienceParams, ThriveAudienceResponse> = {
|
||||
id: 'thrive_create_audience',
|
||||
name: 'Thrive Create Audience',
|
||||
description: 'Create a new audience or structure in Thrive.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The name of the audience (max 100 characters)',
|
||||
},
|
||||
reference: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The external reference for the audience (max 100 characters)',
|
||||
},
|
||||
parentId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'The id or reference of the parent audience/structure; leave blank for a parent audience/structure',
|
||||
},
|
||||
category: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: "The audience category: 'audience' or 'structure'",
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => `${getThriveBaseUrl(params.host, 'v1')}/audiences`,
|
||||
method: 'POST',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
body: (params) => {
|
||||
const body: Record<string, any> = {}
|
||||
if (params.name) body.name = params.name
|
||||
if (params.reference) body.reference = params.reference
|
||||
if (params.parentId) body.parentId = params.parentId
|
||||
if (params.category) body.category = params.category
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveAudienceResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to create audience')
|
||||
return { success: true, output: { audience: data ?? null } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
audience: {
|
||||
type: 'object',
|
||||
description: 'The created audience',
|
||||
properties: THRIVE_AUDIENCE_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import type {
|
||||
ThriveCreateCompletionParams,
|
||||
ThriveCreateCompletionResponse,
|
||||
} from '@/tools/thrive/types'
|
||||
import { getThriveBaseUrl, getThriveHeaders, parseThriveResponse } from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const createCompletionTool: ToolConfig<
|
||||
ThriveCreateCompletionParams,
|
||||
ThriveCreateCompletionResponse
|
||||
> = {
|
||||
id: 'thrive_create_completion',
|
||||
name: 'Thrive Create Completion',
|
||||
description: 'Record a learning completion in Thrive for a user and content item.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
userId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The user ID',
|
||||
},
|
||||
contentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The content ID for the content completed',
|
||||
},
|
||||
completedAt: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'ISO8601 timestamp when the completion occurred',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => `${getThriveBaseUrl(params.host, 'v1')}/learning/completions`,
|
||||
method: 'POST',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
body: (params) => ({
|
||||
userId: params.userId,
|
||||
contentId: params.contentId,
|
||||
completedAt: params.completedAt,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveCreateCompletionResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to create completion')
|
||||
return { success: true, output: { statementId: data?.statementId ?? null } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
statementId: { type: 'string', description: 'The completion statement ID' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
import type { ThriveCreateUserParams, ThriveUserResponse } from '@/tools/thrive/types'
|
||||
import { THRIVE_USER_LIFECYCLE_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import {
|
||||
getThriveBaseUrl,
|
||||
getThriveHeaders,
|
||||
parseThriveJsonObject,
|
||||
parseThriveResponse,
|
||||
} from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const createUserTool: ToolConfig<ThriveCreateUserParams, ThriveUserResponse> = {
|
||||
id: 'thrive_create_user',
|
||||
name: 'Thrive Create User',
|
||||
description: 'Create a new user in Thrive.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
ref: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: "Your organisation's unique identifier for this individual",
|
||||
},
|
||||
firstName: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The given name of the individual',
|
||||
},
|
||||
lastName: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The family name of the individual',
|
||||
},
|
||||
email: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: "The email address for the user (required unless loginMethod is 'ref')",
|
||||
},
|
||||
loginMethod: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: "How the user logs in: 'email' or 'ref' (defaults to 'email')",
|
||||
},
|
||||
role: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
"Role assigned: 'administrator', 'learneradmin', or 'learner' (defaults to 'learner')",
|
||||
},
|
||||
jobTitle: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: "Name of this individual's role in your organisation",
|
||||
},
|
||||
managerRef: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: "Your organisation's unique identifier for this individual's line manager",
|
||||
},
|
||||
startDate: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Date this individual started with your organisation (ISO 8601)',
|
||||
},
|
||||
endDate: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Date this individual left your organisation (ISO 8601)',
|
||||
},
|
||||
timeZone: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: "The user's preferred timezone (tenant default if omitted)",
|
||||
},
|
||||
languageCode: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: "The user's preferred language (e.g. 'en-gb')",
|
||||
},
|
||||
sso: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Whether the account is managed by an authentication provider',
|
||||
},
|
||||
domain: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Domain this individual is associated with',
|
||||
},
|
||||
additionalFields: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'JSON object of custom field key-value pairs. Example: {"department":"Sales"}',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => `${getThriveBaseUrl(params.host, 'v2')}/users`,
|
||||
method: 'POST',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
body: (params) => {
|
||||
const body: Record<string, any> = {
|
||||
ref: params.ref,
|
||||
firstName: params.firstName,
|
||||
lastName: params.lastName,
|
||||
}
|
||||
if (params.email) body.email = params.email
|
||||
if (params.loginMethod) body.loginMethod = params.loginMethod
|
||||
if (params.role) body.role = params.role
|
||||
if (params.jobTitle) body.jobTitle = params.jobTitle
|
||||
if (params.managerRef) body.managerRef = params.managerRef
|
||||
if (params.startDate) body.startDate = params.startDate
|
||||
if (params.endDate) body.endDate = params.endDate
|
||||
if (params.timeZone) body.timeZone = params.timeZone
|
||||
if (params.languageCode) body.languageCode = params.languageCode
|
||||
if (params.sso !== undefined) body.sso = params.sso
|
||||
if (params.domain) body.domain = params.domain
|
||||
if (params.additionalFields) {
|
||||
body.additionalFields = parseThriveJsonObject(params.additionalFields, 'additionalFields')
|
||||
}
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveUserResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to create user')
|
||||
return { success: true, output: { user: data ?? null } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
user: {
|
||||
type: 'object',
|
||||
description: 'The created user',
|
||||
properties: THRIVE_USER_LIFECYCLE_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
import type { ThriveDeleteAssignmentParams, ThriveDeleteResponse } from '@/tools/thrive/types'
|
||||
import { getThriveBaseUrl, getThriveHeaders, parseThriveResponse } from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const deleteAssignmentTool: ToolConfig<ThriveDeleteAssignmentParams, ThriveDeleteResponse> =
|
||||
{
|
||||
id: 'thrive_delete_assignment',
|
||||
name: 'Thrive Delete Assignment',
|
||||
description: 'Delete a compliance assignment in Thrive.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
assignmentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The assignment ID',
|
||||
},
|
||||
audienceId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The audience ID',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/assignments/${encodeURIComponent(params.assignmentId)}`,
|
||||
method: 'DELETE',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
body: (params) => ({ audienceId: params.audienceId }),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveDeleteResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to delete assignment')
|
||||
return { success: true, output: { success: data?.success ?? true } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
success: { type: 'boolean', description: 'Whether the assignment was deleted' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import type { ThriveDeleteAudienceParams, ThriveDeleteResponse } from '@/tools/thrive/types'
|
||||
import { getThriveBaseUrl, getThriveHeaders, parseThriveResponse } from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const deleteAudienceTool: ToolConfig<ThriveDeleteAudienceParams, ThriveDeleteResponse> = {
|
||||
id: 'thrive_delete_audience',
|
||||
name: 'Thrive Delete Audience',
|
||||
description: 'Delete an audience in Thrive (only if it has no child audiences).',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
audienceId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The audience id or audience reference',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/audiences/${encodeURIComponent(params.audienceId)}`,
|
||||
method: 'DELETE',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveDeleteResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to delete audience')
|
||||
return { success: true, output: { success: data?.success ?? true } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
success: { type: 'boolean', description: 'Whether the audience was deleted' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import type { ThriveDeleteResponse, ThriveDeleteUserParams } from '@/tools/thrive/types'
|
||||
import { getThriveBaseUrl, getThriveHeaders, parseThriveResponse } from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const deleteUserTool: ToolConfig<ThriveDeleteUserParams, ThriveDeleteResponse> = {
|
||||
id: 'thrive_delete_user',
|
||||
name: 'Thrive Delete User',
|
||||
description:
|
||||
'Permanently delete (obfuscate) a user in Thrive by ref while retaining training history.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
ref: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The user ref to delete',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v2')}/users/ref/${encodeURIComponent(params.ref)}`,
|
||||
method: 'DELETE',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveDeleteResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to delete user')
|
||||
return { success: true, output: { success: data?.success ?? true } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
success: { type: 'boolean', description: 'Whether the user was deleted' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import type { ThriveActivityResponse, ThriveGetActivityParams } from '@/tools/thrive/types'
|
||||
import { THRIVE_ACTIVITY_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import { getThriveBaseUrl, getThriveHeaders, parseThriveResponse } from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const getActivityTool: ToolConfig<ThriveGetActivityParams, ThriveActivityResponse> = {
|
||||
id: 'thrive_get_activity',
|
||||
name: 'Thrive Get Activity',
|
||||
description: 'Get a single activity record in Thrive by its ID.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
id: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Unique identifier of the activity',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/activity/${encodeURIComponent(params.id)}`,
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveActivityResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to get activity')
|
||||
return { success: true, output: { activity: data ?? null } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
activity: {
|
||||
type: 'object',
|
||||
description: 'The activity record',
|
||||
properties: THRIVE_ACTIVITY_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import type { ThriveAssignmentResponse, ThriveGetAssignmentParams } from '@/tools/thrive/types'
|
||||
import { THRIVE_ASSIGNMENT_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import { getThriveBaseUrl, getThriveHeaders, parseThriveResponse } from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const getAssignmentTool: ToolConfig<ThriveGetAssignmentParams, ThriveAssignmentResponse> = {
|
||||
id: 'thrive_get_assignment',
|
||||
name: 'Thrive Get Assignment',
|
||||
description: 'Get a single compliance assignment in Thrive by its ID.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
assignmentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The assignment ID',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/assignments/${encodeURIComponent(params.assignmentId)}`,
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveAssignmentResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to get assignment')
|
||||
return { success: true, output: { assignment: data ?? null } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
assignment: {
|
||||
type: 'object',
|
||||
description: 'The assignment',
|
||||
properties: THRIVE_ASSIGNMENT_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import type { ThriveAudienceResponse, ThriveGetAudienceParams } from '@/tools/thrive/types'
|
||||
import { THRIVE_AUDIENCE_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import { getThriveBaseUrl, getThriveHeaders, parseThriveResponse } from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const getAudienceTool: ToolConfig<ThriveGetAudienceParams, ThriveAudienceResponse> = {
|
||||
id: 'thrive_get_audience',
|
||||
name: 'Thrive Get Audience',
|
||||
description: 'Get a single audience or structure in Thrive by id or reference.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
audienceId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The audience id or audience reference',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/audiences/${encodeURIComponent(params.audienceId)}`,
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveAudienceResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to get audience')
|
||||
return { success: true, output: { audience: data ?? null } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
audience: {
|
||||
type: 'object',
|
||||
description: 'The audience',
|
||||
properties: THRIVE_AUDIENCE_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import type { ThriveCompletionResponse, ThriveGetCompletionParams } from '@/tools/thrive/types'
|
||||
import { THRIVE_COMPLETION_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import { getThriveBaseUrl, getThriveHeaders, parseThriveResponse } from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const getCompletionTool: ToolConfig<ThriveGetCompletionParams, ThriveCompletionResponse> = {
|
||||
id: 'thrive_get_completion',
|
||||
name: 'Thrive Get Completion',
|
||||
description: 'Get a single learning completion record in Thrive by its ID.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
id: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The completion ID',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/learning/completions/${encodeURIComponent(params.id)}`,
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveCompletionResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to get completion')
|
||||
return { success: true, output: { completion: data ?? null } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
completion: {
|
||||
type: 'object',
|
||||
description: 'The completion record',
|
||||
properties: THRIVE_COMPLETION_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import type { ThriveContentResponse, ThriveGetContentParams } from '@/tools/thrive/types'
|
||||
import { THRIVE_CONTENT_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import { getThriveBaseUrl, getThriveHeaders, parseThriveResponse } from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const getContentTool: ToolConfig<ThriveGetContentParams, ThriveContentResponse> = {
|
||||
id: 'thrive_get_content',
|
||||
name: 'Thrive Get Content',
|
||||
description: 'Get a single content record in Thrive by its ID.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
id: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Unique identifier of the content item',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/contents/${encodeURIComponent(params.id)}`,
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveContentResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to get content')
|
||||
return { success: true, output: { content: data ?? null } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
content: {
|
||||
type: 'object',
|
||||
description: 'The content record',
|
||||
properties: THRIVE_CONTENT_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
import type { ThriveCpdCategoryResponse, ThriveGetCpdCategoryParams } from '@/tools/thrive/types'
|
||||
import { THRIVE_CPD_CATEGORY_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import { getThriveBaseUrl, getThriveHeaders, parseThriveResponse } from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const getCpdCategoryTool: ToolConfig<ThriveGetCpdCategoryParams, ThriveCpdCategoryResponse> =
|
||||
{
|
||||
id: 'thrive_get_cpd_category',
|
||||
name: 'Thrive Get CPD Category',
|
||||
description: 'Get a single CPD category in Thrive by its ID.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
categoryId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The CPD category ID',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/cpdCategories/${encodeURIComponent(params.categoryId)}`,
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveCpdCategoryResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to get CPD category')
|
||||
return { success: true, output: { category: data ?? null } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
category: {
|
||||
type: 'object',
|
||||
description: 'The CPD category',
|
||||
properties: THRIVE_CPD_CATEGORY_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import type { ThriveCpdEntryResponse, ThriveGetCpdEntryParams } from '@/tools/thrive/types'
|
||||
import { THRIVE_CPD_ENTRY_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import { getThriveBaseUrl, getThriveHeaders, parseThriveResponse } from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const getCpdEntryTool: ToolConfig<ThriveGetCpdEntryParams, ThriveCpdEntryResponse> = {
|
||||
id: 'thrive_get_cpd_entry',
|
||||
name: 'Thrive Get CPD Entry',
|
||||
description: 'Get a single CPD log entry in Thrive by its ID.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
logEntryId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The CPD log entry ID',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/cpdEntries/${encodeURIComponent(params.logEntryId)}`,
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveCpdEntryResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to get CPD entry')
|
||||
return { success: true, output: { entry: data ?? null } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
entry: {
|
||||
type: 'object',
|
||||
description: 'The CPD entry',
|
||||
properties: THRIVE_CPD_ENTRY_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import type {
|
||||
ThriveCpdRequirementResponse,
|
||||
ThriveGetCpdRequirementParams,
|
||||
} from '@/tools/thrive/types'
|
||||
import { THRIVE_CPD_REQUIREMENT_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import { getThriveBaseUrl, getThriveHeaders, parseThriveResponse } from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const getCpdRequirementTool: ToolConfig<
|
||||
ThriveGetCpdRequirementParams,
|
||||
ThriveCpdRequirementResponse
|
||||
> = {
|
||||
id: 'thrive_get_cpd_requirement',
|
||||
name: 'Thrive Get CPD Requirement',
|
||||
description: 'Get a single CPD requirement summary in Thrive by its ID.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
audienceRequirementId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The CPD requirement ID',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/cpdRequirementSummaries/${encodeURIComponent(params.audienceRequirementId)}`,
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveCpdRequirementResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to get CPD requirement')
|
||||
return { success: true, output: { requirement: data ?? null } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
requirement: {
|
||||
type: 'object',
|
||||
description: 'The CPD requirement',
|
||||
properties: THRIVE_CPD_REQUIREMENT_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import type { ThriveEnrolmentResponse, ThriveGetEnrolmentParams } from '@/tools/thrive/types'
|
||||
import { THRIVE_ENROLMENT_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import { getThriveBaseUrl, getThriveHeaders, parseThriveResponse } from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const getEnrolmentTool: ToolConfig<ThriveGetEnrolmentParams, ThriveEnrolmentResponse> = {
|
||||
id: 'thrive_get_enrolment',
|
||||
name: 'Thrive Get Enrolment',
|
||||
description: 'Get a single enrolment for a compliance assignment in Thrive.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
assignmentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The assignment ID',
|
||||
},
|
||||
enrolmentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The enrolment ID',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/assignments/${encodeURIComponent(params.assignmentId)}/enrolments/${encodeURIComponent(params.enrolmentId)}`,
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveEnrolmentResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to get enrolment')
|
||||
return { success: true, output: { enrolment: data ?? null } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
enrolment: {
|
||||
type: 'object',
|
||||
description: 'The enrolment',
|
||||
properties: THRIVE_ENROLMENT_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import type { ThriveGetSkillLevelsParams, ThriveSkillLevelsResponse } from '@/tools/thrive/types'
|
||||
import { THRIVE_SKILL_LEVEL_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import { getThriveBaseUrl, getThriveHeaders, parseThriveResponse } from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const getSkillLevelsTool: ToolConfig<ThriveGetSkillLevelsParams, ThriveSkillLevelsResponse> =
|
||||
{
|
||||
id: 'thrive_get_skill_levels',
|
||||
name: 'Thrive Get Skill Levels',
|
||||
description: 'Get the available skill levels configured in Thrive.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => `${getThriveBaseUrl(params.host, 'v1')}/skills/levels`,
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveSkillLevelsResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to get skill levels')
|
||||
return { success: true, output: { levels: Array.isArray(data) ? data : [] } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
levels: {
|
||||
type: 'array',
|
||||
description: 'The available skill levels',
|
||||
items: { type: 'object', properties: THRIVE_SKILL_LEVEL_OUTPUT_PROPERTIES },
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import type { ThriveGetTagParams, ThriveTagResponse } from '@/tools/thrive/types'
|
||||
import { THRIVE_TAG_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import { getThriveBaseUrl, getThriveHeaders, parseThriveResponse } from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const getTagTool: ToolConfig<ThriveGetTagParams, ThriveTagResponse> = {
|
||||
id: 'thrive_get_tag',
|
||||
name: 'Thrive Get Tag',
|
||||
description: 'Get a single tag in Thrive by its ID.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
tagId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The tag ID',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/tags/${encodeURIComponent(params.tagId)}`,
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveTagResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to get tag')
|
||||
return { success: true, output: { tag: data ?? null } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
tag: {
|
||||
type: 'object',
|
||||
description: 'The tag',
|
||||
properties: THRIVE_TAG_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import type { ThriveGetUserByIdParams, ThriveUserResponse } from '@/tools/thrive/types'
|
||||
import { THRIVE_USER_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import { getThriveBaseUrl, getThriveHeaders, parseThriveResponse } from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const getUserByIdTool: ToolConfig<ThriveGetUserByIdParams, ThriveUserResponse> = {
|
||||
id: 'thrive_get_user_by_id',
|
||||
name: 'Thrive Get User by ID',
|
||||
description: 'Get a single user in Thrive by their ID and return basic user information.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
id: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The user ID',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => `${getThriveBaseUrl(params.host, 'v1')}/user/${encodeURIComponent(params.id)}`,
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveUserResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to get user')
|
||||
return { success: true, output: { user: data ?? null } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
user: {
|
||||
type: 'object',
|
||||
description: 'The user',
|
||||
properties: THRIVE_USER_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import type { ThriveGetUserByRefParams, ThriveUserResponse } from '@/tools/thrive/types'
|
||||
import { THRIVE_BASIC_USER_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import { getThriveBaseUrl, getThriveHeaders, parseThriveResponse } from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const getUserByRefTool: ToolConfig<ThriveGetUserByRefParams, ThriveUserResponse> = {
|
||||
id: 'thrive_get_user_by_ref',
|
||||
name: 'Thrive Get User by Ref',
|
||||
description: 'Get a single user in Thrive by their ref and return basic user information.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
ref: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The user ref',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/users/ref/${encodeURIComponent(params.ref)}`,
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveUserResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to get user')
|
||||
return { success: true, output: { user: data ?? null } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
user: {
|
||||
type: 'object',
|
||||
description: 'The user (basic information)',
|
||||
properties: THRIVE_BASIC_USER_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
import { addAudienceManagersTool } from '@/tools/thrive/add_audience_managers'
|
||||
import { addAudienceMembersTool } from '@/tools/thrive/add_audience_members'
|
||||
import { addUserTagsTool } from '@/tools/thrive/add_user_tags'
|
||||
import { createAssignmentTool } from '@/tools/thrive/create_assignment'
|
||||
import { createAudienceTool } from '@/tools/thrive/create_audience'
|
||||
import { createCompletionTool } from '@/tools/thrive/create_completion'
|
||||
import { createUserTool } from '@/tools/thrive/create_user'
|
||||
import { deleteAssignmentTool } from '@/tools/thrive/delete_assignment'
|
||||
import { deleteAudienceTool } from '@/tools/thrive/delete_audience'
|
||||
import { deleteUserTool } from '@/tools/thrive/delete_user'
|
||||
import { getActivityTool } from '@/tools/thrive/get_activity'
|
||||
import { getAssignmentTool } from '@/tools/thrive/get_assignment'
|
||||
import { getAudienceTool } from '@/tools/thrive/get_audience'
|
||||
import { getCompletionTool } from '@/tools/thrive/get_completion'
|
||||
import { getContentTool } from '@/tools/thrive/get_content'
|
||||
import { getCpdCategoryTool } from '@/tools/thrive/get_cpd_category'
|
||||
import { getCpdEntryTool } from '@/tools/thrive/get_cpd_entry'
|
||||
import { getCpdRequirementTool } from '@/tools/thrive/get_cpd_requirement'
|
||||
import { getEnrolmentTool } from '@/tools/thrive/get_enrolment'
|
||||
import { getSkillLevelsTool } from '@/tools/thrive/get_skill_levels'
|
||||
import { getTagTool } from '@/tools/thrive/get_tag'
|
||||
import { getUserByIdTool } from '@/tools/thrive/get_user_by_id'
|
||||
import { getUserByRefTool } from '@/tools/thrive/get_user_by_ref'
|
||||
import { listAssignmentsTool } from '@/tools/thrive/list_assignments'
|
||||
import { listAudienceManagersTool } from '@/tools/thrive/list_audience_managers'
|
||||
import { listAudienceMembersTool } from '@/tools/thrive/list_audience_members'
|
||||
import { listAudiencesTool } from '@/tools/thrive/list_audiences'
|
||||
import { listCompletionsTool } from '@/tools/thrive/list_completions'
|
||||
import { listEnrolmentsTool } from '@/tools/thrive/list_enrolments'
|
||||
import { listTagsTool } from '@/tools/thrive/list_tags'
|
||||
import { queryActivitiesTool } from '@/tools/thrive/query_activities'
|
||||
import { queryContentTool } from '@/tools/thrive/query_content'
|
||||
import { queryCpdCategoriesTool } from '@/tools/thrive/query_cpd_categories'
|
||||
import { queryCpdEntriesTool } from '@/tools/thrive/query_cpd_entries'
|
||||
import { queryCpdRequirementsTool } from '@/tools/thrive/query_cpd_requirements'
|
||||
import { queryCpdUserSummariesTool } from '@/tools/thrive/query_cpd_user_summaries'
|
||||
import { removeAudienceManagerTool } from '@/tools/thrive/remove_audience_manager'
|
||||
import { removeAudienceMemberTool } from '@/tools/thrive/remove_audience_member'
|
||||
import { removeUserTagsTool } from '@/tools/thrive/remove_user_tags'
|
||||
import { replaceAudienceManagersTool } from '@/tools/thrive/replace_audience_managers'
|
||||
import { replaceAudienceMembersTool } from '@/tools/thrive/replace_audience_members'
|
||||
import { searchUsersTool } from '@/tools/thrive/search_users'
|
||||
import { suspendUserTool } from '@/tools/thrive/suspend_user'
|
||||
import { updateAssignmentTool } from '@/tools/thrive/update_assignment'
|
||||
import { updateAudienceTool } from '@/tools/thrive/update_audience'
|
||||
import { updateUserTool } from '@/tools/thrive/update_user'
|
||||
import { updateUserSkillsTool } from '@/tools/thrive/update_user_skills'
|
||||
|
||||
export const thriveCreateUserTool = createUserTool
|
||||
export const thriveUpdateUserTool = updateUserTool
|
||||
export const thriveDeleteUserTool = deleteUserTool
|
||||
export const thriveSuspendUserTool = suspendUserTool
|
||||
export const thriveSearchUsersTool = searchUsersTool
|
||||
export const thriveGetUserByIdTool = getUserByIdTool
|
||||
export const thriveGetUserByRefTool = getUserByRefTool
|
||||
|
||||
export const thriveListAudiencesTool = listAudiencesTool
|
||||
export const thriveCreateAudienceTool = createAudienceTool
|
||||
export const thriveGetAudienceTool = getAudienceTool
|
||||
export const thriveUpdateAudienceTool = updateAudienceTool
|
||||
export const thriveDeleteAudienceTool = deleteAudienceTool
|
||||
export const thriveListAudienceMembersTool = listAudienceMembersTool
|
||||
export const thriveAddAudienceMembersTool = addAudienceMembersTool
|
||||
export const thriveReplaceAudienceMembersTool = replaceAudienceMembersTool
|
||||
export const thriveRemoveAudienceMemberTool = removeAudienceMemberTool
|
||||
export const thriveListAudienceManagersTool = listAudienceManagersTool
|
||||
export const thriveAddAudienceManagersTool = addAudienceManagersTool
|
||||
export const thriveReplaceAudienceManagersTool = replaceAudienceManagersTool
|
||||
export const thriveRemoveAudienceManagerTool = removeAudienceManagerTool
|
||||
|
||||
export const thriveListAssignmentsTool = listAssignmentsTool
|
||||
export const thriveCreateAssignmentTool = createAssignmentTool
|
||||
export const thriveGetAssignmentTool = getAssignmentTool
|
||||
export const thriveUpdateAssignmentTool = updateAssignmentTool
|
||||
export const thriveDeleteAssignmentTool = deleteAssignmentTool
|
||||
export const thriveListEnrolmentsTool = listEnrolmentsTool
|
||||
export const thriveGetEnrolmentTool = getEnrolmentTool
|
||||
|
||||
export const thriveListCompletionsTool = listCompletionsTool
|
||||
export const thriveGetCompletionTool = getCompletionTool
|
||||
export const thriveCreateCompletionTool = createCompletionTool
|
||||
|
||||
export const thriveGetContentTool = getContentTool
|
||||
export const thriveQueryContentTool = queryContentTool
|
||||
|
||||
export const thriveGetActivityTool = getActivityTool
|
||||
export const thriveQueryActivitiesTool = queryActivitiesTool
|
||||
|
||||
export const thriveGetCpdCategoryTool = getCpdCategoryTool
|
||||
export const thriveQueryCpdCategoriesTool = queryCpdCategoriesTool
|
||||
export const thriveGetCpdEntryTool = getCpdEntryTool
|
||||
export const thriveQueryCpdEntriesTool = queryCpdEntriesTool
|
||||
export const thriveGetCpdRequirementTool = getCpdRequirementTool
|
||||
export const thriveQueryCpdRequirementsTool = queryCpdRequirementsTool
|
||||
export const thriveQueryCpdUserSummariesTool = queryCpdUserSummariesTool
|
||||
|
||||
export const thriveListTagsTool = listTagsTool
|
||||
export const thriveGetTagTool = getTagTool
|
||||
export const thriveAddUserTagsTool = addUserTagsTool
|
||||
export const thriveRemoveUserTagsTool = removeUserTagsTool
|
||||
export const thriveUpdateUserSkillsTool = updateUserSkillsTool
|
||||
export const thriveGetSkillLevelsTool = getSkillLevelsTool
|
||||
@@ -0,0 +1,93 @@
|
||||
import type {
|
||||
ThriveListAssignmentsParams,
|
||||
ThriveListAssignmentsResponse,
|
||||
} from '@/tools/thrive/types'
|
||||
import { THRIVE_ASSIGNMENT_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import {
|
||||
appendThriveQuery,
|
||||
getThriveBaseUrl,
|
||||
getThriveHeaders,
|
||||
parseThriveResponse,
|
||||
} from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const listAssignmentsTool: ToolConfig<
|
||||
ThriveListAssignmentsParams,
|
||||
ThriveListAssignmentsResponse
|
||||
> = {
|
||||
id: 'thrive_list_assignments',
|
||||
name: 'Thrive List Assignments',
|
||||
description: 'List compliance assignments in Thrive, optionally filtered by audience.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
audienceId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter by audience ID or audience reference',
|
||||
},
|
||||
updatedSince: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Return only items updated on or after this date/time (ISO 8601)',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number for pagination (default 1)',
|
||||
},
|
||||
perPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of results per page (1-100, default 100)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const url = new URL(`${getThriveBaseUrl(params.host, 'v1')}/assignments`)
|
||||
appendThriveQuery(url, 'audienceId', params.audienceId)
|
||||
appendThriveQuery(url, 'updatedSince', params.updatedSince)
|
||||
appendThriveQuery(url, 'page', params.page)
|
||||
appendThriveQuery(url, 'perPage', params.perPage)
|
||||
return url.toString()
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveListAssignmentsResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to list assignments')
|
||||
return { success: true, output: { assignments: Array.isArray(data) ? data : [] } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
assignments: {
|
||||
type: 'array',
|
||||
description: 'The matching assignments',
|
||||
items: { type: 'object', properties: THRIVE_ASSIGNMENT_OUTPUT_PROPERTIES },
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import type {
|
||||
ThriveListAudienceManagersParams,
|
||||
ThriveListAudienceManagersResponse,
|
||||
} from '@/tools/thrive/types'
|
||||
import { THRIVE_AUDIENCE_MANAGER_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import { getThriveBaseUrl, getThriveHeaders, parseThriveResponse } from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const listAudienceManagersTool: ToolConfig<
|
||||
ThriveListAudienceManagersParams,
|
||||
ThriveListAudienceManagersResponse
|
||||
> = {
|
||||
id: 'thrive_list_audience_managers',
|
||||
name: 'Thrive List Audience Managers',
|
||||
description: 'List the managers of a Thrive audience.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
audienceId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The audience id or audience reference',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/audiences/${encodeURIComponent(params.audienceId)}/managers`,
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveListAudienceManagersResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to list audience managers')
|
||||
return { success: true, output: { managers: Array.isArray(data) ? data : [] } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
managers: {
|
||||
type: 'array',
|
||||
description: 'The audience managers',
|
||||
items: { type: 'object', properties: THRIVE_AUDIENCE_MANAGER_OUTPUT_PROPERTIES },
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
import type {
|
||||
ThriveListAudienceMembersParams,
|
||||
ThriveListAudienceMembersResponse,
|
||||
} from '@/tools/thrive/types'
|
||||
import {
|
||||
THRIVE_AUDIENCE_MEMBER_OUTPUT_PROPERTIES,
|
||||
THRIVE_PAGINATION_OUTPUT_PROPERTIES,
|
||||
} from '@/tools/thrive/types'
|
||||
import {
|
||||
appendThriveQuery,
|
||||
getThriveBaseUrl,
|
||||
getThriveHeaders,
|
||||
parseThriveResponse,
|
||||
} from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const listAudienceMembersTool: ToolConfig<
|
||||
ThriveListAudienceMembersParams,
|
||||
ThriveListAudienceMembersResponse
|
||||
> = {
|
||||
id: 'thrive_list_audience_members',
|
||||
name: 'Thrive List Audience Members',
|
||||
description: 'List the members of a Thrive audience with pagination.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
audienceId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The audience id or audience reference',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number for pagination (default 1)',
|
||||
},
|
||||
perPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of results per page (1-1000, default 100)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const url = new URL(
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/audiences/${encodeURIComponent(params.audienceId)}/members`
|
||||
)
|
||||
appendThriveQuery(url, 'page', params.page)
|
||||
appendThriveQuery(url, 'perPage', params.perPage)
|
||||
return url.toString()
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveListAudienceMembersResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to list audience members')
|
||||
return {
|
||||
success: true,
|
||||
output: { results: data?.results ?? [], pagination: data?.pagination ?? null },
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
results: {
|
||||
type: 'array',
|
||||
description: 'The audience members',
|
||||
items: { type: 'object', properties: THRIVE_AUDIENCE_MEMBER_OUTPUT_PROPERTIES },
|
||||
},
|
||||
pagination: {
|
||||
type: 'object',
|
||||
description: 'Pagination details',
|
||||
properties: THRIVE_PAGINATION_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
import type { ThriveListAudiencesParams, ThriveListAudiencesResponse } from '@/tools/thrive/types'
|
||||
import {
|
||||
THRIVE_AUDIENCE_OUTPUT_PROPERTIES,
|
||||
THRIVE_PAGINATION_OUTPUT_PROPERTIES,
|
||||
} from '@/tools/thrive/types'
|
||||
import {
|
||||
appendThriveQuery,
|
||||
getThriveBaseUrl,
|
||||
getThriveHeaders,
|
||||
parseThriveResponse,
|
||||
} from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const listAudiencesTool: ToolConfig<ThriveListAudiencesParams, ThriveListAudiencesResponse> =
|
||||
{
|
||||
id: 'thrive_list_audiences',
|
||||
name: 'Thrive List Audiences',
|
||||
description: 'List audiences and structures in Thrive with pagination.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
apiControlled: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter to only return audiences which are / are not API controlled',
|
||||
},
|
||||
updatedSince: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Return only audiences updated on or after this date/time (ISO 8601)',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number for pagination (default 1)',
|
||||
},
|
||||
perPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of results per page (1-1000, default 100)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const url = new URL(`${getThriveBaseUrl(params.host, 'v1')}/audiences`)
|
||||
appendThriveQuery(url, 'apiControlled', params.apiControlled)
|
||||
appendThriveQuery(url, 'updatedSince', params.updatedSince)
|
||||
appendThriveQuery(url, 'page', params.page)
|
||||
appendThriveQuery(url, 'perPage', params.perPage)
|
||||
return url.toString()
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveListAudiencesResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to list audiences')
|
||||
return {
|
||||
success: true,
|
||||
output: { results: data?.results ?? [], pagination: data?.pagination ?? null },
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
results: {
|
||||
type: 'array',
|
||||
description: 'The matching audiences',
|
||||
items: { type: 'object', properties: THRIVE_AUDIENCE_OUTPUT_PROPERTIES },
|
||||
},
|
||||
pagination: {
|
||||
type: 'object',
|
||||
description: 'Pagination details',
|
||||
properties: THRIVE_PAGINATION_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
import type {
|
||||
ThriveListCompletionsParams,
|
||||
ThriveListCompletionsResponse,
|
||||
} from '@/tools/thrive/types'
|
||||
import { THRIVE_COMPLETION_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import {
|
||||
appendThriveQuery,
|
||||
getThriveBaseUrl,
|
||||
getThriveHeaders,
|
||||
parseThriveResponse,
|
||||
} from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const listCompletionsTool: ToolConfig<
|
||||
ThriveListCompletionsParams,
|
||||
ThriveListCompletionsResponse
|
||||
> = {
|
||||
id: 'thrive_list_completions',
|
||||
name: 'Thrive List Completions',
|
||||
description:
|
||||
'List learning completion records in Thrive, optionally filtered by user or content.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
contentId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter by content',
|
||||
},
|
||||
isRPL: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter by completions imported via Recognition of Prior Learning (RPL)',
|
||||
},
|
||||
userId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter by user',
|
||||
},
|
||||
completedDateRangeStart: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter by completedDate (completedDate >= this date/date-time)',
|
||||
},
|
||||
completedDateRangeEnd: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter by completedDate (completedDate <= this date/date-time)',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number for pagination (default 1)',
|
||||
},
|
||||
perPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of results per page (1-1000, default 1000)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const url = new URL(`${getThriveBaseUrl(params.host, 'v1')}/learning/completions`)
|
||||
appendThriveQuery(url, 'contentId', params.contentId)
|
||||
appendThriveQuery(url, 'isRPL', params.isRPL)
|
||||
appendThriveQuery(url, 'userId', params.userId)
|
||||
appendThriveQuery(url, 'completedDateRangeStart', params.completedDateRangeStart)
|
||||
appendThriveQuery(url, 'completedDateRangeEnd', params.completedDateRangeEnd)
|
||||
appendThriveQuery(url, 'page', params.page)
|
||||
appendThriveQuery(url, 'perPage', params.perPage)
|
||||
return url.toString()
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveListCompletionsResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to list completions')
|
||||
return { success: true, output: { completions: Array.isArray(data) ? data : [] } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
completions: {
|
||||
type: 'array',
|
||||
description: 'The matching completion records',
|
||||
items: { type: 'object', properties: THRIVE_COMPLETION_OUTPUT_PROPERTIES },
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
import type { ThriveListEnrolmentsParams, ThriveListEnrolmentsResponse } from '@/tools/thrive/types'
|
||||
import { THRIVE_ENROLMENT_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import {
|
||||
appendThriveQuery,
|
||||
getThriveBaseUrl,
|
||||
getThriveHeaders,
|
||||
parseThriveResponse,
|
||||
} from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const listEnrolmentsTool: ToolConfig<
|
||||
ThriveListEnrolmentsParams,
|
||||
ThriveListEnrolmentsResponse
|
||||
> = {
|
||||
id: 'thrive_list_enrolments',
|
||||
name: 'Thrive List Enrolments',
|
||||
description: 'List enrolments for a compliance assignment in Thrive.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
assignmentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The assignment ID',
|
||||
},
|
||||
updatedAtFrom: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Start date to filter enrolments from (ISO 8601)',
|
||||
},
|
||||
updatedAtTo: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Date to filter enrolments up to (ISO 8601). Requires updatedAtFrom.',
|
||||
},
|
||||
status: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Filter by enrolment status: archived, complete, open, overdue, scheduled, or unassigned',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number for pagination (default 1)',
|
||||
},
|
||||
perPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of results per page (1-100, default 100)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const url = new URL(
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/assignments/${encodeURIComponent(params.assignmentId)}/enrolments`
|
||||
)
|
||||
appendThriveQuery(url, 'updatedAtFrom', params.updatedAtFrom)
|
||||
appendThriveQuery(url, 'updatedAtTo', params.updatedAtTo)
|
||||
appendThriveQuery(url, 'status', params.status)
|
||||
appendThriveQuery(url, 'page', params.page)
|
||||
appendThriveQuery(url, 'perPage', params.perPage)
|
||||
return url.toString()
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveListEnrolmentsResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to list enrolments')
|
||||
return { success: true, output: { enrolments: Array.isArray(data) ? data : [] } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
enrolments: {
|
||||
type: 'array',
|
||||
description: 'The matching enrolments',
|
||||
items: { type: 'object', properties: THRIVE_ENROLMENT_OUTPUT_PROPERTIES },
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
import type { ThriveListTagsParams, ThriveListTagsResponse } from '@/tools/thrive/types'
|
||||
import {
|
||||
THRIVE_PAGINATION_OUTPUT_PROPERTIES,
|
||||
THRIVE_TAG_OUTPUT_PROPERTIES,
|
||||
} from '@/tools/thrive/types'
|
||||
import {
|
||||
appendThriveQuery,
|
||||
getThriveBaseUrl,
|
||||
getThriveHeaders,
|
||||
parseThriveResponse,
|
||||
} from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const listTagsTool: ToolConfig<ThriveListTagsParams, ThriveListTagsResponse> = {
|
||||
id: 'thrive_list_tags',
|
||||
name: 'Thrive List Tags',
|
||||
description: 'List tags in Thrive and return tag information with pagination.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number for pagination (default 1)',
|
||||
},
|
||||
perPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of results per page (1-1000, default 100)',
|
||||
},
|
||||
updatedSince: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Return only tags updated on or after this date/time (ISO 8601)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const url = new URL(`${getThriveBaseUrl(params.host, 'v1')}/tags`)
|
||||
appendThriveQuery(url, 'page', params.page)
|
||||
appendThriveQuery(url, 'perPage', params.perPage)
|
||||
appendThriveQuery(url, 'updatedSince', params.updatedSince)
|
||||
return url.toString()
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveListTagsResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to list tags')
|
||||
return {
|
||||
success: true,
|
||||
output: { results: data?.results ?? [], pagination: data?.pagination ?? null },
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
results: {
|
||||
type: 'array',
|
||||
description: 'The tags',
|
||||
items: { type: 'object', properties: THRIVE_TAG_OUTPUT_PROPERTIES },
|
||||
},
|
||||
pagination: {
|
||||
type: 'object',
|
||||
description: 'Pagination details',
|
||||
properties: THRIVE_PAGINATION_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
import type {
|
||||
ThriveQueryActivitiesParams,
|
||||
ThriveQueryActivitiesResponse,
|
||||
} from '@/tools/thrive/types'
|
||||
import {
|
||||
THRIVE_ACTIVITY_OUTPUT_PROPERTIES,
|
||||
THRIVE_PAGINATION_OUTPUT_PROPERTIES,
|
||||
} from '@/tools/thrive/types'
|
||||
import {
|
||||
appendThriveQuery,
|
||||
getThriveBaseUrl,
|
||||
getThriveHeaders,
|
||||
parseThriveResponse,
|
||||
} from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const queryActivitiesTool: ToolConfig<
|
||||
ThriveQueryActivitiesParams,
|
||||
ThriveQueryActivitiesResponse
|
||||
> = {
|
||||
id: 'thrive_query_activities',
|
||||
name: 'Thrive Query Activities',
|
||||
description: 'Query activity records in Thrive with pagination and filtering options.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number for pagination (default 1)',
|
||||
},
|
||||
perPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of results per page (1-1000, default 20)',
|
||||
},
|
||||
actions: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'comma-separated activity types e.g. viewed,completed',
|
||||
},
|
||||
omitActions: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'comma-separated activity types e.g. viewed,completed',
|
||||
},
|
||||
contentIds: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'comma-separated content IDs',
|
||||
},
|
||||
contentType: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter by content type',
|
||||
},
|
||||
timestampFrom: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'format YYYY-MM-DD hh:mm:ss',
|
||||
},
|
||||
timestampTo: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'format YYYY-MM-DD hh:mm:ss',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const url = new URL(`${getThriveBaseUrl(params.host, 'v1')}/activities`)
|
||||
appendThriveQuery(url, 'page', params.page)
|
||||
appendThriveQuery(url, 'perPage', params.perPage)
|
||||
appendThriveQuery(url, 'actions', params.actions)
|
||||
appendThriveQuery(url, 'omitActions', params.omitActions)
|
||||
appendThriveQuery(url, 'contentIds', params.contentIds)
|
||||
appendThriveQuery(url, 'contentType', params.contentType)
|
||||
appendThriveQuery(url, 'timestampFrom', params.timestampFrom)
|
||||
appendThriveQuery(url, 'timestampTo', params.timestampTo)
|
||||
return url.toString()
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveQueryActivitiesResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to query activities')
|
||||
return {
|
||||
success: true,
|
||||
output: { results: data?.results ?? [], pagination: data?.pagination ?? null },
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
results: {
|
||||
type: 'array',
|
||||
description: 'The matching activity records',
|
||||
items: { type: 'object', properties: THRIVE_ACTIVITY_OUTPUT_PROPERTIES },
|
||||
},
|
||||
pagination: {
|
||||
type: 'object',
|
||||
description: 'Pagination details',
|
||||
properties: THRIVE_PAGINATION_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
import type { ThriveQueryContentParams, ThriveQueryContentResponse } from '@/tools/thrive/types'
|
||||
import {
|
||||
THRIVE_CONTENT_OUTPUT_PROPERTIES,
|
||||
THRIVE_PAGINATION_OUTPUT_PROPERTIES,
|
||||
} from '@/tools/thrive/types'
|
||||
import {
|
||||
appendThriveQuery,
|
||||
getThriveBaseUrl,
|
||||
getThriveHeaders,
|
||||
parseThriveResponse,
|
||||
} from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const queryContentTool: ToolConfig<ThriveQueryContentParams, ThriveQueryContentResponse> = {
|
||||
id: 'thrive_query_content',
|
||||
name: 'Thrive Query Content',
|
||||
description: 'Query content records in Thrive with pagination and filtering options.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number for pagination (default 1)',
|
||||
},
|
||||
perPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of results per page (1-1000, default 20)',
|
||||
},
|
||||
types: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Comma-separated content types (article, assessment, broadcast, cmi5, elearning, event, file, pathway, question, quiz, scorm, url, video, mixed). If both set, omitTypes is ignored.',
|
||||
},
|
||||
omitTypes: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Comma-separated content types (article, assessment, broadcast, cmi5, elearning, event, file, pathway, question, quiz, scorm, url, video, mixed). If both set, omitTypes is ignored.',
|
||||
},
|
||||
updatedSince: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Return only items updated on or after this date/time (ISO 8601)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const url = new URL(`${getThriveBaseUrl(params.host, 'v1')}/contents`)
|
||||
appendThriveQuery(url, 'page', params.page)
|
||||
appendThriveQuery(url, 'perPage', params.perPage)
|
||||
appendThriveQuery(url, 'types', params.types)
|
||||
appendThriveQuery(url, 'omitTypes', params.omitTypes)
|
||||
appendThriveQuery(url, 'updatedSince', params.updatedSince)
|
||||
return url.toString()
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveQueryContentResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to query content')
|
||||
return {
|
||||
success: true,
|
||||
output: { results: data?.results ?? [], pagination: data?.pagination ?? null },
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
results: {
|
||||
type: 'array',
|
||||
description: 'The matching content records',
|
||||
items: { type: 'object', properties: THRIVE_CONTENT_OUTPUT_PROPERTIES },
|
||||
},
|
||||
pagination: {
|
||||
type: 'object',
|
||||
description: 'Pagination details',
|
||||
properties: THRIVE_PAGINATION_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
import type {
|
||||
ThriveCpdPaginatedResponse,
|
||||
ThriveQueryCpdCategoriesParams,
|
||||
} from '@/tools/thrive/types'
|
||||
import {
|
||||
THRIVE_CPD_CATEGORY_OUTPUT_PROPERTIES,
|
||||
THRIVE_PAGINATION_OUTPUT_PROPERTIES,
|
||||
} from '@/tools/thrive/types'
|
||||
import {
|
||||
appendThriveQuery,
|
||||
getThriveBaseUrl,
|
||||
getThriveHeaders,
|
||||
parseThriveResponse,
|
||||
} from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const queryCpdCategoriesTool: ToolConfig<
|
||||
ThriveQueryCpdCategoriesParams,
|
||||
ThriveCpdPaginatedResponse
|
||||
> = {
|
||||
id: 'thrive_query_cpd_categories',
|
||||
name: 'Thrive Query CPD Categories',
|
||||
description: 'Query CPD categories in Thrive and return results with pagination.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number for pagination (default 1)',
|
||||
},
|
||||
perPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of results per page (1-1000, default 100)',
|
||||
},
|
||||
updatedSince: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Return only items updated on or after this date/time (ISO 8601)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const url = new URL(`${getThriveBaseUrl(params.host, 'v1')}/cpdCategories`)
|
||||
appendThriveQuery(url, 'page', params.page)
|
||||
appendThriveQuery(url, 'perPage', params.perPage)
|
||||
appendThriveQuery(url, 'updatedSince', params.updatedSince)
|
||||
return url.toString()
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveCpdPaginatedResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to query CPD categories')
|
||||
return {
|
||||
success: true,
|
||||
output: { results: data?.results ?? [], pagination: data?.pagination ?? null },
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
results: {
|
||||
type: 'array',
|
||||
description: 'The matching CPD categories',
|
||||
items: { type: 'object', properties: THRIVE_CPD_CATEGORY_OUTPUT_PROPERTIES },
|
||||
},
|
||||
pagination: {
|
||||
type: 'object',
|
||||
description: 'Pagination details',
|
||||
properties: THRIVE_PAGINATION_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
import type { ThriveCpdPaginatedResponse, ThriveQueryCpdEntriesParams } from '@/tools/thrive/types'
|
||||
import {
|
||||
THRIVE_CPD_ENTRY_OUTPUT_PROPERTIES,
|
||||
THRIVE_PAGINATION_OUTPUT_PROPERTIES,
|
||||
} from '@/tools/thrive/types'
|
||||
import {
|
||||
appendThriveQuery,
|
||||
getThriveBaseUrl,
|
||||
getThriveHeaders,
|
||||
parseThriveResponse,
|
||||
} from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const queryCpdEntriesTool: ToolConfig<
|
||||
ThriveQueryCpdEntriesParams,
|
||||
ThriveCpdPaginatedResponse
|
||||
> = {
|
||||
id: 'thrive_query_cpd_entries',
|
||||
name: 'Thrive Query CPD Entries',
|
||||
description: 'Query CPD log entries in Thrive and return results with pagination.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number for pagination (default 1)',
|
||||
},
|
||||
perPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of results per page (1-1000, default 100)',
|
||||
},
|
||||
entryDateFrom: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter entries after this date (format YYYY-MM-DD hh:mm:ss)',
|
||||
},
|
||||
entryDateTo: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter entries before this date (format YYYY-MM-DD hh:mm:ss)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const url = new URL(`${getThriveBaseUrl(params.host, 'v1')}/cpdEntries`)
|
||||
appendThriveQuery(url, 'page', params.page)
|
||||
appendThriveQuery(url, 'perPage', params.perPage)
|
||||
appendThriveQuery(url, 'entryDateFrom', params.entryDateFrom)
|
||||
appendThriveQuery(url, 'entryDateTo', params.entryDateTo)
|
||||
return url.toString()
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveCpdPaginatedResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to query CPD entries')
|
||||
return {
|
||||
success: true,
|
||||
output: { results: data?.results ?? [], pagination: data?.pagination ?? null },
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
results: {
|
||||
type: 'array',
|
||||
description: 'The matching CPD entries',
|
||||
items: { type: 'object', properties: THRIVE_CPD_ENTRY_OUTPUT_PROPERTIES },
|
||||
},
|
||||
pagination: {
|
||||
type: 'object',
|
||||
description: 'Pagination details',
|
||||
properties: THRIVE_PAGINATION_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
import type {
|
||||
ThriveCpdPaginatedResponse,
|
||||
ThriveQueryCpdRequirementsParams,
|
||||
} from '@/tools/thrive/types'
|
||||
import {
|
||||
THRIVE_CPD_REQUIREMENT_OUTPUT_PROPERTIES,
|
||||
THRIVE_PAGINATION_OUTPUT_PROPERTIES,
|
||||
} from '@/tools/thrive/types'
|
||||
import {
|
||||
appendThriveQuery,
|
||||
getThriveBaseUrl,
|
||||
getThriveHeaders,
|
||||
parseThriveResponse,
|
||||
} from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const queryCpdRequirementsTool: ToolConfig<
|
||||
ThriveQueryCpdRequirementsParams,
|
||||
ThriveCpdPaginatedResponse
|
||||
> = {
|
||||
id: 'thrive_query_cpd_requirements',
|
||||
name: 'Thrive Query CPD Requirements',
|
||||
description: 'Query CPD requirement summaries in Thrive and return results with pagination.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number for pagination (default 1)',
|
||||
},
|
||||
perPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of results per page (1-1000, default 100)',
|
||||
},
|
||||
updatedSince: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Return only items updated on or after this date/time (ISO 8601)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const url = new URL(`${getThriveBaseUrl(params.host, 'v1')}/cpdRequirementSummaries`)
|
||||
appendThriveQuery(url, 'page', params.page)
|
||||
appendThriveQuery(url, 'perPage', params.perPage)
|
||||
appendThriveQuery(url, 'updatedSince', params.updatedSince)
|
||||
return url.toString()
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveCpdPaginatedResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to query CPD requirements')
|
||||
return {
|
||||
success: true,
|
||||
output: { results: data?.results ?? [], pagination: data?.pagination ?? null },
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
results: {
|
||||
type: 'array',
|
||||
description: 'The matching CPD requirements',
|
||||
items: { type: 'object', properties: THRIVE_CPD_REQUIREMENT_OUTPUT_PROPERTIES },
|
||||
},
|
||||
pagination: {
|
||||
type: 'object',
|
||||
description: 'Pagination details',
|
||||
properties: THRIVE_PAGINATION_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
import type {
|
||||
ThriveCpdPaginatedResponse,
|
||||
ThriveQueryCpdUserSummariesParams,
|
||||
} from '@/tools/thrive/types'
|
||||
import {
|
||||
THRIVE_CPD_USER_SUMMARY_OUTPUT_PROPERTIES,
|
||||
THRIVE_PAGINATION_OUTPUT_PROPERTIES,
|
||||
} from '@/tools/thrive/types'
|
||||
import {
|
||||
appendThriveQuery,
|
||||
getThriveBaseUrl,
|
||||
getThriveHeaders,
|
||||
parseThriveResponse,
|
||||
} from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const queryCpdUserSummariesTool: ToolConfig<
|
||||
ThriveQueryCpdUserSummariesParams,
|
||||
ThriveCpdPaginatedResponse
|
||||
> = {
|
||||
id: 'thrive_query_cpd_user_summaries',
|
||||
name: 'Thrive Query CPD User Summaries',
|
||||
description: 'Query CPD user log summaries in Thrive and return results with pagination.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
entryDateFrom: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter entries after this date (format YYYY-MM-DDThh:mm:ss)',
|
||||
},
|
||||
entryDateTo: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter entries before this date (format YYYY-MM-DDThh:mm:ss)',
|
||||
},
|
||||
userIds: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated user IDs to filter by',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number for pagination (default 1)',
|
||||
},
|
||||
perPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of results per page (1-1000, default 100)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const url = new URL(`${getThriveBaseUrl(params.host, 'v1')}/cpdUserLogSummaries`)
|
||||
appendThriveQuery(url, 'entryDateFrom', params.entryDateFrom)
|
||||
appendThriveQuery(url, 'entryDateTo', params.entryDateTo)
|
||||
appendThriveQuery(url, 'userIds', params.userIds)
|
||||
appendThriveQuery(url, 'page', params.page)
|
||||
appendThriveQuery(url, 'perPage', params.perPage)
|
||||
return url.toString()
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveCpdPaginatedResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to query CPD user summaries')
|
||||
return {
|
||||
success: true,
|
||||
output: { results: data?.results ?? [], pagination: data?.pagination ?? null },
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
results: {
|
||||
type: 'array',
|
||||
description: 'The matching CPD user summaries',
|
||||
items: { type: 'object', properties: THRIVE_CPD_USER_SUMMARY_OUTPUT_PROPERTIES },
|
||||
},
|
||||
pagination: {
|
||||
type: 'object',
|
||||
description: 'Pagination details',
|
||||
properties: THRIVE_PAGINATION_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
import type { ThriveDeleteResponse, ThriveRemoveAudienceManagerParams } from '@/tools/thrive/types'
|
||||
import { getThriveBaseUrl, getThriveHeaders, parseThriveResponse } from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const removeAudienceManagerTool: ToolConfig<
|
||||
ThriveRemoveAudienceManagerParams,
|
||||
ThriveDeleteResponse
|
||||
> = {
|
||||
id: 'thrive_remove_audience_manager',
|
||||
name: 'Thrive Remove Audience Manager',
|
||||
description: 'Remove a single manager from a Thrive audience.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
audienceId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The audience id or audience reference',
|
||||
},
|
||||
userId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The user email, ref, or id to remove as a manager',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/audiences/${encodeURIComponent(params.audienceId)}/managers/${encodeURIComponent(params.userId)}`,
|
||||
method: 'DELETE',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveDeleteResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to remove audience manager')
|
||||
return { success: true, output: { success: data?.success ?? true } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
success: { type: 'boolean', description: 'Whether the audience manager was removed' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
import type { ThriveDeleteResponse, ThriveRemoveAudienceMemberParams } from '@/tools/thrive/types'
|
||||
import { getThriveBaseUrl, getThriveHeaders, parseThriveResponse } from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const removeAudienceMemberTool: ToolConfig<
|
||||
ThriveRemoveAudienceMemberParams,
|
||||
ThriveDeleteResponse
|
||||
> = {
|
||||
id: 'thrive_remove_audience_member',
|
||||
name: 'Thrive Remove Audience Member',
|
||||
description: 'Remove a single member from a Thrive audience.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
audienceId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The audience id or audience reference',
|
||||
},
|
||||
userRef: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The user email, ref, or id to remove',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/audiences/${encodeURIComponent(params.audienceId)}/members/${encodeURIComponent(params.userRef)}`,
|
||||
method: 'DELETE',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveDeleteResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to remove audience member')
|
||||
return { success: true, output: { success: data?.success ?? true } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
success: { type: 'boolean', description: 'Whether the audience member was removed' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import type { ThriveMessageResponse, ThriveRemoveUserTagsParams } from '@/tools/thrive/types'
|
||||
import {
|
||||
getThriveBaseUrl,
|
||||
getThriveHeaders,
|
||||
parseThriveArray,
|
||||
parseThriveResponse,
|
||||
} from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const removeUserTagsTool: ToolConfig<ThriveRemoveUserTagsParams, ThriveMessageResponse> = {
|
||||
id: 'thrive_remove_user_tags',
|
||||
name: 'Thrive Remove User Tags',
|
||||
description: 'Remove one or more tags from a learner in Thrive.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
userId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The learner ID',
|
||||
},
|
||||
tags: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'JSON array of tag names to remove (1-100). Example: ["leadership"]',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/users/${encodeURIComponent(params.userId)}/tags`,
|
||||
method: 'PATCH',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
body: (params) => ({
|
||||
op: 'remove',
|
||||
path: 'tags',
|
||||
value: parseThriveArray<string>(params.tags, 'tags'),
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveMessageResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to remove tags from learner')
|
||||
return {
|
||||
success: true,
|
||||
output: { status: data?.status ?? null, message: data?.message ?? null },
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
status: { type: 'number', description: 'The HTTP status code of the operation' },
|
||||
message: { type: 'string', description: 'A human-readable result message' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
import type { ThriveAddUsersResponse, ThriveAudienceManagersParams } from '@/tools/thrive/types'
|
||||
import { THRIVE_ADD_USERS_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import {
|
||||
getThriveBaseUrl,
|
||||
getThriveHeaders,
|
||||
parseThriveArray,
|
||||
parseThriveResponse,
|
||||
} from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const replaceAudienceManagersTool: ToolConfig<
|
||||
ThriveAudienceManagersParams,
|
||||
ThriveAddUsersResponse
|
||||
> = {
|
||||
id: 'thrive_replace_audience_managers',
|
||||
name: 'Thrive Replace Audience Managers',
|
||||
description:
|
||||
"Replace a Thrive audience's entire manager list with the given managers (does not support an empty array).",
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
audienceId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The audience id or audience reference',
|
||||
},
|
||||
managers: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'JSON array of manager objects that replaces the whole manager list (1-100, no empty array). Each: {"reference":"user@example.com","permissions":{"audienceManager":{"manageContent":true,"assignments":true},"peopleManager":{"canViewLearnPage":true,"insights":false,"manage":false},"administrator":{"canAddAudienceManagers":false}}}',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/audiences/${encodeURIComponent(params.audienceId)}/managers`,
|
||||
method: 'PATCH',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
body: (params) => JSON.stringify(parseThriveArray(params.managers, 'managers')),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveAddUsersResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to replace audience managers')
|
||||
return {
|
||||
success: true,
|
||||
output: { result: { success: data?.success ?? null, failure: data?.failure } },
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
result: {
|
||||
type: 'object',
|
||||
description:
|
||||
'The add/replace result, with successfully and unsuccessfully processed entities',
|
||||
properties: THRIVE_ADD_USERS_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
import type { ThriveAddUsersResponse, ThriveAudienceUsersParams } from '@/tools/thrive/types'
|
||||
import { THRIVE_ADD_USERS_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import {
|
||||
getThriveBaseUrl,
|
||||
getThriveHeaders,
|
||||
parseThriveArray,
|
||||
parseThriveResponse,
|
||||
} from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const replaceAudienceMembersTool: ToolConfig<
|
||||
ThriveAudienceUsersParams,
|
||||
ThriveAddUsersResponse
|
||||
> = {
|
||||
id: 'thrive_replace_audience_members',
|
||||
name: 'Thrive Replace Audience Members',
|
||||
description:
|
||||
"Replace a Thrive audience's entire members list with the given users (does not support an empty array).",
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
audienceId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The audience id or audience reference',
|
||||
},
|
||||
users: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'JSON array of user emails/refs/ids that replaces the whole members list (1-100, no empty array). Example: ["user@example.com"]',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/audiences/${encodeURIComponent(params.audienceId)}/members`,
|
||||
method: 'PATCH',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
body: (params) => JSON.stringify(parseThriveArray<string>(params.users, 'users')),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveAddUsersResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to replace audience members')
|
||||
return {
|
||||
success: true,
|
||||
output: { result: { success: data?.success ?? null, failure: data?.failure } },
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
result: {
|
||||
type: 'object',
|
||||
description:
|
||||
'The add/replace result, with successfully and unsuccessfully processed entities',
|
||||
properties: THRIVE_ADD_USERS_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
import type { ThriveSearchUsersParams, ThriveSearchUsersResponse } from '@/tools/thrive/types'
|
||||
import {
|
||||
THRIVE_PAGINATION_OUTPUT_PROPERTIES,
|
||||
THRIVE_USER_OUTPUT_PROPERTIES,
|
||||
} from '@/tools/thrive/types'
|
||||
import {
|
||||
appendThriveQuery,
|
||||
getThriveBaseUrl,
|
||||
getThriveHeaders,
|
||||
parseThriveResponse,
|
||||
} from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const searchUsersTool: ToolConfig<ThriveSearchUsersParams, ThriveSearchUsersResponse> = {
|
||||
id: 'thrive_search_users',
|
||||
name: 'Thrive Search Users',
|
||||
description: 'Search users in Thrive and return basic user information with pagination.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number for pagination (default 1)',
|
||||
},
|
||||
perPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of results per page (1-1000, default 100)',
|
||||
},
|
||||
updatedSince: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Return only users updated on or after this date/time (ISO 8601)',
|
||||
},
|
||||
statuses: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated statuses to include: active, inactive, expired, new',
|
||||
},
|
||||
omitStatuses: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated statuses to exclude: active, inactive, expired, new',
|
||||
},
|
||||
status: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter by a single status: active, inactive, expired, or new',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const url = new URL(`${getThriveBaseUrl(params.host, 'v1')}/users`)
|
||||
appendThriveQuery(url, 'page', params.page)
|
||||
appendThriveQuery(url, 'perPage', params.perPage)
|
||||
appendThriveQuery(url, 'updatedSince', params.updatedSince)
|
||||
appendThriveQuery(url, 'statuses', params.statuses)
|
||||
appendThriveQuery(url, 'omitStatuses', params.omitStatuses)
|
||||
appendThriveQuery(url, 'status', params.status)
|
||||
return url.toString()
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveSearchUsersResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to search users')
|
||||
return {
|
||||
success: true,
|
||||
output: { results: data?.results ?? [], pagination: data?.pagination ?? null },
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
results: {
|
||||
type: 'array',
|
||||
description: 'The matching users',
|
||||
items: { type: 'object', properties: THRIVE_USER_OUTPUT_PROPERTIES },
|
||||
},
|
||||
pagination: {
|
||||
type: 'object',
|
||||
description: 'Pagination details',
|
||||
properties: THRIVE_PAGINATION_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import type { ThriveSuspendUserParams, ThriveUserResponse } from '@/tools/thrive/types'
|
||||
import { THRIVE_USER_LIFECYCLE_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import { getThriveBaseUrl, getThriveHeaders, parseThriveResponse } from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const suspendUserTool: ToolConfig<ThriveSuspendUserParams, ThriveUserResponse> = {
|
||||
id: 'thrive_suspend_user',
|
||||
name: 'Thrive Suspend User',
|
||||
description: 'Suspend a user in Thrive by ref, marking the account inactive.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
ref: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The user ref to suspend',
|
||||
},
|
||||
endDate: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The date this individual left your organisation (ISO 8601)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v2')}/users/ref/${encodeURIComponent(params.ref)}/suspend`,
|
||||
method: 'PATCH',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
body: (params) => {
|
||||
const body: Record<string, any> = {}
|
||||
if (params.endDate) body.endDate = params.endDate
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveUserResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to suspend user')
|
||||
return { success: true, output: { user: data ?? null } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
user: {
|
||||
type: 'object',
|
||||
description: 'The suspended user',
|
||||
properties: THRIVE_USER_LIFECYCLE_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,856 @@
|
||||
import type { OutputProperty, ToolResponse } from '@/tools/types'
|
||||
|
||||
/**
|
||||
* Credentials and region shared by every Thrive tool.
|
||||
* Thrive uses HTTP Basic auth (Tenant ID as username, API key as password).
|
||||
*/
|
||||
export interface ThriveBaseParams {
|
||||
tenantId: string
|
||||
apiKey: string
|
||||
/** Region-specific API host, e.g. `public.api.learn.link`. Defaults to Production. */
|
||||
host?: string
|
||||
}
|
||||
|
||||
export interface ThrivePagination {
|
||||
totalResults: number
|
||||
totalPages: number
|
||||
page: number
|
||||
perPage: number
|
||||
}
|
||||
|
||||
export const THRIVE_PAGINATION_OUTPUT_PROPERTIES: Record<string, OutputProperty> = {
|
||||
totalResults: { type: 'number', description: 'Total number of results matching the query' },
|
||||
totalPages: { type: 'number', description: 'Total number of pages available' },
|
||||
page: { type: 'number', description: 'Current page number' },
|
||||
perPage: { type: 'number', description: 'Number of results per page' },
|
||||
}
|
||||
|
||||
const USER_POSITION_OUTPUT_PROPERTIES: Record<string, OutputProperty> = {
|
||||
id: { type: 'string', description: 'The user ID' },
|
||||
manager: {
|
||||
type: 'object',
|
||||
description: 'Line manager details',
|
||||
properties: {
|
||||
id: { type: 'string', description: "The manager's user ID", nullable: true },
|
||||
name: { type: 'string', description: "The manager's full name", nullable: true },
|
||||
ref: { type: 'string', description: "The manager's unique reference", nullable: true },
|
||||
},
|
||||
},
|
||||
ouId: { type: 'string', description: 'The organisational unit ID', nullable: true },
|
||||
isActive: { type: 'boolean', description: 'Whether the position is active' },
|
||||
startDate: { type: 'string', description: 'Start date (ISO 8601)', nullable: true },
|
||||
endDate: { type: 'string', description: 'End date (ISO 8601)', nullable: true },
|
||||
createdAt: { type: 'string', description: 'Creation timestamp (ISO 8601)', nullable: true },
|
||||
updatedAt: { type: 'string', description: 'Last-update timestamp (ISO 8601)', nullable: true },
|
||||
}
|
||||
|
||||
/** Full `User` schema returned by search-users and get-user-by-id. */
|
||||
export const THRIVE_USER_OUTPUT_PROPERTIES: Record<string, OutputProperty> = {
|
||||
id: { type: 'string', description: "The user's ID" },
|
||||
ref: { type: 'string', description: "The user's ref", nullable: true },
|
||||
firstName: { type: 'string', description: "The user's first name", nullable: true },
|
||||
lastName: { type: 'string', description: "The user's last name", nullable: true },
|
||||
email: { type: 'string', description: "The user's email", nullable: true },
|
||||
role: { type: 'string', description: "The user's role", nullable: true },
|
||||
status: { type: 'string', description: "The user's status", nullable: true },
|
||||
positions: {
|
||||
type: 'array',
|
||||
description: "The user's positions",
|
||||
items: { type: 'object', properties: USER_POSITION_OUTPUT_PROPERTIES },
|
||||
},
|
||||
additionalFields: { type: 'json', description: 'Custom field values', nullable: true },
|
||||
languageCode: { type: 'string', description: "The user's language code", nullable: true },
|
||||
deleted: { type: 'boolean', description: 'Whether the user has been deleted' },
|
||||
compliance: { type: 'number', description: "The user's compliance score" },
|
||||
level: { type: 'number', description: "The user's level" },
|
||||
firstLogin: { type: 'string', description: 'First login timestamp (ISO 8601)', nullable: true },
|
||||
lastLogin: { type: 'string', description: 'Last login timestamp (ISO 8601)', nullable: true },
|
||||
tags: { type: 'json', description: 'Tag membership (e.g. skills)' },
|
||||
usersFollowing: {
|
||||
type: 'array',
|
||||
description: 'IDs of users this user follows',
|
||||
items: { type: 'string' },
|
||||
},
|
||||
tagsFollowing: {
|
||||
type: 'array',
|
||||
description: 'Tags this user follows',
|
||||
items: { type: 'string' },
|
||||
},
|
||||
createdAt: { type: 'string', description: 'Creation timestamp (ISO 8601)', nullable: true },
|
||||
updatedAt: { type: 'string', description: 'Last-update timestamp (ISO 8601)', nullable: true },
|
||||
hasPicture: { type: 'boolean', description: 'Whether the user has a profile picture' },
|
||||
timeZone: { type: 'string', description: "The user's time zone", nullable: true },
|
||||
summary: { type: 'string', description: "The user's summary", nullable: true },
|
||||
relevancy: { type: 'number', description: "The user's relevancy score" },
|
||||
rank: { type: 'json', description: "The user's rank details" },
|
||||
agreedTerms: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the user agreed to the terms',
|
||||
nullable: true,
|
||||
},
|
||||
onboarded: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the user has been onboarded',
|
||||
nullable: true,
|
||||
},
|
||||
audiences: {
|
||||
type: 'array',
|
||||
description: 'Audience IDs the user belongs to',
|
||||
items: { type: 'string' },
|
||||
},
|
||||
singleSignOn: { type: 'boolean', description: 'Whether the user uses single sign-on' },
|
||||
}
|
||||
|
||||
/** Smaller `BasicUser` schema returned by get-user-by-ref. */
|
||||
export const THRIVE_BASIC_USER_OUTPUT_PROPERTIES: Record<string, OutputProperty> = {
|
||||
id: { type: 'string', description: "The user's ID" },
|
||||
ref: { type: 'string', description: "The user's ref", nullable: true },
|
||||
firstName: { type: 'string', description: "The user's first name", nullable: true },
|
||||
lastName: { type: 'string', description: "The user's last name", nullable: true },
|
||||
email: { type: 'string', description: "The user's email", nullable: true },
|
||||
role: { type: 'string', description: "The user's role", nullable: true },
|
||||
status: { type: 'string', description: "The user's status", nullable: true },
|
||||
positions: {
|
||||
type: 'array',
|
||||
description: "The user's positions",
|
||||
items: { type: 'object', properties: USER_POSITION_OUTPUT_PROPERTIES },
|
||||
},
|
||||
additionalFields: { type: 'json', description: 'Custom field values', nullable: true },
|
||||
languageCode: { type: 'string', description: "The user's language code", nullable: true },
|
||||
}
|
||||
|
||||
/** `UserLifecycleResource` returned by create/update/suspend user. */
|
||||
export const THRIVE_USER_LIFECYCLE_OUTPUT_PROPERTIES: Record<string, OutputProperty> = {
|
||||
id: { type: 'string', description: 'The user ID' },
|
||||
loginMethod: { type: 'string', description: 'How the user logs in' },
|
||||
ref: { type: 'string', description: "Your organisation's unique identifier for the user" },
|
||||
email: { type: 'string', description: 'The email address for the user' },
|
||||
firstName: { type: 'string', description: 'The given name of the individual' },
|
||||
lastName: { type: 'string', description: 'The family name of the individual' },
|
||||
role: { type: 'string', description: 'Role assigned to this individual' },
|
||||
jobTitle: { type: 'string', description: "Name of this individual's role" },
|
||||
managerRef: { type: 'string', description: "The line manager's ref", nullable: true },
|
||||
startDate: { type: 'string', description: 'Date started with the organisation', nullable: true },
|
||||
endDate: { type: 'string', description: 'Date left the organisation', nullable: true },
|
||||
timeZone: { type: 'string', description: "The user's preferred timezone" },
|
||||
languageCode: { type: 'string', description: "The user's preferred language" },
|
||||
active: { type: 'boolean', description: 'Whether the account is active or suspended' },
|
||||
createdAt: { type: 'string', description: 'Date/time the user was created' },
|
||||
updatedAt: { type: 'string', description: 'Date/time the user was last modified' },
|
||||
sso: { type: 'boolean', description: 'Whether the account is managed by an auth provider' },
|
||||
domain: {
|
||||
type: 'string',
|
||||
description: 'Domain this individual is associated with',
|
||||
nullable: true,
|
||||
},
|
||||
additionalFields: {
|
||||
type: 'json',
|
||||
description: 'Custom field values for this user',
|
||||
nullable: true,
|
||||
},
|
||||
}
|
||||
|
||||
export const THRIVE_AUDIENCE_OUTPUT_PROPERTIES: Record<string, OutputProperty> = {
|
||||
id: { type: 'string', description: 'The id of the audience' },
|
||||
name: { type: 'string', description: 'The name of the audience' },
|
||||
reference: { type: 'string', description: 'The external reference for the audience' },
|
||||
apiControlled: { type: 'boolean', description: 'Whether the audience is API controlled' },
|
||||
category: { type: 'string', description: 'Either "audience" or "structure"' },
|
||||
type: { type: 'string', description: 'Either "manual" or "smart"' },
|
||||
parent: {
|
||||
type: 'object',
|
||||
description: 'Parent audience/structure information',
|
||||
nullable: true,
|
||||
properties: {
|
||||
name: { type: 'string', description: 'The name of the parent audience' },
|
||||
reference: { type: 'string', description: 'The external reference for the parent' },
|
||||
id: { type: 'string', description: 'The id of the parent audience/structure' },
|
||||
},
|
||||
},
|
||||
createdAt: { type: 'string', description: 'Creation timestamp (ISO 8601)' },
|
||||
updatedAt: { type: 'string', description: 'Last-update timestamp (ISO 8601)' },
|
||||
}
|
||||
|
||||
export const THRIVE_AUDIENCE_MEMBER_OUTPUT_PROPERTIES: Record<string, OutputProperty> = {
|
||||
userId: { type: 'string', description: "The user's id" },
|
||||
reference: { type: 'string', description: "The user's reference" },
|
||||
email: { type: 'string', description: "The user's email" },
|
||||
}
|
||||
|
||||
export const THRIVE_AUDIENCE_MANAGER_OUTPUT_PROPERTIES: Record<string, OutputProperty> = {
|
||||
userId: { type: 'string', description: "The user's id" },
|
||||
reference: { type: 'string', description: "The user's reference" },
|
||||
email: { type: 'string', description: "The user's email" },
|
||||
permissions: {
|
||||
type: 'object',
|
||||
description: 'The manager permissions',
|
||||
properties: {
|
||||
audienceManager: { type: 'json', description: 'Audience manager permissions' },
|
||||
peopleManager: { type: 'json', description: 'People manager permissions' },
|
||||
administrator: {
|
||||
type: 'json',
|
||||
description: 'Administrator permissions (structures only)',
|
||||
nullable: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
/** Superset of SuccessAddUsers / PartialSuccessAddUsers. */
|
||||
export const THRIVE_ADD_USERS_OUTPUT_PROPERTIES: Record<string, OutputProperty> = {
|
||||
success: {
|
||||
type: 'object',
|
||||
description: 'Successfully processed entities',
|
||||
properties: {
|
||||
count: { type: 'number', description: 'Number of successfully processed entities' },
|
||||
entities: {
|
||||
type: 'array',
|
||||
description: 'The successfully processed entities',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: { reference: { type: 'string', description: 'The entity reference' } },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
failure: {
|
||||
type: 'object',
|
||||
description: 'Unsuccessfully processed entities',
|
||||
optional: true,
|
||||
properties: {
|
||||
count: { type: 'number', description: 'Number of unsuccessfully processed entities' },
|
||||
entities: {
|
||||
type: 'array',
|
||||
description: 'The unsuccessfully processed entities',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
reason: { type: 'string', description: 'The reason for the failure' },
|
||||
reference: { type: 'string', description: 'The entity reference' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export const THRIVE_ASSIGNMENT_OUTPUT_PROPERTIES: Record<string, OutputProperty> = {
|
||||
id: { type: 'string', description: 'The assignment ID' },
|
||||
audienceId: { type: 'string', description: 'The audience ID' },
|
||||
primaryContentId: { type: 'string', description: 'The content ID for the primary content' },
|
||||
alternativeContentIds: {
|
||||
type: 'array',
|
||||
description: 'Content IDs that can also complete the assignment',
|
||||
items: { type: 'string' },
|
||||
},
|
||||
hideAlternativeContent: {
|
||||
type: 'boolean',
|
||||
description: 'Whether to hide the alternative content',
|
||||
},
|
||||
completionPeriod: {
|
||||
type: 'number',
|
||||
description: 'Number of days required to complete the assignment',
|
||||
},
|
||||
recurrence: {
|
||||
type: 'number',
|
||||
description: 'Number of days until the assignment reoccurs',
|
||||
nullable: true,
|
||||
},
|
||||
isActive: { type: 'boolean', description: 'Whether the assignment is active' },
|
||||
isDeleted: { type: 'boolean', description: 'Whether the assignment is deleted' },
|
||||
createdAt: { type: 'string', description: 'Creation timestamp (ISO 8601)', nullable: true },
|
||||
deletedAt: { type: 'string', description: 'Deletion timestamp (ISO 8601)', nullable: true },
|
||||
updatedAt: { type: 'string', description: 'Last-update timestamp (ISO 8601)', nullable: true },
|
||||
}
|
||||
|
||||
export const THRIVE_ENROLMENT_OUTPUT_PROPERTIES: Record<string, OutputProperty> = {
|
||||
id: { type: 'string', description: 'The enrolment ID' },
|
||||
userId: { type: 'string', description: 'The assignee user ID' },
|
||||
assignmentId: { type: 'string', description: 'The assignment ID' },
|
||||
audienceId: { type: 'string', description: 'The audience ID' },
|
||||
primaryContentId: { type: 'string', description: 'The assigned content ID' },
|
||||
status: { type: 'string', description: 'Enrolment status' },
|
||||
availableDate: { type: 'string', description: 'Date a scheduled enrolment becomes open' },
|
||||
dueDate: { type: 'string', description: 'Date after which a scheduled enrolment is overdue' },
|
||||
lastCompletedAt: { type: 'string', description: 'Date a scheduled enrolment was last completed' },
|
||||
history: {
|
||||
type: 'array',
|
||||
description: 'Event-log history entries',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
type: { type: 'string', description: 'The type of the logged event' },
|
||||
completionId: { type: 'string', description: 'The completion ID' },
|
||||
previousStatus: { type: 'string', description: 'The previous enrolment status' },
|
||||
nextStatus: { type: 'string', description: 'The next enrolment status' },
|
||||
createdAt: { type: 'string', description: 'Date the event was logged' },
|
||||
updatedAt: { type: 'string', description: 'Date the event was last modified' },
|
||||
},
|
||||
},
|
||||
},
|
||||
updatedAt: { type: 'string', description: 'Date the enrolment was last updated' },
|
||||
}
|
||||
|
||||
export const THRIVE_COMPLETION_OUTPUT_PROPERTIES: Record<string, OutputProperty> = {
|
||||
id: { type: 'string', description: 'The completion ID' },
|
||||
userId: { type: 'string', description: 'The user ID' },
|
||||
contentId: { type: 'string', description: 'The content ID for the content completed' },
|
||||
contentVersion: { type: 'number', description: 'The version of the content' },
|
||||
skills: {
|
||||
type: 'array',
|
||||
description: 'The skills acquired by completing this content',
|
||||
items: { type: 'string' },
|
||||
},
|
||||
completionType: { type: 'string', description: 'The type of completion record' },
|
||||
hadDueDate: { type: 'boolean', description: 'Whether the completion had a due date' },
|
||||
isRPL: { type: 'boolean', description: 'Whether the completion was imported via RPL' },
|
||||
completedAt: { type: 'string', description: 'Timestamp when the completion occurred (ISO 8601)' },
|
||||
activeUntil: {
|
||||
type: 'string',
|
||||
description: 'Timestamp the completion is valid until (ISO 8601)',
|
||||
},
|
||||
}
|
||||
|
||||
const CONTENT_HISTORY_OUTPUT_PROPERTIES: Record<string, OutputProperty> = {
|
||||
action: { type: 'string', description: 'Type of change or event recorded' },
|
||||
timestamp: { type: 'string', description: 'When the action occurred (ISO 8601)' },
|
||||
performedBy: {
|
||||
type: 'object',
|
||||
description: 'The actor that performed the action',
|
||||
properties: {
|
||||
type: { type: 'string', description: 'Kind of actor (e.g. user or system)' },
|
||||
value: { type: 'string', description: 'Identifier or value of the actor' },
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export const THRIVE_CONTENT_OUTPUT_PROPERTIES: Record<string, OutputProperty> = {
|
||||
id: { type: 'string', description: 'Unique identifier for the content' },
|
||||
title: { type: 'string', description: 'Title of the content' },
|
||||
description: { type: 'string', description: 'Detailed description (may contain HTML)' },
|
||||
tags: {
|
||||
type: 'array',
|
||||
description: 'Tags associated with this content',
|
||||
items: { type: 'string' },
|
||||
},
|
||||
type: { type: 'string', description: 'The kind of artifact associated with this content' },
|
||||
createdAt: { type: 'string', description: 'Creation timestamp (ISO 8601)' },
|
||||
updatedAt: { type: 'string', description: 'Last-update timestamp (ISO 8601)' },
|
||||
author: { type: 'string', description: 'User ID who authored the content', nullable: true },
|
||||
isOfficial: { type: 'boolean', description: 'Whether the content is recognised as official' },
|
||||
duration: {
|
||||
type: 'object',
|
||||
description: 'Expected time to complete the content',
|
||||
nullable: true,
|
||||
properties: {
|
||||
value: { type: 'number', description: 'Duration value', nullable: true },
|
||||
unit: { type: 'string', description: "The unit of the duration (always 'minutes')" },
|
||||
},
|
||||
},
|
||||
contentHistory: {
|
||||
type: 'array',
|
||||
description: 'Chronological history of actions on this content',
|
||||
items: { type: 'object', properties: CONTENT_HISTORY_OUTPUT_PROPERTIES },
|
||||
},
|
||||
}
|
||||
|
||||
export const THRIVE_ACTIVITY_OUTPUT_PROPERTIES: Record<string, OutputProperty> = {
|
||||
type: { type: 'string', description: 'The activity action type' },
|
||||
name: { type: 'string', description: 'The name of the activity' },
|
||||
id: { type: 'string', description: 'Unique ID for this activity record' },
|
||||
user: { type: 'string', description: 'User ID who triggered the activity' },
|
||||
date: { type: 'string', description: 'Timestamp when the activity occurred (ISO 8601)' },
|
||||
contextId: { type: 'string', description: 'Identifier for the context item' },
|
||||
contextType: { type: 'string', description: 'What this activity was in relation to' },
|
||||
data: { type: 'json', description: 'Unstructured activity data; shape varies by type' },
|
||||
with: { type: 'json', description: 'Additional context information', nullable: true },
|
||||
}
|
||||
|
||||
export const THRIVE_CPD_CATEGORY_OUTPUT_PROPERTIES: Record<string, OutputProperty> = {
|
||||
categoryId: { type: 'string', description: 'Unique ID for this category record' },
|
||||
name: { type: 'string', description: 'Name of the category of CPD activity' },
|
||||
}
|
||||
|
||||
export const THRIVE_CPD_ENTRY_OUTPUT_PROPERTIES: Record<string, OutputProperty> = {
|
||||
logEntryId: { type: 'string', description: 'Unique ID for this activity record' },
|
||||
userId: { type: 'string', description: 'User ID who triggered this activity record' },
|
||||
activity: {
|
||||
type: 'object',
|
||||
description: 'The content item associated with the CPD log entry',
|
||||
properties: {
|
||||
type: { type: 'string', description: 'The type of content (e.g. file, article, video)' },
|
||||
name: { type: 'string', description: 'The name of the content item' },
|
||||
},
|
||||
},
|
||||
category: {
|
||||
type: 'object',
|
||||
description: 'The CPD category',
|
||||
properties: {
|
||||
categoryId: { type: 'string', description: 'Unique ID for this category record' },
|
||||
name: { type: 'string', description: 'Name of the category of CPD activity' },
|
||||
},
|
||||
},
|
||||
entryDate: {
|
||||
type: 'string',
|
||||
description: 'The date and time the CPD entry was logged (ISO 8601)',
|
||||
},
|
||||
durationMinutes: { type: 'number', description: 'Minutes logged as CPD from this activity' },
|
||||
description: { type: 'string', description: 'Summary or reflective statement', nullable: true },
|
||||
isVerified: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the activity was generated from verified system activity',
|
||||
},
|
||||
}
|
||||
|
||||
export const THRIVE_CPD_REQUIREMENT_OUTPUT_PROPERTIES: Record<string, OutputProperty> = {
|
||||
audienceRequirementId: { type: 'string', description: 'Unique ID for this requirement record' },
|
||||
audienceId: { type: 'string', description: 'ID of the audience this requirement applies to' },
|
||||
requiredMinutes: { type: 'number', description: 'Number of minutes required for CPD completion' },
|
||||
createdAt: { type: 'string', description: 'Creation timestamp (ISO 8601)' },
|
||||
updatedAt: { type: 'string', description: 'Last-update timestamp (ISO 8601)', nullable: true },
|
||||
}
|
||||
|
||||
export const THRIVE_CPD_USER_SUMMARY_OUTPUT_PROPERTIES: Record<string, OutputProperty> = {
|
||||
userId: { type: 'string', description: 'ID of the user this summary is for' },
|
||||
durationMinutes: {
|
||||
type: 'number',
|
||||
description: 'Total CPD minutes logged by the user in the period',
|
||||
},
|
||||
}
|
||||
|
||||
export const THRIVE_TAG_OUTPUT_PROPERTIES: Record<string, OutputProperty> = {
|
||||
tag: { type: 'string', description: 'The name of the tag' },
|
||||
id: { type: 'string', description: 'The ID of the tag' },
|
||||
contents: {
|
||||
type: 'array',
|
||||
description: 'IDs of contents using this tag',
|
||||
items: { type: 'string' },
|
||||
},
|
||||
campaigns: {
|
||||
type: 'array',
|
||||
description: 'IDs of campaigns using this tag',
|
||||
items: { type: 'string' },
|
||||
},
|
||||
interests: {
|
||||
type: 'array',
|
||||
description: 'IDs of users interested in this tag',
|
||||
items: { type: 'string' },
|
||||
},
|
||||
skills: {
|
||||
type: 'array',
|
||||
description: 'IDs of users skilled in this tag',
|
||||
items: { type: 'string' },
|
||||
},
|
||||
}
|
||||
|
||||
export const THRIVE_SKILL_LEVEL_OUTPUT_PROPERTIES: Record<string, OutputProperty> = {
|
||||
name: { type: 'string', description: 'The name of the skill level' },
|
||||
isEnabled: { type: 'boolean', description: 'Whether the skill level is enabled' },
|
||||
value: { type: 'number', description: 'The numeric value of the skill level' },
|
||||
}
|
||||
|
||||
// ─── Users ───────────────────────────────────────────────────────────────────
|
||||
|
||||
export interface ThriveCreateUserParams extends ThriveBaseParams {
|
||||
ref: string
|
||||
firstName: string
|
||||
lastName: string
|
||||
email?: string
|
||||
loginMethod?: string
|
||||
role?: string
|
||||
jobTitle?: string
|
||||
managerRef?: string
|
||||
startDate?: string
|
||||
endDate?: string
|
||||
timeZone?: string
|
||||
languageCode?: string
|
||||
sso?: boolean
|
||||
domain?: string
|
||||
additionalFields?: string
|
||||
}
|
||||
|
||||
export interface ThriveUpdateUserParams extends ThriveBaseParams {
|
||||
ref: string
|
||||
firstName?: string
|
||||
lastName?: string
|
||||
email?: string
|
||||
loginMethod?: string
|
||||
role?: string
|
||||
jobTitle?: string
|
||||
managerRef?: string
|
||||
startDate?: string
|
||||
endDate?: string
|
||||
timeZone?: string
|
||||
languageCode?: string
|
||||
sso?: boolean
|
||||
domain?: string
|
||||
additionalFields?: string
|
||||
}
|
||||
|
||||
export interface ThriveDeleteUserParams extends ThriveBaseParams {
|
||||
ref: string
|
||||
}
|
||||
|
||||
export interface ThriveSuspendUserParams extends ThriveBaseParams {
|
||||
ref: string
|
||||
endDate?: string
|
||||
}
|
||||
|
||||
export interface ThriveSearchUsersParams extends ThriveBaseParams {
|
||||
page?: number
|
||||
perPage?: number
|
||||
updatedSince?: string
|
||||
statuses?: string
|
||||
omitStatuses?: string
|
||||
status?: string
|
||||
}
|
||||
|
||||
export interface ThriveGetUserByIdParams extends ThriveBaseParams {
|
||||
id: string
|
||||
}
|
||||
|
||||
export interface ThriveGetUserByRefParams extends ThriveBaseParams {
|
||||
ref: string
|
||||
}
|
||||
|
||||
export interface ThriveUserResponse extends ToolResponse {
|
||||
output: { user: Record<string, any> }
|
||||
}
|
||||
|
||||
export interface ThriveSearchUsersResponse extends ToolResponse {
|
||||
output: { results: Record<string, any>[]; pagination: ThrivePagination | null }
|
||||
}
|
||||
|
||||
export interface ThriveDeleteResponse extends ToolResponse {
|
||||
output: { success: boolean }
|
||||
}
|
||||
|
||||
// ─── Audiences ─────────────────────────────────────────────────────────────
|
||||
|
||||
export interface ThriveListAudiencesParams extends ThriveBaseParams {
|
||||
apiControlled?: boolean
|
||||
updatedSince?: string
|
||||
page?: number
|
||||
perPage?: number
|
||||
}
|
||||
|
||||
export interface ThriveCreateAudienceParams extends ThriveBaseParams {
|
||||
name?: string
|
||||
reference?: string
|
||||
parentId?: string
|
||||
category?: string
|
||||
}
|
||||
|
||||
export interface ThriveGetAudienceParams extends ThriveBaseParams {
|
||||
audienceId: string
|
||||
}
|
||||
|
||||
export interface ThriveUpdateAudienceParams extends ThriveBaseParams {
|
||||
audienceId: string
|
||||
name?: string
|
||||
reference?: string
|
||||
parentId?: string
|
||||
}
|
||||
|
||||
export interface ThriveDeleteAudienceParams extends ThriveBaseParams {
|
||||
audienceId: string
|
||||
}
|
||||
|
||||
export interface ThriveListAudienceMembersParams extends ThriveBaseParams {
|
||||
audienceId: string
|
||||
page?: number
|
||||
perPage?: number
|
||||
}
|
||||
|
||||
export interface ThriveAudienceUsersParams extends ThriveBaseParams {
|
||||
audienceId: string
|
||||
users: string
|
||||
}
|
||||
|
||||
export interface ThriveRemoveAudienceMemberParams extends ThriveBaseParams {
|
||||
audienceId: string
|
||||
userRef: string
|
||||
}
|
||||
|
||||
export interface ThriveListAudienceManagersParams extends ThriveBaseParams {
|
||||
audienceId: string
|
||||
}
|
||||
|
||||
export interface ThriveAudienceManagersParams extends ThriveBaseParams {
|
||||
audienceId: string
|
||||
managers: string
|
||||
}
|
||||
|
||||
export interface ThriveRemoveAudienceManagerParams extends ThriveBaseParams {
|
||||
audienceId: string
|
||||
userId: string
|
||||
}
|
||||
|
||||
export interface ThriveAudienceResponse extends ToolResponse {
|
||||
output: { audience: Record<string, any> }
|
||||
}
|
||||
|
||||
export interface ThriveListAudiencesResponse extends ToolResponse {
|
||||
output: { results: Record<string, any>[]; pagination: ThrivePagination | null }
|
||||
}
|
||||
|
||||
export interface ThriveListAudienceMembersResponse extends ToolResponse {
|
||||
output: { results: Record<string, any>[]; pagination: ThrivePagination | null }
|
||||
}
|
||||
|
||||
export interface ThriveListAudienceManagersResponse extends ToolResponse {
|
||||
output: { managers: Record<string, any>[] }
|
||||
}
|
||||
|
||||
export interface ThriveAddUsersResponse extends ToolResponse {
|
||||
output: { result: { success: Record<string, any> | null; failure?: Record<string, any> } }
|
||||
}
|
||||
|
||||
export interface ThriveMessageResponse extends ToolResponse {
|
||||
output: { status: number; message: string }
|
||||
}
|
||||
|
||||
// ─── Assignments & Enrolments ──────────────────────────────────────────────
|
||||
|
||||
export interface ThriveListAssignmentsParams extends ThriveBaseParams {
|
||||
audienceId?: string
|
||||
updatedSince?: string
|
||||
page?: number
|
||||
perPage?: number
|
||||
}
|
||||
|
||||
export interface ThriveCreateAssignmentParams extends ThriveBaseParams {
|
||||
audienceId: string
|
||||
contentId: string
|
||||
alternativeContentIds?: string
|
||||
hideAlternativeContent?: boolean
|
||||
completionPeriod?: number
|
||||
recurrence?: number
|
||||
}
|
||||
|
||||
export interface ThriveGetAssignmentParams extends ThriveBaseParams {
|
||||
assignmentId: string
|
||||
}
|
||||
|
||||
export interface ThriveUpdateAssignmentParams extends ThriveBaseParams {
|
||||
assignmentId: string
|
||||
audienceId: string
|
||||
contentId?: string
|
||||
completionPeriod?: number
|
||||
recurrence?: number
|
||||
alternativeContentIds?: string
|
||||
}
|
||||
|
||||
export interface ThriveDeleteAssignmentParams extends ThriveBaseParams {
|
||||
assignmentId: string
|
||||
audienceId: string
|
||||
}
|
||||
|
||||
export interface ThriveListEnrolmentsParams extends ThriveBaseParams {
|
||||
assignmentId: string
|
||||
updatedAtFrom?: string
|
||||
updatedAtTo?: string
|
||||
status?: string
|
||||
page?: number
|
||||
perPage?: number
|
||||
}
|
||||
|
||||
export interface ThriveGetEnrolmentParams extends ThriveBaseParams {
|
||||
assignmentId: string
|
||||
enrolmentId: string
|
||||
}
|
||||
|
||||
export interface ThriveAssignmentResponse extends ToolResponse {
|
||||
output: { assignment: Record<string, any> }
|
||||
}
|
||||
|
||||
export interface ThriveListAssignmentsResponse extends ToolResponse {
|
||||
output: { assignments: Record<string, any>[] }
|
||||
}
|
||||
|
||||
export interface ThriveEnrolmentResponse extends ToolResponse {
|
||||
output: { enrolment: Record<string, any> }
|
||||
}
|
||||
|
||||
export interface ThriveListEnrolmentsResponse extends ToolResponse {
|
||||
output: { enrolments: Record<string, any>[] }
|
||||
}
|
||||
|
||||
// ─── Completions ───────────────────────────────────────────────────────────
|
||||
|
||||
export interface ThriveListCompletionsParams extends ThriveBaseParams {
|
||||
contentId?: string
|
||||
isRPL?: boolean
|
||||
userId?: string
|
||||
completedDateRangeStart?: string
|
||||
completedDateRangeEnd?: string
|
||||
page?: number
|
||||
perPage?: number
|
||||
}
|
||||
|
||||
export interface ThriveGetCompletionParams extends ThriveBaseParams {
|
||||
id: string
|
||||
}
|
||||
|
||||
export interface ThriveCreateCompletionParams extends ThriveBaseParams {
|
||||
userId: string
|
||||
contentId: string
|
||||
completedAt: string
|
||||
}
|
||||
|
||||
export interface ThriveCompletionResponse extends ToolResponse {
|
||||
output: { completion: Record<string, any> }
|
||||
}
|
||||
|
||||
export interface ThriveListCompletionsResponse extends ToolResponse {
|
||||
output: { completions: Record<string, any>[] }
|
||||
}
|
||||
|
||||
export interface ThriveCreateCompletionResponse extends ToolResponse {
|
||||
output: { statementId: string | null }
|
||||
}
|
||||
|
||||
// ─── Content ───────────────────────────────────────────────────────────────
|
||||
|
||||
export interface ThriveGetContentParams extends ThriveBaseParams {
|
||||
id: string
|
||||
}
|
||||
|
||||
export interface ThriveQueryContentParams extends ThriveBaseParams {
|
||||
page?: number
|
||||
perPage?: number
|
||||
types?: string
|
||||
omitTypes?: string
|
||||
updatedSince?: string
|
||||
}
|
||||
|
||||
export interface ThriveContentResponse extends ToolResponse {
|
||||
output: { content: Record<string, any> }
|
||||
}
|
||||
|
||||
export interface ThriveQueryContentResponse extends ToolResponse {
|
||||
output: { results: Record<string, any>[]; pagination: ThrivePagination | null }
|
||||
}
|
||||
|
||||
// ─── Activities ────────────────────────────────────────────────────────────
|
||||
|
||||
export interface ThriveGetActivityParams extends ThriveBaseParams {
|
||||
id: string
|
||||
}
|
||||
|
||||
export interface ThriveQueryActivitiesParams extends ThriveBaseParams {
|
||||
page?: number
|
||||
perPage?: number
|
||||
actions?: string
|
||||
omitActions?: string
|
||||
contentIds?: string
|
||||
contentType?: string
|
||||
timestampFrom?: string
|
||||
timestampTo?: string
|
||||
}
|
||||
|
||||
export interface ThriveActivityResponse extends ToolResponse {
|
||||
output: { activity: Record<string, any> }
|
||||
}
|
||||
|
||||
export interface ThriveQueryActivitiesResponse extends ToolResponse {
|
||||
output: { results: Record<string, any>[]; pagination: ThrivePagination | null }
|
||||
}
|
||||
|
||||
// ─── CPD ───────────────────────────────────────────────────────────────────
|
||||
|
||||
export interface ThriveGetCpdCategoryParams extends ThriveBaseParams {
|
||||
categoryId: string
|
||||
}
|
||||
|
||||
export interface ThriveQueryCpdCategoriesParams extends ThriveBaseParams {
|
||||
page?: number
|
||||
perPage?: number
|
||||
updatedSince?: string
|
||||
}
|
||||
|
||||
export interface ThriveGetCpdEntryParams extends ThriveBaseParams {
|
||||
logEntryId: string
|
||||
}
|
||||
|
||||
export interface ThriveQueryCpdEntriesParams extends ThriveBaseParams {
|
||||
page?: number
|
||||
perPage?: number
|
||||
entryDateFrom?: string
|
||||
entryDateTo?: string
|
||||
}
|
||||
|
||||
export interface ThriveGetCpdRequirementParams extends ThriveBaseParams {
|
||||
audienceRequirementId: string
|
||||
}
|
||||
|
||||
export interface ThriveQueryCpdRequirementsParams extends ThriveBaseParams {
|
||||
page?: number
|
||||
perPage?: number
|
||||
updatedSince?: string
|
||||
}
|
||||
|
||||
export interface ThriveQueryCpdUserSummariesParams extends ThriveBaseParams {
|
||||
entryDateFrom: string
|
||||
entryDateTo: string
|
||||
userIds?: string
|
||||
page?: number
|
||||
perPage?: number
|
||||
}
|
||||
|
||||
export interface ThriveCpdCategoryResponse extends ToolResponse {
|
||||
output: { category: Record<string, any> }
|
||||
}
|
||||
|
||||
export interface ThriveCpdEntryResponse extends ToolResponse {
|
||||
output: { entry: Record<string, any> }
|
||||
}
|
||||
|
||||
export interface ThriveCpdRequirementResponse extends ToolResponse {
|
||||
output: { requirement: Record<string, any> }
|
||||
}
|
||||
|
||||
export interface ThriveCpdPaginatedResponse extends ToolResponse {
|
||||
output: { results: Record<string, any>[]; pagination: ThrivePagination | null }
|
||||
}
|
||||
|
||||
// ─── Tags & Skills ─────────────────────────────────────────────────────────
|
||||
|
||||
export interface ThriveListTagsParams extends ThriveBaseParams {
|
||||
page?: number
|
||||
perPage?: number
|
||||
updatedSince?: string
|
||||
}
|
||||
|
||||
export interface ThriveGetTagParams extends ThriveBaseParams {
|
||||
tagId: string
|
||||
}
|
||||
|
||||
export interface ThriveAddUserTagsParams extends ThriveBaseParams {
|
||||
userId: string
|
||||
tags: string
|
||||
}
|
||||
|
||||
export interface ThriveRemoveUserTagsParams extends ThriveBaseParams {
|
||||
userId: string
|
||||
tags: string
|
||||
}
|
||||
|
||||
export interface ThriveUpdateUserSkillsParams extends ThriveBaseParams {
|
||||
userId: string
|
||||
skills: string
|
||||
}
|
||||
|
||||
export interface ThriveGetSkillLevelsParams extends ThriveBaseParams {}
|
||||
|
||||
export interface ThriveTagResponse extends ToolResponse {
|
||||
output: { tag: Record<string, any> }
|
||||
}
|
||||
|
||||
export interface ThriveListTagsResponse extends ToolResponse {
|
||||
output: { results: Record<string, any>[]; pagination: ThrivePagination | null }
|
||||
}
|
||||
|
||||
export interface ThriveSkillLevelsResponse extends ToolResponse {
|
||||
output: { levels: Record<string, any>[] }
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
import type { ThriveAssignmentResponse, ThriveUpdateAssignmentParams } from '@/tools/thrive/types'
|
||||
import { THRIVE_ASSIGNMENT_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import {
|
||||
getThriveBaseUrl,
|
||||
getThriveHeaders,
|
||||
parseThriveArray,
|
||||
parseThriveResponse,
|
||||
} from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const updateAssignmentTool: ToolConfig<
|
||||
ThriveUpdateAssignmentParams,
|
||||
ThriveAssignmentResponse
|
||||
> = {
|
||||
id: 'thrive_update_assignment',
|
||||
name: 'Thrive Update Assignment',
|
||||
description: 'Update a compliance assignment in Thrive.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
assignmentId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The assignment ID',
|
||||
},
|
||||
audienceId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The audience ID',
|
||||
},
|
||||
contentId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The content ID for the primary content',
|
||||
},
|
||||
completionPeriod: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The number of days required to complete the assignment',
|
||||
},
|
||||
recurrence: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The number of days until the assignment will reoccur',
|
||||
},
|
||||
alternativeContentIds: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'JSON array of content IDs that can also complete the assignment',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/assignments/${encodeURIComponent(params.assignmentId)}`,
|
||||
method: 'PATCH',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
body: (params) => {
|
||||
const body: Record<string, any> = {
|
||||
audienceId: params.audienceId,
|
||||
}
|
||||
if (params.contentId) body.contentId = params.contentId
|
||||
if (params.completionPeriod !== undefined) body.completionPeriod = params.completionPeriod
|
||||
if (params.recurrence !== undefined) body.recurrence = params.recurrence
|
||||
if (params.alternativeContentIds) {
|
||||
body.alternativeContentIds = parseThriveArray<string>(
|
||||
params.alternativeContentIds,
|
||||
'alternativeContentIds'
|
||||
)
|
||||
}
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveAssignmentResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to update assignment')
|
||||
return { success: true, output: { assignment: data ?? null } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
assignment: {
|
||||
type: 'object',
|
||||
description: 'The updated assignment',
|
||||
properties: THRIVE_ASSIGNMENT_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
import type { ThriveAudienceResponse, ThriveUpdateAudienceParams } from '@/tools/thrive/types'
|
||||
import { THRIVE_AUDIENCE_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import { getThriveBaseUrl, getThriveHeaders, parseThriveResponse } from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const updateAudienceTool: ToolConfig<ThriveUpdateAudienceParams, ThriveAudienceResponse> = {
|
||||
id: 'thrive_update_audience',
|
||||
name: 'Thrive Update Audience',
|
||||
description: 'Update an audience in Thrive, optionally moving it to a new parent.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
audienceId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The audience id or audience reference',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The name of the audience (max 100 characters)',
|
||||
},
|
||||
reference: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The external reference for the audience (max 100 characters)',
|
||||
},
|
||||
parentId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The id of the parent audience/structure to move the audience to',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/audiences/${encodeURIComponent(params.audienceId)}`,
|
||||
method: 'PATCH',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
body: (params) => {
|
||||
const body: Record<string, any> = {}
|
||||
if (params.name) body.name = params.name
|
||||
if (params.reference) body.reference = params.reference
|
||||
if (params.parentId) body.parentId = params.parentId
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveAudienceResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to update audience')
|
||||
return { success: true, output: { audience: data ?? null } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
audience: {
|
||||
type: 'object',
|
||||
description: 'The updated audience',
|
||||
properties: THRIVE_AUDIENCE_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
import type { ThriveUpdateUserParams, ThriveUserResponse } from '@/tools/thrive/types'
|
||||
import { THRIVE_USER_LIFECYCLE_OUTPUT_PROPERTIES } from '@/tools/thrive/types'
|
||||
import {
|
||||
getThriveBaseUrl,
|
||||
getThriveHeaders,
|
||||
parseThriveJsonObject,
|
||||
parseThriveResponse,
|
||||
} from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const updateUserTool: ToolConfig<ThriveUpdateUserParams, ThriveUserResponse> = {
|
||||
id: 'thrive_update_user',
|
||||
name: 'Thrive Update User',
|
||||
description: 'Update an existing user in Thrive by ref. Only the fields provided are changed.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
ref: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The user ref to update',
|
||||
},
|
||||
firstName: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The given name of the individual',
|
||||
},
|
||||
lastName: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The family name of the individual',
|
||||
},
|
||||
email: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The email address for the user',
|
||||
},
|
||||
loginMethod: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: "How the user logs in: 'email' or 'ref'",
|
||||
},
|
||||
role: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: "Role assigned: 'administrator', 'learneradmin', or 'learner'",
|
||||
},
|
||||
jobTitle: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: "Name of this individual's role in your organisation",
|
||||
},
|
||||
managerRef: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: "Your organisation's unique identifier for this individual's line manager",
|
||||
},
|
||||
startDate: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Date this individual started with your organisation (ISO 8601)',
|
||||
},
|
||||
endDate: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Date this individual left your organisation (ISO 8601)',
|
||||
},
|
||||
timeZone: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: "The user's preferred timezone",
|
||||
},
|
||||
languageCode: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: "The user's preferred language (e.g. 'en-gb')",
|
||||
},
|
||||
sso: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Whether the account is managed by an authentication provider',
|
||||
},
|
||||
domain: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Domain this individual is associated with',
|
||||
},
|
||||
additionalFields: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'JSON object of custom field key-value pairs. Example: {"department":"Sales"}',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v2')}/users/ref/${encodeURIComponent(params.ref)}`,
|
||||
method: 'PATCH',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
body: (params) => {
|
||||
const body: Record<string, any> = {}
|
||||
if (params.firstName !== undefined) body.firstName = params.firstName
|
||||
if (params.lastName !== undefined) body.lastName = params.lastName
|
||||
if (params.email !== undefined) body.email = params.email
|
||||
if (params.loginMethod !== undefined) body.loginMethod = params.loginMethod
|
||||
if (params.role !== undefined) body.role = params.role
|
||||
if (params.jobTitle !== undefined) body.jobTitle = params.jobTitle
|
||||
if (params.managerRef !== undefined) body.managerRef = params.managerRef
|
||||
if (params.startDate !== undefined) body.startDate = params.startDate
|
||||
if (params.endDate !== undefined) body.endDate = params.endDate
|
||||
if (params.timeZone !== undefined) body.timeZone = params.timeZone
|
||||
if (params.languageCode !== undefined) body.languageCode = params.languageCode
|
||||
if (params.sso !== undefined) body.sso = params.sso
|
||||
if (params.domain !== undefined) body.domain = params.domain
|
||||
if (params.additionalFields) {
|
||||
body.additionalFields = parseThriveJsonObject(params.additionalFields, 'additionalFields')
|
||||
}
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveUserResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to update user')
|
||||
return { success: true, output: { user: data ?? null } }
|
||||
},
|
||||
|
||||
outputs: {
|
||||
user: {
|
||||
type: 'object',
|
||||
description: 'The updated user',
|
||||
properties: THRIVE_USER_LIFECYCLE_OUTPUT_PROPERTIES,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import type { ThriveMessageResponse, ThriveUpdateUserSkillsParams } from '@/tools/thrive/types'
|
||||
import {
|
||||
getThriveBaseUrl,
|
||||
getThriveHeaders,
|
||||
parseThriveArray,
|
||||
parseThriveResponse,
|
||||
} from '@/tools/thrive/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const updateUserSkillsTool: ToolConfig<ThriveUpdateUserSkillsParams, ThriveMessageResponse> =
|
||||
{
|
||||
id: 'thrive_update_user_skills',
|
||||
name: 'Thrive Update User Skills',
|
||||
description: 'Update skills and levels for a learner in Thrive.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
tenantId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive Tenant ID (used as the Basic auth username)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Thrive API key (used as the Basic auth password)',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Region-specific API host',
|
||||
},
|
||||
userId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The learner ID',
|
||||
},
|
||||
skills: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'JSON array of skill objects (1-100). Each: {"tagName":"leadership","level":1,"targetLevel":3}. level/targetLevel optional (min -1).',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) =>
|
||||
`${getThriveBaseUrl(params.host, 'v1')}/users/${encodeURIComponent(params.userId)}/skills`,
|
||||
method: 'PATCH',
|
||||
headers: (params) => getThriveHeaders(params.tenantId, params.apiKey),
|
||||
body: (params) => ({
|
||||
op: 'update',
|
||||
path: 'skills',
|
||||
value: parseThriveArray(params.skills, 'skills'),
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ThriveMessageResponse> => {
|
||||
const data = await parseThriveResponse(response, 'Failed to update skills for learner')
|
||||
return {
|
||||
success: true,
|
||||
output: { status: data?.status ?? null, message: data?.message ?? null },
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
status: { type: 'number', description: 'The HTTP status code of the operation' },
|
||||
message: { type: 'string', description: 'A human-readable result message' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* Default Thrive API host (Production, all regions except MEA).
|
||||
* The Thrive REST API is reached at `https://{host}/rest/{version}`.
|
||||
*/
|
||||
export const THRIVE_DEFAULT_HOST = 'public.api.learn.link'
|
||||
|
||||
/**
|
||||
* Builds the base REST URL for a Thrive API request.
|
||||
*
|
||||
* @param host - The region-specific API host (e.g. `public.api.learn.link`).
|
||||
* @param version - The API version: `v1` for most resources, `v2` for user lifecycle.
|
||||
*/
|
||||
export function getThriveBaseUrl(host: string | undefined, version: 'v1' | 'v2'): string {
|
||||
const resolvedHost = host?.trim() || THRIVE_DEFAULT_HOST
|
||||
return `https://${resolvedHost}/rest/${version}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the HTTP Basic authentication headers for a Thrive API request.
|
||||
* The Tenant ID is used as the username and the API key as the password.
|
||||
*/
|
||||
export function getThriveHeaders(tenantId: string, apiKey: string): Record<string, string> {
|
||||
return {
|
||||
Authorization: `Basic ${btoa(`${tenantId}:${apiKey}`)}`,
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a query parameter to a URL when the value is defined and non-empty.
|
||||
* Numbers are coerced to strings; empty strings and `undefined`/`null` are skipped.
|
||||
*/
|
||||
export function appendThriveQuery(
|
||||
url: URL,
|
||||
key: string,
|
||||
value: string | number | boolean | undefined | null
|
||||
): void {
|
||||
if (value === undefined || value === null) return
|
||||
const stringValue = typeof value === 'string' ? value.trim() : String(value)
|
||||
if (stringValue === '') return
|
||||
url.searchParams.set(key, stringValue)
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a value that may be a JSON array string (from LLM/user input) or an
|
||||
* already-parsed array into a typed array. An empty/whitespace string yields an
|
||||
* empty array; malformed JSON throws so the caller sees a clear error rather
|
||||
* than silently sending an empty collection.
|
||||
*/
|
||||
export function parseThriveArray<T = unknown>(value: unknown, fieldName = 'array'): T[] {
|
||||
if (Array.isArray(value)) return value as T[]
|
||||
if (typeof value === 'string') {
|
||||
const trimmed = value.trim()
|
||||
if (trimmed === '') return []
|
||||
let parsed: unknown
|
||||
try {
|
||||
parsed = JSON.parse(trimmed)
|
||||
} catch {
|
||||
throw new Error(`Invalid JSON provided for ${fieldName}: expected a JSON array`)
|
||||
}
|
||||
return Array.isArray(parsed) ? (parsed as T[]) : [parsed as T]
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a JSON object string (from LLM/user input), throwing a descriptive
|
||||
* error on malformed JSON so it is never silently dropped.
|
||||
*/
|
||||
export function parseThriveJsonObject(value: string, fieldName: string): Record<string, unknown> {
|
||||
try {
|
||||
return JSON.parse(value)
|
||||
} catch {
|
||||
throw new Error(`Invalid JSON provided for ${fieldName}: expected a JSON object`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a Thrive API response, throwing a descriptive error on non-2xx status.
|
||||
* Tolerates empty bodies (returned by some delete endpoints) and non-JSON bodies.
|
||||
*/
|
||||
export async function parseThriveResponse<T = any>(
|
||||
response: Response,
|
||||
fallbackError: string
|
||||
): Promise<T> {
|
||||
const text = await response.text()
|
||||
let data: any = {}
|
||||
if (text) {
|
||||
try {
|
||||
data = JSON.parse(text)
|
||||
} catch {
|
||||
data = { raw: text }
|
||||
}
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
const message =
|
||||
(data && typeof data.message === 'string' && data.message) ||
|
||||
(data && typeof data.error === 'string' && data.error) ||
|
||||
fallbackError
|
||||
throw new Error(message)
|
||||
}
|
||||
|
||||
return data as T
|
||||
}
|
||||
Reference in New Issue
Block a user