BroV: single Mac target, chat brain = local claude CLI (stream-json, resume)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -89,9 +89,23 @@ final class AppState: ObservableObject {
|
||||
}
|
||||
|
||||
// In-chat provider + model — picked via the model selector in the prompt view
|
||||
@Published var chatProvider: ChatProvider = .anthropic {
|
||||
@Published var chatProvider: ChatProvider = .claudeCode {
|
||||
didSet { UserDefaults.standard.set(chatProvider.rawValue, forKey: "chatProvider") }
|
||||
}
|
||||
// Claude Code CLI chat (BroV): model alias ("" = CLI default), folder it runs in,
|
||||
// optional path to the binary, and the permission mode passed to `claude`.
|
||||
@Published var claudeCodeModel: String = "" {
|
||||
didSet { UserDefaults.standard.set(claudeCodeModel, forKey: "claudeCodeModel") }
|
||||
}
|
||||
@Published var chatWorkingDirectory: String = "~" {
|
||||
didSet { UserDefaults.standard.set(chatWorkingDirectory, forKey: "chatWorkingDirectory") }
|
||||
}
|
||||
@Published var claudeBinaryPath: String = "" {
|
||||
didSet { UserDefaults.standard.set(claudeBinaryPath, forKey: "claudeBinaryPath") }
|
||||
}
|
||||
@Published var claudePermissionMode: String = "default" {
|
||||
didSet { UserDefaults.standard.set(claudePermissionMode, forKey: "claudePermissionMode") }
|
||||
}
|
||||
@Published var googleChatModel: String = ChatProvider.google.defaultModel {
|
||||
didSet { UserDefaults.standard.set(googleChatModel, forKey: "googleChatModel") }
|
||||
}
|
||||
@@ -126,6 +140,10 @@ final class AppState: ObservableObject {
|
||||
func fetchModelsIfNeeded(for provider: ChatProvider) {
|
||||
guard !loadingProviderModels.contains(provider),
|
||||
fetchedProviderModels[provider] == nil else { return }
|
||||
if provider == .claudeCode {
|
||||
fetchedProviderModels[provider] = ClaudeCodeCLI.models
|
||||
return
|
||||
}
|
||||
// Local providers: fetch from server URL (no API key needed)
|
||||
if provider.isLocal {
|
||||
let baseURL = provider == .ollama ? ollamaServerURL : lmstudioServerURL
|
||||
@@ -170,6 +188,7 @@ final class AppState: ObservableObject {
|
||||
Task {
|
||||
let models: [(id: String, label: String)]
|
||||
switch provider {
|
||||
case .claudeCode: models = ClaudeCodeCLI.models
|
||||
case .anthropic: models = await ClaudeService.fetchModels(apiKey: apiKey)
|
||||
case .google: models = await ClaudeService.fetchGoogleModels(apiKey: apiKey)
|
||||
case .openai: models = await ClaudeService.fetchOpenAIModels(apiKey: apiKey)
|
||||
@@ -193,7 +212,7 @@ final class AppState: ObservableObject {
|
||||
if !models.contains(where: { $0.id == openAIChatModel }) {
|
||||
openAIChatModel = models.first(where: { $0.id.contains("mini") })?.id ?? models.first!.id
|
||||
}
|
||||
case .ollama, .lmstudio: break
|
||||
case .ollama, .lmstudio, .claudeCode: break
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -202,6 +221,7 @@ final class AppState: ObservableObject {
|
||||
/// The model currently active for chat (provider-aware).
|
||||
var activeChatModel: String {
|
||||
switch chatProvider {
|
||||
case .claudeCode: return claudeCodeModel
|
||||
case .anthropic: return claudeModel
|
||||
case .google: return googleChatModel
|
||||
case .openai: return openAIChatModel
|
||||
@@ -409,6 +429,10 @@ final class AppState: ObservableObject {
|
||||
if let v = ud.string(forKey: "claudeModel"),
|
||||
!v.trimmingCharacters(in: .whitespaces).isEmpty { claudeModel = v }
|
||||
if let v = ud.string(forKey: "chatProvider"), let p = ChatProvider(rawValue: v) { chatProvider = p }
|
||||
if let v = ud.string(forKey: "claudeCodeModel") { claudeCodeModel = v }
|
||||
if let v = ud.string(forKey: "chatWorkingDirectory"), !v.isEmpty { chatWorkingDirectory = v }
|
||||
if let v = ud.string(forKey: "claudeBinaryPath") { claudeBinaryPath = v }
|
||||
if let v = ud.string(forKey: "claudePermissionMode"), !v.isEmpty { claudePermissionMode = v }
|
||||
if let v = ud.string(forKey: "googleChatModel"), !v.isEmpty { googleChatModel = v }
|
||||
if let v = ud.string(forKey: "openAIChatModel"), !v.isEmpty { openAIChatModel = v }
|
||||
if let v = ud.string(forKey: "ollamaChatModel"), !v.isEmpty { ollamaChatModel = v }
|
||||
|
||||
Reference in New Issue
Block a user