ctxman 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.ctxman/custom-profiles.example.json +20 -0
- package/.ctxman/llm-profiles.json +131 -0
- package/.ctxman/logs/ctxman-2026-07-02.log +156 -0
- package/.ctxman/self-knowledge/documents.lance/_transactions/0-b3dd1558-f95b-44b9-a154-18e8c330ae7a.txn +0 -0
- package/.ctxman/self-knowledge/documents.lance/_transactions/1-44bff6d4-e552-4010-a769-e09ad822698d.txn +0 -0
- package/.ctxman/self-knowledge/documents.lance/_transactions/10-37260794-5947-4ecb-b4c8-d732f58f40f1.txn +0 -0
- package/.ctxman/self-knowledge/documents.lance/_transactions/11-0d52a883-5518-463c-9b6d-986c3af89dfd.txn +0 -0
- package/.ctxman/self-knowledge/documents.lance/_transactions/12-ae354646-52f2-49c9-90fb-2e6ed8932663.txn +0 -0
- package/.ctxman/self-knowledge/documents.lance/_transactions/13-5d7d5e57-27da-498b-b734-091b9d38da13.txn +0 -0
- package/.ctxman/self-knowledge/documents.lance/_transactions/14-558ce928-810b-4252-a364-fdd1ee6f8a25.txn +0 -0
- package/.ctxman/self-knowledge/documents.lance/_transactions/15-27e3a58f-8b64-43b8-a9f4-e3369446968b.txn +0 -0
- package/.ctxman/self-knowledge/documents.lance/_transactions/16-a110c390-e5c8-4464-b976-bc7f5195fa15.txn +0 -0
- package/.ctxman/self-knowledge/documents.lance/_transactions/17-97513225-53de-4216-b61a-6337bd0cc4ad.txn +0 -0
- package/.ctxman/self-knowledge/documents.lance/_transactions/18-5ba450f0-c527-459c-bf4f-6d79b5e4285f.txn +0 -0
- package/.ctxman/self-knowledge/documents.lance/_transactions/19-600d3a63-5225-49e9-b8b7-30e037b564ab.txn +0 -0
- package/.ctxman/self-knowledge/documents.lance/_transactions/2-48a61b4e-92cf-4342-8376-914c1b99a9f9.txn +0 -0
- package/.ctxman/self-knowledge/documents.lance/_transactions/20-121dd912-5410-410e-84ff-82c7a23604a0.txn +0 -0
- package/.ctxman/self-knowledge/documents.lance/_transactions/3-bc6844ab-7ea3-4bb3-9ee1-538ce5664a9c.txn +0 -0
- package/.ctxman/self-knowledge/documents.lance/_transactions/4-d5e1754f-dbb5-454e-a9be-2a7da8d7bcf9.txn +0 -0
- package/.ctxman/self-knowledge/documents.lance/_transactions/5-4fae93df-0568-4b6f-8acf-8bef4bba6047.txn +0 -0
- package/.ctxman/self-knowledge/documents.lance/_transactions/6-4b1b8b87-068e-49a3-ba2b-d8dae628b252.txn +0 -0
- package/.ctxman/self-knowledge/documents.lance/_transactions/7-63d040fb-d2fa-4c0f-bed0-53411918a7b0.txn +0 -0
- package/.ctxman/self-knowledge/documents.lance/_transactions/8-c5628cf6-264c-420f-aab8-bc96a9083591.txn +0 -0
- package/.ctxman/self-knowledge/documents.lance/_transactions/9-c94570aa-5e53-4fcb-971f-cecc1d1d5492.txn +0 -0
- package/.ctxman/self-knowledge/documents.lance/_versions/1.manifest +0 -0
- package/.ctxman/self-knowledge/documents.lance/_versions/10.manifest +0 -0
- package/.ctxman/self-knowledge/documents.lance/_versions/11.manifest +0 -0
- package/.ctxman/self-knowledge/documents.lance/_versions/12.manifest +0 -0
- package/.ctxman/self-knowledge/documents.lance/_versions/13.manifest +0 -0
- package/.ctxman/self-knowledge/documents.lance/_versions/14.manifest +0 -0
- package/.ctxman/self-knowledge/documents.lance/_versions/15.manifest +0 -0
- package/.ctxman/self-knowledge/documents.lance/_versions/16.manifest +0 -0
- package/.ctxman/self-knowledge/documents.lance/_versions/17.manifest +0 -0
- package/.ctxman/self-knowledge/documents.lance/_versions/18.manifest +0 -0
- package/.ctxman/self-knowledge/documents.lance/_versions/19.manifest +0 -0
- package/.ctxman/self-knowledge/documents.lance/_versions/2.manifest +0 -0
- package/.ctxman/self-knowledge/documents.lance/_versions/20.manifest +0 -0
- package/.ctxman/self-knowledge/documents.lance/_versions/21.manifest +0 -0
- package/.ctxman/self-knowledge/documents.lance/_versions/3.manifest +0 -0
- package/.ctxman/self-knowledge/documents.lance/_versions/4.manifest +0 -0
- package/.ctxman/self-knowledge/documents.lance/_versions/5.manifest +0 -0
- package/.ctxman/self-knowledge/documents.lance/_versions/6.manifest +0 -0
- package/.ctxman/self-knowledge/documents.lance/_versions/7.manifest +0 -0
- package/.ctxman/self-knowledge/documents.lance/_versions/8.manifest +0 -0
- package/.ctxman/self-knowledge/documents.lance/_versions/9.manifest +0 -0
- package/.ctxman/self-knowledge/documents.lance/data/000010010011011101000010de8621405d9d5cb06540dbf02c.lance +0 -0
- package/.ctxman/self-knowledge/documents.lance/data/0000101001011100011000003fb62a4aa8978974075c144f1c.lance +0 -0
- package/.ctxman/self-knowledge/documents.lance/data/000011010000100111001011c6cc824d628f3bb1f4e04cd5d0.lance +0 -0
- package/.ctxman/self-knowledge/documents.lance/data/001000001000011001011100d8f74349ada090b332cd1df669.lance +0 -0
- package/.ctxman/self-knowledge/documents.lance/data/01000001111010001000010045ab44467bb1e7e4d8ae06bd58.lance +0 -0
- package/.ctxman/self-knowledge/documents.lance/data/01000101101110111110011131ef904241a89e1ffb6ddaf8e3.lance +0 -0
- package/.ctxman/self-knowledge/documents.lance/data/010010110000010000011010fbfcc145c6a8a827b28057a07e.lance +0 -0
- package/.ctxman/self-knowledge/documents.lance/data/1000011000101010001110003fb4f045c3835982efa1405324.lance +0 -0
- package/.ctxman/self-knowledge/documents.lance/data/100111011101110111101011f4396b410fa06af3b028d204e6.lance +0 -0
- package/.ctxman/self-knowledge/documents.lance/data/100111100111101000001100596b174e00995d6cc2969cc8dc.lance +0 -0
- package/.ctxman/self-knowledge/documents.lance/data/1010001100011000110010102ea16b484d887c7c9725feffd6.lance +0 -0
- package/.ctxman/self-knowledge/documents.lance/data/101101100010101111110111c5230944d9b3af7301b6392dda.lance +0 -0
- package/.ctxman/self-knowledge/documents.lance/data/1011011100100111111110105892bf41b5a530fedd7cf516f1.lance +0 -0
- package/.ctxman/self-knowledge/documents.lance/data/10111110000010001011110164e8774742bade87b483c10f36.lance +0 -0
- package/.ctxman/self-knowledge/documents.lance/data/1100000100010110001110103ffaca40a2a42c85067ebaf9ae.lance +0 -0
- package/.ctxman/self-knowledge/documents.lance/data/110000010001110110101110664bde4c76a78dfc14b05e83b8.lance +0 -0
- package/.ctxman/self-knowledge/documents.lance/data/11001100111000010100110050645c4281b1f35b2022234f7f.lance +0 -0
- package/.ctxman/self-knowledge/documents.lance/data/1101111011001100110111017214924a368f5719eab2246619.lance +0 -0
- package/.ctxman/self-knowledge/documents.lance/data/1110000111001010001000002150c24dcab653d39d07032e63.lance +0 -0
- package/.ctxman/self-knowledge/documents.lance/data/1110100000000100000011014d20534967a18b5c87721659ff.lance +0 -0
- package/.ctxman/self-knowledge/documents.lance/data/11110101111010000101011135a0114ef2b35dc6f1297a3381.lance +0 -0
- package/.ctxman/wizard-profiles/code-review/.contextignore +41 -0
- package/.ctxman/wizard-profiles/code-review/.contextinclude +30 -0
- package/.ctxman/wizard-profiles/code-review/.methodignore +26 -0
- package/.ctxman/wizard-profiles/code-review/.methodinclude +47 -0
- package/.ctxman/wizard-profiles/code-review/profile.json +26 -0
- package/.ctxman/wizard-profiles/documentation/.contextignore +21 -0
- package/.ctxman/wizard-profiles/documentation/.contextinclude +24 -0
- package/.ctxman/wizard-profiles/documentation/.methodignore +19 -0
- package/.ctxman/wizard-profiles/documentation/.methodinclude +44 -0
- package/.ctxman/wizard-profiles/documentation/profile.json +27 -0
- package/.ctxman/wizard-profiles/full/.contextignore +23 -0
- package/.ctxman/wizard-profiles/full/.contextinclude +38 -0
- package/.ctxman/wizard-profiles/full/.methodignore +5 -0
- package/.ctxman/wizard-profiles/full/.methodinclude +5 -0
- package/.ctxman/wizard-profiles/full/profile.json +28 -0
- package/.ctxman/wizard-profiles/llm-explain/.contextignore +25 -0
- package/.ctxman/wizard-profiles/llm-explain/.contextinclude +33 -0
- package/.ctxman/wizard-profiles/llm-explain/.methodignore +19 -0
- package/.ctxman/wizard-profiles/llm-explain/.methodinclude +48 -0
- package/.ctxman/wizard-profiles/llm-explain/profile.json +27 -0
- package/.ctxman/wizard-profiles/minimal/.contextignore +27 -0
- package/.ctxman/wizard-profiles/minimal/.contextinclude +14 -0
- package/.ctxman/wizard-profiles/minimal/.methodignore +22 -0
- package/.ctxman/wizard-profiles/minimal/.methodinclude +18 -0
- package/.ctxman/wizard-profiles/minimal/profile.json +26 -0
- package/.ctxman/wizard-profiles/security-audit/.contextignore +36 -0
- package/.ctxman/wizard-profiles/security-audit/.contextinclude +37 -0
- package/.ctxman/wizard-profiles/security-audit/.methodignore +29 -0
- package/.ctxman/wizard-profiles/security-audit/.methodinclude +60 -0
- package/.ctxman/wizard-profiles/security-audit/profile.json +34 -0
- package/README.md +1167 -0
- package/bin/cli.js +650 -0
- package/bin/cm-ask.js +95 -0
- package/bin/cm-gitingest.js +134 -0
- package/bin/cm-update.js +175 -0
- package/bin/mcp-server.js +31 -0
- package/ctxman.js +236 -0
- package/examples/README.md +298 -0
- package/examples/custom-llm-profiles.example.json +19 -0
- package/examples/wizard-profiles/code-review/.contextignore +41 -0
- package/examples/wizard-profiles/code-review/.contextinclude +30 -0
- package/examples/wizard-profiles/code-review/.methodignore +26 -0
- package/examples/wizard-profiles/code-review/.methodinclude +47 -0
- package/examples/wizard-profiles/code-review/profile.json +26 -0
- package/examples/wizard-profiles/documentation/.contextignore +21 -0
- package/examples/wizard-profiles/documentation/.contextinclude +24 -0
- package/examples/wizard-profiles/documentation/.methodignore +19 -0
- package/examples/wizard-profiles/documentation/.methodinclude +44 -0
- package/examples/wizard-profiles/documentation/profile.json +27 -0
- package/examples/wizard-profiles/full/.contextignore +23 -0
- package/examples/wizard-profiles/full/.contextinclude +38 -0
- package/examples/wizard-profiles/full/.methodignore +5 -0
- package/examples/wizard-profiles/full/.methodinclude +5 -0
- package/examples/wizard-profiles/full/profile.json +28 -0
- package/examples/wizard-profiles/llm-explain/.contextignore +25 -0
- package/examples/wizard-profiles/llm-explain/.contextinclude +33 -0
- package/examples/wizard-profiles/llm-explain/.methodignore +19 -0
- package/examples/wizard-profiles/llm-explain/.methodinclude +48 -0
- package/examples/wizard-profiles/llm-explain/profile.json +27 -0
- package/examples/wizard-profiles/minimal/.contextignore +27 -0
- package/examples/wizard-profiles/minimal/.contextinclude +14 -0
- package/examples/wizard-profiles/minimal/.methodignore +22 -0
- package/examples/wizard-profiles/minimal/.methodinclude +18 -0
- package/examples/wizard-profiles/minimal/profile.json +26 -0
- package/examples/wizard-profiles/security-audit/.contextignore +36 -0
- package/examples/wizard-profiles/security-audit/.contextinclude +37 -0
- package/examples/wizard-profiles/security-audit/.methodignore +29 -0
- package/examples/wizard-profiles/security-audit/.methodinclude +60 -0
- package/examples/wizard-profiles/security-audit/profile.json +34 -0
- package/index.js +68 -0
- package/lib/agents/pr-failure-agent.js +201 -0
- package/lib/analyzers/go-method-analyzer.js +126 -0
- package/lib/analyzers/method-analyzer.js +457 -0
- package/lib/analyzers/token-calculator.js +577 -0
- package/lib/api/mcp/prompts.js +319 -0
- package/lib/api/mcp/resources.js +269 -0
- package/lib/api/mcp/server.js +339 -0
- package/lib/api/mcp/transports/HttpSseTransport.js +63 -0
- package/lib/api/rest/server.js +405 -0
- package/lib/cache/CacheManager.js +388 -0
- package/lib/core/Analyzer.js +180 -0
- package/lib/core/ContextBuilder.js +325 -0
- package/lib/core/Reporter.js +270 -0
- package/lib/core/Scanner.js +129 -0
- package/lib/formatters/format-registry.js +419 -0
- package/lib/formatters/gitingest-formatter.js +746 -0
- package/lib/formatters/toon-formatter-v1.3.js +731 -0
- package/lib/formatters/toon-formatter.js +291 -0
- package/lib/integrations/git/BlameTracker.js +142 -0
- package/lib/integrations/git/DiffAnalyzer.js +260 -0
- package/lib/integrations/git/GitClient.js +336 -0
- package/lib/parsers/gitignore-parser.js +127 -0
- package/lib/parsers/method-filter-parser.js +50 -0
- package/lib/plugins/ExporterPlugin.js +102 -0
- package/lib/plugins/LanguagePlugin.js +100 -0
- package/lib/plugins/PluginManager.js +302 -0
- package/lib/rag/DataSourcePlugin.js +31 -0
- package/lib/rag/EmbeddingProvider.js +75 -0
- package/lib/rag/Indexer.js +83 -0
- package/lib/rag/VectorStoreFactory.js +24 -0
- package/lib/rag/sources/FileDataSource.js +70 -0
- package/lib/rag/stores/BaseVectorStore.js +43 -0
- package/lib/rag/stores/ChromaDBStore.js +85 -0
- package/lib/rag/stores/LanceDBStore.js +109 -0
- package/lib/rag/stores/PineconeStore.js +74 -0
- package/lib/ui/dashboard.js +109 -0
- package/lib/ui/index.js +15 -0
- package/lib/ui/progress-bar.js +110 -0
- package/lib/ui/select-input.js +51 -0
- package/lib/ui/wizard.js +359 -0
- package/lib/utils/clipboard-utils.js +66 -0
- package/lib/utils/config-utils.js +94 -0
- package/lib/utils/error-handler.js +145 -0
- package/lib/utils/file-utils.js +89 -0
- package/lib/utils/format-converter.js +325 -0
- package/lib/utils/git-utils.js +337 -0
- package/lib/utils/llm-detector.js +409 -0
- package/lib/utils/logger.js +278 -0
- package/lib/utils/token-utils.js +200 -0
- package/lib/utils/tokenizer-adapter.js +454 -0
- package/lib/utils/updater.js +565 -0
- package/lib/watch/FileWatcher.js +208 -0
- package/lib/watch/IncrementalAnalyzer.js +206 -0
- package/package.json +118 -0
package/bin/cm-ask.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { VectorStoreFactory } from '../lib/rag/VectorStoreFactory.js';
|
|
3
|
+
import { EmbeddingProvider, TransformersEmbeddingProvider } from '../lib/rag/EmbeddingProvider.js';
|
|
4
|
+
import { Indexer } from '../lib/rag/Indexer.js';
|
|
5
|
+
import { FileDataSource } from '../lib/rag/sources/FileDataSource.js';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import fs from 'fs/promises';
|
|
8
|
+
import { TokenizerManager } from '../lib/utils/tokenizer-adapter.js';
|
|
9
|
+
|
|
10
|
+
async function main() {
|
|
11
|
+
const args = process.argv.slice(2);
|
|
12
|
+
const query = args.join(' ');
|
|
13
|
+
|
|
14
|
+
if (!query) {
|
|
15
|
+
console.error('Usage: ctxman ask "Your query here"');
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// 1. Initialize RAG Components
|
|
20
|
+
let provider;
|
|
21
|
+
try {
|
|
22
|
+
// Try to load local transformers
|
|
23
|
+
provider = new TransformersEmbeddingProvider();
|
|
24
|
+
// Lazy init will handle model download on first use
|
|
25
|
+
} catch (e) {
|
|
26
|
+
console.error('⚠️ Failed to initialize embedding provider:', e.message);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Use LanceDB in .ctxman/self-knowledge
|
|
31
|
+
const storePath = path.join(process.cwd(), '.ctxman', 'self-knowledge');
|
|
32
|
+
const store = VectorStoreFactory.create('lancedb', provider, { path: storePath });
|
|
33
|
+
|
|
34
|
+
// 2. Check if indexed
|
|
35
|
+
const isIndexed = await checkIndexExists(storePath);
|
|
36
|
+
|
|
37
|
+
if (!isIndexed) {
|
|
38
|
+
console.log('📚 Index not found. Auto-indexing current project...');
|
|
39
|
+
await indexProject(store);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 3. Search
|
|
43
|
+
console.log(`🔍 Searching for: "${query}"...`);
|
|
44
|
+
const results = await store.search(query, 5); // Get top 5
|
|
45
|
+
|
|
46
|
+
if (results.length === 0) {
|
|
47
|
+
console.log('❌ No relevant context found.');
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// 4. Display Results (or feed to LLM if we had one configured)
|
|
52
|
+
console.log(`\nFound ${results.length} relevant snippets:\n`);
|
|
53
|
+
|
|
54
|
+
results.forEach((r, i) => {
|
|
55
|
+
console.log(`[${i+1}] ${r.metadata.filename} (Score: ${r.score?.toFixed(4)})`);
|
|
56
|
+
console.log('─'.repeat(40));
|
|
57
|
+
// Show a small snippet around the match if possible, but we stored full text.
|
|
58
|
+
// Let's just show the first 200 chars or so.
|
|
59
|
+
console.log(r.text.substring(0, 300).replace(/\n/g, ' ') + '...');
|
|
60
|
+
console.log('\n');
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Future: Pass `results` to an LLM API to generate a real answer.
|
|
64
|
+
// For now, this validates the retrieval pipeline works from CLI.
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function checkIndexExists(storePath) {
|
|
68
|
+
try {
|
|
69
|
+
await fs.access(storePath);
|
|
70
|
+
// Also check if it has tables (LanceDB creates folders)
|
|
71
|
+
const files = await fs.readdir(storePath);
|
|
72
|
+
return files.length > 0;
|
|
73
|
+
} catch {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function indexProject(store) {
|
|
79
|
+
const indexer = new Indexer(store);
|
|
80
|
+
const fileSource = new FileDataSource();
|
|
81
|
+
indexer.registerSource(fileSource);
|
|
82
|
+
|
|
83
|
+
console.log('⏳ Indexing files (this may take a moment)...');
|
|
84
|
+
await indexer.index('local-files', {
|
|
85
|
+
targetDir: process.cwd(),
|
|
86
|
+
include: ['.js', '.md', '.ts', '.json'], // Configurable?
|
|
87
|
+
exclude: ['node_modules', '.git', 'dist', 'coverage', '.ctxman']
|
|
88
|
+
});
|
|
89
|
+
console.log('✅ Indexing complete.');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
main().catch(err => {
|
|
93
|
+
console.error('❌ Error:', err);
|
|
94
|
+
process.exit(1);
|
|
95
|
+
});
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* GitHub GitIngest Command
|
|
4
|
+
* Generate GitIngest digest from GitHub repositories
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const GitUtils = require('../lib/utils/git-utils');
|
|
8
|
+
const { getLogger } = require('../lib/utils/logger');
|
|
9
|
+
|
|
10
|
+
const logger = getLogger({ level: 'info' });
|
|
11
|
+
|
|
12
|
+
async function main() {
|
|
13
|
+
const args = process.argv.slice(2);
|
|
14
|
+
|
|
15
|
+
if (args.length === 0 || args.includes('--help') || args.includes('-h')) {
|
|
16
|
+
printHelp();
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const url = args[0];
|
|
21
|
+
const verbose = args.includes('--verbose') || args.includes('-v');
|
|
22
|
+
const keepClone = args.includes('--keep-clone');
|
|
23
|
+
const shallow = !args.includes('--full-clone');
|
|
24
|
+
|
|
25
|
+
// Parse options
|
|
26
|
+
const outputIndex = args.findIndex(arg => arg === '--output' || arg === '-o');
|
|
27
|
+
const outputFile = outputIndex !== -1 ? args[outputIndex + 1] : null;
|
|
28
|
+
|
|
29
|
+
const branchIndex = args.findIndex(arg => arg === '--branch' || arg === '-b');
|
|
30
|
+
const branch = branchIndex !== -1 ? args[branchIndex + 1] : 'main';
|
|
31
|
+
|
|
32
|
+
const chunkSize = args.includes('--chunk-size')
|
|
33
|
+
? parseInt(args[args.findIndex(arg => arg === '--chunk-size') + 1])
|
|
34
|
+
: null;
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
console.log('╔════════════════════════════════════════════════════════╗');
|
|
38
|
+
console.log('║ GitHub GitIngest Generator v2.3.6 ║');
|
|
39
|
+
console.log('╚════════════════════════════════════════════════════════╝\n');
|
|
40
|
+
|
|
41
|
+
const gitUtils = new GitUtils({
|
|
42
|
+
verbose,
|
|
43
|
+
outputDir: 'docs'
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Get repository info first
|
|
47
|
+
console.log('📋 Fetching repository information...');
|
|
48
|
+
const repoInfo = gitUtils.parseGitHubURL(url);
|
|
49
|
+
repoInfo.branch = branch; // Override branch if specified
|
|
50
|
+
|
|
51
|
+
const repoData = await gitUtils.getRepositoryInfo(repoInfo);
|
|
52
|
+
console.log(`\n📊 Repository Info:`);
|
|
53
|
+
console.log(` Name: ${repoData.fullName}`);
|
|
54
|
+
console.log(` Description: ${repoData.description || 'N/A'}`);
|
|
55
|
+
console.log(` Stars: ⭐ ${repoData.stars.toLocaleString()}`);
|
|
56
|
+
console.log(` Language: ${repoData.language || 'Multiple'}`);
|
|
57
|
+
console.log(` Default Branch: ${repoData.defaultBranch}`);
|
|
58
|
+
|
|
59
|
+
// Generate GitIngest
|
|
60
|
+
const options = {
|
|
61
|
+
outputFile,
|
|
62
|
+
cleanup: !keepClone,
|
|
63
|
+
shallow,
|
|
64
|
+
formatterOptions: chunkSize ? {
|
|
65
|
+
chunking: {
|
|
66
|
+
enabled: true,
|
|
67
|
+
maxTokensPerChunk: chunkSize
|
|
68
|
+
}
|
|
69
|
+
} : {}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const stats = await gitUtils.generateFromGitHub(url, options);
|
|
73
|
+
|
|
74
|
+
// Log to file
|
|
75
|
+
logger.info('GitHub GitIngest generated', {
|
|
76
|
+
repository: stats.repository,
|
|
77
|
+
outputFile: stats.outputFile,
|
|
78
|
+
files: stats.files,
|
|
79
|
+
tokens: stats.tokens
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
console.log('\n✅ Complete!\n');
|
|
83
|
+
|
|
84
|
+
// Show next steps
|
|
85
|
+
console.log('📝 Next steps:');
|
|
86
|
+
console.log(` 1. View digest: cat "${stats.outputFile}"`);
|
|
87
|
+
console.log(` 2. Use in LLM: Copy to clipboard`);
|
|
88
|
+
console.log(` 3. Cleanup: npm run clean\n`);
|
|
89
|
+
|
|
90
|
+
} catch (error) {
|
|
91
|
+
console.error('\n❌ Error:', error.message);
|
|
92
|
+
logger.error('GitHub GitIngest failed', { error: error.message });
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function printHelp() {
|
|
98
|
+
console.log('GitHub GitIngest Generator - Generate digest from GitHub repositories\n');
|
|
99
|
+
console.log('Usage: ctxman github <url> [options]\n');
|
|
100
|
+
console.log('Arguments:');
|
|
101
|
+
console.log(' url GitHub repository URL or owner/repo\n');
|
|
102
|
+
console.log('Options:');
|
|
103
|
+
console.log(' -o, --output FILE Output file path (default: docs/{repo}-gitingest-{hash}.txt)');
|
|
104
|
+
console.log(' -b, --branch BRANCH Branch to clone (default: main)');
|
|
105
|
+
console.log(' -v, --verbose Verbose output');
|
|
106
|
+
console.log(' --keep-clone Keep cloned repository (don\'t cleanup)');
|
|
107
|
+
console.log(' --full-clone Full clone (default: shallow)');
|
|
108
|
+
console.log(' --chunk-size TOKENS Enable chunking with max tokens per chunk');
|
|
109
|
+
console.log(' -h, --help Show this help\n');
|
|
110
|
+
console.log('URL Formats:');
|
|
111
|
+
console.log(' https://github.com/owner/repo');
|
|
112
|
+
console.log(' https://github.com/owner/repo.git');
|
|
113
|
+
console.log(' git@github.com:owner/repo.git');
|
|
114
|
+
console.log(' github.com/owner/repo');
|
|
115
|
+
console.log(' owner/repo\n');
|
|
116
|
+
console.log('Examples:');
|
|
117
|
+
console.log(' # Basic usage');
|
|
118
|
+
console.log(' ctxman github https://github.com/facebook/react\n');
|
|
119
|
+
console.log(' # Short format');
|
|
120
|
+
console.log(' ctxman github facebook/react\n');
|
|
121
|
+
console.log(' # Specific branch');
|
|
122
|
+
console.log(' ctxman github vercel/next.js --branch canary\n');
|
|
123
|
+
console.log(' # Custom output location');
|
|
124
|
+
console.log(' ctxman github angular/angular -o docs/angular-digest.txt\n');
|
|
125
|
+
console.log(' # With chunking');
|
|
126
|
+
console.log(' ctxman github microsoft/vscode --chunk-size 100000\n');
|
|
127
|
+
console.log(' # Keep clone for inspection');
|
|
128
|
+
console.log(' ctxman github nodejs/node --keep-clone --verbose\n');
|
|
129
|
+
console.log('Output:');
|
|
130
|
+
console.log(' Generated digest file in docs/ directory');
|
|
131
|
+
console.log(' Automatic cleanup of temporary clone (unless --keep-clone)\n');
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
main();
|
package/bin/cm-update.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Ctxman - Update Command
|
|
4
|
+
* Handles version updates and channel switching
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const Updater = require('../lib/utils/updater');
|
|
8
|
+
const { getLogger } = require('../lib/utils/logger');
|
|
9
|
+
|
|
10
|
+
const logger = getLogger({ level: 'info' });
|
|
11
|
+
|
|
12
|
+
async function main() {
|
|
13
|
+
const args = process.argv.slice(2);
|
|
14
|
+
|
|
15
|
+
// Parse command
|
|
16
|
+
const command = args[0];
|
|
17
|
+
|
|
18
|
+
const updater = new Updater();
|
|
19
|
+
|
|
20
|
+
switch (command) {
|
|
21
|
+
case 'check':
|
|
22
|
+
await checkForUpdates(updater);
|
|
23
|
+
break;
|
|
24
|
+
|
|
25
|
+
case 'install':
|
|
26
|
+
await installUpdate(updater);
|
|
27
|
+
break;
|
|
28
|
+
|
|
29
|
+
case 'rollback':
|
|
30
|
+
await rollbackVersion(updater);
|
|
31
|
+
break;
|
|
32
|
+
|
|
33
|
+
case 'channel':
|
|
34
|
+
await switchChannel(updater, args[1]);
|
|
35
|
+
break;
|
|
36
|
+
|
|
37
|
+
case 'info':
|
|
38
|
+
showUpdateInfo(updater);
|
|
39
|
+
break;
|
|
40
|
+
|
|
41
|
+
default:
|
|
42
|
+
// Default: check and optionally install
|
|
43
|
+
await checkAndUpdate(updater);
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function checkForUpdates(updater) {
|
|
49
|
+
console.log('🔍 Checking for updates...\n');
|
|
50
|
+
|
|
51
|
+
const updateInfo = await updater.checkForUpdates();
|
|
52
|
+
|
|
53
|
+
if (updateInfo.error) {
|
|
54
|
+
logger.error('Failed to check for updates', { error: updateInfo.error });
|
|
55
|
+
console.log(`\n❌ ${updateInfo.message}`);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (updateInfo.available) {
|
|
60
|
+
console.log('✨ Update available!\n');
|
|
61
|
+
console.log(` Current: ${updateInfo.currentVersion}`);
|
|
62
|
+
console.log(` Latest: ${updateInfo.latestVersion}`);
|
|
63
|
+
console.log(` Channel: ${updateInfo.channel}\n`);
|
|
64
|
+
|
|
65
|
+
if (updateInfo.releaseNotes) {
|
|
66
|
+
console.log('📝 Release Notes:');
|
|
67
|
+
console.log(' ' + updateInfo.releaseNotes.split('\n').join('\n '));
|
|
68
|
+
console.log('');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
console.log('To install: ctxman update install\n');
|
|
72
|
+
} else {
|
|
73
|
+
console.log('✓ You are using the latest version\n');
|
|
74
|
+
console.log(` Version: ${updateInfo.currentVersion}`);
|
|
75
|
+
console.log(` Channel: ${updater.channel}\n`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async function installUpdate(updater) {
|
|
80
|
+
console.log('📦 Installing update...\n');
|
|
81
|
+
|
|
82
|
+
const updateInfo = await updater.checkForUpdates();
|
|
83
|
+
|
|
84
|
+
if (!updateInfo.available) {
|
|
85
|
+
console.log('✓ Already using the latest version\n');
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const result = await updater.installUpdate(updateInfo);
|
|
90
|
+
|
|
91
|
+
if (result.success) {
|
|
92
|
+
console.log('\n✅ Update installed successfully!\n');
|
|
93
|
+
logger.info('Update installed', {
|
|
94
|
+
from: updateInfo.currentVersion,
|
|
95
|
+
to: updateInfo.latestVersion
|
|
96
|
+
});
|
|
97
|
+
} else if (result.manualUpdateRequired) {
|
|
98
|
+
logger.warn('Manual update required');
|
|
99
|
+
} else {
|
|
100
|
+
console.log('\n❌ Update failed\n');
|
|
101
|
+
logger.error('Update failed', { error: result.error });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async function switchChannel(updater, newChannel) {
|
|
106
|
+
if (!newChannel) {
|
|
107
|
+
console.log('❌ Please specify a channel: stable or insider\n');
|
|
108
|
+
console.log('Usage: ctxman update channel <stable|insider>\n');
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
console.log(`🔄 Switching to ${newChannel} channel...\n`);
|
|
114
|
+
|
|
115
|
+
const updateInfo = await updater.switchChannel(newChannel);
|
|
116
|
+
|
|
117
|
+
logger.info('Channel switched', { channel: newChannel });
|
|
118
|
+
|
|
119
|
+
if (updateInfo.available) {
|
|
120
|
+
console.log(`\n✨ Update available on ${newChannel} channel!\n`);
|
|
121
|
+
console.log(` Latest: ${updateInfo.latestVersion}\n`);
|
|
122
|
+
console.log('To install: ctxman update install\n');
|
|
123
|
+
}
|
|
124
|
+
} catch (error) {
|
|
125
|
+
console.log(`\n❌ ${error.message}\n`);
|
|
126
|
+
logger.error('Failed to switch channel', { error: error.message });
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async function rollbackVersion(updater) {
|
|
131
|
+
console.log('🔄 Rolling back to previous version...\n');
|
|
132
|
+
|
|
133
|
+
const result = await updater.rollback();
|
|
134
|
+
|
|
135
|
+
if (result.success) {
|
|
136
|
+
console.log(`\n✅ Successfully rolled back to v${result.restoredVersion}\n`);
|
|
137
|
+
logger.info('Version rolled back', {
|
|
138
|
+
restoredVersion: result.restoredVersion
|
|
139
|
+
});
|
|
140
|
+
} else {
|
|
141
|
+
console.log(`\n❌ Rollback failed: ${result.error}\n`);
|
|
142
|
+
logger.error('Rollback failed', { error: result.error });
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function showUpdateInfo(updater) {
|
|
147
|
+
console.log('ℹ️ Update Configuration\n');
|
|
148
|
+
console.log(` Current version: ${updater.currentVersion}`);
|
|
149
|
+
console.log(` Update channel: ${updater.channel}`);
|
|
150
|
+
console.log(` Auto-update: ${updater.autoUpdate ? 'Enabled' : 'Disabled'}\n`);
|
|
151
|
+
|
|
152
|
+
console.log('Available commands:\n');
|
|
153
|
+
console.log(' ctxman update check - Check for updates');
|
|
154
|
+
console.log(' ctxman update install - Install latest update');
|
|
155
|
+
console.log(' ctxman update rollback - Rollback to previous version');
|
|
156
|
+
console.log(' ctxman update channel - Switch update channel');
|
|
157
|
+
console.log(' ctxman update info - Show this information\n');
|
|
158
|
+
|
|
159
|
+
console.log('Channels:\n');
|
|
160
|
+
console.log(' stable - Stable releases (recommended)');
|
|
161
|
+
console.log(' insider - Pre-release builds (bleeding edge)\n');
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
async function checkAndUpdate(updater) {
|
|
165
|
+
const updateInfo = await updater.checkAndNotify();
|
|
166
|
+
|
|
167
|
+
if (updateInfo && updateInfo.available) {
|
|
168
|
+
console.log('Run "ctxman update install" to update\n');
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
main().catch(error => {
|
|
173
|
+
console.error('Update command failed:', error.message);
|
|
174
|
+
process.exit(1);
|
|
175
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import MCPServer from "../lib/api/mcp/server.js";
|
|
4
|
+
import { HttpSseTransport } from "../lib/api/mcp/transports/HttpSseTransport.js";
|
|
5
|
+
|
|
6
|
+
const args = process.argv.slice(2);
|
|
7
|
+
const transportType = args.includes("--transport=sse") ? "sse" : "stdio";
|
|
8
|
+
const port = args.find(arg => arg.startsWith("--port="))?.split("=")[1] || 3000;
|
|
9
|
+
const apiKey = args.find(arg => arg.startsWith("--api-key="))?.split("=")[1];
|
|
10
|
+
|
|
11
|
+
const server = new MCPServer();
|
|
12
|
+
|
|
13
|
+
async function main() {
|
|
14
|
+
try {
|
|
15
|
+
if (transportType === "sse") {
|
|
16
|
+
const transport = new HttpSseTransport({
|
|
17
|
+
port: parseInt(port),
|
|
18
|
+
auth: apiKey ? { apiKey } : undefined
|
|
19
|
+
});
|
|
20
|
+
await transport.start();
|
|
21
|
+
await server.start(transport.transport);
|
|
22
|
+
} else {
|
|
23
|
+
await server.start();
|
|
24
|
+
}
|
|
25
|
+
} catch (error) {
|
|
26
|
+
console.error("Fatal error running MCP server:", error);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
main();
|
package/ctxman.js
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Ctxman - Main Orchestrator
|
|
5
|
+
* LLM context optimization with method-level filtering and GitIngest support
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import TokenCalculator from './lib/analyzers/token-calculator.js';
|
|
11
|
+
import GitIngestFormatter from './lib/formatters/gitingest-formatter.js';
|
|
12
|
+
import TokenUtils from './lib/utils/token-utils.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Generate GitIngest digest from token-analysis-report.json
|
|
16
|
+
*/
|
|
17
|
+
function generateDigestFromReport(reportPath) {
|
|
18
|
+
console.log('📄 Loading token analysis report...');
|
|
19
|
+
|
|
20
|
+
if (!fs.existsSync(reportPath)) {
|
|
21
|
+
console.error(`❌ Error: Report file not found: ${reportPath}`);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
const report = JSON.parse(fs.readFileSync(reportPath, 'utf8'));
|
|
27
|
+
|
|
28
|
+
if (!report.metadata || !report.summary || !report.files) {
|
|
29
|
+
console.error('❌ Error: Invalid report format. Missing required fields.');
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const projectRoot = report.metadata.projectRoot || process.cwd();
|
|
34
|
+
|
|
35
|
+
console.log(`✅ Report loaded: ${report.files.length} files`);
|
|
36
|
+
console.log('📄 Generating GitIngest digest from report...\n');
|
|
37
|
+
|
|
38
|
+
const formatter = new GitIngestFormatter(
|
|
39
|
+
projectRoot,
|
|
40
|
+
report.summary,
|
|
41
|
+
report.files
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
const digestPath = path.join(process.cwd(), 'digest.txt');
|
|
45
|
+
const digestSize = formatter.saveToFile(digestPath);
|
|
46
|
+
|
|
47
|
+
console.log(`💾 GitIngest digest saved to: digest.txt`);
|
|
48
|
+
console.log(`📊 Digest size: ${(digestSize / 1024).toFixed(1)} KB`);
|
|
49
|
+
console.log(`✨ Generated from: ${path.basename(reportPath)}`);
|
|
50
|
+
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.error(`❌ Error processing report: ${error.message}`);
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Generate GitIngest digest from llm-context.json
|
|
59
|
+
*/
|
|
60
|
+
function generateDigestFromContext(contextPath) {
|
|
61
|
+
console.log('📄 Loading LLM context file...');
|
|
62
|
+
|
|
63
|
+
if (!fs.existsSync(contextPath)) {
|
|
64
|
+
console.error(`❌ Error: Context file not found: ${contextPath}`);
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
const context = JSON.parse(fs.readFileSync(contextPath, 'utf8'));
|
|
70
|
+
|
|
71
|
+
if (!context.project || !context.paths) {
|
|
72
|
+
console.error('❌ Error: Invalid context format. Missing required fields.');
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
console.log(`✅ Context loaded: ${context.project.totalFiles} files`);
|
|
77
|
+
console.log('📄 Generating GitIngest digest from context...\n');
|
|
78
|
+
|
|
79
|
+
// Extract files from context.paths structure
|
|
80
|
+
const files = [];
|
|
81
|
+
for (const [dirPath, fileNames] of Object.entries(context.paths)) {
|
|
82
|
+
for (const fileName of fileNames) {
|
|
83
|
+
const relativePath = dirPath === '/'
|
|
84
|
+
? fileName
|
|
85
|
+
: `${dirPath}${fileName}`;
|
|
86
|
+
|
|
87
|
+
const fullPath = path.join(process.cwd(), relativePath);
|
|
88
|
+
|
|
89
|
+
if (fs.existsSync(fullPath)) {
|
|
90
|
+
const stats = fs.statSync(fullPath);
|
|
91
|
+
files.push({
|
|
92
|
+
path: fullPath,
|
|
93
|
+
relativePath: relativePath,
|
|
94
|
+
sizeBytes: stats.size,
|
|
95
|
+
tokens: 0,
|
|
96
|
+
lines: 0
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
console.log(`📁 Found ${files.length} accessible files`);
|
|
103
|
+
|
|
104
|
+
const stats = {
|
|
105
|
+
totalFiles: files.length,
|
|
106
|
+
totalTokens: context.project.totalTokens,
|
|
107
|
+
totalBytes: files.reduce((sum, f) => sum + f.sizeBytes, 0),
|
|
108
|
+
totalLines: 0
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const formatter = new GitIngestFormatter(
|
|
112
|
+
process.cwd(),
|
|
113
|
+
stats,
|
|
114
|
+
files
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
const digestPath = path.join(process.cwd(), 'digest.txt');
|
|
118
|
+
const digestSize = formatter.saveToFile(digestPath);
|
|
119
|
+
|
|
120
|
+
console.log(`💾 GitIngest digest saved to: digest.txt`);
|
|
121
|
+
console.log(`📊 Digest size: ${(digestSize / 1024).toFixed(1)} KB`);
|
|
122
|
+
console.log(`✨ Generated from: ${path.basename(contextPath)}`);
|
|
123
|
+
|
|
124
|
+
} catch (error) {
|
|
125
|
+
console.error(`❌ Error processing context: ${error.message}`);
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Main execution
|
|
132
|
+
*/
|
|
133
|
+
async function main(args = process.argv.slice(2)) {
|
|
134
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
135
|
+
printHelp();
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Handle --gitingest-from-report
|
|
140
|
+
const reportFlagIndex = args.indexOf('--gitingest-from-report');
|
|
141
|
+
if (reportFlagIndex !== -1) {
|
|
142
|
+
const reportPath = args[reportFlagIndex + 1] || 'token-analysis-report.json';
|
|
143
|
+
generateDigestFromReport(reportPath);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Handle --gitingest-from-context
|
|
148
|
+
const contextFlagIndex = args.indexOf('--gitingest-from-context');
|
|
149
|
+
if (contextFlagIndex !== -1) {
|
|
150
|
+
const contextPath = args[contextFlagIndex + 1] || 'llm-context.json';
|
|
151
|
+
generateDigestFromContext(contextPath);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const options = {
|
|
156
|
+
saveReport: args.includes('--save-report') || args.includes('-s'),
|
|
157
|
+
verbose: args.includes('--verbose') || args.includes('-v'),
|
|
158
|
+
contextExport: args.includes('--context-export'),
|
|
159
|
+
contextToClipboard: args.includes('--context-clipboard'),
|
|
160
|
+
methodLevel: args.includes('--method-level') || args.includes('-m'),
|
|
161
|
+
gitingest: args.includes('--gitingest') || args.includes('-g')
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
printStartupInfo();
|
|
165
|
+
|
|
166
|
+
const calculator = new TokenCalculator(process.cwd(), options);
|
|
167
|
+
await calculator.run();
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function printStartupInfo() {
|
|
171
|
+
console.log('🚀 Code Analyzer by Hakkı Sağdıç');
|
|
172
|
+
console.log('='.repeat(50));
|
|
173
|
+
console.log('📋 Available options:');
|
|
174
|
+
console.log(' --save-report, -s Save detailed JSON report');
|
|
175
|
+
console.log(' --verbose, -v Show included files and directories');
|
|
176
|
+
console.log(' --context-export Generate LLM context file list');
|
|
177
|
+
console.log(' --context-clipboard Copy context to clipboard');
|
|
178
|
+
console.log(' --method-level, -m Enable method-level analysis');
|
|
179
|
+
console.log(' --gitingest, -g Generate GitIngest-style digest');
|
|
180
|
+
console.log(' --help, -h Show this help message');
|
|
181
|
+
|
|
182
|
+
if (!TokenUtils.hasExactCounting()) {
|
|
183
|
+
console.log('\n💡 For exact token counts, install tiktoken: npm install tiktoken');
|
|
184
|
+
}
|
|
185
|
+
console.log();
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function printHelp() {
|
|
189
|
+
console.log('Ctxman - LLM context optimization with method-level filtering');
|
|
190
|
+
console.log();
|
|
191
|
+
console.log('Usage: ctxman [options]');
|
|
192
|
+
console.log(' node ctxman.js [options] # Direct usage');
|
|
193
|
+
console.log();
|
|
194
|
+
console.log('Options:');
|
|
195
|
+
console.log(' -s, --save-report Save detailed JSON report');
|
|
196
|
+
console.log(' -v, --verbose Show all included files');
|
|
197
|
+
console.log(' --context-export Generate LLM context file');
|
|
198
|
+
console.log(' --context-clipboard Copy context to clipboard');
|
|
199
|
+
console.log(' -m, --method-level Enable method-level analysis');
|
|
200
|
+
console.log(' -g, --gitingest Generate GitIngest-style digest');
|
|
201
|
+
console.log(' --gitingest-from-report <file> Generate digest from report JSON');
|
|
202
|
+
console.log(' --gitingest-from-context <file> Generate digest from context JSON');
|
|
203
|
+
console.log(' -h, --help Show this help');
|
|
204
|
+
console.log();
|
|
205
|
+
console.log('Method-level Configuration:');
|
|
206
|
+
console.log(' .methodinclude Include only specified methods');
|
|
207
|
+
console.log(' .methodignore Exclude specified methods');
|
|
208
|
+
console.log();
|
|
209
|
+
console.log('Examples:');
|
|
210
|
+
console.log(' # Standard workflow');
|
|
211
|
+
console.log(' ctxman # Interactive export selection');
|
|
212
|
+
console.log(' ctxman --save-report # Save JSON report');
|
|
213
|
+
console.log(' ctxman --gitingest # Generate digest.txt');
|
|
214
|
+
console.log(' ctxman -g -s # Both digest + report');
|
|
215
|
+
console.log();
|
|
216
|
+
console.log(' # Generate digest from existing JSON files (fast, no re-scan)');
|
|
217
|
+
console.log(' ctxman --gitingest-from-report token-analysis-report.json');
|
|
218
|
+
console.log(' ctxman --gitingest-from-context llm-context.json');
|
|
219
|
+
console.log();
|
|
220
|
+
console.log(' # Two-step workflow');
|
|
221
|
+
console.log(' ctxman -s # Step 1: Analyze and save report');
|
|
222
|
+
console.log(' ctxman --gitingest-from-report token-analysis-report.json');
|
|
223
|
+
console.log(' # Step 2: Generate digest (instant)');
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// ESM entry point check
|
|
227
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
228
|
+
main();
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export {
|
|
232
|
+
TokenCalculator,
|
|
233
|
+
generateDigestFromReport,
|
|
234
|
+
generateDigestFromContext,
|
|
235
|
+
main
|
|
236
|
+
};
|