tagword-codeagent 1.1.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- codeagent/__init__.py +10 -0
- codeagent/__main__.py +13 -0
- codeagent/cli/__init__.py +13 -0
- codeagent/cli/entrypoint.py +161 -0
- codeagent/cli/main.py +979 -0
- codeagent/core/__init__.py +2 -0
- codeagent/core/attachments.py +342 -0
- codeagent/core/audio_models.py +50 -0
- codeagent/core/bootstrap.py +178 -0
- codeagent/core/default_presets.py +159 -0
- codeagent/core/env.py +106 -0
- codeagent/core/folder_picker.py +151 -0
- codeagent/core/image_understanding.py +90 -0
- codeagent/core/models.py +6 -0
- codeagent/core/paths.py +238 -0
- codeagent/core/pricing.py +107 -0
- codeagent/core/process_ports.py +258 -0
- codeagent/core/seed_bridge.py +21 -0
- codeagent/core/settings.py +98 -0
- codeagent/core/speech_synth.py +330 -0
- codeagent/core/team_config.py +247 -0
- codeagent/core/team_manager.py +245 -0
- codeagent/core/token_counter.py +41 -0
- codeagent/core/tts_voices.py +103 -0
- codeagent/core/usage_billing.py +72 -0
- codeagent/core/vision_models.py +93 -0
- codeagent/memory/diary.py +144 -0
- codeagent/persona_defaults/README.md +12 -0
- codeagent/persona_defaults/agent.md +352 -0
- codeagent/persona_defaults/identity.md +29 -0
- codeagent/persona_defaults/memory.md +4 -0
- codeagent/persona_defaults/skills.md +325 -0
- codeagent/persona_defaults/soul.md +38 -0
- codeagent/persona_defaults/tools.md +41 -0
- codeagent/persona_defaults/user.md +18 -0
- codeagent/runtime/__init__.py +11 -0
- codeagent/runtime/agent_context.py +6 -0
- codeagent/runtime/agent_runtime.py +21 -0
- codeagent/runtime/compact_prompt.py +9 -0
- codeagent/runtime/compact_state.py +40 -0
- codeagent/runtime/llm_worker.py +132 -0
- codeagent/runtime/orchestrator.py +161 -0
- codeagent/runtime/prompt_enrichment.py +324 -0
- codeagent/runtime/session_manager.py +30 -0
- codeagent/runtime/task_split.py +38 -0
- codeagent/runtime/turn_loop.py +13 -0
- codeagent/runtime/worker.py +48 -0
- codeagent/server/__init__.py +505 -0
- codeagent/server/app_factory.py +1292 -0
- codeagent/server/attachment_api.py +261 -0
- codeagent/server/hub.py +175 -0
- codeagent/server/icon.png +0 -0
- codeagent/server/self_healing.py +143 -0
- codeagent/server/team_engine.py +243 -0
- codeagent/server/tts_api.py +51 -0
- codeagent/server/webui_api_app.py +3180 -0
- codeagent/skills/__init__.py +2 -0
- codeagent/skills/select.py +144 -0
- codeagent/tools/__init__.py +6 -0
- codeagent/tools/agent_tools.py +10 -0
- codeagent/web/__init__.py +1 -0
- codeagent/web/__pycache__/__init__.cpython-313.pyc +0 -0
- codeagent/web/__pycache__/app.cpython-313.pyc +0 -0
- codeagent/web/__pycache__/auth_impl.cpython-313.pyc +0 -0
- codeagent/web/auth_impl.py +326 -0
- codeagent/web/static/00-marked.min.js +6 -0
- codeagent/web/static/00-mermaid.min.js +2314 -0
- codeagent/web/static/00-purify.min.js +3 -0
- codeagent/web/static/00-storage.js +83 -0
- codeagent/web/static/00-utils.js +51 -0
- codeagent/web/static/01-theme.css +96 -0
- codeagent/web/static/01a-scroll.js +86 -0
- codeagent/web/static/01b-think.js +62 -0
- codeagent/web/static/01c-session-identity.js +81 -0
- codeagent/web/static/01c-session-thinking.js +61 -0
- codeagent/web/static/01c-session-tree-menus.js +349 -0
- codeagent/web/static/01c-session-tree.js +531 -0
- codeagent/web/static/01c-session-utilities.js +83 -0
- codeagent/web/static/01c-vision-model.js +132 -0
- codeagent/web/static/01d-image-gen-model.js +84 -0
- codeagent/web/static/01e-audio-model.js +97 -0
- codeagent/web/static/01f-compose-ui.js +88 -0
- codeagent/web/static/01g-tts-settings.js +128 -0
- codeagent/web/static/01h-music-model.js +85 -0
- codeagent/web/static/01i-model-stack.js +291 -0
- codeagent/web/static/01j-video-gen-model.js +85 -0
- codeagent/web/static/01k-model-stack-bootstrap.js +66 -0
- codeagent/web/static/01k-model-stack-state.js +209 -0
- codeagent/web/static/01q-inflight.js +195 -0
- codeagent/web/static/02-reset.css +22 -0
- codeagent/web/static/02-session-ui.js +201 -0
- codeagent/web/static/03-layout-p1.css +2 -0
- codeagent/web/static/03-layout-p2.css +2 -0
- codeagent/web/static/03a-links-stream.js +88 -0
- codeagent/web/static/03b-stream-text.js +119 -0
- codeagent/web/static/03c-render-bubble.js +520 -0
- codeagent/web/static/03d-agent-bubble.js +126 -0
- codeagent/web/static/03e-tool-trace.js +182 -0
- codeagent/web/static/03f-timeline.js +54 -0
- codeagent/web/static/03g-bubble-tts.js +292 -0
- codeagent/web/static/04-components-p1.css +1 -0
- codeagent/web/static/04-components-p2b.css +1 -0
- codeagent/web/static/04-components-p3.css +2 -0
- codeagent/web/static/04-components-p4.css +1 -0
- codeagent/web/static/04-components-p5.css +1 -0
- codeagent/web/static/04-components-p6.css +58 -0
- codeagent/web/static/04-components-p7.css +4 -0
- codeagent/web/static/04-components-p8.css +1 -0
- codeagent/web/static/04-components-p9.css +1 -0
- codeagent/web/static/04-ws-connect.js +351 -0
- codeagent/web/static/04-ws-helpers.js +116 -0
- codeagent/web/static/05-chat-p1.css +1058 -0
- codeagent/web/static/05-chat-p2.css +1 -0
- codeagent/web/static/05-chat-p3.css +295 -0
- codeagent/web/static/05a-session-history.js +176 -0
- codeagent/web/static/05b-session-list.js +114 -0
- codeagent/web/static/05c-dialog.js +123 -0
- codeagent/web/static/05d-project-create.js +172 -0
- codeagent/web/static/05e-project-remote.js +143 -0
- codeagent/web/static/06-chat.js +552 -0
- codeagent/web/static/06-utilities.css +181 -0
- codeagent/web/static/06b-attachments.js +304 -0
- codeagent/web/static/06c-camera.js +488 -0
- codeagent/web/static/07-activity-bar.css +127 -0
- codeagent/web/static/09-git-p1.css +1 -0
- codeagent/web/static/09-git-p2.css +1 -0
- codeagent/web/static/09a-init-bind.js +110 -0
- codeagent/web/static/09b-panel-toggle.js +80 -0
- codeagent/web/static/09c-api-refresh.js +100 -0
- codeagent/web/static/09d-status-log.js +80 -0
- codeagent/web/static/09e-commit.js +80 -0
- codeagent/web/static/09f-remote.js +93 -0
- codeagent/web/static/11a-cron-parse.js +117 -0
- codeagent/web/static/11b-cron-panel.js +100 -0
- codeagent/web/static/11c-cron-card.js +133 -0
- codeagent/web/static/11d-cron-form.js +105 -0
- codeagent/web/static/11e-env-config.js +168 -0
- codeagent/web/static/11f-env-llm-a-state.js +136 -0
- codeagent/web/static/11f-env-llm-b-form.js +409 -0
- codeagent/web/static/11f-env-llm-c-board.js +322 -0
- codeagent/web/static/11g-env-paths-git.js +973 -0
- codeagent/web/static/11h-env-mcp-a-state.js +161 -0
- codeagent/web/static/11h-env-mcp-b-form.js +229 -0
- codeagent/web/static/11h-env-mcp-c-board.js +565 -0
- codeagent/web/static/12-plugins.js +127 -0
- codeagent/web/static/13a-skills.js +156 -0
- codeagent/web/static/13a-todo-utils.js +140 -0
- codeagent/web/static/13b-todo-fetch.js +106 -0
- codeagent/web/static/13b-tools.js +127 -0
- codeagent/web/static/13c-todo-crud.js +92 -0
- codeagent/web/static/14-activity-bar.js +177 -0
- codeagent/web/static/15-plans.css +194 -0
- codeagent/web/static/15-plans.js +219 -0
- codeagent/web/static/16-mobile.css +612 -0
- codeagent/web/static/16-mobile.js +178 -0
- codeagent/web/static/17-preset-ux.css +287 -0
- codeagent/web/static/18-agent-mgr.css +616 -0
- codeagent/web/static/18-agent-mgr.js +204 -0
- codeagent/web/static/24-health-dashboard.js +68 -0
- codeagent/web/static/99-brand-polish.css +152 -0
- codeagent/web/static/body.html +824 -0
- codeagent/web/static/setup/setup_form.html +171 -0
- codeagent/web/static/setup/setup_head.html +100 -0
- codeagent/web/static/setup/setup_tail.html +264 -0
- codeagent/web/static/setup/setup_test.html +38 -0
- codeagent/web/web_login.html +265 -0
- codeagent/web/webui.html +35 -0
- tagword_codeagent-1.1.6.dist-info/METADATA +273 -0
- tagword_codeagent-1.1.6.dist-info/RECORD +173 -0
- tagword_codeagent-1.1.6.dist-info/WHEEL +5 -0
- tagword_codeagent-1.1.6.dist-info/entry_points.txt +3 -0
- tagword_codeagent-1.1.6.dist-info/licenses/LICENSE +21 -0
- tagword_codeagent-1.1.6.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/* Vision LLM selector — per-session via ModelStackState */
|
|
2
|
+
|
|
3
|
+
const VISION_MODEL_KEY = 'oa_vision_preset_id'; // legacy, kept for migration
|
|
4
|
+
|
|
5
|
+
function getSelectedVisionModel() {
|
|
6
|
+
if (window.ModelStackState) return window.ModelStackState.getEffectiveModel('vision');
|
|
7
|
+
try { return localStorage.getItem(VISION_MODEL_KEY) || ''; } catch (_) { return ''; }
|
|
8
|
+
}
|
|
9
|
+
function setSelectedVisionModel(val) {
|
|
10
|
+
if (window.ModelStackState) {
|
|
11
|
+
if (val && val !== '__none__') {
|
|
12
|
+
window.ModelStackState.setSessionOverride('vision', val);
|
|
13
|
+
window.ModelStackState.schedulePersistToBackend();
|
|
14
|
+
} else {
|
|
15
|
+
window.ModelStackState.clearSessionOverride('vision');
|
|
16
|
+
window.ModelStackState.schedulePersistToBackend();
|
|
17
|
+
}
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
try { localStorage.setItem(VISION_MODEL_KEY, String(val || '').trim()); } catch (_) {}
|
|
21
|
+
}
|
|
22
|
+
function clearSelectedVisionModel() { setSelectedVisionModel(''); }
|
|
23
|
+
|
|
24
|
+
function hasVisionPresets() {
|
|
25
|
+
return typeof _visionPresetsCache !== 'undefined' && _visionPresetsCache.length > 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
window._mcpImageReady = false;
|
|
29
|
+
window._mcpImageConfigured = false;
|
|
30
|
+
|
|
31
|
+
async function refreshMcpImageReady() {
|
|
32
|
+
try {
|
|
33
|
+
const r = await fetch('/api/ui/mcp');
|
|
34
|
+
if (!r.ok) return;
|
|
35
|
+
const j = await r.json();
|
|
36
|
+
const iu = j.image_understanding || {};
|
|
37
|
+
window._mcpImageConfigured = !!iu.configured;
|
|
38
|
+
window._mcpImageReady = !!iu.configured;
|
|
39
|
+
window._mcpVisionSentinel = iu.sentinel || '__mcp_minimax__';
|
|
40
|
+
} catch (_) {}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function mcpImageReadyForAttachments() {
|
|
44
|
+
return !!window._mcpImageReady;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function visionModelReadyForAttachments() {
|
|
48
|
+
if (!hasVisionPresets()) return false;
|
|
49
|
+
const v = getSelectedVisionModel();
|
|
50
|
+
if (v === (window._mcpVisionSentinel || '__mcp_minimax__')) return false;
|
|
51
|
+
return !!v && v !== '__none__';
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function attachmentImageReady() {
|
|
55
|
+
return visionModelReadyForAttachments() || mcpImageReadyForAttachments();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function attachmentVideoReady() {
|
|
59
|
+
return visionModelReadyForAttachments();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function refreshVisionModelSelect() {
|
|
63
|
+
const sel = document.getElementById('visionModelSelect');
|
|
64
|
+
if (!sel) return;
|
|
65
|
+
await refreshMcpImageReady();
|
|
66
|
+
try {
|
|
67
|
+
const r = await fetch('/api/ui/llm/presets');
|
|
68
|
+
if (!r.ok) return;
|
|
69
|
+
const j = await r.json();
|
|
70
|
+
const presets = (j.presets || []).filter(function(p) { return p.supports_vision === true; });
|
|
71
|
+
window._visionPresetsCache = presets;
|
|
72
|
+
const cur = getSelectedVisionModel();
|
|
73
|
+
const mcpSentinel = window._mcpVisionSentinel || '__mcp_minimax__';
|
|
74
|
+
sel.innerHTML = '';
|
|
75
|
+
if (!presets.length && !window._mcpImageConfigured) {
|
|
76
|
+
sel.disabled = true;
|
|
77
|
+
const o = document.createElement('option');
|
|
78
|
+
o.value = '';
|
|
79
|
+
o.textContent = '未配置多模态 / MCP 识图';
|
|
80
|
+
sel.appendChild(o);
|
|
81
|
+
updateAttachmentUiGate();
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
sel.disabled = false;
|
|
85
|
+
const ph = document.createElement('option');
|
|
86
|
+
ph.value = '';
|
|
87
|
+
ph.textContent = '— 识图方式 —';
|
|
88
|
+
sel.appendChild(ph);
|
|
89
|
+
if (window._mcpImageConfigured) {
|
|
90
|
+
const om = document.createElement('option');
|
|
91
|
+
om.value = mcpSentinel;
|
|
92
|
+
om.textContent = 'MiniMax MCP 识图 (understand_image)';
|
|
93
|
+
sel.appendChild(om);
|
|
94
|
+
}
|
|
95
|
+
presets.forEach(function(p) {
|
|
96
|
+
const o = document.createElement('option');
|
|
97
|
+
o.value = p.id || '';
|
|
98
|
+
o.textContent = (p.name || p.model || p.id) + ' (多模态 LLM)';
|
|
99
|
+
sel.appendChild(o);
|
|
100
|
+
});
|
|
101
|
+
if (cur && (cur === mcpSentinel && window._mcpImageConfigured)) {
|
|
102
|
+
sel.value = cur;
|
|
103
|
+
} else if (cur && presets.some(function(p) { return p.id === cur; })) {
|
|
104
|
+
sel.value = cur;
|
|
105
|
+
} else if (!cur && window._mcpImageConfigured && !presets.length) {
|
|
106
|
+
sel.value = mcpSentinel;
|
|
107
|
+
setSelectedVisionModel(mcpSentinel);
|
|
108
|
+
} else if (!cur && presets.length === 1) {
|
|
109
|
+
sel.value = presets[0].id;
|
|
110
|
+
setSelectedVisionModel(presets[0].id);
|
|
111
|
+
} else if (!cur && window._mcpImageConfigured) {
|
|
112
|
+
sel.value = mcpSentinel;
|
|
113
|
+
setSelectedVisionModel(mcpSentinel);
|
|
114
|
+
}
|
|
115
|
+
updateAttachmentUiGate();
|
|
116
|
+
} catch (_) {}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
(function bindVisionModelSelect() {
|
|
120
|
+
const sel = document.getElementById('visionModelSelect');
|
|
121
|
+
if (!sel) return;
|
|
122
|
+
sel.addEventListener('change', function() {
|
|
123
|
+
setSelectedVisionModel(sel.value);
|
|
124
|
+
updateAttachmentUiGate();
|
|
125
|
+
});
|
|
126
|
+
})();
|
|
127
|
+
|
|
128
|
+
const _origRefreshModelSelect = typeof refreshModelSelect === 'function' ? refreshModelSelect : null;
|
|
129
|
+
refreshModelSelect = async function() {
|
|
130
|
+
if (_origRefreshModelSelect) await _origRefreshModelSelect();
|
|
131
|
+
await refreshVisionModelSelect();
|
|
132
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/* Image-gen LLM selector — per-session via ModelStackState */
|
|
2
|
+
|
|
3
|
+
const IMAGE_GEN_MODEL_KEY = 'oa_image_gen_preset_id'; // legacy, kept for migration
|
|
4
|
+
|
|
5
|
+
function getSelectedImageGenModel() {
|
|
6
|
+
if (window.ModelStackState) return window.ModelStackState.getEffectiveModel('image_gen');
|
|
7
|
+
try { return localStorage.getItem(IMAGE_GEN_MODEL_KEY) || ''; } catch (_) { return ''; }
|
|
8
|
+
}
|
|
9
|
+
function setSelectedImageGenModel(val) {
|
|
10
|
+
if (window.ModelStackState) {
|
|
11
|
+
if (val && val !== '__none__') {
|
|
12
|
+
window.ModelStackState.setSessionOverride('image_gen', val);
|
|
13
|
+
window.ModelStackState.schedulePersistToBackend();
|
|
14
|
+
} else {
|
|
15
|
+
window.ModelStackState.clearSessionOverride('image_gen');
|
|
16
|
+
window.ModelStackState.schedulePersistToBackend();
|
|
17
|
+
}
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
try { localStorage.setItem(IMAGE_GEN_MODEL_KEY, String(val || '').trim()); } catch (_) {}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function refreshImageGenModelSelect() {
|
|
24
|
+
const sel = document.getElementById('imageGenModelSelect');
|
|
25
|
+
if (!sel) return;
|
|
26
|
+
try {
|
|
27
|
+
const r = await fetch('/api/ui/llm/presets');
|
|
28
|
+
if (!r.ok) return;
|
|
29
|
+
const j = await r.json();
|
|
30
|
+
const presets = (j.presets || []).filter(function(p) { return p.supports_image_gen === true; });
|
|
31
|
+
window._imageGenPresetsCache = presets;
|
|
32
|
+
const cur = getSelectedImageGenModel();
|
|
33
|
+
sel.innerHTML = '';
|
|
34
|
+
if (!presets.length) {
|
|
35
|
+
sel.disabled = true;
|
|
36
|
+
const o = document.createElement('option');
|
|
37
|
+
o.value = '';
|
|
38
|
+
o.textContent = '未配置生图模型';
|
|
39
|
+
sel.appendChild(o);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
sel.disabled = false;
|
|
43
|
+
const ph = document.createElement('option');
|
|
44
|
+
ph.value = '';
|
|
45
|
+
ph.textContent = '— 生图模型 —';
|
|
46
|
+
sel.appendChild(ph);
|
|
47
|
+
presets.forEach(function(p) {
|
|
48
|
+
const o = document.createElement('option');
|
|
49
|
+
o.value = p.id || '';
|
|
50
|
+
o.textContent = (p.name || p.model || p.id) + ' (生图)';
|
|
51
|
+
sel.appendChild(o);
|
|
52
|
+
});
|
|
53
|
+
if (cur && presets.some(function(p) { return p.id === cur; })) {
|
|
54
|
+
sel.value = cur;
|
|
55
|
+
} else if (presets.length === 1) {
|
|
56
|
+
sel.value = presets[0].id;
|
|
57
|
+
setSelectedImageGenModel(presets[0].id);
|
|
58
|
+
}
|
|
59
|
+
} catch (_) {}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
(function bindImageGenModelSelect() {
|
|
63
|
+
const sel = document.getElementById('imageGenModelSelect');
|
|
64
|
+
if (!sel) return;
|
|
65
|
+
sel.addEventListener('change', function() {
|
|
66
|
+
setSelectedImageGenModel(sel.value);
|
|
67
|
+
});
|
|
68
|
+
})();
|
|
69
|
+
|
|
70
|
+
const _origRefreshVisionForImageGen = typeof refreshModelSelect === 'function' ? refreshModelSelect : null;
|
|
71
|
+
if (typeof refreshVisionModelSelect === 'function') {
|
|
72
|
+
const _origRefreshVision = refreshVisionModelSelect;
|
|
73
|
+
refreshVisionModelSelect = async function() {
|
|
74
|
+
await _origRefreshVision();
|
|
75
|
+
await refreshImageGenModelSelect();
|
|
76
|
+
};
|
|
77
|
+
} else if (_origRefreshVisionForImageGen) {
|
|
78
|
+
refreshModelSelect = async function() {
|
|
79
|
+
await _origRefreshVisionForImageGen();
|
|
80
|
+
await refreshImageGenModelSelect();
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
refreshImageGenModelSelect().catch(function() {});
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/* Audio transcription LLM selector — per-session via ModelStackState */
|
|
2
|
+
|
|
3
|
+
const AUDIO_MODEL_KEY = 'oa_audio_preset_id'; // legacy, kept for migration
|
|
4
|
+
|
|
5
|
+
function getSelectedAudioModel() {
|
|
6
|
+
if (window.ModelStackState) return window.ModelStackState.getEffectiveModel('audio');
|
|
7
|
+
try { return localStorage.getItem(AUDIO_MODEL_KEY) || ''; } catch (_) { return ''; }
|
|
8
|
+
}
|
|
9
|
+
function setSelectedAudioModel(val) {
|
|
10
|
+
if (window.ModelStackState) {
|
|
11
|
+
if (val && val !== '__none__') {
|
|
12
|
+
window.ModelStackState.setSessionOverride('audio', val);
|
|
13
|
+
window.ModelStackState.schedulePersistToBackend();
|
|
14
|
+
} else {
|
|
15
|
+
window.ModelStackState.clearSessionOverride('audio');
|
|
16
|
+
window.ModelStackState.schedulePersistToBackend();
|
|
17
|
+
}
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
try { localStorage.setItem(AUDIO_MODEL_KEY, String(val || '').trim()); } catch (_) {}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function hasAudioPresets() {
|
|
24
|
+
return typeof _audioPresetsCache !== 'undefined' && _audioPresetsCache.length > 0;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function audioModelReadyForAttachments() {
|
|
28
|
+
if (!hasAudioPresets()) return false;
|
|
29
|
+
const v = getSelectedAudioModel();
|
|
30
|
+
return !!v && v !== '__none__';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function refreshAudioModelSelect() {
|
|
34
|
+
const sel = document.getElementById('audioModelSelect');
|
|
35
|
+
if (!sel) return;
|
|
36
|
+
try {
|
|
37
|
+
const r = await fetch('/api/ui/llm/presets');
|
|
38
|
+
if (!r.ok) return;
|
|
39
|
+
const j = await r.json();
|
|
40
|
+
const presets = (j.presets || []).filter(function(p) { return p.supports_audio === true; });
|
|
41
|
+
window._audioPresetsCache = presets;
|
|
42
|
+
const cur = getSelectedAudioModel();
|
|
43
|
+
sel.innerHTML = '';
|
|
44
|
+
if (!presets.length) {
|
|
45
|
+
sel.disabled = true;
|
|
46
|
+
const o = document.createElement('option');
|
|
47
|
+
o.value = '';
|
|
48
|
+
o.textContent = '未配置音频模型';
|
|
49
|
+
sel.appendChild(o);
|
|
50
|
+
if (typeof updateAttachmentUiGate === 'function') updateAttachmentUiGate();
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
sel.disabled = false;
|
|
54
|
+
const ph = document.createElement('option');
|
|
55
|
+
ph.value = '';
|
|
56
|
+
ph.textContent = '— 音频转写 —';
|
|
57
|
+
sel.appendChild(ph);
|
|
58
|
+
presets.forEach(function(p) {
|
|
59
|
+
const o = document.createElement('option');
|
|
60
|
+
o.value = p.id || '';
|
|
61
|
+
o.textContent = (p.name || p.model || p.id) + ' (音频)';
|
|
62
|
+
sel.appendChild(o);
|
|
63
|
+
});
|
|
64
|
+
if (cur && presets.some(function(p) { return p.id === cur; })) {
|
|
65
|
+
sel.value = cur;
|
|
66
|
+
} else if (presets.length === 1) {
|
|
67
|
+
sel.value = presets[0].id;
|
|
68
|
+
setSelectedAudioModel(presets[0].id);
|
|
69
|
+
}
|
|
70
|
+
if (typeof updateAttachmentUiGate === 'function') updateAttachmentUiGate();
|
|
71
|
+
} catch (_) {}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
(function bindAudioModelSelect() {
|
|
75
|
+
const sel = document.getElementById('audioModelSelect');
|
|
76
|
+
if (!sel) return;
|
|
77
|
+
sel.addEventListener('change', function() {
|
|
78
|
+
setSelectedAudioModel(sel.value);
|
|
79
|
+
if (typeof updateAttachmentUiGate === 'function') updateAttachmentUiGate();
|
|
80
|
+
});
|
|
81
|
+
})();
|
|
82
|
+
|
|
83
|
+
if (typeof refreshImageGenModelSelect === 'function') {
|
|
84
|
+
const _origRefreshImageGen = refreshImageGenModelSelect;
|
|
85
|
+
refreshImageGenModelSelect = async function() {
|
|
86
|
+
await _origRefreshImageGen();
|
|
87
|
+
await refreshAudioModelSelect();
|
|
88
|
+
};
|
|
89
|
+
} else if (typeof refreshVisionModelSelect === 'function') {
|
|
90
|
+
const _origRefreshVisionAudio = refreshVisionModelSelect;
|
|
91
|
+
refreshVisionModelSelect = async function() {
|
|
92
|
+
await _origRefreshVisionAudio();
|
|
93
|
+
await refreshAudioModelSelect();
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
refreshAudioModelSelect().catch(function() {});
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/* Compose UI: multimodal model select refresh, attachment thumbnail rendering
|
|
2
|
+
for chat & activity bar compose surfaces. */
|
|
3
|
+
|
|
4
|
+
async function refreshMultimodalModelSelects() {
|
|
5
|
+
if (typeof refreshModelSelect === 'function') {
|
|
6
|
+
await refreshModelSelect();
|
|
7
|
+
} else if (typeof refreshChatModelSelect === 'function') {
|
|
8
|
+
await refreshChatModelSelect();
|
|
9
|
+
}
|
|
10
|
+
if (typeof refreshTtsOptions === 'function') {
|
|
11
|
+
await refreshTtsOptions().catch(function() {});
|
|
12
|
+
}
|
|
13
|
+
if (typeof refreshComposeModelStackUi === 'function') {
|
|
14
|
+
refreshComposeModelStackUi();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function truncateComposeLabel(text, maxLen) {
|
|
19
|
+
const s = String(text || '').trim();
|
|
20
|
+
const cap = typeof maxLen === 'number' ? maxLen : 20;
|
|
21
|
+
if (s.length <= cap) return s;
|
|
22
|
+
return s.slice(0, cap - 1) + '…';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function composePillMaxLenFallback() {
|
|
26
|
+
try {
|
|
27
|
+
return window.matchMedia('(max-width: 768px)').matches ? 12 : 20;
|
|
28
|
+
} catch (_) {
|
|
29
|
+
return 20;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function updateComposeModelPill() {
|
|
34
|
+
if (typeof updateComposeModelStackPill === 'function') {
|
|
35
|
+
updateComposeModelStackPill();
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const pill = document.getElementById('composeModelPillLabel');
|
|
39
|
+
const sel = document.getElementById('modelSelect');
|
|
40
|
+
if (!pill || !sel) return;
|
|
41
|
+
const text = (typeof getChatMainDisplayLabel === 'function')
|
|
42
|
+
? getChatMainDisplayLabel(sel)
|
|
43
|
+
: ((sel.options[sel.selectedIndex] && sel.options[sel.selectedIndex].textContent) || '默认模型').trim();
|
|
44
|
+
pill.textContent = truncateComposeLabel(text, typeof composePillMaxLen === 'function' ? composePillMaxLen() : composePillMaxLenFallback());
|
|
45
|
+
pill.title = text;
|
|
46
|
+
const trigger = document.getElementById('composeModelTrigger');
|
|
47
|
+
if (trigger) trigger.title = '当前:' + text;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function setComposeSettingsOpen(open) {
|
|
51
|
+
const sheet = document.getElementById('composeSettingsSheet');
|
|
52
|
+
const trigger = document.getElementById('composeModelTrigger');
|
|
53
|
+
const box = document.getElementById('composeBox');
|
|
54
|
+
if (!sheet || !trigger) return;
|
|
55
|
+
sheet.hidden = !open;
|
|
56
|
+
trigger.setAttribute('aria-expanded', open ? 'true' : 'false');
|
|
57
|
+
trigger.classList.toggle('is-open', open);
|
|
58
|
+
if (box) box.classList.toggle('compose__box--sheet-open', open);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function toggleComposeSettings() {
|
|
62
|
+
const sheet = document.getElementById('composeSettingsSheet');
|
|
63
|
+
setComposeSettingsOpen(!!(sheet && sheet.hidden));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
(function initComposeUi() {
|
|
67
|
+
const trigger = document.getElementById('composeModelTrigger');
|
|
68
|
+
const closeBtn = document.getElementById('composeSettingsClose');
|
|
69
|
+
const box = document.getElementById('composeBox');
|
|
70
|
+
const sel = document.getElementById('modelSelect');
|
|
71
|
+
|
|
72
|
+
trigger && trigger.addEventListener('click', function(e) {
|
|
73
|
+
e.stopPropagation();
|
|
74
|
+
toggleComposeSettings();
|
|
75
|
+
});
|
|
76
|
+
closeBtn && closeBtn.addEventListener('click', function() {
|
|
77
|
+
setComposeSettingsOpen(false);
|
|
78
|
+
});
|
|
79
|
+
document.addEventListener('click', function() {
|
|
80
|
+
setComposeSettingsOpen(false);
|
|
81
|
+
});
|
|
82
|
+
box && box.addEventListener('click', function(e) {
|
|
83
|
+
e.stopPropagation();
|
|
84
|
+
});
|
|
85
|
+
sel && sel.addEventListener('change', updateComposeModelPill);
|
|
86
|
+
|
|
87
|
+
updateComposeModelPill();
|
|
88
|
+
})();
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
const TTS_VOICE_KEY = 'oa_tts_voice_id';
|
|
2
|
+
const TTS_MODEL_KEY = 'oa_tts_model';
|
|
3
|
+
|
|
4
|
+
function getSelectedTtsVoice() {
|
|
5
|
+
try { return localStorage.getItem(TTS_VOICE_KEY) || ''; } catch (_) { return ''; }
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function setSelectedTtsVoice(val) {
|
|
9
|
+
try { localStorage.setItem(TTS_VOICE_KEY, String(val || '').trim()); } catch (_) {}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function getSelectedTtsModel() {
|
|
13
|
+
try { return localStorage.getItem(TTS_MODEL_KEY) || ''; } catch (_) { return ''; }
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function setSelectedTtsModel(val) {
|
|
17
|
+
try { localStorage.setItem(TTS_MODEL_KEY, String(val || '').trim()); } catch (_) {}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function getTtsPlaybackSettings() {
|
|
21
|
+
var voiceSel = document.getElementById('ttsVoiceSelect');
|
|
22
|
+
var modelSel = document.getElementById('ttsModelSelect');
|
|
23
|
+
return {
|
|
24
|
+
voice_id: (voiceSel && voiceSel.value) || getSelectedTtsVoice() || '',
|
|
25
|
+
model: (modelSel && modelSel.value) || getSelectedTtsModel() || '',
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function populateTtsSelects(data) {
|
|
30
|
+
var voiceSel = document.getElementById('ttsVoiceSelect');
|
|
31
|
+
var modelSel = document.getElementById('ttsModelSelect');
|
|
32
|
+
var hint = document.getElementById('ttsVoiceHint');
|
|
33
|
+
if (!voiceSel || !modelSel) return;
|
|
34
|
+
|
|
35
|
+
var configured = !!(data && data.configured);
|
|
36
|
+
var voices = (data && data.voices) || [];
|
|
37
|
+
var models = (data && data.models) || [];
|
|
38
|
+
var curVoice = getSelectedTtsVoice() || (data && data.default_voice_id) || '';
|
|
39
|
+
var curModel = getSelectedTtsModel() || (data && data.default_model) || '';
|
|
40
|
+
|
|
41
|
+
voiceSel.innerHTML = '';
|
|
42
|
+
modelSel.innerHTML = '';
|
|
43
|
+
|
|
44
|
+
if (!configured) {
|
|
45
|
+
voiceSel.disabled = true;
|
|
46
|
+
modelSel.disabled = true;
|
|
47
|
+
var o1 = document.createElement('option');
|
|
48
|
+
o1.value = '';
|
|
49
|
+
o1.textContent = '需 MiniMax API Key(LLM 预设或 MCP)';
|
|
50
|
+
voiceSel.appendChild(o1);
|
|
51
|
+
var o2 = document.createElement('option');
|
|
52
|
+
o2.value = '';
|
|
53
|
+
o2.textContent = '需 MiniMax API Key(LLM 预设或 MCP)';
|
|
54
|
+
modelSel.appendChild(o2);
|
|
55
|
+
if (hint) hint.style.display = '';
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
voiceSel.disabled = false;
|
|
60
|
+
modelSel.disabled = false;
|
|
61
|
+
if (hint) hint.style.display = '';
|
|
62
|
+
|
|
63
|
+
var groups = {};
|
|
64
|
+
voices.forEach(function(v) {
|
|
65
|
+
var lang = v.lang || '其他';
|
|
66
|
+
if (!groups[lang]) groups[lang] = [];
|
|
67
|
+
groups[lang].push(v);
|
|
68
|
+
});
|
|
69
|
+
Object.keys(groups).sort().forEach(function(lang) {
|
|
70
|
+
var og = document.createElement('optgroup');
|
|
71
|
+
og.label = lang;
|
|
72
|
+
groups[lang].forEach(function(v) {
|
|
73
|
+
var o = document.createElement('option');
|
|
74
|
+
o.value = v.id;
|
|
75
|
+
o.textContent = v.name + ' · ' + v.id;
|
|
76
|
+
if (v.id === curVoice) o.selected = true;
|
|
77
|
+
og.appendChild(o);
|
|
78
|
+
});
|
|
79
|
+
voiceSel.appendChild(og);
|
|
80
|
+
});
|
|
81
|
+
if (curVoice && !Array.from(voiceSel.options).some(function(o) { return o.value === curVoice; })) {
|
|
82
|
+
var extra = document.createElement('option');
|
|
83
|
+
extra.value = curVoice;
|
|
84
|
+
extra.textContent = curVoice + '(自定义)';
|
|
85
|
+
extra.selected = true;
|
|
86
|
+
voiceSel.insertBefore(extra, voiceSel.firstChild);
|
|
87
|
+
}
|
|
88
|
+
if (!voiceSel.value && data.default_voice_id) {
|
|
89
|
+
voiceSel.value = data.default_voice_id;
|
|
90
|
+
setSelectedTtsVoice(voiceSel.value);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
models.forEach(function(m) {
|
|
94
|
+
var o = document.createElement('option');
|
|
95
|
+
o.value = m.id;
|
|
96
|
+
o.textContent = m.name || m.id;
|
|
97
|
+
if (m.id === curModel) o.selected = true;
|
|
98
|
+
modelSel.appendChild(o);
|
|
99
|
+
});
|
|
100
|
+
if (!modelSel.value && data.default_model) {
|
|
101
|
+
modelSel.value = data.default_model;
|
|
102
|
+
setSelectedTtsModel(modelSel.value);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async function refreshTtsOptions() {
|
|
107
|
+
try {
|
|
108
|
+
var r = await fetch('/api/ui/tts/options');
|
|
109
|
+
if (!r.ok) return;
|
|
110
|
+
var j = await r.json();
|
|
111
|
+
populateTtsSelects(j);
|
|
112
|
+
} catch (_) {}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
(function initTtsSettings() {
|
|
116
|
+
var voiceSel = document.getElementById('ttsVoiceSelect');
|
|
117
|
+
var modelSel = document.getElementById('ttsModelSelect');
|
|
118
|
+
refreshTtsOptions().catch(function() {});
|
|
119
|
+
|
|
120
|
+
voiceSel && voiceSel.addEventListener('change', function() {
|
|
121
|
+
setSelectedTtsVoice(voiceSel.value);
|
|
122
|
+
if (typeof clearAllBubbleTtsCaches === 'function') clearAllBubbleTtsCaches();
|
|
123
|
+
});
|
|
124
|
+
modelSel && modelSel.addEventListener('change', function() {
|
|
125
|
+
setSelectedTtsModel(modelSel.value);
|
|
126
|
+
if (typeof clearAllBubbleTtsCaches === 'function') clearAllBubbleTtsCaches();
|
|
127
|
+
});
|
|
128
|
+
})();
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/* Music LLM selector — per-session via ModelStackState */
|
|
2
|
+
|
|
3
|
+
const MUSIC_MODEL_KEY = 'oa_music_preset_id'; // legacy, kept for migration
|
|
4
|
+
|
|
5
|
+
function getSelectedMusicModel() {
|
|
6
|
+
if (window.ModelStackState) return window.ModelStackState.getEffectiveModel('music');
|
|
7
|
+
try { return localStorage.getItem(MUSIC_MODEL_KEY) || ''; } catch (_) { return ''; }
|
|
8
|
+
}
|
|
9
|
+
function setSelectedMusicModel(val) {
|
|
10
|
+
if (window.ModelStackState) {
|
|
11
|
+
if (val && val !== '__none__') {
|
|
12
|
+
window.ModelStackState.setSessionOverride('music', val);
|
|
13
|
+
window.ModelStackState.schedulePersistToBackend();
|
|
14
|
+
} else {
|
|
15
|
+
window.ModelStackState.clearSessionOverride('music');
|
|
16
|
+
window.ModelStackState.schedulePersistToBackend();
|
|
17
|
+
}
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
try { localStorage.setItem(MUSIC_MODEL_KEY, String(val || '').trim()); } catch (_) {}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function refreshMusicModelSelect() {
|
|
24
|
+
const sel = document.getElementById('musicModelSelect');
|
|
25
|
+
if (!sel) return;
|
|
26
|
+
try {
|
|
27
|
+
const r = await fetch('/api/ui/llm/presets');
|
|
28
|
+
if (!r.ok) return;
|
|
29
|
+
const j = await r.json();
|
|
30
|
+
const presets = (j.presets || []).filter(function(p) { return p.supports_music === true; });
|
|
31
|
+
window._musicPresetsCache = presets;
|
|
32
|
+
const cur = getSelectedMusicModel();
|
|
33
|
+
sel.innerHTML = '';
|
|
34
|
+
if (!presets.length) {
|
|
35
|
+
sel.disabled = true;
|
|
36
|
+
const o = document.createElement('option');
|
|
37
|
+
o.value = '';
|
|
38
|
+
o.textContent = '未配置音乐模型';
|
|
39
|
+
sel.appendChild(o);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
sel.disabled = false;
|
|
43
|
+
const ph = document.createElement('option');
|
|
44
|
+
ph.value = '';
|
|
45
|
+
ph.textContent = '— 音乐生成 —';
|
|
46
|
+
sel.appendChild(ph);
|
|
47
|
+
presets.forEach(function(p) {
|
|
48
|
+
const o = document.createElement('option');
|
|
49
|
+
o.value = p.id || '';
|
|
50
|
+
const modelLabel = (p.model_label || p.model || p.id || '').trim();
|
|
51
|
+
o.textContent = (p.name || modelLabel) + ' · ' + modelLabel + ' (音乐)';
|
|
52
|
+
sel.appendChild(o);
|
|
53
|
+
});
|
|
54
|
+
if (cur && presets.some(function(p) { return p.id === cur; })) {
|
|
55
|
+
sel.value = cur;
|
|
56
|
+
} else if (presets.length === 1) {
|
|
57
|
+
sel.value = presets[0].id;
|
|
58
|
+
setSelectedMusicModel(presets[0].id);
|
|
59
|
+
}
|
|
60
|
+
} catch (_) {}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
(function bindMusicModelSelect() {
|
|
64
|
+
const sel = document.getElementById('musicModelSelect');
|
|
65
|
+
if (!sel) return;
|
|
66
|
+
sel.addEventListener('change', function() {
|
|
67
|
+
setSelectedMusicModel(sel.value);
|
|
68
|
+
});
|
|
69
|
+
})();
|
|
70
|
+
|
|
71
|
+
if (typeof refreshAudioModelSelect === 'function') {
|
|
72
|
+
const _origRefreshAudioForMusic = refreshAudioModelSelect;
|
|
73
|
+
refreshAudioModelSelect = async function() {
|
|
74
|
+
await _origRefreshAudioForMusic();
|
|
75
|
+
await refreshMusicModelSelect();
|
|
76
|
+
};
|
|
77
|
+
} else if (typeof refreshImageGenModelSelect === 'function') {
|
|
78
|
+
const _origRefreshImageGenForMusic = refreshImageGenModelSelect;
|
|
79
|
+
refreshImageGenModelSelect = async function() {
|
|
80
|
+
await _origRefreshImageGenForMusic();
|
|
81
|
+
await refreshMusicModelSelect();
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
refreshMusicModelSelect().catch(function() {});
|