diff --git a/open-sse/config/providers.js b/open-sse/config/providers.js
index e118bd1a..9e3ba5f7 100644
--- a/open-sse/config/providers.js
+++ b/open-sse/config/providers.js
@@ -357,6 +357,11 @@ export const PROVIDERS = {
format: "perplexity-web",
authType: "cookie"
},
+ azure: {
+ baseUrl: "",
+ format: "openai",
+ headers: {}
+ },
};
export const OLLAMA_LOCAL_DEFAULT_HOST = "http://localhost:11434";
diff --git a/open-sse/executors/azure.js b/open-sse/executors/azure.js
new file mode 100644
index 00000000..574cda22
--- /dev/null
+++ b/open-sse/executors/azure.js
@@ -0,0 +1,57 @@
+import { DefaultExecutor } from "./default.js";
+
+export class AzureExecutor extends DefaultExecutor {
+ constructor() {
+ super("azure");
+ }
+
+ buildUrl(model, stream, urlIndex = 0, credentials = null) {
+ const azureEndpoint = credentials?.providerSpecificData?.azureEndpoint
+ || process.env.AZURE_ENDPOINT
+ || "https://api.openai.com";
+
+ const apiVersion = credentials?.providerSpecificData?.apiVersion
+ || process.env.AZURE_API_VERSION
+ || "2024-10-01-preview";
+
+ const deployment = credentials?.providerSpecificData?.deployment
+ || model
+ || process.env.AZURE_DEPLOYMENT
+ || "gpt-4";
+
+ const endpoint = azureEndpoint.replace(/\/$/, "");
+ return `${endpoint}/openai/deployments/${deployment}/chat/completions?api-version=${apiVersion}`;
+ }
+
+ buildHeaders(credentials, stream = true) {
+ const headers = {
+ "Content-Type": "application/json",
+ ...this.config.headers
+ };
+
+ const apiKey = credentials?.apiKey
+ || credentials?.accessToken
+ || process.env.OPENAI_API_KEY;
+
+ if (apiKey) {
+ headers["api-key"] = apiKey;
+ }
+
+ const organization = credentials?.providerSpecificData?.organization
+ || process.env.AZURE_ORGANIZATION;
+
+ if (organization) {
+ headers["OpenAI-Organization"] = organization;
+ }
+
+ if (stream) {
+ headers["Accept"] = "text/event-stream";
+ }
+
+ return headers;
+ }
+
+ transformRequest(model, body, stream, credentials) {
+ return body;
+ }
+}
diff --git a/open-sse/executors/index.js b/open-sse/executors/index.js
index b7ca8a15..655fb3c0 100644
--- a/open-sse/executors/index.js
+++ b/open-sse/executors/index.js
@@ -1,4 +1,5 @@
import { AntigravityExecutor } from "./antigravity.js";
+import { AzureExecutor } from "./azure.js";
import { GeminiCLIExecutor } from "./gemini-cli.js";
import { GithubExecutor } from "./github.js";
import { IFlowExecutor } from "./iflow.js";
@@ -16,6 +17,7 @@ import { DefaultExecutor } from "./default.js";
const executors = {
antigravity: new AntigravityExecutor(),
+ azure: new AzureExecutor(),
"gemini-cli": new GeminiCLIExecutor(),
github: new GithubExecutor(),
iflow: new IFlowExecutor(),
@@ -47,6 +49,7 @@ export function hasSpecializedExecutor(provider) {
export { BaseExecutor } from "./base.js";
export { AntigravityExecutor } from "./antigravity.js";
+export { AzureExecutor } from "./azure.js";
export { GeminiCLIExecutor } from "./gemini-cli.js";
export { GithubExecutor } from "./github.js";
export { IFlowExecutor } from "./iflow.js";
diff --git a/src/app/(dashboard)/dashboard/providers/[id]/AddApiKeyModal.js b/src/app/(dashboard)/dashboard/providers/[id]/AddApiKeyModal.js
index 532167d0..91782acd 100644
--- a/src/app/(dashboard)/dashboard/providers/[id]/AddApiKeyModal.js
+++ b/src/app/(dashboard)/dashboard/providers/[id]/AddApiKeyModal.js
@@ -13,6 +13,8 @@ export default function AddApiKeyModal({ isOpen, provider, providerName, isCompa
? (provider === "grok-web" ? "sso=xxxxx... or just the raw value" : "eyJhbGciOi...")
: "";
+ const isAzure = provider === "azure";
+
const [formData, setFormData] = useState({
name: "",
apiKey: "",
@@ -20,6 +22,12 @@ export default function AddApiKeyModal({ isOpen, provider, providerName, isCompa
proxyPoolId: NONE_PROXY_POOL_VALUE,
ollamaHostUrl: "",
});
+ const [azureData, setAzureData] = useState({
+ azureEndpoint: "",
+ apiVersion: "2024-10-01-preview",
+ deployment: "",
+ organization: "",
+ });
const [validating, setValidating] = useState(false);
const [validationResult, setValidationResult] = useState(null);
const [saving, setSaving] = useState(false);
@@ -28,6 +36,14 @@ export default function AddApiKeyModal({ isOpen, provider, providerName, isCompa
if (isOllamaLocal && formData.ollamaHostUrl.trim()) {
return { baseUrl: formData.ollamaHostUrl.trim() };
}
+ if (isAzure) {
+ return {
+ azureEndpoint: azureData.azureEndpoint,
+ apiVersion: azureData.apiVersion,
+ deployment: azureData.deployment,
+ organization: azureData.organization,
+ };
+ }
return undefined;
};
@@ -164,6 +180,38 @@ export default function AddApiKeyModal({ isOpen, provider, providerName, isCompa
}
)}
+ {isAzure && (
+
+ )}
+
-