@openeryc/pi-coding-agent 0.75.46 → 0.75.47

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.
@@ -3810,6 +3810,14 @@ export class InteractiveMode {
3810
3810
  authType: "api_key",
3811
3811
  });
3812
3812
  }
3813
+ // Add synthetic entry for OpenAI-compatible custom endpoints (always available)
3814
+ if (authType !== "oauth") {
3815
+ options.push({
3816
+ id: "__openai_compatible__",
3817
+ name: "OpenAI Compatible",
3818
+ authType: "api_key",
3819
+ });
3820
+ }
3813
3821
  const filteredOptions = authType ? options.filter((option) => option.authType === authType) : options;
3814
3822
  return filteredOptions.sort((a, b) => a.name.localeCompare(b.name));
3815
3823
  }
@@ -3821,9 +3829,13 @@ export class InteractiveMode {
3821
3829
  if (!credential) {
3822
3830
  continue;
3823
3831
  }
3832
+ // For OpenAI-compatible providers, show the base URL as the display name
3833
+ const name = credential.type === "openai_compatible"
3834
+ ? `OpenAI Compatible (${credential.baseUrl})`
3835
+ : this.session.modelRegistry.getProviderDisplayName(providerId);
3824
3836
  options.push({
3825
3837
  id: providerId,
3826
- name: this.session.modelRegistry.getProviderDisplayName(providerId),
3838
+ name,
3827
3839
  authType: credential.type,
3828
3840
  });
3829
3841
  }
@@ -3860,6 +3872,9 @@ export class InteractiveMode {
3860
3872
  if (providerOption.authType === "oauth") {
3861
3873
  await this.showLoginDialog(providerOption.id, providerOption.name);
3862
3874
  }
3875
+ else if (providerOption.id === "__openai_compatible__") {
3876
+ await this.showOpenAICompatibleLoginDialog();
3877
+ }
3863
3878
  else if (providerOption.id === BEDROCK_PROVIDER_ID) {
3864
3879
  this.showBedrockSetupDialog(providerOption.id, providerOption.name);
3865
3880
  }
@@ -4010,6 +4025,66 @@ export class InteractiveMode {
4010
4025
  }
4011
4026
  }
4012
4027
  }
4028
+ async showOpenAICompatibleLoginDialog() {
4029
+ const previousModel = this.session.model;
4030
+ const providerId = `openai-compatible-${crypto.randomUUID().slice(0, 8)}`;
4031
+ const providerName = "OpenAI Compatible";
4032
+ const dialog = new LoginDialogComponent(this.ui, providerId, (_success, _message) => {
4033
+ // Completion handled below
4034
+ }, providerName, "Configure OpenAI Compatible Provider");
4035
+ this.editorContainer.clear();
4036
+ this.editorContainer.addChild(dialog);
4037
+ this.ui.setFocus(dialog);
4038
+ this.ui.requestRender();
4039
+ const restoreEditor = () => {
4040
+ this.editorContainer.clear();
4041
+ this.editorContainer.addChild(this.editor);
4042
+ this.ui.setFocus(this.editor);
4043
+ this.ui.requestRender();
4044
+ };
4045
+ try {
4046
+ const baseUrl = (await dialog.showPrompt("Enter base URL:", "http://localhost:11434/v1")).trim();
4047
+ if (!baseUrl) {
4048
+ throw new Error("Base URL cannot be empty.");
4049
+ }
4050
+ const apiKey = (await dialog.showPrompt("Enter API key (or leave blank for local endpoints):")).trim();
4051
+ const modelNames = (await dialog.showPrompt("Enter model name(s) (comma-separated):", "llama3.1")).trim();
4052
+ if (!modelNames) {
4053
+ throw new Error("At least one model name is required.");
4054
+ }
4055
+ const models = modelNames
4056
+ .split(",")
4057
+ .map((s) => s.trim())
4058
+ .filter((s) => s.length > 0)
4059
+ .map((id) => ({
4060
+ id,
4061
+ name: id,
4062
+ }));
4063
+ const effectiveApiKey = apiKey || "not-needed";
4064
+ // Immediately register the provider so models are available
4065
+ this.session.modelRegistry.configureOpenAICompatibleProvider(providerId, {
4066
+ baseUrl,
4067
+ apiKey: effectiveApiKey,
4068
+ models,
4069
+ });
4070
+ // Persist to auth.json so it survives restarts
4071
+ this.session.modelRegistry.authStorage.set(providerId, {
4072
+ type: "openai_compatible",
4073
+ key: effectiveApiKey,
4074
+ baseUrl,
4075
+ models,
4076
+ });
4077
+ restoreEditor();
4078
+ await this.completeProviderAuthentication(providerId, `${baseUrl}`, "api_key", previousModel);
4079
+ }
4080
+ catch (error) {
4081
+ restoreEditor();
4082
+ const errorMsg = error instanceof Error ? error.message : String(error);
4083
+ if (errorMsg !== "Login cancelled") {
4084
+ this.showError(`Failed to configure OpenAI Compatible provider: ${errorMsg}`);
4085
+ }
4086
+ }
4087
+ }
4013
4088
  showOAuthLoginSelect(dialog, prompt) {
4014
4089
  return new Promise((resolve) => {
4015
4090
  const restoreDialog = () => {