diff --git a/packages/api/src/admin/skills.ts b/packages/api/src/admin/skills.ts index 3105f08b67..4588d0091e 100644 --- a/packages/api/src/admin/skills.ts +++ b/packages/api/src/admin/skills.ts @@ -18,7 +18,7 @@ import type { NextFunction, Request, RequestHandler, Response } from 'express'; import type { Types } from 'mongoose'; import type { GitHubSkillSyncRunner } from '~/skills/sync'; -type AdminSkillsRequest = Request & { +export type AdminSkillsRequest = Request & { user?: { _id?: Types.ObjectId; id?: string; @@ -67,6 +67,23 @@ export type AdminSkillSyncAccessDeps = { hasCapability: (user: SkillSyncCapabilityUser, capability: SystemCapability) => Promise; }; +type AdminSkillsSyncHandler = (req: AdminSkillsRequest, res: Response) => Promise; + +export type AdminSkillsSyncHandlers = { + getSyncStatus: AdminSkillsSyncHandler; + runSync: AdminSkillsSyncHandler; + setCredential: AdminSkillsSyncHandler; + deleteCredential: (req: Request, res: Response) => Promise; +}; + +export type AdminSkillsSyncAccess = { + attachBaseSkillSyncConfig: RequestHandler; + attachCredentialReadAccess: RequestHandler; + requireReadSkills: RequestHandler; + requirePlatformManageSkills: RequestHandler; + requireSyncRunCapability: RequestHandler; +}; + const CREDENTIAL_KEY_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$/; function toIso(date: Date | undefined): string | undefined { @@ -181,7 +198,7 @@ function sendInternalServerError(res: Response): void { res.status(500).json({ message: 'Internal Server Error' }); } -export function createAdminSkillsSyncAccess(deps: AdminSkillSyncAccessDeps) { +export function createAdminSkillsSyncAccess(deps: AdminSkillSyncAccessDeps): AdminSkillsSyncAccess { async function hasSkillCapability( req: AdminSkillSyncAccessRequest, capability: SystemCapability, @@ -299,7 +316,7 @@ export function createAdminSkillsSyncAccess(deps: AdminSkillSyncAccessDeps) { }; } -export function createAdminSkillsSyncHandlers(deps: AdminSkillSyncDeps) { +export function createAdminSkillsSyncHandlers(deps: AdminSkillSyncDeps): AdminSkillsSyncHandlers { function getRunner(req: Request): GitHubSkillSyncRunner { const runner = deps.getRunner?.(req) ?? deps.runner; if (!runner) { diff --git a/packages/api/src/skills/import.ts b/packages/api/src/skills/import.ts index 2718a7adba..c93b021593 100644 --- a/packages/api/src/skills/import.ts +++ b/packages/api/src/skills/import.ts @@ -1,7 +1,7 @@ import path from 'path'; import JSZip from 'jszip'; import crypto from 'crypto'; -import { logger, stripYamlTrailingComment } from '@librechat/data-schemas'; +import { logger } from '@librechat/data-schemas'; import { ResourceType, AccessRoleIds, PrincipalType } from 'librechat-data-provider'; import type { ISkill, diff --git a/packages/api/src/skills/sync/github.ts b/packages/api/src/skills/sync/github.ts index 75289563ed..5af41921f3 100644 --- a/packages/api/src/skills/sync/github.ts +++ b/packages/api/src/skills/sync/github.ts @@ -227,6 +227,20 @@ export type GitHubSkillSyncRunResult = { sources: Array; }; +export type GitHubSkillSyncStatus = { + enabled: boolean; + intervalMinutes: number; + runOnStartup: boolean; + sources: Array; + credentials: SkillSyncCredentialSummary[]; + fineGrainedTokenRecommendation: string; +}; + +export type GitHubSkillSyncRunner = { + getStatus: () => Promise; + runOnce: () => Promise; +}; + class SkillSyncError extends Error { code: string; @@ -1713,11 +1727,11 @@ function getGithubConfig(config: SkillSyncConfig | undefined): { }; } -export function createGitHubSkillSyncRunner(deps: GitHubSkillSyncDeps) { +export function createGitHubSkillSyncRunner(deps: GitHubSkillSyncDeps): GitHubSkillSyncRunner { const fetchFn = deps.fetchFn ?? fetch; const lockOwnerPrefix = deps.lockOwner ?? `${process.pid}`; - async function getStatus() { + async function getStatus(): Promise { const github = getGithubConfig(await deps.getConfig()); const allowServerCredentials = deps.allowServerCredentials !== false; const [storedStatuses, credentials] = await Promise.all([ @@ -1856,5 +1870,3 @@ export function createGitHubSkillSyncRunner(deps: GitHubSkillSyncDeps) { return { getStatus, runOnce }; } - -export type GitHubSkillSyncRunner = ReturnType; diff --git a/packages/api/src/skills/sync/orchestrator.ts b/packages/api/src/skills/sync/orchestrator.ts index 2783787ff7..05ecd64ded 100644 --- a/packages/api/src/skills/sync/orchestrator.ts +++ b/packages/api/src/skills/sync/orchestrator.ts @@ -7,18 +7,18 @@ const REQUEST_SYNC_STALE_RUNNING_MS = 35 * 60 * 1000; type MaybePromise = T | Promise; -type SkillSyncAppConfigLike = { +export type SkillSyncAppConfigLike = { skillSync?: unknown; config?: { skillSync?: unknown; }; }; -type SkillSyncRequestUser = { +export type SkillSyncRequestUser = { tenantId?: string | null; }; -type SkillSyncRequestLike = { +export type SkillSyncRequestLike = { config?: SkillSyncAppConfigLike; user?: SkillSyncRequestUser; skillSyncAllowServerCredentials?: boolean; @@ -51,6 +51,11 @@ export type SkillSyncTriggerOrchestratorDeps = { inFlight?: Set; }; +export type SkillSyncTriggerOrchestrator = { + getRunnerForAdminRequest: (request: SkillSyncRequestLike) => GitHubSkillSyncRunner; + maybeRunForRequest: (request: SkillSyncRequestLike) => Promise; +}; + function parseSkillSyncConfig( raw: unknown, logger: SkillSyncTriggerLogger, @@ -199,7 +204,9 @@ function getRequestSyncKey( return `${tenantId}:${sources}`; } -export function createSkillSyncTriggerOrchestrator(deps: SkillSyncTriggerOrchestratorDeps) { +export function createSkillSyncTriggerOrchestrator( + deps: SkillSyncTriggerOrchestratorDeps, +): SkillSyncTriggerOrchestrator { const inFlight = deps.inFlight ?? new Set(); const minIntervalMs = deps.minIntervalMs ?? REQUEST_SYNC_MIN_INTERVAL_MS; const staleRunningMs = deps.staleRunningMs ?? REQUEST_SYNC_STALE_RUNNING_MS; diff --git a/packages/api/src/skills/sync/scheduler.ts b/packages/api/src/skills/sync/scheduler.ts index ada7ebc7a0..7aad2d7bab 100644 --- a/packages/api/src/skills/sync/scheduler.ts +++ b/packages/api/src/skills/sync/scheduler.ts @@ -5,7 +5,7 @@ import { registerShutdownTask } from '~/app/shutdown'; const NODE_TIMER_MAX_MS = 2147483647; const SKILL_SYNC_MIN_INTERVAL_MINUTES = 5; -export const SKILL_SYNC_MAX_TIMER_INTERVAL_MINUTES = Math.floor(NODE_TIMER_MAX_MS / 60_000); +export const SKILL_SYNC_MAX_TIMER_INTERVAL_MINUTES: number = Math.floor(NODE_TIMER_MAX_MS / 60_000); type MaybePromise = T | Promise;