feat: Migrate documentation to Mintlify and implement Helper Agent with search functionality (#15443)

This commit is contained in:
Abdul Rahman
2025-10-31 14:47:54 +05:30
committed by GitHub
parent 5211d6ac7e
commit 2c39fc04c2
307 changed files with 14107 additions and 74 deletions
@@ -11,8 +11,11 @@ import { ToolAdapterService } from 'src/engine/core-modules/ai/services/tool-ada
import { ToolService } from 'src/engine/core-modules/ai/services/tool.service';
import { TokenModule } from 'src/engine/core-modules/auth/token/token.module';
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
import { FileEntity } from 'src/engine/core-modules/file/entities/file.entity';
import { FileModule } from 'src/engine/core-modules/file/file.module';
import { RecordCrudModule } from 'src/engine/core-modules/record-crud/record-crud.module';
import { ToolRegistryService } from 'src/engine/core-modules/tool/services/tool-registry.service';
import { SearchArticlesTool } from 'src/engine/core-modules/tool/tools/search-articles-tool/search-articles-tool';
import { SendEmailTool } from 'src/engine/core-modules/tool/tools/send-email-tool/send-email-tool';
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
@@ -22,8 +25,6 @@ import { WorkspacePermissionsCacheModule } from 'src/engine/metadata-modules/wor
import { TwentyORMModule } from 'src/engine/twenty-orm/twenty-orm.module';
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
import { MessagingModule } from 'src/modules/messaging/messaging.module';
import { FileEntity } from 'src/engine/core-modules/file/entities/file.entity';
import { FileModule } from 'src/engine/core-modules/file/file.module';
@Global()
@Module({
@@ -51,6 +52,7 @@ import { FileModule } from 'src/engine/core-modules/file/file.module';
AIBillingService,
McpService,
SendEmailTool,
SearchArticlesTool,
],
exports: [
AiService,
@@ -61,6 +63,7 @@ import { FileModule } from 'src/engine/core-modules/file/file.module';
ToolRegistryService,
McpService,
SendEmailTool,
SearchArticlesTool,
],
})
export class AiModule {}
@@ -0,0 +1,18 @@
import { z } from 'zod';
export const SearchArticlesInputZodSchema = z.object({
query: z
.string()
.describe('The search query to find relevant help articles about Twenty'),
});
export const SearchArticlesToolParametersZodSchema = z.object({
loadingMessage: z
.string()
.describe(
'A clear, human-readable status message describing the search being performed. This will be shown to the user while the tool is being called, so phrase it as a present-tense status update (e.g., "Searching help articles for..."). Explain what you are searching for in natural language.',
),
input: SearchArticlesInputZodSchema,
});
export type SearchArticlesInput = z.infer<typeof SearchArticlesInputZodSchema>;
@@ -0,0 +1,73 @@
import { Injectable } from '@nestjs/common';
import axios from 'axios';
import { SearchArticlesToolParametersZodSchema } from 'src/engine/core-modules/tool/tools/search-articles-tool/search-articles-tool.schema';
import { type ToolInput } from 'src/engine/core-modules/tool/types/tool-input.type';
import { type ToolOutput } from 'src/engine/core-modules/tool/types/tool-output.type';
import { type Tool } from 'src/engine/core-modules/tool/types/tool.type';
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
@Injectable()
export class SearchArticlesTool implements Tool {
description =
'Search Twenty documentation and help articles to find information about features, setup, usage, and troubleshooting.';
inputSchema = SearchArticlesToolParametersZodSchema;
constructor(private readonly twentyConfigService: TwentyConfigService) {}
async execute(parameters: ToolInput): Promise<ToolOutput> {
const { query } = parameters;
try {
const MINTLIFY_API_KEY = this.twentyConfigService.get('MINTLIFY_API_KEY');
const MINTLIFY_SUBDOMAIN =
this.twentyConfigService.get('MINTLIFY_SUBDOMAIN');
const useDirectApi = MINTLIFY_API_KEY && MINTLIFY_SUBDOMAIN;
const endpoint = useDirectApi
? `https://api-dsc.mintlify.com/v1/search/${MINTLIFY_SUBDOMAIN}`
: 'https://twenty-help-search.com/search/twenty';
const headers = {
'Content-Type': 'application/json',
...(useDirectApi && { Authorization: `Bearer ${MINTLIFY_API_KEY}` }),
};
const response = await axios.post(
endpoint,
{ query, pageSize: 10 },
{ headers },
);
const results = response.data;
if (results.length === 0) {
return {
success: true,
message: `No help articles found for "${query}"`,
result: [],
};
}
return {
success: true,
message: `Found ${results.length} relevant help article${results.length === 1 ? '' : 's'} for "${query}"`,
result: results,
};
} catch (error) {
const errorDetail = axios.isAxiosError(error)
? error.response?.data?.message || error.message
: error instanceof Error
? error.message
: 'Documentation search failed';
return {
success: false,
message: `Failed to search help articles for "${query}"`,
error: errorDetail,
};
}
}
}
@@ -1262,6 +1262,26 @@ export class ConfigVariables {
@ValidateIf((env) => env.IS_MAPS_AND_ADDRESS_AUTOCOMPLETE_ENABLED)
GOOGLE_MAP_API_KEY: string;
@ConfigVariablesMetadata({
group: ConfigVariablesGroup.OTHER,
isSensitive: true,
description: 'Mintlify API key for documentation search',
isEnvOnly: true,
type: ConfigVariableType.STRING,
})
@IsOptional()
MINTLIFY_API_KEY: string;
@ConfigVariablesMetadata({
group: ConfigVariablesGroup.OTHER,
isSensitive: true,
description: 'Mintlify subdomain for documentation search',
isEnvOnly: true,
type: ConfigVariableType.STRING,
})
@IsOptional()
MINTLIFY_SUBDOMAIN: string;
@ConfigVariablesMetadata({
group: ConfigVariablesGroup.AWS_SES_SETTINGS,
description: 'AWS region',