|
|
|
@@ -1,7 +1,5 @@
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
import { renameSession, setSessionWorkspace, batchDeleteSessions, exportSession } from "@/api/hermes/sessions";
|
|
|
|
|
import type { AvailableModelGroup } from "@/api/hermes/system";
|
|
|
|
|
import { fetchCodingAgentsStatus, inferCodingAgentApiMode, normalizeCodingAgentApiMode, type ChatCodingAgentId, type CodingAgentApiMode, type CodingAgentId } from "@/api/coding-agents";
|
|
|
|
|
import { useChatStore, type Session } from "@/stores/hermes/chat";
|
|
|
|
|
import { useAppStore } from "@/stores/hermes/app";
|
|
|
|
|
import { useProfilesStore } from "@/stores/hermes/profiles";
|
|
|
|
@@ -16,8 +14,6 @@ import {
|
|
|
|
|
NSelect,
|
|
|
|
|
NTooltip,
|
|
|
|
|
NPopconfirm,
|
|
|
|
|
NRadioButton,
|
|
|
|
|
NRadioGroup,
|
|
|
|
|
useMessage,
|
|
|
|
|
type DropdownOption,
|
|
|
|
|
} from "naive-ui";
|
|
|
|
@@ -321,14 +317,9 @@ const headerTitle = computed(() =>
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const showNewChatModal = ref(false);
|
|
|
|
|
const newChatAgent = ref<"hermes" | ChatCodingAgentId>("hermes");
|
|
|
|
|
const newChatAgentMode = ref<"global" | "scoped">("scoped");
|
|
|
|
|
const newChatProfile = ref<string>("default");
|
|
|
|
|
const newChatProvider = ref<string>("");
|
|
|
|
|
const newChatModel = ref<string>("");
|
|
|
|
|
const newChatBaseUrl = ref<string>("");
|
|
|
|
|
const newChatApiKey = ref<string>("");
|
|
|
|
|
const newChatApiMode = ref<CodingAgentApiMode>("codex_responses");
|
|
|
|
|
const newChatWorkspace = ref("");
|
|
|
|
|
const newChatLoading = ref(false);
|
|
|
|
|
|
|
|
|
@@ -425,30 +416,6 @@ const hiddenDefaultWorkspaces = computed(() => {
|
|
|
|
|
return defaultWorkspaces.value.filter(ws => !visible.has(ws));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const CODING_AGENT_AUTH_PROVIDER_KEYS = new Set(["openai-codex", "copilot", "xai-oauth", "nous", "google-gemini-cli", "claude-oauth"]);
|
|
|
|
|
|
|
|
|
|
const showEkkoAgentEntry = import.meta.env.DEV;
|
|
|
|
|
const newChatAgentOptions = computed(() => {
|
|
|
|
|
const options = [
|
|
|
|
|
{ label: "Hermes", value: "hermes" },
|
|
|
|
|
{ label: "Claude Code", value: "claude-code" },
|
|
|
|
|
{ label: "Codex", value: "codex" },
|
|
|
|
|
];
|
|
|
|
|
if (showEkkoAgentEntry) options.push({ label: "Ekko Agent", value: "ekko-agent" });
|
|
|
|
|
return options;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const newChatApiModeOptions = computed(() => [
|
|
|
|
|
{ label: t("codingAgents.protocolOpenAiChat"), value: "chat_completions" },
|
|
|
|
|
{ label: t("codingAgents.protocolOpenAiResponses"), value: "codex_responses" },
|
|
|
|
|
{ label: t("codingAgents.protocolAnthropicMessages"), value: "anthropic_messages" },
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
const newChatAgentModeOptions = computed(() => [
|
|
|
|
|
{ label: t("codingAgents.launchModeGlobal"), value: "global" },
|
|
|
|
|
{ label: t("codingAgents.launchModeScoped"), value: "scoped" },
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
function getModelGroupsForProfile(profile: string) {
|
|
|
|
|
const profileModels = appStore.profileModelGroups.find(
|
|
|
|
|
(entry) => entry.profile === profile,
|
|
|
|
@@ -456,18 +423,8 @@ function getModelGroupsForProfile(profile: string) {
|
|
|
|
|
return profileModels?.groups || [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isCodingAgentAuthProvider(provider?: string) {
|
|
|
|
|
return CODING_AGENT_AUTH_PROVIDER_KEYS.has(String(provider || "").toLowerCase());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isNewChatProviderAllowed(group: AvailableModelGroup) {
|
|
|
|
|
const mode = newChatAgent.value === "ekko-agent" ? "scoped" : newChatAgentMode.value;
|
|
|
|
|
if (!(newChatAgent.value !== "hermes" && mode === "scoped")) return true;
|
|
|
|
|
return !isCodingAgentAuthProvider(group.provider);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getSelectableModelGroupsForProfile(profile: string) {
|
|
|
|
|
return getModelGroupsForProfile(profile).filter(isNewChatProviderAllowed);
|
|
|
|
|
return getModelGroupsForProfile(profile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getDefaultModelForProfile(profile: string) {
|
|
|
|
@@ -536,66 +493,28 @@ const selectedNewChatProviderGroup = computed(() =>
|
|
|
|
|
newChatModelGroups.value.find((item) => item.provider === newChatProvider.value),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const isNewChatCodingAgent = computed(() => newChatAgent.value !== "hermes");
|
|
|
|
|
const isNewChatExternalCodingAgent = computed(() => newChatAgent.value === "claude-code" || newChatAgent.value === "codex");
|
|
|
|
|
const effectiveNewChatAgentMode = computed(() =>
|
|
|
|
|
newChatAgent.value === "ekko-agent" ? "scoped" : newChatAgentMode.value,
|
|
|
|
|
);
|
|
|
|
|
const isNewChatGlobalCodingAgent = computed(() =>
|
|
|
|
|
isNewChatCodingAgent.value && effectiveNewChatAgentMode.value === "global",
|
|
|
|
|
);
|
|
|
|
|
const newChatUsesProviderModel = computed(() => !isNewChatGlobalCodingAgent.value);
|
|
|
|
|
const newChatNeedsBaseUrl = computed(() =>
|
|
|
|
|
isNewChatCodingAgent.value && effectiveNewChatAgentMode.value === "scoped" && !selectedNewChatProviderGroup.value?.base_url,
|
|
|
|
|
);
|
|
|
|
|
const newChatNeedsApiKey = computed(() =>
|
|
|
|
|
isNewChatCodingAgent.value && effectiveNewChatAgentMode.value === "scoped" && !selectedNewChatProviderGroup.value?.api_key,
|
|
|
|
|
);
|
|
|
|
|
const canConfirmNewChat = computed(() => {
|
|
|
|
|
if (!newChatProfile.value) return false;
|
|
|
|
|
if (!newChatUsesProviderModel.value) return true;
|
|
|
|
|
if (!newChatProvider.value || !newChatModel.value) return false;
|
|
|
|
|
if (!isNewChatCodingAgent.value) return true;
|
|
|
|
|
if (isNewChatExternalCodingAgent.value && !newChatApiMode.value) return false;
|
|
|
|
|
if (newChatNeedsBaseUrl.value && !newChatBaseUrl.value.trim()) return false;
|
|
|
|
|
if (newChatNeedsApiKey.value && !newChatApiKey.value.trim()) return false;
|
|
|
|
|
return true;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
function defaultNewChatApiMode(group?: AvailableModelGroup): CodingAgentApiMode {
|
|
|
|
|
const providerKey = String(group?.provider || newChatProvider.value || "").toLowerCase();
|
|
|
|
|
const baseUrl = String(group?.base_url || newChatBaseUrl.value || "").toLowerCase();
|
|
|
|
|
return normalizeCodingAgentApiMode(
|
|
|
|
|
group?.api_mode,
|
|
|
|
|
inferCodingAgentApiMode(providerKey, baseUrl),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function syncNewChatApiMode() {
|
|
|
|
|
newChatApiMode.value = defaultNewChatApiMode(selectedNewChatProviderGroup.value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function syncNewChatModelSelection() {
|
|
|
|
|
const defaults = getDefaultModelForProfile(newChatProfile.value);
|
|
|
|
|
newChatProvider.value = defaults.provider;
|
|
|
|
|
newChatModel.value = defaults.model;
|
|
|
|
|
newChatBaseUrl.value = "";
|
|
|
|
|
newChatApiKey.value = "";
|
|
|
|
|
syncNewChatApiMode();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function ensureNewChatProviderSelection() {
|
|
|
|
|
if (!newChatUsesProviderModel.value) return;
|
|
|
|
|
const currentGroup = selectedNewChatProviderGroup.value;
|
|
|
|
|
if (currentGroup && currentGroup.models.includes(newChatModel.value)) {
|
|
|
|
|
syncNewChatApiMode();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
syncNewChatModelSelection();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
watch(
|
|
|
|
|
() => [newChatAgent.value, newChatAgentMode.value, newChatProfile.value],
|
|
|
|
|
() => [newChatProfile.value],
|
|
|
|
|
() => {
|
|
|
|
|
ensureNewChatProviderSelection();
|
|
|
|
|
// Reload workspace data when profile changes
|
|
|
|
@@ -646,56 +565,16 @@ function handleNewChatProfileChange(value: string) {
|
|
|
|
|
function handleNewChatProviderChange(value: string) {
|
|
|
|
|
newChatProvider.value = value;
|
|
|
|
|
newChatModel.value = newChatModelOptions.value[0]?.value || "";
|
|
|
|
|
newChatBaseUrl.value = "";
|
|
|
|
|
newChatApiKey.value = "";
|
|
|
|
|
syncNewChatApiMode();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function confirmNewChat() {
|
|
|
|
|
if (isNewChatExternalCodingAgent.value) {
|
|
|
|
|
newChatLoading.value = true;
|
|
|
|
|
try {
|
|
|
|
|
const agentId = newChatAgent.value as CodingAgentId;
|
|
|
|
|
const status = await fetchCodingAgentsStatus();
|
|
|
|
|
const tool = status.tools.find((item) => item.id === agentId);
|
|
|
|
|
if (!tool?.installed) {
|
|
|
|
|
const fallbackName = agentId === "codex" ? "Codex" : "Claude Code";
|
|
|
|
|
message.warning(t("codingAgents.installRequired", { agent: tool?.name || fallbackName }));
|
|
|
|
|
showNewChatModal.value = false;
|
|
|
|
|
await router.push({ name: "hermes.codingAgents" });
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
} catch {
|
|
|
|
|
message.error(t("codingAgents.loadFailed"));
|
|
|
|
|
return;
|
|
|
|
|
} finally {
|
|
|
|
|
newChatLoading.value = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const group = selectedNewChatProviderGroup.value;
|
|
|
|
|
const source = newChatAgent.value === "hermes" ? "cli" : "coding_agent";
|
|
|
|
|
const codingAgentMode = effectiveNewChatAgentMode.value;
|
|
|
|
|
const isGlobalCodingAgent = source === "coding_agent" && codingAgentMode === "global";
|
|
|
|
|
const agent = newChatAgent.value === "codex"
|
|
|
|
|
? "codex"
|
|
|
|
|
: newChatAgent.value === "claude-code"
|
|
|
|
|
? "claude"
|
|
|
|
|
: newChatAgent.value === "ekko-agent"
|
|
|
|
|
? "ekko-agent"
|
|
|
|
|
: "hermes";
|
|
|
|
|
const session = chatStore.newChat({
|
|
|
|
|
profile: newChatProfile.value,
|
|
|
|
|
provider: isGlobalCodingAgent ? undefined : newChatProvider.value,
|
|
|
|
|
model: isGlobalCodingAgent ? undefined : newChatModel.value,
|
|
|
|
|
source,
|
|
|
|
|
agent,
|
|
|
|
|
codingAgentId: newChatAgent.value === "hermes" ? undefined : newChatAgent.value,
|
|
|
|
|
codingAgentMode: source === "coding_agent" ? codingAgentMode : undefined,
|
|
|
|
|
provider: newChatProvider.value,
|
|
|
|
|
model: newChatModel.value,
|
|
|
|
|
source: "cli",
|
|
|
|
|
agent: "hermes",
|
|
|
|
|
workspace: newChatWorkspace.value || null,
|
|
|
|
|
baseUrl: source === "coding_agent" && !isGlobalCodingAgent ? group?.base_url || newChatBaseUrl.value.trim() || undefined : undefined,
|
|
|
|
|
apiKey: source === "coding_agent" && !isGlobalCodingAgent ? group?.api_key || newChatApiKey.value.trim() || undefined : undefined,
|
|
|
|
|
apiMode: isNewChatExternalCodingAgent.value && !isGlobalCodingAgent ? newChatApiMode.value : undefined,
|
|
|
|
|
});
|
|
|
|
|
// Record workspace to recent list
|
|
|
|
|
if (newChatWorkspace.value && workspaceComposable) {
|
|
|
|
@@ -867,7 +746,7 @@ const contextMenuOptions = computed(() => {
|
|
|
|
|
|
|
|
|
|
options.push({ label: t("chat.setWorkspace"), key: "workspace" })
|
|
|
|
|
|
|
|
|
|
if (contextSession.value?.source === "cli" || contextSession.value?.source === "coding_agent") {
|
|
|
|
|
if (contextSession.value?.source === "cli") {
|
|
|
|
|
options.push({ label: t("chat.setModel"), key: "model" })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1041,7 +920,6 @@ async function handleWorkspaceConfirm() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const showSessionModelModal = ref(false);
|
|
|
|
|
const showSessionModelModeModal = ref(false);
|
|
|
|
|
const sessionModelSessionId = ref<string | null>(null);
|
|
|
|
|
const sessionModelSearch = ref("");
|
|
|
|
|
const sessionModelCollapsedGroups = ref<Record<string, boolean>>({});
|
|
|
|
@@ -1049,44 +927,14 @@ const sessionModelValue = ref("");
|
|
|
|
|
const sessionModelProvider = ref("");
|
|
|
|
|
const sessionModelCustomInput = ref("");
|
|
|
|
|
const sessionModelCustomProvider = ref("");
|
|
|
|
|
const sessionModelApiMode = ref<CodingAgentApiMode>("codex_responses");
|
|
|
|
|
const pendingSessionModelSwitch = ref<{ model: string; provider: string } | null>(null);
|
|
|
|
|
|
|
|
|
|
const sessionModelProfile = computed<string | null>(() => {
|
|
|
|
|
const session = chatStore.sessions.find((s) => s.id === sessionModelSessionId.value);
|
|
|
|
|
return session?.profile || null;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const sessionModelSession = computed(() =>
|
|
|
|
|
chatStore.sessions.find((s) => s.id === sessionModelSessionId.value) ||
|
|
|
|
|
(chatStore.activeSession?.id === sessionModelSessionId.value ? chatStore.activeSession : undefined),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const isSessionModelScopedCodingAgent = computed(() =>
|
|
|
|
|
sessionModelSession.value?.source === "coding_agent" &&
|
|
|
|
|
sessionModelSession.value?.codingAgentMode !== "global",
|
|
|
|
|
);
|
|
|
|
|
const sessionModelCodingAgentId = computed<ChatCodingAgentId | undefined>(() =>
|
|
|
|
|
sessionModelSession.value?.codingAgentId ||
|
|
|
|
|
(sessionModelSession.value?.agent === "claude"
|
|
|
|
|
? "claude-code"
|
|
|
|
|
: sessionModelSession.value?.agent === "codex"
|
|
|
|
|
? "codex"
|
|
|
|
|
: sessionModelSession.value?.agent === "ekko-agent"
|
|
|
|
|
? "ekko-agent"
|
|
|
|
|
: undefined),
|
|
|
|
|
);
|
|
|
|
|
const isSessionModelExternalCodingAgent = computed(() =>
|
|
|
|
|
isSessionModelScopedCodingAgent.value &&
|
|
|
|
|
(sessionModelCodingAgentId.value === "claude-code" || sessionModelCodingAgentId.value === "codex"),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const sessionModelBaseGroups = computed(() =>
|
|
|
|
|
sessionModelProfile.value
|
|
|
|
|
? getModelGroupsForProfile(sessionModelProfile.value).filter((group) => (
|
|
|
|
|
!isSessionModelScopedCodingAgent.value || !isCodingAgentAuthProvider(group.provider)
|
|
|
|
|
))
|
|
|
|
|
: [],
|
|
|
|
|
sessionModelProfile.value ? getModelGroupsForProfile(sessionModelProfile.value) : [],
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const sessionModelProviderOptions = computed(() =>
|
|
|
|
@@ -1176,25 +1024,12 @@ function sessionModelAlias(model: string, provider: string) {
|
|
|
|
|
return appStore.getModelAlias(model, provider);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function defaultSessionModelApiMode(provider: string): CodingAgentApiMode {
|
|
|
|
|
const group = sessionModelBaseGroups.value.find((item) => item.provider === provider);
|
|
|
|
|
const providerKey = String(group?.provider || provider || "").toLowerCase();
|
|
|
|
|
const baseUrl = String(group?.base_url || "").toLowerCase();
|
|
|
|
|
return normalizeCodingAgentApiMode(
|
|
|
|
|
group?.api_mode,
|
|
|
|
|
inferCodingAgentApiMode(providerKey, baseUrl),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function applySessionModelSwitch(model: string, provider: string, apiMode?: CodingAgentApiMode) {
|
|
|
|
|
async function applySessionModelSwitch(model: string, provider: string) {
|
|
|
|
|
if (!sessionModelSessionId.value) return;
|
|
|
|
|
const ok = await chatStore.switchSessionModel(model, provider, sessionModelSessionId.value, apiMode);
|
|
|
|
|
const ok = await chatStore.switchSessionModel(model, provider, sessionModelSessionId.value);
|
|
|
|
|
if (ok) {
|
|
|
|
|
sessionModelValue.value = model;
|
|
|
|
|
sessionModelProvider.value = provider;
|
|
|
|
|
if (apiMode) sessionModelApiMode.value = apiMode;
|
|
|
|
|
pendingSessionModelSwitch.value = null;
|
|
|
|
|
showSessionModelModeModal.value = false;
|
|
|
|
|
showSessionModelModal.value = false;
|
|
|
|
|
message.success(t("chat.modelSet"));
|
|
|
|
|
} else {
|
|
|
|
@@ -1205,28 +1040,9 @@ async function applySessionModelSwitch(model: string, provider: string, apiMode?
|
|
|
|
|
async function selectSessionModel(model: string, provider: string) {
|
|
|
|
|
const meta = sessionModelBaseGroups.value.find((group) => group.provider === provider)?.model_meta?.[model];
|
|
|
|
|
if (meta?.disabled || !sessionModelSessionId.value) return;
|
|
|
|
|
if (isSessionModelExternalCodingAgent.value) {
|
|
|
|
|
pendingSessionModelSwitch.value = { model, provider };
|
|
|
|
|
sessionModelApiMode.value = sessionModelSession.value?.provider === provider && sessionModelSession.value.apiMode
|
|
|
|
|
? normalizeCodingAgentApiMode(sessionModelSession.value.apiMode, defaultSessionModelApiMode(provider))
|
|
|
|
|
: defaultSessionModelApiMode(provider);
|
|
|
|
|
showSessionModelModeModal.value = true;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
await applySessionModelSwitch(model, provider);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function confirmSessionModelMode() {
|
|
|
|
|
const pending = pendingSessionModelSwitch.value;
|
|
|
|
|
if (!pending) return;
|
|
|
|
|
await applySessionModelSwitch(pending.model, pending.provider, sessionModelApiMode.value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function cancelSessionModelMode() {
|
|
|
|
|
pendingSessionModelSwitch.value = null;
|
|
|
|
|
showSessionModelModeModal.value = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function handleSessionModelCustomSubmit() {
|
|
|
|
|
const model = sessionModelCustomInput.value.trim();
|
|
|
|
|
const provider = sessionModelCustomProvider.value;
|
|
|
|
@@ -1589,27 +1405,6 @@ async function handleSessionModelCustomSubmit() {
|
|
|
|
|
</div>
|
|
|
|
|
</NModal>
|
|
|
|
|
|
|
|
|
|
<NModal
|
|
|
|
|
v-model:show="showSessionModelModeModal"
|
|
|
|
|
preset="dialog"
|
|
|
|
|
:title="t('codingAgents.protocolScope')"
|
|
|
|
|
:mask-closable="true"
|
|
|
|
|
style="width: min(420px, calc(100vw - 32px))"
|
|
|
|
|
>
|
|
|
|
|
<NSelect
|
|
|
|
|
v-model:value="sessionModelApiMode"
|
|
|
|
|
:options="newChatApiModeOptions"
|
|
|
|
|
/>
|
|
|
|
|
<template #action>
|
|
|
|
|
<NButton size="small" @click="cancelSessionModelMode">
|
|
|
|
|
{{ t('common.cancel') }}
|
|
|
|
|
</NButton>
|
|
|
|
|
<NButton size="small" type="primary" @click="confirmSessionModelMode">
|
|
|
|
|
{{ t('common.confirm') }}
|
|
|
|
|
</NButton>
|
|
|
|
|
</template>
|
|
|
|
|
</NModal>
|
|
|
|
|
|
|
|
|
|
<NDrawer
|
|
|
|
|
v-model:show="showNewChatModal"
|
|
|
|
|
class="new-chat-drawer"
|
|
|
|
@@ -1619,26 +1414,6 @@ async function handleSessionModelCustomSubmit() {
|
|
|
|
|
>
|
|
|
|
|
<NDrawerContent :title="t('chat.newChat')" closable>
|
|
|
|
|
<div class="new-chat-form">
|
|
|
|
|
<label class="new-chat-field">
|
|
|
|
|
<span class="new-chat-label">{{ t("chat.agent") }}</span>
|
|
|
|
|
<NSelect
|
|
|
|
|
v-model:value="newChatAgent"
|
|
|
|
|
:options="newChatAgentOptions"
|
|
|
|
|
:disabled="newChatLoading"
|
|
|
|
|
/>
|
|
|
|
|
</label>
|
|
|
|
|
<label v-if="isNewChatExternalCodingAgent" class="new-chat-field">
|
|
|
|
|
<span class="new-chat-label">{{ t("codingAgents.launchModeScope") }}</span>
|
|
|
|
|
<NRadioGroup v-model:value="newChatAgentMode" name="new-chat-coding-agent-mode">
|
|
|
|
|
<NRadioButton
|
|
|
|
|
v-for="option in newChatAgentModeOptions"
|
|
|
|
|
:key="option.value"
|
|
|
|
|
:value="option.value"
|
|
|
|
|
>
|
|
|
|
|
{{ option.label }}
|
|
|
|
|
</NRadioButton>
|
|
|
|
|
</NRadioGroup>
|
|
|
|
|
</label>
|
|
|
|
|
<label class="new-chat-field">
|
|
|
|
|
<span class="new-chat-label">{{ t("sidebar.profiles") }}</span>
|
|
|
|
|
<NSelect
|
|
|
|
@@ -1648,7 +1423,7 @@ async function handleSessionModelCustomSubmit() {
|
|
|
|
|
@update:value="handleNewChatProfileChange"
|
|
|
|
|
/>
|
|
|
|
|
</label>
|
|
|
|
|
<label v-if="newChatUsesProviderModel" class="new-chat-field">
|
|
|
|
|
<label class="new-chat-field">
|
|
|
|
|
<span class="new-chat-label">{{ t("models.provider") }}</span>
|
|
|
|
|
<NSelect
|
|
|
|
|
:value="newChatProvider"
|
|
|
|
@@ -1657,7 +1432,7 @@ async function handleSessionModelCustomSubmit() {
|
|
|
|
|
@update:value="handleNewChatProviderChange"
|
|
|
|
|
/>
|
|
|
|
|
</label>
|
|
|
|
|
<label v-if="newChatUsesProviderModel" class="new-chat-field">
|
|
|
|
|
<label class="new-chat-field">
|
|
|
|
|
<span class="new-chat-label">{{ t("models.models") }}</span>
|
|
|
|
|
<NSelect
|
|
|
|
|
v-model:value="newChatModel"
|
|
|
|
@@ -1666,30 +1441,6 @@ async function handleSessionModelCustomSubmit() {
|
|
|
|
|
filterable
|
|
|
|
|
/>
|
|
|
|
|
</label>
|
|
|
|
|
<label v-if="isNewChatExternalCodingAgent && effectiveNewChatAgentMode === 'scoped'" class="new-chat-field">
|
|
|
|
|
<span class="new-chat-label">{{ t("codingAgents.protocolScope") }}</span>
|
|
|
|
|
<NSelect
|
|
|
|
|
v-model:value="newChatApiMode"
|
|
|
|
|
:options="newChatApiModeOptions"
|
|
|
|
|
:disabled="newChatLoading"
|
|
|
|
|
/>
|
|
|
|
|
</label>
|
|
|
|
|
<label v-if="newChatNeedsBaseUrl" class="new-chat-field">
|
|
|
|
|
<span class="new-chat-label">{{ t("models.baseUrl") }}</span>
|
|
|
|
|
<NInput
|
|
|
|
|
v-model:value="newChatBaseUrl"
|
|
|
|
|
:placeholder="t('models.baseUrlPlaceholder')"
|
|
|
|
|
/>
|
|
|
|
|
</label>
|
|
|
|
|
<label v-if="newChatNeedsApiKey" class="new-chat-field">
|
|
|
|
|
<span class="new-chat-label">{{ t("models.apiKey") }}</span>
|
|
|
|
|
<NInput
|
|
|
|
|
v-model:value="newChatApiKey"
|
|
|
|
|
type="password"
|
|
|
|
|
show-password-on="click"
|
|
|
|
|
:placeholder="t('models.apiKeyPlaceholder')"
|
|
|
|
|
/>
|
|
|
|
|
</label>
|
|
|
|
|
<div class="new-chat-field">
|
|
|
|
|
<span class="new-chat-label">
|
|
|
|
|
{{ t("chat.workspace") }}
|
|
|
|
|