UNPKG

@git.zone/tsdoc

Version:

A comprehensive TypeScript documentation tool that leverages AI to generate and enhance project documentation, including dynamic README creation, API docs via TypeDoc, and smart commit message generation.

166 lines (144 loc) 6.02 kB
import * as plugins from './plugins.js'; import * as aiDocsClasses from './aidocs_classes/index.js'; export class AiDoc { private openaiToken: string; public npmextraKV: plugins.npmextra.KeyValueStore; public qenvInstance: plugins.qenv.Qenv; public aidocInteract: plugins.smartinteract.SmartInteract; public smartAiInstance: plugins.smartai.SmartAi; argvArg: any; constructor(argvArg?: any) { this.argvArg = argvArg; } private printSanitizedToken() { // Check if the token length is greater than the sum of startLength and endLength let printToken: string; if (this.openaiToken.length > 6) { // Extract the beginning and end parts of the token const start = this.openaiToken.substring(0, 3); const end = this.openaiToken.substring(this.openaiToken.length - 3); printToken = `${start}...${end}`; } else { // If the token is not long enough, return it as is printToken = this.openaiToken; } console.log(`OpenAI Token on record: ${printToken}`); } public async start() { // lets care about prerequisites this.aidocInteract = new plugins.smartinteract.SmartInteract(); this.qenvInstance = new plugins.qenv.Qenv(); if (!(await this.qenvInstance.getEnvVarOnDemand('OPENAI_TOKEN'))) { // Migrate old KV store path to new path if needed const homeDir = plugins.smartpath.get.home(); const oldKvPath = plugins.path.join(homeDir, '.npmextra/kv/tsdoc.json'); const newKvDir = plugins.path.join(homeDir, '.npmextra/kv/@git.zone'); const newKvPath = plugins.path.join(newKvDir, 'tsdoc.json'); if ( await plugins.fsInstance.file(oldKvPath).exists() && !(await plugins.fsInstance.file(newKvPath).exists()) ) { console.log('Migrating tsdoc KeyValueStore to @git.zone/tsdoc...'); await plugins.fsInstance.directory(newKvDir).recursive().create(); await plugins.fsInstance.file(oldKvPath).copy(newKvPath); await plugins.fsInstance.file(oldKvPath).delete(); console.log('Migration complete: tsdoc.json -> @git.zone/tsdoc.json'); } this.npmextraKV = new plugins.npmextra.KeyValueStore({ typeArg: 'userHomeDir', identityArg: '@git.zone/tsdoc', mandatoryKeys: ['OPENAI_TOKEN'], }); const missingKeys = await this.npmextraKV.getMissingMandatoryKeys(); if (missingKeys.length > 0) { // lets try argv if (this.argvArg?.OPENAI_TOKEN) { this.openaiToken = this.argvArg.OPENAI_TOKEN; } else { // lets try smartinteract // wait for a second until OpenAI fixes punycode problem... await plugins.smartdelay.delayFor(1000); const answerObject = await this.aidocInteract.askQuestion({ type: 'input', message: `Please provide your OpenAI token. This will be persisted in your home directory.`, name: 'OPENAI_TOKEN', default: '', }); this.openaiToken = answerObject.value; } this.printSanitizedToken(); await this.npmextraKV.writeKey('OPENAI_TOKEN', this.openaiToken); } } if (!this.openaiToken && this.npmextraKV) { this.openaiToken = await this.npmextraKV.readKey('OPENAI_TOKEN'); } // lets assume we have an OPENAI_Token now this.smartAiInstance = new plugins.smartai.SmartAi({ openaiToken: this.openaiToken, }); await this.smartAiInstance.start(); } public async stop() { if (this.smartAiInstance) { await this.smartAiInstance.stop(); } // No explicit cleanup needed for npmextraKV or aidocInteract // They don't keep event loop alive } /** * Get the OpenAI provider for direct chat calls * This is a convenience getter to access the provider from SmartAi */ public get openaiProvider(): plugins.smartai.OpenAiProvider { return this.smartAiInstance.openaiProvider; } public getOpenaiToken(): string { return this.openaiToken; } public async buildReadme(projectDirArg: string) { const readmeInstance = new aiDocsClasses.Readme(this, projectDirArg); return await readmeInstance.build(); } public async buildDescription(projectDirArg: string) { const descriptionInstance = new aiDocsClasses.Description(this, projectDirArg); return await descriptionInstance.build(); } public async buildNextCommitObject(projectDirArg: string) { const commitInstance = new aiDocsClasses.Commit(this, projectDirArg); return await commitInstance.buildNextCommitObject(); } public async getProjectContext(projectDirArg: string) { const projectContextInstance = new aiDocsClasses.ProjectContext(projectDirArg); return await projectContextInstance.gatherFiles(); } /** * Get the context with token count information * @param projectDirArg The path to the project directory * @returns An object containing the context string and its token count */ public async getProjectContextWithTokenCount(projectDirArg: string) { const projectContextInstance = new aiDocsClasses.ProjectContext(projectDirArg); await projectContextInstance.update(); return projectContextInstance.getContextWithTokenCount(); } /** * Get just the token count for a project's context * @param projectDirArg The path to the project directory * @returns The number of tokens in the project context */ public async getProjectContextTokenCount(projectDirArg: string) { const projectContextInstance = new aiDocsClasses.ProjectContext(projectDirArg); await projectContextInstance.update(); return projectContextInstance.getTokenCount(); } /** * Estimate token count in a text string * @param text The text to estimate tokens for * @returns Estimated number of tokens */ public countTokens(text: string): number { const projectContextInstance = new aiDocsClasses.ProjectContext(''); return projectContextInstance.countTokens(text); } }