Compare commits
3 Commits
v0.3.4-bet
...
v0.3.5-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
167ab82978 | ||
|
|
a23c0c5b94 | ||
|
|
24b31b0b47 |
@@ -8,6 +8,7 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -495,22 +496,34 @@ func (s *Server) handleProvidersQuota(w http.ResponseWriter, r *http.Request) {
|
||||
if json.Unmarshal(body, &data) == nil {
|
||||
if d, ok := data["data"].(map[string]interface{}); ok {
|
||||
if limits, ok := d["limits"].([]interface{}); ok {
|
||||
timeLimit := map[string]interface{}{}
|
||||
models := make([]map[string]interface{}, 0)
|
||||
for _, l := range limits {
|
||||
if lm, ok := l.(map[string]interface{}); ok && lm["type"] == "TIME_LIMIT" {
|
||||
if lm, ok := l.(map[string]interface{}); ok {
|
||||
name := "Z.AI"
|
||||
if model, ok := lm["model"].(string); ok && model != "" {
|
||||
name = model
|
||||
} else if t, ok := lm["type"].(string); ok && t != "TIME_LIMIT" {
|
||||
name = t
|
||||
}
|
||||
usage, _ := lm["usage"].(float64)
|
||||
remaining, _ := lm["remaining"].(float64)
|
||||
limitVal, hasLimit := lm["limit"].(float64)
|
||||
total := usage + remaining
|
||||
timeLimit = map[string]interface{}{
|
||||
"model": "Z.AI",
|
||||
"used": usage,
|
||||
"total": total,
|
||||
"remaining": remaining,
|
||||
if hasLimit && limitVal > 0 {
|
||||
total = limitVal
|
||||
}
|
||||
if total > 0 {
|
||||
models = append(models, map[string]interface{}{
|
||||
"model": name,
|
||||
"used": usage,
|
||||
"total": total,
|
||||
"remaining": remaining,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(timeLimit) > 0 {
|
||||
q.Data = map[string]interface{}{"models": []map[string]interface{}{timeLimit}}
|
||||
if len(models) > 0 {
|
||||
q.Data = map[string]interface{}{"models": models}
|
||||
q.Healthy = true
|
||||
}
|
||||
}
|
||||
@@ -553,10 +566,11 @@ func (s *Server) handleRecentCommands(w http.ResponseWriter, r *http.Request) {
|
||||
shell = "zsh"
|
||||
}
|
||||
lines := strings.Split(string(data), "\n")
|
||||
start := len(lines) - 25
|
||||
start := len(lines) - 50
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
|
||||
for i := len(lines) - 1; i >= start; i-- {
|
||||
line := strings.TrimSpace(lines[i])
|
||||
if line == "" || strings.HasPrefix(line, "#") {
|
||||
@@ -573,6 +587,15 @@ func (s *Server) handleRecentCommands(w http.ResponseWriter, r *http.Request) {
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
base := strings.Fields(line)[0]
|
||||
if len(base) < 2 {
|
||||
continue
|
||||
}
|
||||
if !regexp.MustCompile(`^[a-zA-Z@./]`).MatchString(base) {
|
||||
continue
|
||||
}
|
||||
|
||||
entries = append(entries, cmdEntry{Cmd: line, Shell: shell})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
const (
|
||||
Name = "muyue"
|
||||
Version = "0.3.4"
|
||||
Version = "0.3.5"
|
||||
Author = "La Légion de Muyue"
|
||||
)
|
||||
|
||||
|
||||
@@ -93,13 +93,14 @@ export default function Dashboard({ api, refreshRef }) {
|
||||
const minimax = (quota || []).find(p => p.name === 'minimax')
|
||||
const zai = (quota || []).find(p => p.name === 'zai')
|
||||
|
||||
const EXCLUDE_CMDS = ['ls', 'cd', 'pwd', 'clear', 'exit', 'history']
|
||||
const EXCLUDE_CMDS = ['ls', 'cd', 'pwd', 'clear', 'exit', 'history', 'cat', 'echo', 'grep', 'export', 'alias', 'unalias', 'set', 'unset', 'source', '.', 'fg', 'bg', 'jobs', 'wait', 'true', 'false', 'yes', 'sleep', 'date', 'whoami', 'id', 'uname', 'hostname', 'uptime', 'df', 'free', 'top', 'htop', 'nano', 'vi', 'vim', 'less', 'more', 'tail', 'head', 'man', 'info', 'which', 'whereis', 'type', 'command', 'hash', 'builtin', 'help']
|
||||
|
||||
const topCmds = (() => {
|
||||
const counts = {}
|
||||
for (const c of recentCmds) {
|
||||
const base = c.cmd.split(/\s+/)[0]
|
||||
if (EXCLUDE_CMDS.includes(base) || !base) continue
|
||||
if (!base || base.length < 2 || EXCLUDE_CMDS.includes(base)) continue
|
||||
if (!/^[a-zA-Z@.\/]/.test(base)) continue
|
||||
counts[base] = (counts[base] || 0) + 1
|
||||
}
|
||||
return Object.entries(counts)
|
||||
|
||||
@@ -28,7 +28,16 @@ function renderContent(text) {
|
||||
lastIndex = match.index + full.length
|
||||
}
|
||||
if (lastIndex < text.length) {
|
||||
parts.push({ type: 'text', content: text.slice(lastIndex) })
|
||||
const remaining = text.slice(lastIndex)
|
||||
const openBlock = remaining.match(/```(\w*)\n?([\s\S]*)$/)
|
||||
if (openBlock) {
|
||||
if (openBlock.index > 0) {
|
||||
parts.push({ type: 'text', content: remaining.slice(0, openBlock.index) })
|
||||
}
|
||||
parts.push({ type: 'code', lang: openBlock[1] || '', content: openBlock[2] || '' })
|
||||
} else {
|
||||
parts.push({ type: 'text', content: remaining })
|
||||
}
|
||||
}
|
||||
return parts
|
||||
}
|
||||
@@ -308,7 +317,7 @@ export default function Shell({ api }) {
|
||||
if (tabsRef.current[tabId]) return
|
||||
|
||||
const container = document.getElementById(`terminal-${tabId}`)
|
||||
if (!container || container.offsetHeight === 0) return
|
||||
if (!container) return
|
||||
|
||||
const s = settingsRef.current
|
||||
const { term, fitAddon } = createTerminal(container, {
|
||||
@@ -368,7 +377,12 @@ export default function Shell({ api }) {
|
||||
if (!tab) return
|
||||
|
||||
const tryInit = (attempt) => {
|
||||
if (attempt > 10) return
|
||||
if (attempt > 20) return
|
||||
const shellCol = document.querySelector('.shell-terminal-col')
|
||||
if (!shellCol || shellCol.offsetParent === null) {
|
||||
setTimeout(() => tryInit(attempt + 1), 150)
|
||||
return
|
||||
}
|
||||
const container = document.getElementById(`terminal-${tab.id}`)
|
||||
if (!container || container.offsetHeight === 0) {
|
||||
setTimeout(() => tryInit(attempt + 1), 100)
|
||||
@@ -404,7 +418,17 @@ export default function Shell({ api }) {
|
||||
useEffect(() => {
|
||||
const onKey = (e) => {
|
||||
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return
|
||||
if (!e.altKey) return
|
||||
if (!e.altKey && !(e.key === 'Tab' && e.shiftKey)) return
|
||||
|
||||
if (e.key === 'Tab' && e.shiftKey) {
|
||||
const shellTab = document.querySelector('.shell-layout')
|
||||
if (!shellTab || shellTab.closest('.tab-hidden')) return
|
||||
e.preventDefault()
|
||||
const idx = tabs.findIndex(t => t.id === activeTab)
|
||||
const next = (idx + 1) % tabs.length
|
||||
setActiveTab(tabs[next].id)
|
||||
return
|
||||
}
|
||||
|
||||
const num = parseInt(e.key)
|
||||
if (num >= 1 && num <= tabs.length) {
|
||||
|
||||
@@ -47,7 +47,16 @@ function renderContent(text) {
|
||||
lastIndex = match.index + full.length
|
||||
}
|
||||
if (lastIndex < text.length) {
|
||||
parts.push({ type: 'text', content: text.slice(lastIndex) })
|
||||
const remaining = text.slice(lastIndex)
|
||||
const openBlock = remaining.match(/```(\w*)\n?([\s\S]*)$/)
|
||||
if (openBlock) {
|
||||
if (openBlock.index > 0) {
|
||||
parts.push({ type: 'text', content: remaining.slice(0, openBlock.index) })
|
||||
}
|
||||
parts.push({ type: 'code', lang: openBlock[1] || '', content: openBlock[2] || '' })
|
||||
} else {
|
||||
parts.push({ type: 'text', content: remaining })
|
||||
}
|
||||
}
|
||||
return parts
|
||||
}
|
||||
|
||||
@@ -626,7 +626,7 @@ input::placeholder { color: var(--text-disabled); }
|
||||
position: relative;
|
||||
background: var(--bg-card); border: 1px solid var(--border);
|
||||
border-radius: var(--radius-lg); padding: 14px 16px;
|
||||
display: flex; flex-direction: column; gap: 8px;
|
||||
display: flex; flex-direction: column; justify-content: center; gap: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user