Added multi-env support

This commit is contained in:
2026-01-17 17:09:47 -05:00
parent 2638e08453
commit e3c7cbba95
5 changed files with 475 additions and 126 deletions

View File

@@ -19,6 +19,8 @@ const DEFAULT_SETTINGS = {
activeApiKeyId: "",
apiConfigs: [],
activeApiConfigId: "",
envConfigs: [],
activeEnvConfigId: "",
apiBaseUrl: "https://api.openai.com/v1",
apiKeyHeader: "Authorization",
apiKeyPrefix: "Bearer ",
@@ -188,6 +190,58 @@ chrome.runtime.onInstalled.addListener(async () => {
}
}
const resolvedApiConfigs = updates.apiConfigs || stored.apiConfigs || [];
const resolvedActiveApiConfigId =
updates.activeApiConfigId ||
stored.activeApiConfigId ||
resolvedApiConfigs[0]?.id ||
"";
const hasEnvConfigs =
Array.isArray(stored.envConfigs) && stored.envConfigs.length > 0;
if (!hasEnvConfigs) {
const id = crypto?.randomUUID
? crypto.randomUUID()
: `env-${Date.now()}-${Math.random().toString(16).slice(2, 8)}`;
updates.envConfigs = [
{
id,
name: "Default",
apiConfigId: resolvedActiveApiConfigId,
systemPrompt: stored.systemPrompt || DEFAULT_SETTINGS.systemPrompt
}
];
updates.activeEnvConfigId = id;
} else {
const normalizedEnvs = stored.envConfigs.map((config) => ({
...config,
apiConfigId: config.apiConfigId || resolvedActiveApiConfigId,
systemPrompt: config.systemPrompt ?? ""
}));
const envNeedsUpdate = normalizedEnvs.some((config, index) => {
const original = stored.envConfigs[index];
return (
config.apiConfigId !== original.apiConfigId ||
(config.systemPrompt || "") !== (original.systemPrompt || "")
);
});
if (envNeedsUpdate) {
updates.envConfigs = normalizedEnvs;
}
const envActiveId = updates.activeEnvConfigId || stored.activeEnvConfigId;
if (envActiveId) {
const exists = stored.envConfigs.some(
(config) => config.id === envActiveId
);
if (!exists) {
updates.activeEnvConfigId = stored.envConfigs[0].id;
}
} else {
updates.activeEnvConfigId = stored.envConfigs[0].id;
}
}
if (Object.keys(updates).length) {
await chrome.storage.local.set(updates);
}
@@ -307,6 +361,10 @@ async function handleAnalysisRequest(port, payload, signal) {
safePost(port, { type: "ERROR", message: "Missing request template." });
return;
}
if (apiKeyHeader && !apiKey) {
safePost(port, { type: "ERROR", message: "Missing API key." });
return;
}
} else {
if (!apiBaseUrl) {
safePost(port, { type: "ERROR", message: "Missing API base URL." });
@@ -345,6 +403,10 @@ async function handleAnalysisRequest(port, payload, signal) {
apiKey,
apiUrl,
requestTemplate,
apiKeyHeader,
apiKeyPrefix,
apiBaseUrl,
model,
systemPrompt: systemPrompt || "",
userMessage,
signal,
@@ -511,6 +573,10 @@ async function streamCustomCompletion({
apiKey,
apiUrl,
requestTemplate,
apiKeyHeader,
apiKeyPrefix,
apiBaseUrl,
model,
systemPrompt,
userMessage,
signal,
@@ -519,16 +585,24 @@ async function streamCustomCompletion({
const replacements = {
PROMPT_GOES_HERE: userMessage,
SYSTEM_PROMPT_GOES_HERE: systemPrompt,
API_KEY_GOES_HERE: apiKey
API_KEY_GOES_HERE: apiKey,
MODEL_GOES_HERE: model || "",
API_BASE_URL_GOES_HERE: apiBaseUrl || ""
};
const resolvedUrl = replaceUrlTokens(apiUrl, replacements);
const body = buildTemplateBody(requestTemplate, replacements);
const headers = {
"Content-Type": "application/json"
};
const authHeader = buildAuthHeader(apiKeyHeader, apiKeyPrefix, apiKey);
if (authHeader) {
headers[authHeader.name] = authHeader.value;
}
const response = await fetch(resolvedUrl, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
headers,
body: JSON.stringify(body),
signal
});