mirror of
https://github.com/iflytek/skillhub.git
synced 2026-08-28 11:25:00 +00:00
* feat(ci): add AI-powered release notes generation - Add GitHub Models integration for automated release notes - Support bilingual (EN) release notes with highlights extraction - Fallback to conventional commit grouping when LLM unavailable - Trigger on tag push or manual workflow dispatch - Zero configuration: uses GitHub Models (gpt-4o-mini) by default * chore: pin action versions and update gitignore - Pin checkout and setup-deno to commit hashes matching project convention - Add .playwright-mcp/ and .mcp.json to gitignore
53 lines
1.3 KiB
TypeScript
53 lines
1.3 KiB
TypeScript
import { IssueLlmConfig } from "./issue-llm-types.ts";
|
|
|
|
const DEFAULT_TIMEOUT_MS = 30000;
|
|
const DEFAULT_MAX_ATTEMPTS = 2;
|
|
const DEFAULT_RETRY_BACKOFF_MS = 1500;
|
|
const DEFAULT_TEMPERATURE = 0.2;
|
|
|
|
export function readReleaseNotesLlmConfig(): IssueLlmConfig | null {
|
|
const baseUrl = normalizeUrl(
|
|
Deno.env.get("RELEASE_NOTES_LLM_BASE_URL") ||
|
|
Deno.env.get("ISSUE_TRIAGE_LLM_BASE_URL"),
|
|
);
|
|
const apiKey = (
|
|
Deno.env.get("RELEASE_NOTES_LLM_API_KEY") ||
|
|
Deno.env.get("ISSUE_TRIAGE_LLM_API_KEY")
|
|
)?.trim() ?? "";
|
|
const model = (
|
|
Deno.env.get("RELEASE_NOTES_LLM_MODEL") ||
|
|
Deno.env.get("ISSUE_TRIAGE_LLM_MODEL")
|
|
)?.trim() ?? "";
|
|
|
|
if (!baseUrl || !apiKey || !model) {
|
|
console.warn(
|
|
"LLM config missing, will use fallback mode (conventional commit grouping)",
|
|
);
|
|
return null;
|
|
}
|
|
|
|
return {
|
|
mode: "assist",
|
|
provider: "openai-compatible",
|
|
baseUrl,
|
|
apiKey,
|
|
model,
|
|
timeoutMs: DEFAULT_TIMEOUT_MS,
|
|
maxAttempts: DEFAULT_MAX_ATTEMPTS,
|
|
retryBackoffMs: DEFAULT_RETRY_BACKOFF_MS,
|
|
temperature: DEFAULT_TEMPERATURE,
|
|
maxComments: 0,
|
|
maxCommentChars: 0,
|
|
maxBodyChars: 0,
|
|
};
|
|
}
|
|
|
|
function normalizeUrl(value: string | undefined | null) {
|
|
const trimmed = value?.trim();
|
|
|
|
if (!trimmed) {
|
|
return "";
|
|
}
|
|
|
|
return trimmed.endsWith("/") ? trimmed.slice(0, -1) : trimmed;
|
|
}
|