diff --git a/DEVLOG.md b/DEVLOG.md index 0e8519e..a972f53 100644 --- a/DEVLOG.md +++ b/DEVLOG.md @@ -1,7 +1,37 @@ # OpenClaw Manager — 开发日志 > 最后更新:2026-02-27 -> 当前版本:v0.7.0 +> 当前版本:v0.7.1 + +--- + +## v0.7.1 更新日志(2026-02-27) + +### New Features + +**Dashboard Guidance Block (Telegram-first usage + safety)** +- Added a concise guidance card under Dashboard explaining OCM's intended Telegram workflow +- Clarifies prerequisites: users should already have basic OpenClaw CLI experience +- Clarifies purpose: OCM mainly helps visualize and update `openclaw.json` for easier main-agent/sub-agent management and multi-tree structures +- Added explicit Telegram security checklist: + - BotFather `Allow Groups = ON` + - BotFather `Group Privacy = OFF` + - Keep each group private (only you + agent/sub-agents), do not invite others + +### Improvements + +**Model Dropdown Source — only `openclaw models list`** +- Model dropdown options are now sourced from real CLI output (`openclaw models list`) instead of built-in/static lists or config-only additions +- Applies to all relevant selectors: agent/sub-agent creation forms, agent inline model switcher, primary model selector, and fallback picker +- Added warning message when model list loading/parsing fails + +### Technical Notes + +- Added model ID parser for CLI output and short-term cache for model list fetches +- `GET /api/models` now returns: + - `knownModels` from CLI + - `modelListError` for UI warning display +- Startup script banners updated to `v0.7.1` (`start.sh` / `start.bat`) --- diff --git a/openclaw-manager.js b/openclaw-manager.js index 9339c48..84e0448 100644 --- a/openclaw-manager.js +++ b/openclaw-manager.js @@ -1,6 +1,6 @@ #!/usr/bin/env node // ================================================================ -// OpenClaw Manager v0.7.0 +// OpenClaw Manager v0.7.1 // 跨平台本地管理工具 (Windows / macOS / Linux) // // 用法: @@ -24,7 +24,7 @@ const SCRIPT_DIR = __dirname; const MANAGER_CONFIG = path.join(SCRIPT_DIR, 'manager-config.json'); let PORT = 3333; let HOST = '0.0.0.0'; -const APP_VERSION = '0.7.0'; +const APP_VERSION = '0.7.1'; // --port 参数 const portIdx = process.argv.indexOf('--port'); if (portIdx !== -1 && process.argv[portIdx + 1]) PORT = parseInt(process.argv[portIdx + 1]) || 3333; @@ -197,6 +197,37 @@ function runOpenclawCmd(args) { }); } +function parseModelIdsFromCliOutput(raw) { + if (!raw) return []; + const set = new Set(); + const isModelId = (s) => /^[a-z0-9][a-z0-9_-]*(?:\/[A-Za-z0-9._:-]+)+$/.test(s); + for (const line of raw.split(/\r?\n/)) { + const trimmed = line.trim(); + if (!trimmed) continue; + const normalized = trimmed.replace(/^[-*]\s+/, ''); + const first = normalized.split(/\s+/)[0].replace(/^`|`$/g, ''); + if (isModelId(first)) set.add(first); + } + return Array.from(set).sort((a, b) => a.localeCompare(b)); +} + +let MODEL_LIST_CACHE = { ts: 0, knownModels: [], error: '' }; +async function getKnownModelsFromCli() { + const now = Date.now(); + if (now - MODEL_LIST_CACHE.ts < 30000) return MODEL_LIST_CACHE; + try { + const out = await runOpenclawCmd('models list'); + const ids = parseModelIdsFromCliOutput(out); + const knownModels = ids.map(id => ({ id, label: id, group: id.split('/')[0] || 'other' })); + const error = knownModels.length ? '' : 'No model IDs found in `openclaw models list` output'; + MODEL_LIST_CACHE = { ts: now, knownModels, error }; + return MODEL_LIST_CACHE; + } catch (e) { + MODEL_LIST_CACHE = { ts: now, knownModels: [], error: e.message || 'openclaw models list failed' }; + return MODEL_LIST_CACHE; + } +} + // 过滤 ANSI 终端控制码(光标移动、清行、颜色等) function stripAnsi(str) { return str @@ -628,13 +659,15 @@ async function handleApi(req, res, urlObj, body) { // GET /api/models if (method === 'GET' && pathname === '/api/models') { const cfg = await readConfig(); + const modelList = await getKnownModelsFromCli(); res.writeHead(200); res.end(JSON.stringify({ models: cfg.agents?.defaults?.models || {}, authProfiles: cfg.auth?.profiles || {}, primaryModel: cfg.agents?.defaults?.model?.primary || '', fallbacks: cfg.agents?.defaults?.model?.fallbacks || [], - knownModels: KNOWN_MODELS, + knownModels: modelList.knownModels || [], + modelListError:modelList.error || '', authProviders: AUTH_PROVIDERS, })); return; @@ -1627,6 +1660,10 @@ select option { background:var(--surface); } .dash-sections { display:grid; grid-template-columns:repeat(auto-fit,minmax(300px,1fr)); gap:16px; } .dash-card { padding:20px; } .dash-card h3 { font-size:14px; font-weight:600; margin-bottom:14px; color:var(--text); } +.dash-notice { margin-top:18px; padding:16px 18px; } +.dash-notice h3 { font-size:14px; margin-bottom:10px; } +.dash-note-list { margin-left:16px; color:var(--muted); font-size:12px; line-height:1.7; } +.dash-note-list li { margin-bottom:4px; } .dash-row { display:flex; justify-content:space-between; align-items:center; padding:6px 0; border-bottom:1px solid var(--border); font-size:12px; } .dash-row:last-child { border-bottom:none; } .dash-label { color:var(--muted); } @@ -1824,6 +1861,15 @@ const MAIN_HTML_BODY = String.raw`
模型由 openclaw onboard 注册,此处管理主模型和 Fallback 链。
+模型下拉仅显示 openclaw models list 返回的模型。
+