178 lines
6.7 KiB
TypeScript
178 lines
6.7 KiB
TypeScript
import * as plugins from './plugins.js';
|
|
import * as paths from './paths.js';
|
|
import { logger } from './logging.js';
|
|
|
|
import { TypeDoc } from './classes.typedoc.js';
|
|
import { AiDoc } from './classes.aidoc.js';
|
|
import * as context from './context/index.js';
|
|
|
|
export const run = async () => {
|
|
const tsdocCli = new plugins.smartcli.Smartcli();
|
|
|
|
tsdocCli.standardCommand().subscribe(async (argvArg) => {
|
|
logger.log('warn', `Auto detecting environment!`);
|
|
switch (true) {
|
|
case await TypeDoc.isTypeDocDir(paths.cwd):
|
|
logger.log('ok', `Detected TypeDoc compliant directory at ${paths.cwd}`);
|
|
tsdocCli.triggerCommand('typedoc', argvArg);
|
|
break;
|
|
default:
|
|
logger.log('error', `Cannot determine docs format at ${paths.cwd}`);
|
|
}
|
|
});
|
|
|
|
tsdocCli.addCommand('typedoc').subscribe(async (argvArg) => {
|
|
const typeDocInstance = new TypeDoc(paths.cwd);
|
|
await typeDocInstance.compile({
|
|
publicSubdir: argvArg.publicSubdir,
|
|
});
|
|
});
|
|
|
|
tsdocCli.addCommand('aidoc').subscribe(async (argvArg) => {
|
|
const aidocInstance = new AiDoc();
|
|
await aidocInstance.start();
|
|
|
|
// Get context token count if requested
|
|
if (argvArg.tokens || argvArg.showTokens) {
|
|
logger.log('info', `Calculating context token count...`);
|
|
const tokenCount = await aidocInstance.getProjectContextTokenCount(paths.cwd);
|
|
logger.log('ok', `Total context token count: ${tokenCount}`);
|
|
|
|
if (argvArg.tokensOnly) {
|
|
return; // Exit early if we only want token count
|
|
}
|
|
}
|
|
|
|
logger.log('info', `Generating new readme...`);
|
|
logger.log('info', `This may take some time...`);
|
|
await aidocInstance.buildReadme(paths.cwd);
|
|
logger.log('info', `Generating new keywords...`);
|
|
logger.log('info', `This may take some time...`);
|
|
await aidocInstance.buildDescription(paths.cwd);
|
|
});
|
|
|
|
tsdocCli.addCommand('tokens').subscribe(async (argvArg) => {
|
|
const aidocInstance = new AiDoc();
|
|
await aidocInstance.start();
|
|
|
|
logger.log('info', `Calculating context token count...`);
|
|
|
|
// Determine context mode based on args
|
|
let contextMode: context.ContextMode = 'full';
|
|
if (argvArg.trim || argvArg.trimmed) {
|
|
contextMode = 'trimmed';
|
|
} else if (argvArg.summarize || argvArg.summarized) {
|
|
contextMode = 'summarized';
|
|
}
|
|
|
|
// Get task type if specified
|
|
let taskType: context.TaskType | undefined = undefined;
|
|
if (argvArg.task) {
|
|
if (['readme', 'commit', 'description'].includes(argvArg.task)) {
|
|
taskType = argvArg.task as context.TaskType;
|
|
} else {
|
|
logger.log('warn', `Unknown task type: ${argvArg.task}. Using default context.`);
|
|
}
|
|
}
|
|
|
|
// Use enhanced context
|
|
const taskFactory = new context.TaskContextFactory(paths.cwd);
|
|
await taskFactory.initialize();
|
|
|
|
let contextResult: context.IContextResult;
|
|
|
|
if (argvArg.all) {
|
|
// Show stats for all task types
|
|
const stats = await taskFactory.getTokenStats();
|
|
|
|
logger.log('ok', 'Token statistics by task:');
|
|
for (const [task, data] of Object.entries(stats)) {
|
|
logger.log('info', `\n${task.toUpperCase()}:`);
|
|
logger.log('info', ` Tokens: ${data.tokenCount}`);
|
|
logger.log('info', ` Token savings: ${data.savings}`);
|
|
logger.log('info', ` Files: ${data.includedFiles} included, ${data.trimmedFiles} trimmed, ${data.excludedFiles} excluded`);
|
|
|
|
// Calculate percentage of model context
|
|
const o4MiniPercentage = (data.tokenCount / 200000 * 100).toFixed(2);
|
|
logger.log('info', ` Context usage: ${o4MiniPercentage}% of o4-mini (200K tokens)`);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (taskType) {
|
|
// Get context for specific task
|
|
contextResult = await taskFactory.createContextForTask(taskType);
|
|
} else {
|
|
// Get generic context with specified mode
|
|
const enhancedContext = new context.EnhancedContext(paths.cwd);
|
|
await enhancedContext.initialize();
|
|
enhancedContext.setContextMode(contextMode);
|
|
|
|
if (argvArg.maxTokens) {
|
|
enhancedContext.setTokenBudget(parseInt(argvArg.maxTokens, 10));
|
|
}
|
|
|
|
contextResult = await enhancedContext.buildContext();
|
|
}
|
|
|
|
// Display results
|
|
logger.log('ok', `Total context token count: ${contextResult.tokenCount}`);
|
|
logger.log('info', `Files included: ${contextResult.includedFiles.length}`);
|
|
logger.log('info', `Files trimmed: ${contextResult.trimmedFiles.length}`);
|
|
logger.log('info', `Files excluded: ${contextResult.excludedFiles.length}`);
|
|
logger.log('info', `Token savings: ${contextResult.tokenSavings}`);
|
|
|
|
if (argvArg.detailed) {
|
|
// Show more detailed info about the context and token usage
|
|
const o4MiniPercentage = (contextResult.tokenCount / 200000 * 100).toFixed(2);
|
|
logger.log('info', `Token usage: ${o4MiniPercentage}% of o4-mini 200K token context window`);
|
|
|
|
if (argvArg.model) {
|
|
// Show percentages for different models
|
|
if (argvArg.model === 'gpt4') {
|
|
const gpt4Percentage = (contextResult.tokenCount / 8192 * 100).toFixed(2);
|
|
logger.log('info', `Token usage (GPT-4): ${gpt4Percentage}% of 8192 token context window`);
|
|
} else if (argvArg.model === 'gpt35') {
|
|
const gpt35Percentage = (contextResult.tokenCount / 4096 * 100).toFixed(2);
|
|
logger.log('info', `Token usage (GPT-3.5): ${gpt35Percentage}% of 4096 token context window`);
|
|
}
|
|
}
|
|
|
|
// Estimate cost (approximate values)
|
|
const o4MiniInputCost = 0.00005; // per 1K tokens for o4-mini
|
|
const estimatedCost = (contextResult.tokenCount / 1000 * o4MiniInputCost).toFixed(6);
|
|
logger.log('info', `Estimated input cost: $${estimatedCost} (o4-mini)`);
|
|
|
|
if (argvArg.listFiles) {
|
|
// List files included in context
|
|
logger.log('info', '\nIncluded files:');
|
|
contextResult.includedFiles.forEach(file => {
|
|
logger.log('info', ` ${file.relativePath} (${file.tokenCount} tokens)`);
|
|
});
|
|
|
|
logger.log('info', '\nTrimmed files:');
|
|
contextResult.trimmedFiles.forEach(file => {
|
|
logger.log('info', ` ${file.relativePath} (${file.tokenCount} tokens)`);
|
|
});
|
|
|
|
if (contextResult.excludedFiles.length > 0) {
|
|
logger.log('info', '\nExcluded files:');
|
|
contextResult.excludedFiles.forEach(file => {
|
|
logger.log('info', ` ${file.relativePath} (${file.tokenCount} tokens)`);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
tsdocCli.addCommand('test').subscribe((argvArg) => {
|
|
tsdocCli.triggerCommand('typedoc', argvArg);
|
|
process.on('exit', async () => {
|
|
await plugins.smartfile.fs.remove(paths.publicDir);
|
|
});
|
|
});
|
|
|
|
tsdocCli.startParse();
|
|
};
|