Skip to content

Commit 11c2660

Browse files
keeping in mind for provider base url
1 parent 3c56036 commit 11c2660

9 files changed

Lines changed: 139 additions & 16 deletions

File tree

.github/workflows/action-test.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ jobs:
161161
github_token: ${{ secrets.GITHUB_TOKEN }}
162162
llm_provider: groq
163163
llm_api_key: ${{ secrets.GROQ_API_KEY }}
164+
llm_provider_url: https://api.groq.com/openai/v1/models
164165
reviewer_models: ${{ steps.model_config.outputs.reviewer_models }}
165166
judge_model: ${{ steps.model_config.outputs.judge_model }}
166167
max_consensus_rounds: "3"

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,15 @@ Go to your repository:
3333
- **Settings****Secrets and variables****Actions**
3434
- Add a provider-specific secret, e.g. `GROQ_API_KEY`
3535

36-
### 3. Use the Action
36+
### 3. Optional base URL for Groq
37+
38+
If you are using Groq OpenAI-compatible models, set `llm_provider_url` to the Groq OpenAI endpoint:
39+
40+
```yaml
41+
llm_provider_url: https://api.groq.com/openai/v1/models
42+
```
43+
44+
### 4. Use the Action
3745
3846
Create `.github/workflows/ai-review.yml`:
3947

@@ -61,6 +69,7 @@ jobs:
6169
github_token: ${{ secrets.GITHUB_TOKEN }}
6270
llm_provider: groq
6371
llm_api_key: ${{ secrets.GROQ_API_KEY }}
72+
llm_provider_url: https://api.groq.com/openai/v1/models
6473
# Optional: customize model configuration
6574
# reviewer_models: "gemini-2.5-flash,gemini-2.5-flash-lite,gemini-2.5-pro"
6675
# judge_model: "gemini-2.5-pro"
@@ -80,6 +89,7 @@ with:
8089
github_token: ${{ secrets.GITHUB_TOKEN }}
8190
llm_provider: groq
8291
llm_api_key: ${{ secrets.GROQ_API_KEY }}
92+
llm_provider_url: https://api.groq.com/openai/v1/models
8393
8494
# Optional: Model Configuration
8595
reviewer_models: "gemini-2.5-flash,gemini-2.5-flash-lite,gemini-2.5-pro" # 3 models

action.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ inputs:
1414
llm_api_key:
1515
description: "API key for the chosen LLM provider. Use a provider-specific API key such as GROQ_API_KEY for groq."
1616
required: false
17+
llm_provider_url:
18+
description: "Optional base URL for the chosen LLM provider. For Groq, use https://api.groq.com/openai/v1/models if needed."
19+
required: false
1720
reviewer_models:
1821
description: "Comma-separated list of 3 review models. Use provider-specific model IDs such as llama-3.1-8b-instant or openai/gpt-oss-20b."
1922
required: false

dist/index.js

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -662,10 +662,12 @@ async function main() {
662662
logger.step(1, "Parsing inputs from action.yml");
663663
const llmProviderInput = core.getInput("llm_provider") || "groq";
664664
const llmApiKeyInput = core.getInput("llm_api_key");
665+
const llmProviderUrlInput = core.getInput("llm_provider_url");
665666
const config = {
666667
githubToken: core.getInput("github_token"),
667668
llmProvider: llmProviderInput,
668669
llmApiKey: llmApiKeyInput,
670+
llmProviderUrl: llmProviderUrlInput || undefined,
669671
reviewerModels: (core.getInput("reviewer_models") || DEFAULT_REVIEWER_MODELS.join(","))
670672
.split(",")
671673
.map((m) => m.trim()),
@@ -685,6 +687,9 @@ async function main() {
685687
}
686688
logger.success("✓ Inputs validated");
687689
logger.info(` - LLM Provider: ${config.llmProvider}`);
690+
if (config.llmProviderUrl) {
691+
logger.info(` - LLM Provider URL: ${config.llmProviderUrl}`);
692+
}
688693
logger.info(` - Reviewer Models: ${config.reviewerModels.join(", ")}`);
689694
logger.info(` - Judge Model: ${config.judgeModel}`);
690695
logger.info(` - Max Consensus Rounds: ${config.maxConsensusRounds}`);
@@ -804,6 +809,7 @@ async function main() {
804809
maxConsensusRounds: config.maxConsensusRounds,
805810
debug: config.debug,
806811
provider: config.llmProvider,
812+
providerUrl: config.llmProviderUrl,
807813
});
808814
const reviewResult = await orchestrator.runConsensusReview(llmContext);
809815
logger.success("✓ Consensus review complete");
@@ -964,7 +970,7 @@ class LLMClient {
964970
this.baseUrl =
965971
options.baseUrl ||
966972
(this.provider === "groq"
967-
? "https://api.groq.com/v1/models"
973+
? "https://api.groq.com/openai/v1/models"
968974
: "https://generativelanguage.googleapis.com/v1beta/models");
969975
}
970976
/**
@@ -1418,12 +1424,49 @@ RESPOND ONLY WITH THE JSON OBJECT. NO OTHER TEXT.`;
14181424
return this.availableGenerateContentModels;
14191425
}
14201426
if (this.provider === "groq") {
1421-
const availableModels = new Set([
1422-
...FALLBACK_MODELS.groq.reviewer,
1423-
...FALLBACK_MODELS.groq.judge,
1424-
]);
1425-
this.availableGenerateContentModels = availableModels;
1426-
return availableModels;
1427+
const availableModels = new Set();
1428+
const url = new URL(this.baseUrl);
1429+
try {
1430+
const response = await (0, node_fetch_1.default)(url.toString(), {
1431+
method: "GET",
1432+
headers: {
1433+
"Content-Type": "application/json",
1434+
Authorization: `Bearer ${this.apiKey}`,
1435+
},
1436+
});
1437+
if (!response.ok) {
1438+
const errorData = await response.json().catch(() => ({}));
1439+
throw new LLMApiError(response.status, `Groq model list error: ${response.status} - ${errorData.error?.message || "Unknown error"}`);
1440+
}
1441+
const data = (await response.json());
1442+
const models = Array.isArray(data.data)
1443+
? data.data
1444+
: Array.isArray(data.models)
1445+
? data.models
1446+
: [];
1447+
for (const model of models) {
1448+
const modelName = this.normalizeModelName(String(model.id || model.name || model.model || ""));
1449+
if (modelName) {
1450+
availableModels.add(modelName);
1451+
}
1452+
}
1453+
if (availableModels.size === 0) {
1454+
this.logger.warn("Could not parse Groq model list response. Falling back to known Groq models.");
1455+
FALLBACK_MODELS.groq.reviewer.forEach((model) => availableModels.add(model));
1456+
FALLBACK_MODELS.groq.judge.forEach((model) => availableModels.add(model));
1457+
}
1458+
this.availableGenerateContentModels = availableModels;
1459+
return availableModels;
1460+
}
1461+
catch (error) {
1462+
this.logger.warn(`Could not fetch Groq model list from ${url.toString()}: ${error instanceof Error ? error.message : String(error)}`);
1463+
const fallbackModels = new Set([
1464+
...FALLBACK_MODELS.groq.reviewer,
1465+
...FALLBACK_MODELS.groq.judge,
1466+
]);
1467+
this.availableGenerateContentModels = fallbackModels;
1468+
return fallbackModels;
1469+
}
14271470
}
14281471
const availableModels = new Set();
14291472
let pageToken;
@@ -2041,6 +2084,7 @@ class ReviewOrchestrator {
20412084
this.llmClient = new llm_client_js_1.LLMClient(apiKey, {
20422085
debug: options.debug,
20432086
provider: options.provider,
2087+
baseUrl: options.providerUrl,
20442088
});
20452089
this.logger = new logger_js_1.Logger(options.debug);
20462090
this.reviewerModels = options.reviewerModels;

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,13 @@ async function main() {
6666

6767
const llmProviderInput = core.getInput("llm_provider") || "groq";
6868
const llmApiKeyInput = core.getInput("llm_api_key");
69+
const llmProviderUrlInput = core.getInput("llm_provider_url");
6970

7071
const config: ActionConfig = {
7172
githubToken: core.getInput("github_token"),
7273
llmProvider: llmProviderInput as ActionConfig["llmProvider"],
7374
llmApiKey: llmApiKeyInput,
75+
llmProviderUrl: llmProviderUrlInput || undefined,
7476
reviewerModels: (
7577
core.getInput("reviewer_models") || DEFAULT_REVIEWER_MODELS.join(",")
7678
)
@@ -99,6 +101,9 @@ async function main() {
99101

100102
logger.success("✓ Inputs validated");
101103
logger.info(` - LLM Provider: ${config.llmProvider}`);
104+
if (config.llmProviderUrl) {
105+
logger.info(` - LLM Provider URL: ${config.llmProviderUrl}`);
106+
}
102107
logger.info(` - Reviewer Models: ${config.reviewerModels.join(", ")}`);
103108
logger.info(` - Judge Model: ${config.judgeModel}`);
104109
logger.info(` - Max Consensus Rounds: ${config.maxConsensusRounds}`);
@@ -275,6 +280,7 @@ async function main() {
275280
maxConsensusRounds: config.maxConsensusRounds,
276281
debug: config.debug,
277282
provider: config.llmProvider,
283+
providerUrl: config.llmProviderUrl,
278284
});
279285

280286
const reviewResult = await orchestrator.runConsensusReview(llmContext);

src/llm/llm-client.ts

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ export class LLMClient {
143143
this.baseUrl =
144144
options.baseUrl ||
145145
(this.provider === "groq"
146-
? "https://api.groq.com/v1/models"
146+
? "https://api.groq.com/openai/v1/models"
147147
: "https://generativelanguage.googleapis.com/v1beta/models");
148148
}
149149

@@ -788,12 +788,68 @@ RESPOND ONLY WITH THE JSON OBJECT. NO OTHER TEXT.`;
788788
}
789789

790790
if (this.provider === "groq") {
791-
const availableModels = new Set<string>([
792-
...FALLBACK_MODELS.groq.reviewer,
793-
...FALLBACK_MODELS.groq.judge,
794-
]);
795-
this.availableGenerateContentModels = availableModels;
796-
return availableModels;
791+
const availableModels = new Set<string>();
792+
const url = new URL(this.baseUrl);
793+
794+
try {
795+
const response = await fetch(url.toString(), {
796+
method: "GET",
797+
headers: {
798+
"Content-Type": "application/json",
799+
Authorization: `Bearer ${this.apiKey}`,
800+
},
801+
});
802+
803+
if (!response.ok) {
804+
const errorData = await response.json().catch(() => ({}));
805+
throw new LLMApiError(
806+
response.status,
807+
`Groq model list error: ${response.status} - ${(errorData as any).error?.message || "Unknown error"}`
808+
);
809+
}
810+
811+
const data = (await response.json()) as Record<string, unknown>;
812+
813+
const models = Array.isArray(data.data)
814+
? (data.data as Array<Record<string, unknown>>)
815+
: Array.isArray(data.models)
816+
? (data.models as Array<Record<string, unknown>>)
817+
: [];
818+
819+
for (const model of models) {
820+
const modelName = this.normalizeModelName(
821+
String(model.id || model.name || model.model || "")
822+
);
823+
if (modelName) {
824+
availableModels.add(modelName);
825+
}
826+
}
827+
828+
if (availableModels.size === 0) {
829+
this.logger.warn(
830+
"Could not parse Groq model list response. Falling back to known Groq models."
831+
);
832+
FALLBACK_MODELS.groq.reviewer.forEach((model) =>
833+
availableModels.add(model)
834+
);
835+
FALLBACK_MODELS.groq.judge.forEach((model) => availableModels.add(model));
836+
}
837+
838+
this.availableGenerateContentModels = availableModels;
839+
return availableModels;
840+
} catch (error) {
841+
this.logger.warn(
842+
`Could not fetch Groq model list from ${url.toString()}: ${
843+
error instanceof Error ? error.message : String(error)
844+
}`
845+
);
846+
const fallbackModels = new Set<string>([
847+
...FALLBACK_MODELS.groq.reviewer,
848+
...FALLBACK_MODELS.groq.judge,
849+
]);
850+
this.availableGenerateContentModels = fallbackModels;
851+
return fallbackModels;
852+
}
797853
}
798854

799855
const availableModels = new Set<string>();

src/review/review-orchestrator.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ interface OrchestratorOptions {
2828
maxConsensusRounds: number;
2929
debug?: boolean;
3030
provider?: LLMProvider;
31+
providerUrl?: string;
3132
}
3233

3334
export class ReviewOrchestrator {
@@ -42,6 +43,7 @@ export class ReviewOrchestrator {
4243
this.llmClient = new LLMClient(apiKey, {
4344
debug: options.debug,
4445
provider: options.provider,
46+
baseUrl: options.providerUrl,
4547
});
4648
this.logger = new Logger(options.debug);
4749
this.reviewerModels = options.reviewerModels;

src/utils/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ export interface ActionConfig {
183183
githubToken: string;
184184
llmProvider: LLMProvider;
185185
llmApiKey: string;
186+
llmProviderUrl?: string;
186187
reviewerModels: string[];
187188
judgeModel: string;
188189
maxConsensusRounds: number;

0 commit comments

Comments
 (0)