@eminent337/aery 0.1.110 → 0.1.112
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/core/custom-openai-compatible.d.ts +13 -0
- package/dist/core/custom-openai-compatible.d.ts.map +1 -0
- package/dist/core/custom-openai-compatible.js +102 -0
- package/dist/core/custom-openai-compatible.js.map +1 -0
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +2 -2
- package/dist/core/model-registry.js.map +1 -1
- package/dist/migrations.d.ts +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +0 -1
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +80 -2
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/docs/models.md +2 -0
- package/docs/providers.md +12 -0
- package/package.json +3 -3
|
@@ -11,9 +11,10 @@ import { CombinedAutocompleteProvider, Container, fuzzyFilter, Loader, Markdown,
|
|
|
11
11
|
import { spawn, spawnSync } from "child_process";
|
|
12
12
|
import { collectCapabilitiesReport, formatCapabilitiesReport } from "../../cli/capabilities.js";
|
|
13
13
|
import { formatCurrentCoreExtensionsReport } from "../../cli/doctor.js";
|
|
14
|
-
import { APP_NAME, getAgentDir, getAuthPath, getDebugLogPath, getShareViewerUrl, getUpdateInstruction, VERSION, } from "../../config.js";
|
|
14
|
+
import { APP_NAME, getAgentDir, getAuthPath, getDebugLogPath, getModelsPath, getShareViewerUrl, getUpdateInstruction, VERSION, } from "../../config.js";
|
|
15
15
|
import { parseSkillBlock } from "../../core/agent-session.js";
|
|
16
16
|
import { SessionImportFileNotFoundError } from "../../core/agent-session-runtime.js";
|
|
17
|
+
import { CUSTOM_OPENAI_COMPATIBLE_PROVIDER_ID, saveCustomOpenAICompatibleProvider, } from "../../core/custom-openai-compatible.js";
|
|
17
18
|
import { FooterDataProvider } from "../../core/footer-data-provider.js";
|
|
18
19
|
import { KeybindingsManager } from "../../core/keybindings.js";
|
|
19
20
|
import { createCompactionSummaryMessage } from "../../core/messages.js";
|
|
@@ -117,6 +118,7 @@ const API_KEY_PROVIDER_NAMES = {
|
|
|
117
118
|
zai: "ZAI",
|
|
118
119
|
};
|
|
119
120
|
const API_KEY_LOGIN_PROVIDER_BLOCKLIST = new Set(["amazon-bedrock", "llama.cpp", "lmstudio", "ollama"]);
|
|
121
|
+
const CUSTOM_OPENAI_COMPATIBLE_PROVIDER_LABEL = "Custom OpenAI-compatible";
|
|
120
122
|
export function isApiKeyLoginProvider(providerId, oauthProviderIds, builtInProviderIds = new Set(getProviders())) {
|
|
121
123
|
if (API_KEY_PROVIDER_NAMES[providerId])
|
|
122
124
|
return true;
|
|
@@ -3687,6 +3689,13 @@ export class InteractiveMode {
|
|
|
3687
3689
|
authType: "api_key",
|
|
3688
3690
|
});
|
|
3689
3691
|
}
|
|
3692
|
+
if (!authType || authType === "api_key") {
|
|
3693
|
+
options.push({
|
|
3694
|
+
id: CUSTOM_OPENAI_COMPATIBLE_PROVIDER_ID,
|
|
3695
|
+
name: CUSTOM_OPENAI_COMPATIBLE_PROVIDER_LABEL,
|
|
3696
|
+
authType: "api_key",
|
|
3697
|
+
});
|
|
3698
|
+
}
|
|
3690
3699
|
const filteredOptions = authType ? options.filter((option) => option.authType === authType) : options;
|
|
3691
3700
|
return filteredOptions.sort((a, b) => a.name.localeCompare(b.name));
|
|
3692
3701
|
}
|
|
@@ -3737,7 +3746,10 @@ export class InteractiveMode {
|
|
|
3737
3746
|
if (!providerOption) {
|
|
3738
3747
|
return;
|
|
3739
3748
|
}
|
|
3740
|
-
if (providerOption.
|
|
3749
|
+
if (providerOption.id === CUSTOM_OPENAI_COMPATIBLE_PROVIDER_ID) {
|
|
3750
|
+
await this.showCustomOpenAICompatibleLoginDialog();
|
|
3751
|
+
}
|
|
3752
|
+
else if (providerOption.authType === "oauth") {
|
|
3741
3753
|
await this.showLoginDialog(providerOption.id, providerOption.name);
|
|
3742
3754
|
}
|
|
3743
3755
|
else {
|
|
@@ -3889,6 +3901,72 @@ export class InteractiveMode {
|
|
|
3889
3901
|
}
|
|
3890
3902
|
}
|
|
3891
3903
|
}
|
|
3904
|
+
async showCustomOpenAICompatibleLoginDialog() {
|
|
3905
|
+
const previousModel = this.session.model;
|
|
3906
|
+
const dialog = new LoginDialogComponent(this.ui, CUSTOM_OPENAI_COMPATIBLE_PROVIDER_ID, (_success, _message) => { }, `Configure ${CUSTOM_OPENAI_COMPATIBLE_PROVIDER_LABEL}`);
|
|
3907
|
+
this.editorContainer.clear();
|
|
3908
|
+
this.editorContainer.addChild(dialog);
|
|
3909
|
+
this.ui.setFocus(dialog);
|
|
3910
|
+
this.ui.requestRender();
|
|
3911
|
+
const restoreEditor = () => {
|
|
3912
|
+
this.editorContainer.clear();
|
|
3913
|
+
this.editorContainer.addChild(this.editor);
|
|
3914
|
+
this.ui.setFocus(this.editor);
|
|
3915
|
+
this.ui.requestRender();
|
|
3916
|
+
};
|
|
3917
|
+
try {
|
|
3918
|
+
const baseUrl = (await dialog.showPrompt("Enter base URL:", "https://api.example.com/v1")).trim();
|
|
3919
|
+
if (!baseUrl) {
|
|
3920
|
+
throw new Error("Base URL cannot be empty.");
|
|
3921
|
+
}
|
|
3922
|
+
const modelId = (await dialog.showPrompt("Enter model ID:", "gpt-4o-mini")).trim();
|
|
3923
|
+
if (!modelId) {
|
|
3924
|
+
throw new Error("Model ID cannot be empty.");
|
|
3925
|
+
}
|
|
3926
|
+
const apiKey = (await dialog.showPrompt("Enter API key:", "sk-...")).trim();
|
|
3927
|
+
if (!apiKey) {
|
|
3928
|
+
throw new Error("API key cannot be empty.");
|
|
3929
|
+
}
|
|
3930
|
+
const saved = saveCustomOpenAICompatibleProvider({
|
|
3931
|
+
modelsPath: getModelsPath(),
|
|
3932
|
+
baseUrl,
|
|
3933
|
+
modelId,
|
|
3934
|
+
});
|
|
3935
|
+
this.session.modelRegistry.authStorage.set(saved.providerId, { type: "api_key", key: apiKey });
|
|
3936
|
+
this.session.modelRegistry.refresh();
|
|
3937
|
+
restoreEditor();
|
|
3938
|
+
await this.updateAvailableProviderCount();
|
|
3939
|
+
this.footer.invalidate();
|
|
3940
|
+
this.updateEditorBorderColor();
|
|
3941
|
+
const model = this.session.modelRegistry.find(saved.providerId, saved.modelId);
|
|
3942
|
+
let selectedModel = false;
|
|
3943
|
+
if (model) {
|
|
3944
|
+
try {
|
|
3945
|
+
await this.session.setModel(model);
|
|
3946
|
+
selectedModel = true;
|
|
3947
|
+
}
|
|
3948
|
+
catch (error) {
|
|
3949
|
+
this.showError(`Saved ${saved.providerId}/${saved.modelId}, but selecting it failed: ${error instanceof Error ? error.message : String(error)}. Use /model to select it manually.`);
|
|
3950
|
+
}
|
|
3951
|
+
}
|
|
3952
|
+
if (selectedModel) {
|
|
3953
|
+
this.showStatus(`Configured ${saved.providerId}/${saved.modelId}. Provider saved to ${saved.modelsPath}; API key saved to ${getAuthPath()}.`);
|
|
3954
|
+
}
|
|
3955
|
+
else {
|
|
3956
|
+
this.showStatus(`Configured ${saved.providerId}/${saved.modelId}. Provider saved to ${saved.modelsPath}; API key saved to ${getAuthPath()}. Use /model to select it.`);
|
|
3957
|
+
}
|
|
3958
|
+
if (isUnknownModel(previousModel) && !selectedModel) {
|
|
3959
|
+
this.showWarning(`Custom provider ${saved.providerId} is available, but no model was selected automatically.`);
|
|
3960
|
+
}
|
|
3961
|
+
}
|
|
3962
|
+
catch (error) {
|
|
3963
|
+
restoreEditor();
|
|
3964
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
3965
|
+
if (errorMsg !== "Login cancelled") {
|
|
3966
|
+
this.showError(`Failed to configure ${CUSTOM_OPENAI_COMPATIBLE_PROVIDER_LABEL}: ${errorMsg}`);
|
|
3967
|
+
}
|
|
3968
|
+
}
|
|
3969
|
+
}
|
|
3892
3970
|
async showLoginDialog(providerId, providerName) {
|
|
3893
3971
|
const providerInfo = this.session.modelRegistry.authStorage
|
|
3894
3972
|
.getOAuthProviders()
|