feat: AI terminal, Z.AI quota, /model change, formatting fixes, update redirects
All checks were successful
Beta Release / beta (push) Successful in 49s

- Add dedicated AI Terminal tab (non-deletable) shared between user and AI
- Add Z.AI quota display on dashboard via /api/monitor/usage/quota/limit
- Add /model change command in Studio to toggle MiniMax/ZAI
- Apply Studio formatting (formatText, renderContent) to Shell AI messages
- Add render tick refresh for Shell (1s streaming, 5s idle)
- Add analysis viewer modal (Eye button) in Shell panel
- Fix multi-shell tab creation with retry init and settings ref
- Persist shell tabs to localStorage
- Fix line spacing in Studio (line-height 1.7→1.5, cleanup stray <br/>)
- Redirect Config updates to AI terminal via custom events
- Fix CI: delete existing release before recreating
- Bump version to 0.3.4

💘 Generated with Crush

Assisted-by: GLM-5.1 via Crush <crush@charm.land>
This commit is contained in:
Augustin
2026-04-23 23:07:54 +02:00
parent 1074b019d3
commit 8c540eba93
12 changed files with 477 additions and 141 deletions

View File

@@ -43,6 +43,7 @@ export default function Dashboard({ api, refreshRef }) {
const [recentCmds, setRecentCmds] = useState([])
const [processes, setProcesses] = useState([])
const [metrics, setMetrics] = useState(null)
const [copiedIdx, setCopiedIdx] = useState(-1)
const cpuRef = useRef([])
const memRef = useRef([])
const netRxRef = useRef([])
@@ -158,10 +159,19 @@ export default function Dashboard({ api, refreshRef }) {
<span className="dash-quota-val" style={{ color: 'var(--text-tertiary)' }}>{minimax.error || 'no data'}</span>
</div>
)}
{zai && (
{zai && zai.data?.models?.map((m, i) => (
<div key={i} className="dash-quota-row">
<span className="dash-quota-name">{String(m.model)}</span>
<div className="dash-bar">
<div className="dash-bar-fill" style={{ width: `${Math.min(100, (m.used / m.total) * 100)}%` }} />
</div>
<span className="dash-quota-val">{m.used}/{m.total}</span>
</div>
))}
{zai && !zai.data?.models?.length && (
<div className="dash-quota-row">
<span className="dash-quota-name">Z.AI</span>
<span className="dash-quota-val">{zai.healthy ? '✓ active' : zai.error || ''}</span>
<span className="dash-quota-val" style={{ color: 'var(--text-tertiary)' }}>{zai.error || 'no data'}</span>
</div>
)}
{!minimax && !zai && <span className="dash-quota-val" style={{ color: 'var(--text-tertiary)' }}>No providers</span>}
@@ -193,8 +203,8 @@ export default function Dashboard({ api, refreshRef }) {
{topCmds.length > 0 && (
<div className="dash-cmd-top">
{topCmds.map((c, i) => (
<div key={i} className="dash-cmd-chip" onClick={() => navigator.clipboard.writeText(c.cmd)} title="Copier">
<span className="dash-cmd-chip-name">{c.cmd}</span>
<div key={i} className={'dash-cmd-chip' + (copiedIdx === i ? ' dash-cmd-chip-copied' : '')} onClick={() => { navigator.clipboard.writeText(c.cmd); setCopiedIdx(i); setTimeout(() => setCopiedIdx(-1), 1200); }}>
<span className="dash-cmd-chip-name">{copiedIdx === i ? '✓ Copié' : c.cmd}</span>
<span className="dash-cmd-chip-count">{c.count}×</span>
</div>
))}