Compare commits
4 Commits
v0.3.5-bet
...
v0.3.5-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d0f807fb0 | ||
|
|
cbf623b98b | ||
|
|
b85ebb8e54 | ||
|
|
7cc206dc20 |
@@ -530,6 +530,11 @@ func (s *Server) handleProvidersQuota(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
}
|
||||
case "mimo":
|
||||
q.Healthy = p.APIKey != ""
|
||||
if p.APIKey == "" {
|
||||
q.Error = "no API key"
|
||||
}
|
||||
case "claude", "anthropic":
|
||||
// Claude Code n'a pas d'API externe, vérifier l'installation
|
||||
claudePath := "/usr/bin/claude"
|
||||
|
||||
@@ -269,6 +269,12 @@ func Default() *MuyueConfig {
|
||||
BaseURL: "https://api.minimax.io/v1",
|
||||
Active: true,
|
||||
},
|
||||
{
|
||||
Name: "mimo",
|
||||
Model: "MiMo-V2.5-Pro",
|
||||
BaseURL: "https://token-plan-ams.xiaomimimo.com/v1",
|
||||
Active: false,
|
||||
},
|
||||
{
|
||||
Name: "zai",
|
||||
Model: "glm",
|
||||
|
||||
@@ -476,6 +476,8 @@ func getProviderBaseURL(name string) string {
|
||||
return "https://api.openai.com/v1"
|
||||
case "zai":
|
||||
return "https://api.z.ai/v1"
|
||||
case "mimo":
|
||||
return "https://token-plan-ams.xiaomimimo.com/v1"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
@@ -503,11 +505,19 @@ func (o *Orchestrator) sendWithFallback(reqBody ChatRequest, baseURLOverride str
|
||||
if o.provider != nil {
|
||||
providerOrder = append(providerOrder, o.provider)
|
||||
}
|
||||
var zaiProvider *config.AIProvider
|
||||
for _, p := range providers {
|
||||
if o.provider == nil || p.Name != o.provider.Name {
|
||||
providerOrder = append(providerOrder, p)
|
||||
if p.Name == "zai" {
|
||||
zaiProvider = p
|
||||
} else {
|
||||
providerOrder = append(providerOrder, p)
|
||||
}
|
||||
}
|
||||
}
|
||||
if zaiProvider != nil {
|
||||
providerOrder = append(providerOrder, zaiProvider)
|
||||
}
|
||||
|
||||
var lastErr error
|
||||
var triedProviders []string
|
||||
|
||||
@@ -92,6 +92,8 @@ export default function App() {
|
||||
{ keys: `${layout.keys.shift}+${layout.keys.enter}`, desc: t('statusbar.newLine') },
|
||||
],
|
||||
shell: [
|
||||
{ keys: `${layout.keys.ctrl}+${layout.keys.shift}+C`, desc: t('statusbar.copy') },
|
||||
{ keys: `${layout.keys.ctrl}+${layout.keys.shift}+V`, desc: t('statusbar.paste') },
|
||||
{ keys: layout.keys.enter, desc: t('statusbar.runCommand') },
|
||||
{ keys: `${layout.keys.up}/${layout.keys.down}`, desc: t('statusbar.commandHistory') },
|
||||
],
|
||||
|
||||
@@ -343,7 +343,7 @@ function PanelProviders({ providers, editProvider, providerForm, setProviderForm
|
||||
setValidating(null)
|
||||
}
|
||||
|
||||
const displayed = providers.filter(p => p.name === 'minimax' || p.name === 'zai')
|
||||
const displayed = providers.filter(p => p.name === 'minimax' || p.name === 'mimo')
|
||||
|
||||
return (
|
||||
<div className="config-providers-list">
|
||||
|
||||
@@ -143,6 +143,32 @@ function createTerminal(container, settings = {}) {
|
||||
const webLinksAddon = new WebLinksAddon()
|
||||
term.loadAddon(fitAddon)
|
||||
term.loadAddon(webLinksAddon)
|
||||
|
||||
term.attachCustomKeyEventHandler((e) => {
|
||||
if (e.type !== 'keydown') return true
|
||||
const ctrl = e.ctrlKey || e.metaKey
|
||||
const shift = e.shiftKey
|
||||
|
||||
if (ctrl && shift && e.key === 'C') {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
const selection = term.getSelection()
|
||||
if (selection) navigator.clipboard.writeText(selection)
|
||||
return false
|
||||
}
|
||||
|
||||
if (ctrl && shift && e.key === 'V') {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
navigator.clipboard.readText().then(text => {
|
||||
if (text) term.paste(text)
|
||||
}).catch(() => {})
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
term.open(container)
|
||||
fitAddon.fit()
|
||||
|
||||
@@ -693,7 +719,7 @@ export default function Shell({ api }) {
|
||||
|
||||
if (!fromEvent) {
|
||||
setAiInput('')
|
||||
focusAiTerminal()
|
||||
setTimeout(() => focusAiTerminal(), 0)
|
||||
}
|
||||
|
||||
if (trimmed === '/clear') {
|
||||
@@ -937,7 +963,7 @@ export default function Shell({ api }) {
|
||||
<input
|
||||
value={aiInput}
|
||||
onChange={e => setAiInput(e.target.value)}
|
||||
onKeyDown={e => e.key === 'Enter' && handleAiSend()}
|
||||
onKeyDown={e => { if (e.key === 'Enter') { e.preventDefault(); e.stopPropagation(); handleAiSend() } }}
|
||||
placeholder={aiAtLimit ? '/clear pour continuer' : t('shell.askAi')}
|
||||
disabled={aiAtLimit && aiInput !== '/clear'}
|
||||
/>
|
||||
|
||||
@@ -452,15 +452,15 @@ export default function Studio({ api }) {
|
||||
api.getProviders().then(data => {
|
||||
const providers = data.providers || []
|
||||
const minimax = providers.find(p => p.name.toUpperCase() === 'MINIMAX')
|
||||
const zai = providers.find(p => p.name.toUpperCase() === 'ZAI')
|
||||
if (!minimax || !zai) {
|
||||
setMessages(prev => [...prev, { id: Date.now().toString(), role: 'assistant', content: 'MiniMax et ZAI doivent être configurés pour utiliser `/model change`.', time: new Date().toISOString() }])
|
||||
const mimo = providers.find(p => p.name.toUpperCase() === 'MIMO')
|
||||
if (!minimax || !mimo) {
|
||||
setMessages(prev => [...prev, { id: Date.now().toString(), role: 'assistant', content: 'MiniMax et MiMo doivent être configurés pour utiliser `/model change`.', time: new Date().toISOString() }])
|
||||
return
|
||||
}
|
||||
const active = providers.find(p => p.active)
|
||||
const activeName = active ? active.name.toUpperCase() : ''
|
||||
const switchTo = activeName === 'MINIMAX' ? 'ZAI' : 'MINIMAX'
|
||||
const target = switchTo === 'MINIMAX' ? minimax : zai
|
||||
const switchTo = activeName === 'MINIMAX' ? 'MIMO' : 'MINIMAX'
|
||||
const target = switchTo === 'MINIMAX' ? minimax : mimo
|
||||
api.saveProvider({ name: target.name, active: true }).then(() => {
|
||||
setMessages(prev => [...prev, { id: Date.now().toString(), role: 'assistant', content: `✓ Provider changé: **${target.name}** (${target.model})`, time: new Date().toISOString() }])
|
||||
}).catch(() => {
|
||||
|
||||
@@ -16,6 +16,8 @@ const en = {
|
||||
switchWindow: 'Switch window',
|
||||
sendMessage: 'Send message',
|
||||
newLine: 'New line',
|
||||
copy: 'Copy',
|
||||
paste: 'Paste',
|
||||
runCommand: 'Run command',
|
||||
commandHistory: 'Command history',
|
||||
},
|
||||
|
||||
@@ -16,6 +16,8 @@ const fr = {
|
||||
switchWindow: 'Changer de fen\u00eatre',
|
||||
sendMessage: 'Envoyer le message',
|
||||
newLine: 'Nouvelle ligne',
|
||||
copy: 'Copier',
|
||||
paste: 'Coller',
|
||||
runCommand: 'Ex\u00e9cuter',
|
||||
commandHistory: 'Historique',
|
||||
},
|
||||
|
||||
@@ -155,7 +155,7 @@ input::placeholder { color: var(--text-disabled); }
|
||||
.header-clock { font-family: var(--font-mono); font-size: 12px; color: var(--accent); font-weight: 600; }
|
||||
|
||||
.content { flex: 1; overflow: hidden; position: relative; }
|
||||
.content > div { height: 100%; }
|
||||
.content > div { position: absolute; inset: 0; overflow: hidden; }
|
||||
.tab-hidden { display: none; }
|
||||
|
||||
.statusbar {
|
||||
|
||||
Reference in New Issue
Block a user