diff --git a/README.md b/README.md index 6a236f47ef..f444da7a29 100644 --- a/README.md +++ b/README.md @@ -145,6 +145,7 @@ gitnexus clean --all --force # Delete all indexes gitnexus wiki [path] # Generate repository wiki from knowledge graph gitnexus wiki --model # Wiki with custom LLM model (default: gpt-4o-mini) gitnexus wiki --base-url # Wiki with custom LLM API base URL +gitnexus wiki --language zh-CN # Wiki in Chinese (or ja, ko, etc.) ``` ### What Your AI Agent Gets @@ -447,6 +448,10 @@ gitnexus wiki --base-url https://api.anthropic.com/v1 # Force full regeneration gitnexus wiki --force + +# Generate wiki in a specific language +gitnexus wiki --language zh-CN +gitnexus wiki --language ja ``` The wiki generator reads the indexed graph structure, groups files into modules via LLM, generates per-module documentation pages, and creates an overview page — all with cross-references to the knowledge graph. diff --git a/gitnexus/src/cli/index.ts b/gitnexus/src/cli/index.ts index 10268db837..ad88b578cd 100644 --- a/gitnexus/src/cli/index.ts +++ b/gitnexus/src/cli/index.ts @@ -74,6 +74,7 @@ program .option('--base-url ', 'LLM API base URL (default: OpenAI)') .option('--api-key ', 'LLM API key (saved to ~/.gitnexus/config.json)') .option('--concurrency ', 'Parallel LLM calls (default: 3)', '3') + .option('--language ', 'Output language for wiki (e.g. zh-CN, ja, ko)') .option('--gist', 'Publish wiki as a public GitHub Gist after generation') .action(wikiCommand); diff --git a/gitnexus/src/cli/wiki.ts b/gitnexus/src/cli/wiki.ts index 70ab00785b..b8f28f4e67 100644 --- a/gitnexus/src/cli/wiki.ts +++ b/gitnexus/src/cli/wiki.ts @@ -20,6 +20,7 @@ export interface WikiCommandOptions { baseUrl?: string; apiKey?: string; concurrency?: string; + language?: string; gist?: boolean; } @@ -242,6 +243,7 @@ export const wikiCommand = async ( model: options?.model, baseUrl: options?.baseUrl, concurrency: options?.concurrency ? parseInt(options.concurrency, 10) : undefined, + language: options?.language, }; const generator = new WikiGenerator( diff --git a/gitnexus/src/core/wiki/generator.ts b/gitnexus/src/core/wiki/generator.ts index 666dc6e463..4cb328ca5a 100644 --- a/gitnexus/src/core/wiki/generator.ts +++ b/gitnexus/src/core/wiki/generator.ts @@ -63,6 +63,7 @@ export interface WikiOptions { apiKey?: string; maxTokensPerModule?: number; concurrency?: number; + language?: string; } export interface WikiMeta { @@ -97,6 +98,7 @@ export class WikiGenerator { private llmConfig: LLMConfig; private maxTokensPerModule: number; private concurrency: number; + private language?: string; private options: WikiOptions; private onProgress: ProgressCallback; private failedModules: string[] = []; @@ -116,6 +118,7 @@ export class WikiGenerator { this.options = options; this.llmConfig = llmConfig; this.maxTokensPerModule = options.maxTokensPerModule ?? DEFAULT_MAX_TOKENS_PER_MODULE; + this.language = options.language; this.concurrency = options.concurrency ?? 3; const progressFn = onProgress || (() => {}); this.onProgress = (phase, percent, detail) => { @@ -488,7 +491,7 @@ export class WikiGenerator { }); const response = await callLLM( - prompt, this.llmConfig, MODULE_SYSTEM_PROMPT, + prompt, this.llmConfig, this.withLanguage(MODULE_SYSTEM_PROMPT), this.streamOpts(node.name), ); @@ -531,7 +534,7 @@ export class WikiGenerator { }); const response = await callLLM( - prompt, this.llmConfig, PARENT_SYSTEM_PROMPT, + prompt, this.llmConfig, this.withLanguage(PARENT_SYSTEM_PROMPT), this.streamOpts(node.name), ); @@ -578,7 +581,7 @@ export class WikiGenerator { }); const response = await callLLM( - prompt, this.llmConfig, OVERVIEW_SYSTEM_PROMPT, + prompt, this.llmConfig, this.withLanguage(OVERVIEW_SYSTEM_PROMPT), this.streamOpts('Generating overview', 88), ); @@ -909,6 +912,14 @@ export class WikiGenerator { return null; } + /** + * Append a language instruction to the system prompt when --language is set. + */ + private withLanguage(systemPrompt: string): string { + if (!this.language) return systemPrompt; + return `${systemPrompt}\n\nIMPORTANT: Write ALL documentation output in ${this.language}. Use ${this.language} for headings, descriptions, and explanations. Keep code identifiers, file paths, and Mermaid node labels in their original form.`; + } + private slugify(name: string): string { return name .toLowerCase()