모델 등록 UI에 CP4D 사용자 이름+비밀번호 방식과 사용자 이름+API 키 방식을 별도 인증 유형으로 추가하고 선택에 따라 입력 라벨이 달라지도록 정리했습니다. LlmService, SettingsViewModel, AppSettings를 갱신해 cp4d_password와 cp4d_api_key 저장값을 공식 지원하고 기존 cp4d 값은 비밀번호 방식으로 계속 호환되게 유지했습니다. README와 DEVELOPMENT 문서를 2026-04-06 17:01 (KST) 기준으로 갱신했고 Release 빌드 경고 0 오류 0을 확인했습니다.
This commit is contained in:
@@ -1286,3 +1286,6 @@ MIT License
|
||||
- 업데이트: 2026-04-06 16:55 (KST)
|
||||
- IBM/CP4D 계열 연결 점검 결과, 일부 환경은 `/icp4d-api/v1/authorize` 호출 시 `username + password`가 아니라 `username + api_key` JSON 본문을 요구하는 것을 확인했다.
|
||||
- [Cp4dTokenService.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/Cp4dTokenService.cs) 에서 CP4D 토큰 요청을 먼저 `username + password`, 실패 시 `username + api_key`로 한 번 더 시도하도록 보강해, IBM 연결형 vLLM 환경 호환성을 높였다.
|
||||
- 업데이트: 2026-04-06 17:01 (KST)
|
||||
- 모델 등록 단계에서 IBM/CP4D 인증 방식을 명확히 고를 수 있게 분기했다. [ModelRegistrationDialog.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ModelRegistrationDialog.cs)에 `CP4D (사용자 이름 + 비밀번호)`와 `CP4D (사용자 이름 + API 키)` 항목을 따로 추가하고, 선택에 따라 마지막 입력 필드 라벨이 `비밀번호` 또는 `API 키`로 바뀌도록 정리했다.
|
||||
- [LlmService.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/LlmService.cs), [SettingsViewModel.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/ViewModels/SettingsViewModel.cs), [AppSettings.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Models/AppSettings.cs) 도 함께 갱신해 `cp4d_password`, `cp4d_api_key` 저장값을 공식 지원하고, 기존 `cp4d` 값은 비밀번호 방식으로 계속 호환되게 유지했다.
|
||||
|
||||
@@ -4980,3 +4980,5 @@ ow + toggle ?쒓컖 ?몄뼱濡??ㅼ떆 ?뺣젹?덈떎.
|
||||
- Document update: 2026-04-06 16:44 (KST) - Moved the separator for the AX Agent internal-settings `운영 모드` block from the bottom edge to the top edge in `ChatWindow.xaml` so the line reads as the start of the operation-mode section rather than trailing under the previous storage block.
|
||||
- Document update: 2026-04-06 16:49 (KST) - Removed the separator between the AX Agent internal-settings `서비스와 모델` block and the adjacent `등록 모델 관리` block in `ChatWindow.xaml` so the two model-management sections read as one continuous flow instead of two unrelated groups.
|
||||
- Document update: 2026-04-06 16:55 (KST) - Hardened `Cp4dTokenService.cs` for IBM/CP4D-style token endpoints that expect `username + api_key` instead of `username + password`. The service now tries `username/password` first and automatically retries with `username/api_key` before failing.
|
||||
- Document update: 2026-04-06 17:01 (KST) - Split the CP4D auth choice at model-registration time. `ModelRegistrationDialog.cs` now exposes `CP4D (사용자 이름 + 비밀번호)` and `CP4D (사용자 이름 + API 키)` as separate auth types and changes the final credential label accordingly.
|
||||
- Document update: 2026-04-06 17:01 (KST) - Updated `LlmService.cs`, `SettingsViewModel.cs`, and `AppSettings.cs` to formally support `cp4d_password` and `cp4d_api_key` while preserving legacy `cp4d` values as the password-based path for backward compatibility.
|
||||
|
||||
@@ -1383,7 +1383,7 @@ public class RegisteredModel
|
||||
|
||||
// ── CP4D (IBM Cloud Pak for Data) 인증 ──────────────────────────────
|
||||
|
||||
/// <summary>인증 방식. bearer (기본) | ibm_iam | cp4d</summary>
|
||||
/// <summary>인증 방식. bearer (기본) | ibm_iam | cp4d_password | cp4d_api_key</summary>
|
||||
[JsonPropertyName("authType")]
|
||||
public string AuthType { get; set; } = "bearer";
|
||||
|
||||
@@ -1395,7 +1395,7 @@ public class RegisteredModel
|
||||
[JsonPropertyName("cp4dUsername")]
|
||||
public string Cp4dUsername { get; set; } = "";
|
||||
|
||||
/// <summary>CP4D 비밀번호 또는 API 키 (EncryptionEnabled=true 시 암호화 저장)</summary>
|
||||
/// <summary>CP4D 비밀번호 또는 API 키 (인증 방식에 따라 사용, EncryptionEnabled=true 시 암호화 저장)</summary>
|
||||
[JsonPropertyName("cp4dPassword")]
|
||||
public string Cp4dPassword { get; set; } = "";
|
||||
}
|
||||
|
||||
@@ -344,7 +344,9 @@ public partial class LlmService : IDisposable
|
||||
|
||||
// CP4D 인증 방식인 경우
|
||||
if (registered != null &&
|
||||
registered.AuthType.Equals("cp4d", StringComparison.OrdinalIgnoreCase) &&
|
||||
(registered.AuthType.Equals("cp4d", StringComparison.OrdinalIgnoreCase) ||
|
||||
registered.AuthType.Equals("cp4d_password", StringComparison.OrdinalIgnoreCase) ||
|
||||
registered.AuthType.Equals("cp4d_api_key", StringComparison.OrdinalIgnoreCase)) &&
|
||||
!string.IsNullOrWhiteSpace(registered.Cp4dUrl))
|
||||
{
|
||||
var password = CryptoService.DecryptIfEnabled(registered.Cp4dPassword, llm.EncryptionEnabled);
|
||||
|
||||
@@ -2028,7 +2028,7 @@ public class RegisteredModelRow : INotifyPropertyChanged
|
||||
private string _cp4dUsername = "";
|
||||
private string _cp4dPassword = "";
|
||||
|
||||
/// <summary>인증 방식. bearer | ibm_iam | cp4d</summary>
|
||||
/// <summary>인증 방식. bearer | ibm_iam | cp4d_password | cp4d_api_key</summary>
|
||||
public string AuthType
|
||||
{
|
||||
get => _authType;
|
||||
@@ -2059,7 +2059,9 @@ public class RegisteredModelRow : INotifyPropertyChanged
|
||||
/// <summary>인증 방식 라벨</summary>
|
||||
public string AuthLabel => (_authType ?? "bearer").ToLowerInvariant() switch
|
||||
{
|
||||
"cp4d" => "CP4D",
|
||||
"cp4d" => "CP4D 비밀번호",
|
||||
"cp4d_password" => "CP4D 비밀번호",
|
||||
"cp4d_api_key" => "CP4D API 키",
|
||||
"ibm_iam" => "IBM IAM",
|
||||
_ => "Bearer",
|
||||
};
|
||||
|
||||
@@ -272,13 +272,17 @@ internal sealed class ModelRegistrationDialog : Window
|
||||
};
|
||||
var bearerItem = new ComboBoxItem { Content = "Bearer 토큰 (API 키)", Tag = "bearer" };
|
||||
var ibmIamItem = new ComboBoxItem { Content = "IBM IAM (토큰 교환)", Tag = "ibm_iam" };
|
||||
var cp4dItem = new ComboBoxItem { Content = "CP4D (IBM Cloud Pak for Data)", Tag = "cp4d" };
|
||||
var cp4dPasswordItem = new ComboBoxItem { Content = "CP4D (사용자 이름 + 비밀번호)", Tag = "cp4d_password" };
|
||||
var cp4dApiKeyItem = new ComboBoxItem { Content = "CP4D (사용자 이름 + API 키)", Tag = "cp4d_api_key" };
|
||||
_authTypeBox.Items.Add(bearerItem);
|
||||
_authTypeBox.Items.Add(ibmIamItem);
|
||||
_authTypeBox.Items.Add(cp4dItem);
|
||||
_authTypeBox.Items.Add(cp4dPasswordItem);
|
||||
_authTypeBox.Items.Add(cp4dApiKeyItem);
|
||||
_authTypeBox.SelectedItem = existingAuthType switch
|
||||
{
|
||||
"cp4d" => cp4dItem,
|
||||
"cp4d" => cp4dPasswordItem,
|
||||
"cp4d_password" => cp4dPasswordItem,
|
||||
"cp4d_api_key" => cp4dApiKeyItem,
|
||||
"ibm_iam" => ibmIamItem,
|
||||
_ => bearerItem,
|
||||
};
|
||||
@@ -302,8 +306,9 @@ internal sealed class ModelRegistrationDialog : Window
|
||||
apiKeyPanel.Children.Add(new Border { CornerRadius = new CornerRadius(8), ClipToBounds = true, Child = _apiKeyBox });
|
||||
stack.Children.Add(apiKeyPanel);
|
||||
|
||||
// ── CP4D 인증: URL + 사용자명 + 비밀번호 ────────────────────────────
|
||||
_cp4dPanel = new StackPanel { Visibility = existingAuthType == "cp4d" ? Visibility.Visible : Visibility.Collapsed };
|
||||
// ── CP4D 인증: URL + 사용자명 + 비밀번호/API 키 ───────────────────────
|
||||
var initialCp4dAuth = existingAuthType is "cp4d" or "cp4d_password" or "cp4d_api_key";
|
||||
_cp4dPanel = new StackPanel { Visibility = initialCp4dAuth ? Visibility.Visible : Visibility.Collapsed };
|
||||
|
||||
_cp4dPanel.Children.Add(new TextBlock
|
||||
{
|
||||
@@ -340,12 +345,13 @@ internal sealed class ModelRegistrationDialog : Window
|
||||
};
|
||||
_cp4dPanel.Children.Add(new Border { CornerRadius = new CornerRadius(8), ClipToBounds = true, Child = _cp4dUsernameBox });
|
||||
|
||||
_cp4dPanel.Children.Add(new TextBlock
|
||||
var cp4dSecretLabel = new TextBlock
|
||||
{
|
||||
Text = "비밀번호 / API 키",
|
||||
Text = "비밀번호",
|
||||
FontSize = 12, FontWeight = FontWeights.SemiBold,
|
||||
Foreground = primaryText, Margin = new Thickness(0, 10, 0, 6),
|
||||
});
|
||||
};
|
||||
_cp4dPanel.Children.Add(cp4dSecretLabel);
|
||||
_cp4dPasswordBox = new PasswordBox
|
||||
{
|
||||
Password = existingCp4dPassword,
|
||||
@@ -358,14 +364,19 @@ internal sealed class ModelRegistrationDialog : Window
|
||||
stack.Children.Add(_cp4dPanel);
|
||||
|
||||
// 인증 방식 전환 시 패널 표시/숨김
|
||||
_authTypeBox.SelectionChanged += (_, _) =>
|
||||
void UpdateAuthPanels()
|
||||
{
|
||||
var isCp4d = AuthType == "cp4d";
|
||||
var isCp4d = AuthType is "cp4d" or "cp4d_password" or "cp4d_api_key";
|
||||
_cp4dPanel.Visibility = isCp4d ? Visibility.Visible : Visibility.Collapsed;
|
||||
apiKeyPanel.Visibility = isCp4d ? Visibility.Collapsed : Visibility.Visible;
|
||||
cp4dSecretLabel.Text = AuthType == "cp4d_api_key" ? "API 키" : "비밀번호";
|
||||
}
|
||||
_authTypeBox.SelectionChanged += (_, _) =>
|
||||
{
|
||||
UpdateAuthPanels();
|
||||
};
|
||||
// 초기 상태 설정
|
||||
apiKeyPanel.Visibility = existingAuthType == "cp4d" ? Visibility.Collapsed : Visibility.Visible;
|
||||
UpdateAuthPanels();
|
||||
|
||||
// 보안 안내
|
||||
var securityNote = new StackPanel
|
||||
|
||||
Reference in New Issue
Block a user