explainthisrepo 0.9.5 → 0.9.6
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/dist/init.js +34 -18
- package/dist/providers/groq.d.ts +17 -0
- package/dist/providers/groq.js +70 -0
- package/dist/providers/index.d.ts +1 -0
- package/dist/providers/index.js +1 -0
- package/package.json +62 -62
package/dist/init.js
CHANGED
|
@@ -7,7 +7,8 @@ const PROVIDERS = {
|
|
|
7
7
|
"2": "openai",
|
|
8
8
|
"3": "ollama",
|
|
9
9
|
"4": "anthropic",
|
|
10
|
-
"5": "
|
|
10
|
+
"5": "groq",
|
|
11
|
+
"6": "openrouter",
|
|
11
12
|
};
|
|
12
13
|
export async function runInit() {
|
|
13
14
|
const err = process.stderr;
|
|
@@ -44,8 +45,9 @@ async function promptProvider() {
|
|
|
44
45
|
err.write(" 1) Gemini\n");
|
|
45
46
|
err.write(" 2) OpenAI\n");
|
|
46
47
|
err.write(" 3) Ollama (local)\n");
|
|
47
|
-
err.write(" 4) Anthropic\n");
|
|
48
|
-
err.write(" 5)
|
|
48
|
+
err.write(" 4) Anthropic (Claude)\n");
|
|
49
|
+
err.write(" 5) Groq\n");
|
|
50
|
+
err.write(" 6) OpenRouter\n");
|
|
49
51
|
const choice = (await prompt("> ")).trim();
|
|
50
52
|
const provider = PROVIDERS[choice];
|
|
51
53
|
if (!provider) {
|
|
@@ -56,42 +58,57 @@ async function promptProvider() {
|
|
|
56
58
|
async function promptProviderConfig(provider) {
|
|
57
59
|
if (provider === "gemini") {
|
|
58
60
|
const key = (await promptHidden("Gemini API key: ")).trim();
|
|
59
|
-
if (!key)
|
|
61
|
+
if (!key)
|
|
60
62
|
throw new Error("API key cannot be empty");
|
|
61
|
-
}
|
|
62
63
|
return { api_key: key };
|
|
63
64
|
}
|
|
64
65
|
if (provider === "openai") {
|
|
65
66
|
const key = (await promptHidden("OpenAI API key: ")).trim();
|
|
66
|
-
if (!key)
|
|
67
|
+
if (!key)
|
|
67
68
|
throw new Error("API key cannot be empty");
|
|
68
|
-
}
|
|
69
69
|
return { api_key: key };
|
|
70
70
|
}
|
|
71
71
|
if (provider === "anthropic") {
|
|
72
|
-
const key = (await promptHidden("Anthropic API key: ")).trim();
|
|
73
|
-
if (!key)
|
|
72
|
+
const key = (await promptHidden("Anthropic (Claude) API key: ")).trim();
|
|
73
|
+
if (!key)
|
|
74
74
|
throw new Error("API key cannot be empty");
|
|
75
|
-
}
|
|
76
75
|
return { api_key: key };
|
|
77
76
|
}
|
|
78
77
|
if (provider === "ollama") {
|
|
79
|
-
const model = (await prompt("Ollama model (e.g. llama3, glm-5:cloud): ")).trim();
|
|
80
|
-
if (!model)
|
|
78
|
+
const model = (await prompt("Ollama model (e.g. llama3, glm-5:cloud, gemma3:4b): ")).trim();
|
|
79
|
+
if (!model)
|
|
81
80
|
throw new Error("Model cannot be empty");
|
|
82
|
-
}
|
|
83
81
|
const host = (await prompt("Ollama host [http://localhost:11434]: ")).trim() ||
|
|
84
82
|
"http://localhost:11434";
|
|
83
|
+
return { model, host };
|
|
84
|
+
}
|
|
85
|
+
if (provider === "groq") {
|
|
86
|
+
const key = (await promptHidden("Groq API key: ")).trim();
|
|
87
|
+
if (!key)
|
|
88
|
+
throw new Error("API key cannot be empty");
|
|
89
|
+
const err = process.stderr;
|
|
90
|
+
err.write(chalk.bold("Select Groq model:\n"));
|
|
91
|
+
err.write(" 1) llama3-70b-8192\n");
|
|
92
|
+
err.write(" 2) mixtral-8x7b\n");
|
|
93
|
+
err.write(" 3) deepseek-r1-distill-llama-70b\n");
|
|
94
|
+
const choice = (await prompt("> ")).trim();
|
|
95
|
+
const modelMap = {
|
|
96
|
+
"1": "llama3-70b-8192",
|
|
97
|
+
"2": "mixtral-8x7b",
|
|
98
|
+
"3": "deepseek-r1-distill-llama-70b",
|
|
99
|
+
};
|
|
100
|
+
const model = modelMap[choice];
|
|
101
|
+
if (!model)
|
|
102
|
+
throw new Error("Invalid model selection");
|
|
85
103
|
return {
|
|
104
|
+
api_key: key,
|
|
86
105
|
model,
|
|
87
|
-
host,
|
|
88
106
|
};
|
|
89
107
|
}
|
|
90
108
|
if (provider === "openrouter") {
|
|
91
109
|
const key = (await promptHidden("OpenRouter API key: ")).trim();
|
|
92
|
-
if (!key)
|
|
110
|
+
if (!key)
|
|
93
111
|
throw new Error("API key cannot be empty");
|
|
94
|
-
}
|
|
95
112
|
const err = process.stderr;
|
|
96
113
|
err.write(chalk.bold("Select OpenRouter model:\n"));
|
|
97
114
|
err.write(" 1) openai/gpt-4o (balanced)\n");
|
|
@@ -112,9 +129,8 @@ async function promptProviderConfig(provider) {
|
|
|
112
129
|
}
|
|
113
130
|
else {
|
|
114
131
|
model = modelMap[choice];
|
|
115
|
-
if (!model)
|
|
132
|
+
if (!model)
|
|
116
133
|
throw new Error("Invalid model selection");
|
|
117
|
-
}
|
|
118
134
|
}
|
|
119
135
|
if (!model || !model.trim()) {
|
|
120
136
|
throw new Error("Model cannot be empty");
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { LLMProvider } from "./base.js";
|
|
2
|
+
type GroqConfig = {
|
|
3
|
+
api_key?: string;
|
|
4
|
+
model?: string;
|
|
5
|
+
};
|
|
6
|
+
export declare class GroqProvider implements LLMProvider {
|
|
7
|
+
name: string;
|
|
8
|
+
private apiKey;
|
|
9
|
+
private model;
|
|
10
|
+
private client;
|
|
11
|
+
constructor(config?: GroqConfig);
|
|
12
|
+
validateConfig(): void;
|
|
13
|
+
private getClient;
|
|
14
|
+
generate(prompt: string): Promise<string>;
|
|
15
|
+
doctor(): Promise<string[]>;
|
|
16
|
+
}
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { LLMProviderError } from "./base.js";
|
|
2
|
+
export class GroqProvider {
|
|
3
|
+
name = "groq";
|
|
4
|
+
apiKey;
|
|
5
|
+
model;
|
|
6
|
+
client = null;
|
|
7
|
+
constructor(config = {}) {
|
|
8
|
+
this.apiKey = config.api_key ?? "";
|
|
9
|
+
this.model = config.model;
|
|
10
|
+
this.validateConfig();
|
|
11
|
+
}
|
|
12
|
+
validateConfig() {
|
|
13
|
+
if (!this.apiKey || !this.apiKey.trim()) {
|
|
14
|
+
throw new LLMProviderError("Groq provider requires an API key.\n" +
|
|
15
|
+
"Run `explainthisrepo init` or set providers.groq.api_key.");
|
|
16
|
+
}
|
|
17
|
+
if (!this.model || !String(this.model).trim()) {
|
|
18
|
+
throw new LLMProviderError("Groq provider requires a model.\n" +
|
|
19
|
+
"Set providers.groq.model (e.g. llama3-70b-8192, mixtral-8x7b, deepseek-r1-distill-llama-70b).");
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
getClient() {
|
|
23
|
+
if (this.client) {
|
|
24
|
+
return this.client;
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
const Groq = require("groq");
|
|
28
|
+
this.client = new Groq({ apiKey: this.apiKey });
|
|
29
|
+
return this.client;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
throw new LLMProviderError("Groq support is not installed.\n" +
|
|
33
|
+
"Install it with:\n" +
|
|
34
|
+
" npm install groq");
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
async generate(prompt) {
|
|
38
|
+
const client = this.getClient();
|
|
39
|
+
let response;
|
|
40
|
+
try {
|
|
41
|
+
response = await client.chat.completions.create({
|
|
42
|
+
model: this.model,
|
|
43
|
+
messages: [
|
|
44
|
+
{ role: "user", content: prompt }
|
|
45
|
+
]
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
const message = err?.message ? String(err.message) : String(err);
|
|
50
|
+
throw new LLMProviderError(`Groq request failed: ${message}`);
|
|
51
|
+
}
|
|
52
|
+
let text = null;
|
|
53
|
+
try {
|
|
54
|
+
text = response?.choices?.[0]?.message?.content ?? null;
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
text = null;
|
|
58
|
+
}
|
|
59
|
+
if (!text || !text.trim()) {
|
|
60
|
+
throw new LLMProviderError("Groq returned no text");
|
|
61
|
+
}
|
|
62
|
+
return text.trim();
|
|
63
|
+
}
|
|
64
|
+
async doctor() {
|
|
65
|
+
return [
|
|
66
|
+
`GROQ_API_KEY set: ${Boolean(this.apiKey)}`,
|
|
67
|
+
`model: ${this.model}`,
|
|
68
|
+
];
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { LLMProvider, LLMProviderError } from "./base.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { LLMProviderError } from "./base.js";
|
package/package.json
CHANGED
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "explainthisrepo",
|
|
3
|
-
"version": "0.9.
|
|
4
|
-
"description": "The fastest way to understand any codebase in plain English. Not blind AI summarization",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"author": "Caleb Wodi <calebwodi33@gmail.com>",
|
|
8
|
-
"homepage": "https://explainthisrepo.com",
|
|
9
|
-
"repository": {
|
|
10
|
-
"type": "git",
|
|
11
|
-
"url": "git+https://github.com/calchiwo/ExplainThisRepo.git",
|
|
12
|
-
"directory": "node_version"
|
|
13
|
-
},
|
|
14
|
-
"bugs": {
|
|
15
|
-
"url": "https://github.com/calchiwo/ExplainThisRepo/issues"
|
|
16
|
-
},
|
|
17
|
-
"keywords": [
|
|
18
|
-
"github",
|
|
19
|
-
"cli",
|
|
20
|
-
"explain",
|
|
21
|
-
"repository",
|
|
22
|
-
"ai",
|
|
23
|
-
"repo-analysis",
|
|
24
|
-
"code-explanater",
|
|
25
|
-
"documentation",
|
|
26
|
-
"developer-productivity",
|
|
27
|
-
"developer-tools"
|
|
28
|
-
],
|
|
29
|
-
"bin": {
|
|
30
|
-
"explainthisrepo": "dist/cli.js",
|
|
31
|
-
"explain-this-repo": "dist/cli.js",
|
|
32
|
-
"etr": "dist/cli.js"
|
|
33
|
-
},
|
|
34
|
-
"files": [
|
|
35
|
-
"dist",
|
|
36
|
-
"README.md",
|
|
37
|
-
"LICENSE"
|
|
38
|
-
],
|
|
39
|
-
"scripts": {
|
|
40
|
-
"build": "tsc",
|
|
41
|
-
"start": "node dist/cli.js",
|
|
42
|
-
"sync-meta": "cp ../README.md README.md && cp ../LICENSE LICENSE",
|
|
43
|
-
"prepublishOnly": "npm run sync-meta && npm run build"
|
|
44
|
-
},
|
|
45
|
-
"engines": {
|
|
46
|
-
"node": ">=20"
|
|
47
|
-
},
|
|
48
|
-
"dependencies": {
|
|
49
|
-
"@google/generative-ai": "^0.24.1",
|
|
50
|
-
"@iarna/toml": "^2.2.5",
|
|
51
|
-
"axios": "^1.13.2",
|
|
52
|
-
"commander": "^14.0.3",
|
|
53
|
-
"dotenv": "^17.2.3",
|
|
54
|
-
"openai": "^4.0.0",
|
|
55
|
-
"ora": "^9.3.0",
|
|
56
|
-
"toml": "^3.0.0"
|
|
57
|
-
},
|
|
58
|
-
"devDependencies": {
|
|
59
|
-
"@types/node": "^22.0.0",
|
|
60
|
-
"typescript": "^5.6.0"
|
|
61
|
-
}
|
|
62
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "explainthisrepo",
|
|
3
|
+
"version": "0.9.6",
|
|
4
|
+
"description": "The fastest way to understand any codebase in plain English. Not blind AI summarization",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"author": "Caleb Wodi <calebwodi33@gmail.com>",
|
|
8
|
+
"homepage": "https://explainthisrepo.com",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/calchiwo/ExplainThisRepo.git",
|
|
12
|
+
"directory": "node_version"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/calchiwo/ExplainThisRepo/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"github",
|
|
19
|
+
"cli",
|
|
20
|
+
"explain",
|
|
21
|
+
"repository",
|
|
22
|
+
"ai",
|
|
23
|
+
"repo-analysis",
|
|
24
|
+
"code-explanater",
|
|
25
|
+
"documentation",
|
|
26
|
+
"developer-productivity",
|
|
27
|
+
"developer-tools"
|
|
28
|
+
],
|
|
29
|
+
"bin": {
|
|
30
|
+
"explainthisrepo": "dist/cli.js",
|
|
31
|
+
"explain-this-repo": "dist/cli.js",
|
|
32
|
+
"etr": "dist/cli.js"
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"dist",
|
|
36
|
+
"README.md",
|
|
37
|
+
"LICENSE"
|
|
38
|
+
],
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsc",
|
|
41
|
+
"start": "node dist/cli.js",
|
|
42
|
+
"sync-meta": "cp ../README.md README.md && cp ../LICENSE LICENSE",
|
|
43
|
+
"prepublishOnly": "npm run sync-meta && npm run build"
|
|
44
|
+
},
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=20"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"@google/generative-ai": "^0.24.1",
|
|
50
|
+
"@iarna/toml": "^2.2.5",
|
|
51
|
+
"axios": "^1.13.2",
|
|
52
|
+
"commander": "^14.0.3",
|
|
53
|
+
"dotenv": "^17.2.3",
|
|
54
|
+
"openai": "^4.0.0",
|
|
55
|
+
"ora": "^9.3.0",
|
|
56
|
+
"toml": "^3.0.0"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@types/node": "^22.0.0",
|
|
60
|
+
"typescript": "^5.6.0"
|
|
61
|
+
}
|
|
62
|
+
}
|