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

This commit is contained in:
wehub-resource-sync
2026-07-13 13:20:55 +08:00
commit d25d482dc2
13754 changed files with 4996608 additions and 0 deletions
@@ -0,0 +1,104 @@
import {
appendSportmonksQuery,
buildSportmonksHeaders,
handleSportmonksError,
SPORTMONKS_PAGINATION_OUTPUT,
type SportmonksBaseParams,
type SportmonksPagination,
type SportmonksPaginationParams,
} from '@/tools/sportmonks/types'
import {
SPORTMONKS_CITY_PROPERTIES,
SPORTMONKS_CORE_BASE_URL,
type SportmonksCity,
} from '@/tools/sportmonks_core/types'
import type { ToolConfig, ToolResponse } from '@/tools/types'
export interface SportmonksGetCitiesParams
extends SportmonksBaseParams,
SportmonksPaginationParams {}
export interface SportmonksGetCitiesResponse extends ToolResponse {
output: {
cities: SportmonksCity[]
pagination?: SportmonksPagination | null
}
}
export const sportmonksCoreGetCitiesTool: ToolConfig<
SportmonksGetCitiesParams,
SportmonksGetCitiesResponse
> = {
id: 'sportmonks_core_get_cities',
name: 'Get Cities',
description: 'Retrieve all cities from the Sportmonks Core API',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Sportmonks API token',
},
include: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Semicolon-separated relations to enrich the response (e.g. region)',
},
filters: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filters to apply',
},
per_page: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Number of results per page (max 50, default 25)',
},
page: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Page number to retrieve',
},
order: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Order direction (asc or desc)',
},
},
request: {
url: (params) => appendSportmonksQuery(`${SPORTMONKS_CORE_BASE_URL}/cities`, params),
method: 'GET',
headers: (params) => buildSportmonksHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
handleSportmonksError(data, response.status, 'get_cities')
}
return {
success: true,
output: {
cities: Array.isArray(data.data) ? data.data : [],
pagination: data.pagination ?? null,
},
}
},
outputs: {
cities: {
type: 'array',
description: 'Array of city objects',
items: { type: 'object', properties: SPORTMONKS_CITY_PROPERTIES },
},
pagination: SPORTMONKS_PAGINATION_OUTPUT,
},
}
@@ -0,0 +1,83 @@
import {
appendSportmonksQuery,
buildSportmonksHeaders,
handleSportmonksError,
type SportmonksBaseParams,
} from '@/tools/sportmonks/types'
import {
SPORTMONKS_CITY_PROPERTIES,
SPORTMONKS_CORE_BASE_URL,
type SportmonksCity,
} from '@/tools/sportmonks_core/types'
import type { ToolConfig, ToolResponse } from '@/tools/types'
export interface SportmonksGetCityParams extends SportmonksBaseParams {
cityId: string
}
export interface SportmonksGetCityResponse extends ToolResponse {
output: {
city: SportmonksCity | null
}
}
export const sportmonksCoreGetCityTool: ToolConfig<
SportmonksGetCityParams,
SportmonksGetCityResponse
> = {
id: 'sportmonks_core_get_city',
name: 'Get City by ID',
description: 'Retrieve a single city by its ID from the Sportmonks Core API',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Sportmonks API token',
},
cityId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The unique id of the city',
},
include: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Semicolon-separated relations to enrich the response (e.g. region)',
},
},
request: {
url: (params) => {
const url = `${SPORTMONKS_CORE_BASE_URL}/cities/${encodeURIComponent(params.cityId.trim())}`
return appendSportmonksQuery(url, params)
},
method: 'GET',
headers: (params) => buildSportmonksHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
handleSportmonksError(data, response.status, 'get_city')
}
return {
success: true,
output: {
city: data.data ?? null,
},
}
},
outputs: {
city: {
type: 'object',
description: 'The requested city object',
properties: SPORTMONKS_CITY_PROPERTIES,
},
},
}
@@ -0,0 +1,83 @@
import {
appendSportmonksQuery,
buildSportmonksHeaders,
handleSportmonksError,
type SportmonksBaseParams,
} from '@/tools/sportmonks/types'
import {
SPORTMONKS_CONTINENT_PROPERTIES,
SPORTMONKS_CORE_BASE_URL,
type SportmonksContinent,
} from '@/tools/sportmonks_core/types'
import type { ToolConfig, ToolResponse } from '@/tools/types'
export interface SportmonksGetContinentParams extends SportmonksBaseParams {
continentId: string
}
export interface SportmonksGetContinentResponse extends ToolResponse {
output: {
continent: SportmonksContinent | null
}
}
export const sportmonksCoreGetContinentTool: ToolConfig<
SportmonksGetContinentParams,
SportmonksGetContinentResponse
> = {
id: 'sportmonks_core_get_continent',
name: 'Get Continent by ID',
description: 'Retrieve a single continent by its ID from the Sportmonks Core API',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Sportmonks API token',
},
continentId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The unique id of the continent',
},
include: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Semicolon-separated relations to enrich the response (e.g. countries)',
},
},
request: {
url: (params) => {
const url = `${SPORTMONKS_CORE_BASE_URL}/continents/${encodeURIComponent(params.continentId.trim())}`
return appendSportmonksQuery(url, params)
},
method: 'GET',
headers: (params) => buildSportmonksHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
handleSportmonksError(data, response.status, 'get_continent')
}
return {
success: true,
output: {
continent: data.data ?? null,
},
}
},
outputs: {
continent: {
type: 'object',
description: 'The requested continent object',
properties: SPORTMONKS_CONTINENT_PROPERTIES,
},
},
}
@@ -0,0 +1,98 @@
import {
appendSportmonksQuery,
buildSportmonksHeaders,
handleSportmonksError,
SPORTMONKS_PAGINATION_OUTPUT,
type SportmonksBaseParams,
type SportmonksPagination,
type SportmonksPaginationParams,
} from '@/tools/sportmonks/types'
import {
SPORTMONKS_CONTINENT_PROPERTIES,
SPORTMONKS_CORE_BASE_URL,
type SportmonksContinent,
} from '@/tools/sportmonks_core/types'
import type { ToolConfig, ToolResponse } from '@/tools/types'
export interface SportmonksGetContinentsParams
extends SportmonksBaseParams,
SportmonksPaginationParams {}
export interface SportmonksGetContinentsResponse extends ToolResponse {
output: {
continents: SportmonksContinent[]
pagination?: SportmonksPagination | null
}
}
export const sportmonksCoreGetContinentsTool: ToolConfig<
SportmonksGetContinentsParams,
SportmonksGetContinentsResponse
> = {
id: 'sportmonks_core_get_continents',
name: 'Get Continents',
description: 'Retrieve all continents from the Sportmonks Core API',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Sportmonks API token',
},
include: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Semicolon-separated relations to enrich the response (e.g. countries)',
},
per_page: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Number of results per page (max 50, default 25)',
},
page: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Page number to retrieve',
},
order: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Order direction (asc or desc)',
},
},
request: {
url: (params) => appendSportmonksQuery(`${SPORTMONKS_CORE_BASE_URL}/continents`, params),
method: 'GET',
headers: (params) => buildSportmonksHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
handleSportmonksError(data, response.status, 'get_continents')
}
return {
success: true,
output: {
continents: Array.isArray(data.data) ? data.data : [],
pagination: data.pagination ?? null,
},
}
},
outputs: {
continents: {
type: 'array',
description: 'Array of continent objects',
items: { type: 'object', properties: SPORTMONKS_CONTINENT_PROPERTIES },
},
pagination: SPORTMONKS_PAGINATION_OUTPUT,
},
}
@@ -0,0 +1,104 @@
import {
appendSportmonksQuery,
buildSportmonksHeaders,
handleSportmonksError,
SPORTMONKS_PAGINATION_OUTPUT,
type SportmonksBaseParams,
type SportmonksPagination,
type SportmonksPaginationParams,
} from '@/tools/sportmonks/types'
import {
SPORTMONKS_CORE_BASE_URL,
SPORTMONKS_COUNTRY_PROPERTIES,
type SportmonksCountry,
} from '@/tools/sportmonks_core/types'
import type { ToolConfig, ToolResponse } from '@/tools/types'
export interface SportmonksGetCountriesParams
extends SportmonksBaseParams,
SportmonksPaginationParams {}
export interface SportmonksGetCountriesResponse extends ToolResponse {
output: {
countries: SportmonksCountry[]
pagination?: SportmonksPagination | null
}
}
export const sportmonksCoreGetCountriesTool: ToolConfig<
SportmonksGetCountriesParams,
SportmonksGetCountriesResponse
> = {
id: 'sportmonks_core_get_countries',
name: 'Get Countries',
description: 'Retrieve all countries from the Sportmonks Core API',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Sportmonks API token',
},
include: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Semicolon-separated relations to enrich the response (e.g. continent;regions)',
},
filters: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filters to apply',
},
per_page: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Number of results per page (max 50, default 25)',
},
page: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Page number to retrieve',
},
order: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Order direction (asc or desc)',
},
},
request: {
url: (params) => appendSportmonksQuery(`${SPORTMONKS_CORE_BASE_URL}/countries`, params),
method: 'GET',
headers: (params) => buildSportmonksHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
handleSportmonksError(data, response.status, 'get_countries')
}
return {
success: true,
output: {
countries: Array.isArray(data.data) ? data.data : [],
pagination: data.pagination ?? null,
},
}
},
outputs: {
countries: {
type: 'array',
description: 'Array of country objects',
items: { type: 'object', properties: SPORTMONKS_COUNTRY_PROPERTIES },
},
pagination: SPORTMONKS_PAGINATION_OUTPUT,
},
}
@@ -0,0 +1,83 @@
import {
appendSportmonksQuery,
buildSportmonksHeaders,
handleSportmonksError,
type SportmonksBaseParams,
} from '@/tools/sportmonks/types'
import {
SPORTMONKS_CORE_BASE_URL,
SPORTMONKS_COUNTRY_PROPERTIES,
type SportmonksCountry,
} from '@/tools/sportmonks_core/types'
import type { ToolConfig, ToolResponse } from '@/tools/types'
export interface SportmonksGetCountryParams extends SportmonksBaseParams {
countryId: string
}
export interface SportmonksGetCountryResponse extends ToolResponse {
output: {
country: SportmonksCountry | null
}
}
export const sportmonksCoreGetCountryTool: ToolConfig<
SportmonksGetCountryParams,
SportmonksGetCountryResponse
> = {
id: 'sportmonks_core_get_country',
name: 'Get Country by ID',
description: 'Retrieve a single country by its ID from the Sportmonks Core API',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Sportmonks API token',
},
countryId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The unique id of the country',
},
include: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Semicolon-separated relations to enrich the response (e.g. continent;regions)',
},
},
request: {
url: (params) => {
const url = `${SPORTMONKS_CORE_BASE_URL}/countries/${encodeURIComponent(params.countryId.trim())}`
return appendSportmonksQuery(url, params)
},
method: 'GET',
headers: (params) => buildSportmonksHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
handleSportmonksError(data, response.status, 'get_country')
}
return {
success: true,
output: {
country: data.data ?? null,
},
}
},
outputs: {
country: {
type: 'object',
description: 'The requested country object',
properties: SPORTMONKS_COUNTRY_PROPERTIES,
},
},
}
@@ -0,0 +1,61 @@
import {
buildSportmonksHeaders,
handleSportmonksError,
type SportmonksBaseParams,
} from '@/tools/sportmonks/types'
import { SPORTMONKS_MY_BASE_URL, type SportmonksEntityFilters } from '@/tools/sportmonks_core/types'
import type { ToolConfig, ToolResponse } from '@/tools/types'
export interface SportmonksGetEntityFiltersParams extends SportmonksBaseParams {}
export interface SportmonksGetEntityFiltersResponse extends ToolResponse {
output: {
entityFilters: SportmonksEntityFilters | null
}
}
export const sportmonksCoreGetEntityFiltersTool: ToolConfig<
SportmonksGetEntityFiltersParams,
SportmonksGetEntityFiltersResponse
> = {
id: 'sportmonks_core_get_entity_filters',
name: 'Get All Entity Filters',
description: 'Retrieve all available filters grouped per entity from the Sportmonks Core API',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Sportmonks API token',
},
},
request: {
url: () => `${SPORTMONKS_MY_BASE_URL}/filters/entity`,
method: 'GET',
headers: (params) => buildSportmonksHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
handleSportmonksError(data, response.status, 'get_entity_filters')
}
return {
success: true,
output: {
entityFilters: data.data ?? null,
},
}
},
outputs: {
entityFilters: {
type: 'json',
description:
'Map of entity name to its available filter names, e.g. {fixture: ["fixtureLeagues", "fixtureSeasons"], event: ["eventTypes"]}',
},
},
}
@@ -0,0 +1,92 @@
import {
appendSportmonksQuery,
buildSportmonksHeaders,
handleSportmonksError,
SPORTMONKS_PAGINATION_OUTPUT,
type SportmonksBaseParams,
type SportmonksPagination,
type SportmonksPaginationParams,
} from '@/tools/sportmonks/types'
import {
SPORTMONKS_MY_BASE_URL,
SPORTMONKS_USAGE_PROPERTIES,
type SportmonksUsage,
} from '@/tools/sportmonks_core/types'
import type { ToolConfig, ToolResponse } from '@/tools/types'
export interface SportmonksGetMyUsageParams
extends SportmonksBaseParams,
SportmonksPaginationParams {}
export interface SportmonksGetMyUsageResponse extends ToolResponse {
output: {
usage: SportmonksUsage[]
pagination?: SportmonksPagination | null
}
}
export const sportmonksCoreGetMyUsageTool: ToolConfig<
SportmonksGetMyUsageParams,
SportmonksGetMyUsageResponse
> = {
id: 'sportmonks_core_get_my_usage',
name: 'Get My Usage',
description: 'Retrieve your Sportmonks API usage aggregated per 5 minutes',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Sportmonks API token',
},
per_page: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Number of results per page (max 50, default 25)',
},
page: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Page number to retrieve',
},
order: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Order direction (asc or desc)',
},
},
request: {
url: (params) => appendSportmonksQuery(`${SPORTMONKS_MY_BASE_URL}/usage`, params),
method: 'GET',
headers: (params) => buildSportmonksHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
handleSportmonksError(data, response.status, 'get_my_usage')
}
return {
success: true,
output: {
usage: Array.isArray(data.data) ? data.data : [],
pagination: data.pagination ?? null,
},
}
},
outputs: {
usage: {
type: 'array',
description: 'Array of API usage records aggregated per 5-minute period',
items: { type: 'object', properties: SPORTMONKS_USAGE_PROPERTIES },
},
pagination: SPORTMONKS_PAGINATION_OUTPUT,
},
}
@@ -0,0 +1,83 @@
import {
appendSportmonksQuery,
buildSportmonksHeaders,
handleSportmonksError,
type SportmonksBaseParams,
} from '@/tools/sportmonks/types'
import {
SPORTMONKS_CORE_BASE_URL,
SPORTMONKS_REGION_PROPERTIES,
type SportmonksRegion,
} from '@/tools/sportmonks_core/types'
import type { ToolConfig, ToolResponse } from '@/tools/types'
export interface SportmonksGetRegionParams extends SportmonksBaseParams {
regionId: string
}
export interface SportmonksGetRegionResponse extends ToolResponse {
output: {
region: SportmonksRegion | null
}
}
export const sportmonksCoreGetRegionTool: ToolConfig<
SportmonksGetRegionParams,
SportmonksGetRegionResponse
> = {
id: 'sportmonks_core_get_region',
name: 'Get Region by ID',
description: 'Retrieve a single region by its ID from the Sportmonks Core API',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Sportmonks API token',
},
regionId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The unique id of the region',
},
include: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Semicolon-separated relations to enrich the response (e.g. country;cities)',
},
},
request: {
url: (params) => {
const url = `${SPORTMONKS_CORE_BASE_URL}/regions/${encodeURIComponent(params.regionId.trim())}`
return appendSportmonksQuery(url, params)
},
method: 'GET',
headers: (params) => buildSportmonksHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
handleSportmonksError(data, response.status, 'get_region')
}
return {
success: true,
output: {
region: data.data ?? null,
},
}
},
outputs: {
region: {
type: 'object',
description: 'The requested region object',
properties: SPORTMONKS_REGION_PROPERTIES,
},
},
}
@@ -0,0 +1,104 @@
import {
appendSportmonksQuery,
buildSportmonksHeaders,
handleSportmonksError,
SPORTMONKS_PAGINATION_OUTPUT,
type SportmonksBaseParams,
type SportmonksPagination,
type SportmonksPaginationParams,
} from '@/tools/sportmonks/types'
import {
SPORTMONKS_CORE_BASE_URL,
SPORTMONKS_REGION_PROPERTIES,
type SportmonksRegion,
} from '@/tools/sportmonks_core/types'
import type { ToolConfig, ToolResponse } from '@/tools/types'
export interface SportmonksGetRegionsParams
extends SportmonksBaseParams,
SportmonksPaginationParams {}
export interface SportmonksGetRegionsResponse extends ToolResponse {
output: {
regions: SportmonksRegion[]
pagination?: SportmonksPagination | null
}
}
export const sportmonksCoreGetRegionsTool: ToolConfig<
SportmonksGetRegionsParams,
SportmonksGetRegionsResponse
> = {
id: 'sportmonks_core_get_regions',
name: 'Get Regions',
description: 'Retrieve all regions from the Sportmonks Core API',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Sportmonks API token',
},
include: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Semicolon-separated relations to enrich the response (e.g. country;cities)',
},
filters: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filters to apply',
},
per_page: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Number of results per page (max 50, default 25)',
},
page: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Page number to retrieve',
},
order: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Order direction (asc or desc)',
},
},
request: {
url: (params) => appendSportmonksQuery(`${SPORTMONKS_CORE_BASE_URL}/regions`, params),
method: 'GET',
headers: (params) => buildSportmonksHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
handleSportmonksError(data, response.status, 'get_regions')
}
return {
success: true,
output: {
regions: Array.isArray(data.data) ? data.data : [],
pagination: data.pagination ?? null,
},
}
},
outputs: {
regions: {
type: 'array',
description: 'Array of region objects',
items: { type: 'object', properties: SPORTMONKS_REGION_PROPERTIES },
},
pagination: SPORTMONKS_PAGINATION_OUTPUT,
},
}
@@ -0,0 +1,61 @@
import {
buildSportmonksHeaders,
handleSportmonksError,
type SportmonksBaseParams,
} from '@/tools/sportmonks/types'
import { SPORTMONKS_CORE_BASE_URL } from '@/tools/sportmonks_core/types'
import type { ToolConfig, ToolResponse } from '@/tools/types'
export interface SportmonksGetTimezonesParams extends SportmonksBaseParams {}
export interface SportmonksGetTimezonesResponse extends ToolResponse {
output: {
timezones: string[]
}
}
export const sportmonksCoreGetTimezonesTool: ToolConfig<
SportmonksGetTimezonesParams,
SportmonksGetTimezonesResponse
> = {
id: 'sportmonks_core_get_timezones',
name: 'Get Timezones',
description: 'Retrieve all supported time zones (IANA names) from the Sportmonks Core API',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Sportmonks API token',
},
},
request: {
url: () => `${SPORTMONKS_CORE_BASE_URL}/timezones`,
method: 'GET',
headers: (params) => buildSportmonksHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
handleSportmonksError(data, response.status, 'get_timezones')
}
return {
success: true,
output: {
timezones: Array.isArray(data.data) ? data.data : [],
},
}
},
outputs: {
timezones: {
type: 'array',
description: 'Array of supported IANA time zone names (e.g. Europe/London)',
items: { type: 'string', description: 'IANA time zone name' },
},
},
}
@@ -0,0 +1,74 @@
import {
buildSportmonksHeaders,
handleSportmonksError,
type SportmonksBaseParams,
} from '@/tools/sportmonks/types'
import {
SPORTMONKS_CORE_BASE_URL,
SPORTMONKS_TYPE_PROPERTIES,
type SportmonksType,
} from '@/tools/sportmonks_core/types'
import type { ToolConfig, ToolResponse } from '@/tools/types'
export interface SportmonksGetTypeParams extends SportmonksBaseParams {
typeId: string
}
export interface SportmonksGetTypeResponse extends ToolResponse {
output: {
type: SportmonksType | null
}
}
export const sportmonksCoreGetTypeTool: ToolConfig<
SportmonksGetTypeParams,
SportmonksGetTypeResponse
> = {
id: 'sportmonks_core_get_type',
name: 'Get Type by ID',
description: 'Retrieve a single type by its ID from the Sportmonks Core API',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Sportmonks API token',
},
typeId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The unique id of the type',
},
},
request: {
url: (params) =>
`${SPORTMONKS_CORE_BASE_URL}/types/${encodeURIComponent(params.typeId.trim())}`,
method: 'GET',
headers: (params) => buildSportmonksHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
handleSportmonksError(data, response.status, 'get_type')
}
return {
success: true,
output: {
type: data.data ?? null,
},
}
},
outputs: {
type: {
type: 'object',
description: 'The requested type object',
properties: SPORTMONKS_TYPE_PROPERTIES,
},
},
}
@@ -0,0 +1,64 @@
import {
buildSportmonksHeaders,
handleSportmonksError,
type SportmonksBaseParams,
} from '@/tools/sportmonks/types'
import {
SPORTMONKS_CORE_BASE_URL,
type SportmonksTypesByEntity,
} from '@/tools/sportmonks_core/types'
import type { ToolConfig, ToolResponse } from '@/tools/types'
export interface SportmonksGetTypeByEntityParams extends SportmonksBaseParams {}
export interface SportmonksGetTypeByEntityResponse extends ToolResponse {
output: {
typesByEntity: SportmonksTypesByEntity | null
}
}
export const sportmonksCoreGetTypeByEntityTool: ToolConfig<
SportmonksGetTypeByEntityParams,
SportmonksGetTypeByEntityResponse
> = {
id: 'sportmonks_core_get_type_by_entity',
name: 'Get Type by Entity',
description: 'Retrieve the available types grouped per entity from the Sportmonks Core API',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Sportmonks API token',
},
},
request: {
url: () => `${SPORTMONKS_CORE_BASE_URL}/types/entities`,
method: 'GET',
headers: (params) => buildSportmonksHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
handleSportmonksError(data, response.status, 'get_type_by_entity')
}
return {
success: true,
output: {
typesByEntity: data.data ?? null,
},
}
},
outputs: {
typesByEntity: {
type: 'json',
description:
'Map of entity name to its available types, e.g. {CoachStatisticDetail: {updated_at, types: [{id, name, code, developer_name, model_type, stat_group}]}}',
},
},
}
@@ -0,0 +1,93 @@
import {
appendSportmonksQuery,
buildSportmonksHeaders,
handleSportmonksError,
SPORTMONKS_PAGINATION_OUTPUT,
type SportmonksBaseParams,
type SportmonksPagination,
type SportmonksPaginationParams,
} from '@/tools/sportmonks/types'
import {
SPORTMONKS_CORE_BASE_URL,
SPORTMONKS_TYPE_PROPERTIES,
type SportmonksType,
} from '@/tools/sportmonks_core/types'
import type { ToolConfig, ToolResponse } from '@/tools/types'
export interface SportmonksGetTypesParams
extends SportmonksBaseParams,
SportmonksPaginationParams {}
export interface SportmonksGetTypesResponse extends ToolResponse {
output: {
types: SportmonksType[]
pagination?: SportmonksPagination | null
}
}
export const sportmonksCoreGetTypesTool: ToolConfig<
SportmonksGetTypesParams,
SportmonksGetTypesResponse
> = {
id: 'sportmonks_core_get_types',
name: 'Get Types',
description:
'Retrieve all types (reference data describing events, statistics, positions, etc.) from the Sportmonks Core API',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Sportmonks API token',
},
per_page: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Number of results per page (max 50, default 25)',
},
page: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Page number to retrieve',
},
order: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Order direction (asc or desc)',
},
},
request: {
url: (params) => appendSportmonksQuery(`${SPORTMONKS_CORE_BASE_URL}/types`, params),
method: 'GET',
headers: (params) => buildSportmonksHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
handleSportmonksError(data, response.status, 'get_types')
}
return {
success: true,
output: {
types: Array.isArray(data.data) ? data.data : [],
pagination: data.pagination ?? null,
},
}
},
outputs: {
types: {
type: 'array',
description: 'Array of type objects',
items: { type: 'object', properties: SPORTMONKS_TYPE_PROPERTIES },
},
pagination: SPORTMONKS_PAGINATION_OUTPUT,
},
}
+17
View File
@@ -0,0 +1,17 @@
export { sportmonksCoreGetCitiesTool } from './get_cities'
export { sportmonksCoreGetCityTool } from './get_city'
export { sportmonksCoreGetContinentTool } from './get_continent'
export { sportmonksCoreGetContinentsTool } from './get_continents'
export { sportmonksCoreGetCountriesTool } from './get_countries'
export { sportmonksCoreGetCountryTool } from './get_country'
export { sportmonksCoreGetEntityFiltersTool } from './get_entity_filters'
export { sportmonksCoreGetMyUsageTool } from './get_my_usage'
export { sportmonksCoreGetRegionTool } from './get_region'
export { sportmonksCoreGetRegionsTool } from './get_regions'
export { sportmonksCoreGetTimezonesTool } from './get_timezones'
export { sportmonksCoreGetTypeTool } from './get_type'
export { sportmonksCoreGetTypeByEntityTool } from './get_type_by_entity'
export { sportmonksCoreGetTypesTool } from './get_types'
export { sportmonksCoreSearchCitiesTool } from './search_cities'
export { sportmonksCoreSearchCountriesTool } from './search_countries'
export { sportmonksCoreSearchRegionsTool } from './search_regions'
@@ -0,0 +1,115 @@
import {
appendSportmonksQuery,
buildSportmonksHeaders,
handleSportmonksError,
SPORTMONKS_PAGINATION_OUTPUT,
type SportmonksBaseParams,
type SportmonksPagination,
type SportmonksPaginationParams,
} from '@/tools/sportmonks/types'
import {
SPORTMONKS_CITY_PROPERTIES,
SPORTMONKS_CORE_BASE_URL,
type SportmonksCity,
} from '@/tools/sportmonks_core/types'
import type { ToolConfig, ToolResponse } from '@/tools/types'
export interface SportmonksSearchCitiesParams
extends SportmonksBaseParams,
SportmonksPaginationParams {
query: string
}
export interface SportmonksSearchCitiesResponse extends ToolResponse {
output: {
cities: SportmonksCity[]
pagination?: SportmonksPagination | null
}
}
export const sportmonksCoreSearchCitiesTool: ToolConfig<
SportmonksSearchCitiesParams,
SportmonksSearchCitiesResponse
> = {
id: 'sportmonks_core_search_cities',
name: 'Search Cities',
description: 'Search for cities by name from the Sportmonks Core API',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Sportmonks API token',
},
query: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The city name to search for (e.g. London)',
},
include: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Semicolon-separated relations to enrich the response (e.g. region)',
},
filters: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filters to apply',
},
per_page: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Number of results per page (max 50, default 25)',
},
page: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Page number to retrieve',
},
order: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Order direction (asc or desc)',
},
},
request: {
url: (params) => {
const url = `${SPORTMONKS_CORE_BASE_URL}/cities/search/${encodeURIComponent(params.query.trim())}`
return appendSportmonksQuery(url, params)
},
method: 'GET',
headers: (params) => buildSportmonksHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
handleSportmonksError(data, response.status, 'search_cities')
}
return {
success: true,
output: {
cities: Array.isArray(data.data) ? data.data : [],
pagination: data.pagination ?? null,
},
}
},
outputs: {
cities: {
type: 'array',
description: 'Array of city objects matching the search query',
items: { type: 'object', properties: SPORTMONKS_CITY_PROPERTIES },
},
pagination: SPORTMONKS_PAGINATION_OUTPUT,
},
}
@@ -0,0 +1,115 @@
import {
appendSportmonksQuery,
buildSportmonksHeaders,
handleSportmonksError,
SPORTMONKS_PAGINATION_OUTPUT,
type SportmonksBaseParams,
type SportmonksPagination,
type SportmonksPaginationParams,
} from '@/tools/sportmonks/types'
import {
SPORTMONKS_CORE_BASE_URL,
SPORTMONKS_COUNTRY_PROPERTIES,
type SportmonksCountry,
} from '@/tools/sportmonks_core/types'
import type { ToolConfig, ToolResponse } from '@/tools/types'
export interface SportmonksSearchCountriesParams
extends SportmonksBaseParams,
SportmonksPaginationParams {
query: string
}
export interface SportmonksSearchCountriesResponse extends ToolResponse {
output: {
countries: SportmonksCountry[]
pagination?: SportmonksPagination | null
}
}
export const sportmonksCoreSearchCountriesTool: ToolConfig<
SportmonksSearchCountriesParams,
SportmonksSearchCountriesResponse
> = {
id: 'sportmonks_core_search_countries',
name: 'Search Countries',
description: 'Search for countries by name from the Sportmonks Core API',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Sportmonks API token',
},
query: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The country name to search for (e.g. Brazil)',
},
include: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Semicolon-separated relations to enrich the response (e.g. continent;regions)',
},
filters: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filters to apply',
},
per_page: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Number of results per page (max 50, default 25)',
},
page: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Page number to retrieve',
},
order: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Order direction (asc or desc)',
},
},
request: {
url: (params) => {
const url = `${SPORTMONKS_CORE_BASE_URL}/countries/search/${encodeURIComponent(params.query.trim())}`
return appendSportmonksQuery(url, params)
},
method: 'GET',
headers: (params) => buildSportmonksHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
handleSportmonksError(data, response.status, 'search_countries')
}
return {
success: true,
output: {
countries: Array.isArray(data.data) ? data.data : [],
pagination: data.pagination ?? null,
},
}
},
outputs: {
countries: {
type: 'array',
description: 'Array of country objects matching the search query',
items: { type: 'object', properties: SPORTMONKS_COUNTRY_PROPERTIES },
},
pagination: SPORTMONKS_PAGINATION_OUTPUT,
},
}
@@ -0,0 +1,115 @@
import {
appendSportmonksQuery,
buildSportmonksHeaders,
handleSportmonksError,
SPORTMONKS_PAGINATION_OUTPUT,
type SportmonksBaseParams,
type SportmonksPagination,
type SportmonksPaginationParams,
} from '@/tools/sportmonks/types'
import {
SPORTMONKS_CORE_BASE_URL,
SPORTMONKS_REGION_PROPERTIES,
type SportmonksRegion,
} from '@/tools/sportmonks_core/types'
import type { ToolConfig, ToolResponse } from '@/tools/types'
export interface SportmonksSearchRegionsParams
extends SportmonksBaseParams,
SportmonksPaginationParams {
query: string
}
export interface SportmonksSearchRegionsResponse extends ToolResponse {
output: {
regions: SportmonksRegion[]
pagination?: SportmonksPagination | null
}
}
export const sportmonksCoreSearchRegionsTool: ToolConfig<
SportmonksSearchRegionsParams,
SportmonksSearchRegionsResponse
> = {
id: 'sportmonks_core_search_regions',
name: 'Search Regions',
description: 'Search for regions by name from the Sportmonks Core API',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Sportmonks API token',
},
query: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The region name to search for (e.g. Utrecht)',
},
include: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Semicolon-separated relations to enrich the response (e.g. country;cities)',
},
filters: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filters to apply',
},
per_page: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Number of results per page (max 50, default 25)',
},
page: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Page number to retrieve',
},
order: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Order direction (asc or desc)',
},
},
request: {
url: (params) => {
const url = `${SPORTMONKS_CORE_BASE_URL}/regions/search/${encodeURIComponent(params.query.trim())}`
return appendSportmonksQuery(url, params)
},
method: 'GET',
headers: (params) => buildSportmonksHeaders(params.apiKey),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
handleSportmonksError(data, response.status, 'search_regions')
}
return {
success: true,
output: {
regions: Array.isArray(data.data) ? data.data : [],
pagination: data.pagination ?? null,
},
}
},
outputs: {
regions: {
type: 'array',
description: 'Array of region objects matching the search query',
items: { type: 'object', properties: SPORTMONKS_REGION_PROPERTIES },
},
pagination: SPORTMONKS_PAGINATION_OUTPUT,
},
}
+246
View File
@@ -0,0 +1,246 @@
import type { OutputProperty } from '@/tools/types'
/**
* Base URL for the Sportmonks Core API v3 (shared reference data).
* @see https://docs.sportmonks.com/v3/core-api/core
*/
export const SPORTMONKS_CORE_BASE_URL = 'https://api.sportmonks.com/v3/core'
/**
* Base URL for the Sportmonks "My Sportmonks" endpoints (account/subscription
* scoped data such as entity filters and API usage). These live under `/v3/my`
* rather than `/v3/core` but are documented as part of the Core API.
* @see https://docs.sportmonks.com/v3/core-api/my-sportmonks/get-my-usage
*/
export const SPORTMONKS_MY_BASE_URL = 'https://api.sportmonks.com/v3/my'
/**
* Output property definitions for a Continent object.
* @see https://docs.sportmonks.com/v3/core-api/entities/core
*/
export const SPORTMONKS_CONTINENT_PROPERTIES = {
id: { type: 'number', description: 'Unique id of the continent' },
name: { type: 'string', description: 'Name of the continent' },
code: { type: 'string', description: 'Short code of the continent', optional: true },
} as const satisfies Record<string, OutputProperty>
/**
* Output property definitions for a Country object.
* @see https://docs.sportmonks.com/v3/core-api/entities/core
*/
export const SPORTMONKS_COUNTRY_PROPERTIES = {
id: { type: 'number', description: 'Unique id of the country' },
continent_id: { type: 'number', description: 'Continent of the country', nullable: true },
name: { type: 'string', description: 'Name of the country' },
official_name: { type: 'string', description: 'Official name of the country', optional: true },
fifa_name: {
type: 'string',
description: 'Official FIFA short code name',
nullable: true,
optional: true,
},
iso2: { type: 'string', description: 'Two letter country code', nullable: true, optional: true },
iso3: {
type: 'string',
description: 'Three letter country code',
nullable: true,
optional: true,
},
latitude: {
type: 'string',
description: 'Latitude position of the country',
nullable: true,
optional: true,
},
longitude: {
type: 'string',
description: 'Longitude position of the country',
nullable: true,
optional: true,
},
geonameid: { type: 'number', description: 'Official geonameid', nullable: true, optional: true },
borders: {
type: 'array',
description: 'Neighbouring countries (ISO3 codes)',
nullable: true,
optional: true,
items: { type: 'string', description: 'ISO3 country code' },
},
image_path: { type: 'string', description: 'Image path to the country flag', optional: true },
} as const satisfies Record<string, OutputProperty>
/**
* Output property definitions for a Region object.
* @see https://docs.sportmonks.com/v3/core-api/entities/core
*/
export const SPORTMONKS_REGION_PROPERTIES = {
id: { type: 'number', description: 'Unique id of the region' },
country_id: { type: 'number', description: 'Country of the region' },
name: { type: 'string', description: 'Name of the region' },
} as const satisfies Record<string, OutputProperty>
/**
* Output property definitions for a City object.
* @see https://docs.sportmonks.com/v3/core-api/entities/core
*/
export const SPORTMONKS_CITY_PROPERTIES = {
id: { type: 'number', description: 'Unique id of the city' },
country_id: { type: 'number', description: 'Country of the city' },
region_id: {
type: 'number',
description: 'Region id of the city',
nullable: true,
optional: true,
},
name: { type: 'string', description: 'Name of the city' },
latitude: { type: 'string', description: 'Latitude of the city', nullable: true, optional: true },
longitude: {
type: 'string',
description: 'Longitude of the city',
nullable: true,
optional: true,
},
geonameid: {
type: 'number',
description: 'Official geonameid of the city',
nullable: true,
optional: true,
},
} as const satisfies Record<string, OutputProperty>
/**
* Output property definitions for a Type object.
* @see https://docs.sportmonks.com/v3/core-api/entities/core
*/
export const SPORTMONKS_TYPE_PROPERTIES = {
id: { type: 'number', description: 'Unique id of the type' },
parent_id: { type: 'number', description: 'Parent type of the type', nullable: true },
name: { type: 'string', description: 'Name of the type' },
code: { type: 'string', description: 'Code of the type', nullable: true, optional: true },
developer_name: {
type: 'string',
description: 'Developer name of the type',
nullable: true,
optional: true,
},
group: {
type: 'string',
description: 'Group the type falls under',
nullable: true,
optional: true,
},
description: {
type: 'string',
description: 'Description of the type',
nullable: true,
optional: true,
},
} as const satisfies Record<string, OutputProperty>
/**
* Output property definitions for a My Sportmonks API usage record.
* @see https://docs.sportmonks.com/v3/core-api/my-sportmonks/get-my-usage
*/
export const SPORTMONKS_USAGE_PROPERTIES = {
id: { type: 'number', description: 'Identifier of the usage record' },
endpoint: { type: 'string', description: 'Identifier of the requested endpoint' },
count: { type: 'number', description: 'Total calls for the given timeframe' },
entity: { type: 'string', description: 'The entity the rate limit applies on' },
remaining_requests: {
type: 'number',
description: 'Amount of requests remaining for the entity in the hourly rate limit',
},
period_start: {
type: 'number',
description: 'Timestamp representing the aggregation start time',
},
period_end: {
type: 'number',
description: 'Timestamp representing the aggregation end time',
},
} as const satisfies Record<string, OutputProperty>
export interface SportmonksContinent {
id: number
name: string
code?: string
}
export interface SportmonksCountry {
id: number
continent_id: number | null
name: string
official_name?: string
fifa_name?: string | null
iso2?: string | null
iso3?: string | null
latitude?: string | null
longitude?: string | null
geonameid?: number | null
borders?: string[] | null
image_path?: string
}
export interface SportmonksRegion {
id: number
country_id: number
name: string
}
export interface SportmonksCity {
id: number
country_id: number
region_id?: number | null
name: string
latitude?: string | null
longitude?: string | null
geonameid?: number | null
}
export interface SportmonksType {
id: number
parent_id: number | null
name: string
code?: string | null
developer_name?: string | null
group?: string | null
description?: string | null
}
export interface SportmonksUsage {
id: number
endpoint: string
count: number
entity: string
remaining_requests: number
period_start: number
period_end: number
}
/** A single type entry as returned by the "Type by Entity" endpoint. */
export interface SportmonksTypeEntityEntry {
id: number
name: string
code?: string | null
developer_name?: string | null
model_type?: string | null
stat_group?: string | null
}
/** The per-entity grouping returned by the "Type by Entity" endpoint. */
export interface SportmonksTypeEntityGroup {
updated_at: string
types: SportmonksTypeEntityEntry[]
}
/**
* Response shape of the "Type by Entity" endpoint: a map keyed by entity name
* (e.g. CoachStatisticDetail) to its available types.
*/
export type SportmonksTypesByEntity = Record<string, SportmonksTypeEntityGroup>
/**
* Response shape of the "All Entity Filters" endpoint: a map keyed by entity
* name to the list of filter names available on that entity.
*/
export type SportmonksEntityFilters = Record<string, string[]>