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 CHANGED
@@ -7,7 +7,8 @@ const PROVIDERS = {
7
7
  "2": "openai",
8
8
  "3": "ollama",
9
9
  "4": "anthropic",
10
- "5": "openrouter",
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) OpenRouter\n");
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.5",
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
+ }