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.
Files changed (173) hide show
  1. codeagent/__init__.py +10 -0
  2. codeagent/__main__.py +13 -0
  3. codeagent/cli/__init__.py +13 -0
  4. codeagent/cli/entrypoint.py +161 -0
  5. codeagent/cli/main.py +979 -0
  6. codeagent/core/__init__.py +2 -0
  7. codeagent/core/attachments.py +342 -0
  8. codeagent/core/audio_models.py +50 -0
  9. codeagent/core/bootstrap.py +178 -0
  10. codeagent/core/default_presets.py +159 -0
  11. codeagent/core/env.py +106 -0
  12. codeagent/core/folder_picker.py +151 -0
  13. codeagent/core/image_understanding.py +90 -0
  14. codeagent/core/models.py +6 -0
  15. codeagent/core/paths.py +238 -0
  16. codeagent/core/pricing.py +107 -0
  17. codeagent/core/process_ports.py +258 -0
  18. codeagent/core/seed_bridge.py +21 -0
  19. codeagent/core/settings.py +98 -0
  20. codeagent/core/speech_synth.py +330 -0
  21. codeagent/core/team_config.py +247 -0
  22. codeagent/core/team_manager.py +245 -0
  23. codeagent/core/token_counter.py +41 -0
  24. codeagent/core/tts_voices.py +103 -0
  25. codeagent/core/usage_billing.py +72 -0
  26. codeagent/core/vision_models.py +93 -0
  27. codeagent/memory/diary.py +144 -0
  28. codeagent/persona_defaults/README.md +12 -0
  29. codeagent/persona_defaults/agent.md +352 -0
  30. codeagent/persona_defaults/identity.md +29 -0
  31. codeagent/persona_defaults/memory.md +4 -0
  32. codeagent/persona_defaults/skills.md +325 -0
  33. codeagent/persona_defaults/soul.md +38 -0
  34. codeagent/persona_defaults/tools.md +41 -0
  35. codeagent/persona_defaults/user.md +18 -0
  36. codeagent/runtime/__init__.py +11 -0
  37. codeagent/runtime/agent_context.py +6 -0
  38. codeagent/runtime/agent_runtime.py +21 -0
  39. codeagent/runtime/compact_prompt.py +9 -0
  40. codeagent/runtime/compact_state.py +40 -0
  41. codeagent/runtime/llm_worker.py +132 -0
  42. codeagent/runtime/orchestrator.py +161 -0
  43. codeagent/runtime/prompt_enrichment.py +324 -0
  44. codeagent/runtime/session_manager.py +30 -0
  45. codeagent/runtime/task_split.py +38 -0
  46. codeagent/runtime/turn_loop.py +13 -0
  47. codeagent/runtime/worker.py +48 -0
  48. codeagent/server/__init__.py +505 -0
  49. codeagent/server/app_factory.py +1292 -0
  50. codeagent/server/attachment_api.py +261 -0
  51. codeagent/server/hub.py +175 -0
  52. codeagent/server/icon.png +0 -0
  53. codeagent/server/self_healing.py +143 -0
  54. codeagent/server/team_engine.py +243 -0
  55. codeagent/server/tts_api.py +51 -0
  56. codeagent/server/webui_api_app.py +3180 -0
  57. codeagent/skills/__init__.py +2 -0
  58. codeagent/skills/select.py +144 -0
  59. codeagent/tools/__init__.py +6 -0
  60. codeagent/tools/agent_tools.py +10 -0
  61. codeagent/web/__init__.py +1 -0
  62. codeagent/web/__pycache__/__init__.cpython-313.pyc +0 -0
  63. codeagent/web/__pycache__/app.cpython-313.pyc +0 -0
  64. codeagent/web/__pycache__/auth_impl.cpython-313.pyc +0 -0
  65. codeagent/web/auth_impl.py +326 -0
  66. codeagent/web/static/00-marked.min.js +6 -0
  67. codeagent/web/static/00-mermaid.min.js +2314 -0
  68. codeagent/web/static/00-purify.min.js +3 -0
  69. codeagent/web/static/00-storage.js +83 -0
  70. codeagent/web/static/00-utils.js +51 -0
  71. codeagent/web/static/01-theme.css +96 -0
  72. codeagent/web/static/01a-scroll.js +86 -0
  73. codeagent/web/static/01b-think.js +62 -0
  74. codeagent/web/static/01c-session-identity.js +81 -0
  75. codeagent/web/static/01c-session-thinking.js +61 -0
  76. codeagent/web/static/01c-session-tree-menus.js +349 -0
  77. codeagent/web/static/01c-session-tree.js +531 -0
  78. codeagent/web/static/01c-session-utilities.js +83 -0
  79. codeagent/web/static/01c-vision-model.js +132 -0
  80. codeagent/web/static/01d-image-gen-model.js +84 -0
  81. codeagent/web/static/01e-audio-model.js +97 -0
  82. codeagent/web/static/01f-compose-ui.js +88 -0
  83. codeagent/web/static/01g-tts-settings.js +128 -0
  84. codeagent/web/static/01h-music-model.js +85 -0
  85. codeagent/web/static/01i-model-stack.js +291 -0
  86. codeagent/web/static/01j-video-gen-model.js +85 -0
  87. codeagent/web/static/01k-model-stack-bootstrap.js +66 -0
  88. codeagent/web/static/01k-model-stack-state.js +209 -0
  89. codeagent/web/static/01q-inflight.js +195 -0
  90. codeagent/web/static/02-reset.css +22 -0
  91. codeagent/web/static/02-session-ui.js +201 -0
  92. codeagent/web/static/03-layout-p1.css +2 -0
  93. codeagent/web/static/03-layout-p2.css +2 -0
  94. codeagent/web/static/03a-links-stream.js +88 -0
  95. codeagent/web/static/03b-stream-text.js +119 -0
  96. codeagent/web/static/03c-render-bubble.js +520 -0
  97. codeagent/web/static/03d-agent-bubble.js +126 -0
  98. codeagent/web/static/03e-tool-trace.js +182 -0
  99. codeagent/web/static/03f-timeline.js +54 -0
  100. codeagent/web/static/03g-bubble-tts.js +292 -0
  101. codeagent/web/static/04-components-p1.css +1 -0
  102. codeagent/web/static/04-components-p2b.css +1 -0
  103. codeagent/web/static/04-components-p3.css +2 -0
  104. codeagent/web/static/04-components-p4.css +1 -0
  105. codeagent/web/static/04-components-p5.css +1 -0
  106. codeagent/web/static/04-components-p6.css +58 -0
  107. codeagent/web/static/04-components-p7.css +4 -0
  108. codeagent/web/static/04-components-p8.css +1 -0
  109. codeagent/web/static/04-components-p9.css +1 -0
  110. codeagent/web/static/04-ws-connect.js +351 -0
  111. codeagent/web/static/04-ws-helpers.js +116 -0
  112. codeagent/web/static/05-chat-p1.css +1058 -0
  113. codeagent/web/static/05-chat-p2.css +1 -0
  114. codeagent/web/static/05-chat-p3.css +295 -0
  115. codeagent/web/static/05a-session-history.js +176 -0
  116. codeagent/web/static/05b-session-list.js +114 -0
  117. codeagent/web/static/05c-dialog.js +123 -0
  118. codeagent/web/static/05d-project-create.js +172 -0
  119. codeagent/web/static/05e-project-remote.js +143 -0
  120. codeagent/web/static/06-chat.js +552 -0
  121. codeagent/web/static/06-utilities.css +181 -0
  122. codeagent/web/static/06b-attachments.js +304 -0
  123. codeagent/web/static/06c-camera.js +488 -0
  124. codeagent/web/static/07-activity-bar.css +127 -0
  125. codeagent/web/static/09-git-p1.css +1 -0
  126. codeagent/web/static/09-git-p2.css +1 -0
  127. codeagent/web/static/09a-init-bind.js +110 -0
  128. codeagent/web/static/09b-panel-toggle.js +80 -0
  129. codeagent/web/static/09c-api-refresh.js +100 -0
  130. codeagent/web/static/09d-status-log.js +80 -0
  131. codeagent/web/static/09e-commit.js +80 -0
  132. codeagent/web/static/09f-remote.js +93 -0
  133. codeagent/web/static/11a-cron-parse.js +117 -0
  134. codeagent/web/static/11b-cron-panel.js +100 -0
  135. codeagent/web/static/11c-cron-card.js +133 -0
  136. codeagent/web/static/11d-cron-form.js +105 -0
  137. codeagent/web/static/11e-env-config.js +168 -0
  138. codeagent/web/static/11f-env-llm-a-state.js +136 -0
  139. codeagent/web/static/11f-env-llm-b-form.js +409 -0
  140. codeagent/web/static/11f-env-llm-c-board.js +322 -0
  141. codeagent/web/static/11g-env-paths-git.js +973 -0
  142. codeagent/web/static/11h-env-mcp-a-state.js +161 -0
  143. codeagent/web/static/11h-env-mcp-b-form.js +229 -0
  144. codeagent/web/static/11h-env-mcp-c-board.js +565 -0
  145. codeagent/web/static/12-plugins.js +127 -0
  146. codeagent/web/static/13a-skills.js +156 -0
  147. codeagent/web/static/13a-todo-utils.js +140 -0
  148. codeagent/web/static/13b-todo-fetch.js +106 -0
  149. codeagent/web/static/13b-tools.js +127 -0
  150. codeagent/web/static/13c-todo-crud.js +92 -0
  151. codeagent/web/static/14-activity-bar.js +177 -0
  152. codeagent/web/static/15-plans.css +194 -0
  153. codeagent/web/static/15-plans.js +219 -0
  154. codeagent/web/static/16-mobile.css +612 -0
  155. codeagent/web/static/16-mobile.js +178 -0
  156. codeagent/web/static/17-preset-ux.css +287 -0
  157. codeagent/web/static/18-agent-mgr.css +616 -0
  158. codeagent/web/static/18-agent-mgr.js +204 -0
  159. codeagent/web/static/24-health-dashboard.js +68 -0
  160. codeagent/web/static/99-brand-polish.css +152 -0
  161. codeagent/web/static/body.html +824 -0
  162. codeagent/web/static/setup/setup_form.html +171 -0
  163. codeagent/web/static/setup/setup_head.html +100 -0
  164. codeagent/web/static/setup/setup_tail.html +264 -0
  165. codeagent/web/static/setup/setup_test.html +38 -0
  166. codeagent/web/web_login.html +265 -0
  167. codeagent/web/webui.html +35 -0
  168. tagword_codeagent-1.1.6.dist-info/METADATA +273 -0
  169. tagword_codeagent-1.1.6.dist-info/RECORD +173 -0
  170. tagword_codeagent-1.1.6.dist-info/WHEEL +5 -0
  171. tagword_codeagent-1.1.6.dist-info/entry_points.txt +3 -0
  172. tagword_codeagent-1.1.6.dist-info/licenses/LICENSE +21 -0
  173. tagword_codeagent-1.1.6.dist-info/top_level.txt +1 -0
@@ -0,0 +1,322 @@
1
+ /* ================================================================
2
+ * 11f-env-llm-c-board.js
3
+ * LLM Preset 看板与网络层:
4
+ * - 渲染 (renderPresetBoard):按 use_type 分组展示所有 preset
5
+ * - 网络 (loadLlmPresets):拉 /api/ui/llm/presets 写回缓存
6
+ * - 卡片 (buildPresetCard):单条 preset 的卡片 + 展开/编辑
7
+ * - 新建 (showNewPresetForm):点 + 添加 时插入临时表单
8
+ * - init IIFE:DOMContentLoaded 时绑定 + 首次加载
9
+ *
10
+ * 依赖 11f-env-llm-a-state.js (inferPresetUseType / llmDefaultId /
11
+ * PRESET_USE_TYPE_LABELS / PRESET_USE_TYPE_ORDER /
12
+ * PRESET_BOARD_EMPTY_HINTS / providerLabel / resolvePresetProviderId)
13
+ * 11f-env-llm-b-form.js (presetFormHtml / wirePresetForm /
14
+ * wirePresetSaveAndTest / setSelectedUseType /
15
+ * syncPresetFormFromProvider / refreshPresetCopyFromOptions /
16
+ * updatePresetCapabilityHint / presetCardTitle)
17
+ * 上游依赖:00-utils.js (escapeHtml)。
18
+ *
19
+ * DOM 缓存:llmDom = { list, status, btnAdd, btnRefresh } 在 init IIFE
20
+ * 中一次性 getElementById 填充,避免 8 处散落调用。
21
+ * ================================================================ */
22
+
23
+ const llmDom = {};
24
+
25
+ function renderPresetBoard(presets) {
26
+ const list = llmDom.list;
27
+ if (!list) return;
28
+ list.innerHTML = '';
29
+ list.className = 'preset-board';
30
+
31
+ PRESET_USE_TYPE_ORDER.forEach(function(useType) {
32
+ const section = document.createElement('section');
33
+ section.className = 'preset-board-section';
34
+ section.setAttribute('data-use-type', useType);
35
+
36
+ const sectionPresets = presets.filter(function(p) {
37
+ return inferPresetUseType(p) === useType;
38
+ });
39
+
40
+ const head = document.createElement('div');
41
+ head.className = 'preset-board-section__head';
42
+ const title = document.createElement('h4');
43
+ title.className = 'preset-board-section__title';
44
+ title.textContent = PRESET_USE_TYPE_LABELS[useType] || useType;
45
+ const count = document.createElement('span');
46
+ count.className = 'preset-board-section__count';
47
+ count.textContent = String(sectionPresets.length);
48
+ title.appendChild(count);
49
+
50
+ const addBtn = document.createElement('button');
51
+ addBtn.type = 'button';
52
+ addBtn.className = 'btn btn--ghost btn--xs preset-board-add';
53
+ addBtn.textContent = '+ 添加' + (PRESET_USE_TYPE_LABELS[useType] || useType);
54
+ addBtn.addEventListener('click', function() { showNewPresetForm(useType, section); });
55
+
56
+ head.appendChild(title);
57
+ head.appendChild(addBtn);
58
+ section.appendChild(head);
59
+
60
+ const body = document.createElement('div');
61
+ body.className = 'preset-board-section__body';
62
+
63
+ if (!sectionPresets.length) {
64
+ const empty = document.createElement('p');
65
+ empty.className = 'preset-board-section__empty';
66
+ empty.textContent = PRESET_BOARD_EMPTY_HINTS[useType] || '暂无预设';
67
+ body.appendChild(empty);
68
+ } else {
69
+ sectionPresets.forEach(function(p) {
70
+ body.appendChild(buildPresetCard(p));
71
+ });
72
+ }
73
+
74
+ section.appendChild(body);
75
+ list.appendChild(section);
76
+ });
77
+ }
78
+
79
+ async function loadLlmPresets() {
80
+ const list = llmDom.list;
81
+ const status = llmDom.status;
82
+ if (!list) return;
83
+ if (status) status.classList.remove('is-err');
84
+ try {
85
+ await ensureProviderCatalog();
86
+ const r = await fetch('/api/ui/llm/presets');
87
+ if (!r.ok) throw new Error((await r.json()).detail || r.statusText);
88
+ const j = await r.json();
89
+ const presets = j.presets || [];
90
+ window._llmPresetsCache = presets;
91
+ window._llmDefaultId = j.default_id || '';
92
+ llmDefaultId = j.default_id || '';
93
+ if (j.providers && j.providers.length) llmProviderCatalog = j.providers;
94
+
95
+ renderPresetBoard(presets);
96
+
97
+ if (status) {
98
+ status.classList.remove('is-err');
99
+ status.textContent = '共 ' + presets.length + ' 个预设';
100
+ }
101
+ if (typeof refreshMultimodalModelSelects === 'function') {
102
+ refreshMultimodalModelSelects().catch(function() {});
103
+ }
104
+ } catch (e) {
105
+ if (status) {
106
+ status.classList.add('is-err');
107
+ status.textContent = '加载预设失败:' + String(e);
108
+ }
109
+ }
110
+ }
111
+
112
+ function buildPresetCard(p) {
113
+ const wrap = document.createElement('div');
114
+ wrap.className = 'preset-card-wrap';
115
+ const isDefault = p.id === llmDefaultId;
116
+ const useType = inferPresetUseType(p);
117
+
118
+ const header = document.createElement('div');
119
+ header.className = 'preset-card';
120
+
121
+ const info = document.createElement('div');
122
+ info.className = 'preset-card__info';
123
+
124
+ const nameRow = document.createElement('div');
125
+ nameRow.className = 'preset-card__name';
126
+ nameRow.textContent = presetCardTitle(p);
127
+ if (isDefault) {
128
+ const badge = document.createElement('span');
129
+ badge.className = 'preset-card__badge';
130
+ badge.textContent = '默认';
131
+ nameRow.appendChild(badge);
132
+ }
133
+ const provBadge = document.createElement('span');
134
+ provBadge.className = 'preset-card__badge preset-card__badge--provider';
135
+ provBadge.textContent = providerLabel(p);
136
+ nameRow.appendChild(provBadge);
137
+
138
+ const detail = document.createElement('div');
139
+ detail.className = 'preset-card__detail';
140
+ const modelTxt = (p.model_label || p.model || '').trim();
141
+ const urlHint = (p.base_url || '').trim();
142
+ detail.textContent = (modelTxt ? modelTxt + ' · ' : '') +
143
+ (urlHint ? urlHint + ' · ' : '') +
144
+ (p.api_key ? '已配置 Key' : '未配置 Key');
145
+
146
+ info.appendChild(nameRow);
147
+ info.appendChild(detail);
148
+
149
+ const actions = document.createElement('div');
150
+ actions.className = 'preset-card__actions';
151
+
152
+ if (!isDefault && useType === 'chat') {
153
+ const btnDefault = document.createElement('button');
154
+ btnDefault.type = 'button';
155
+ btnDefault.className = 'btn btn--ghost btn--xs';
156
+ btnDefault.textContent = '设为默认';
157
+ btnDefault.addEventListener('click', async function(ev) {
158
+ ev.stopPropagation();
159
+ try {
160
+ const dr = await fetch('/api/ui/llm/presets/default', {
161
+ method: 'POST',
162
+ headers: { 'Content-Type': 'application/json' },
163
+ credentials: 'same-origin',
164
+ body: JSON.stringify({ preset_id: p.id }),
165
+ });
166
+ const dj = await dr.json().catch(function() { return {}; });
167
+ if (!dr.ok) throw new Error(dj.detail || dr.statusText);
168
+ await loadLlmPresets();
169
+ if (typeof refreshMultimodalModelSelects === 'function') {
170
+ await refreshMultimodalModelSelects();
171
+ } else {
172
+ refreshChatModelSelect();
173
+ }
174
+ } catch (e) {
175
+ const st = llmDom.status;
176
+ if (st) { st.classList.add('is-err'); st.textContent = String(e); }
177
+ }
178
+ });
179
+ actions.appendChild(btnDefault);
180
+ }
181
+
182
+ const btnDel = document.createElement('button');
183
+ btnDel.type = 'button';
184
+ btnDel.className = 'btn btn--ghost btn--xs preset-del';
185
+ btnDel.textContent = '删除';
186
+ btnDel.addEventListener('click', async function(ev) {
187
+ ev.stopPropagation();
188
+ if (!confirm('确定删除预设「' + presetCardTitle(p) + '」?')) return;
189
+ try {
190
+ const dr = await fetch('/api/ui/llm/presets/delete', {
191
+ method: 'POST',
192
+ headers: { 'Content-Type': 'application/json' },
193
+ credentials: 'same-origin',
194
+ body: JSON.stringify({ preset_id: p.id }),
195
+ });
196
+ const dj = await dr.json().catch(function() { return {}; });
197
+ if (!dr.ok) throw new Error(dj.detail || dr.statusText);
198
+ await loadLlmPresets();
199
+ if (typeof refreshMultimodalModelSelects === 'function') {
200
+ await refreshMultimodalModelSelects();
201
+ } else {
202
+ refreshChatModelSelect();
203
+ if (typeof refreshTtsOptions === 'function') refreshTtsOptions().catch(function() {});
204
+ }
205
+ } catch (e) {
206
+ const st = llmDom.status;
207
+ if (st) { st.classList.add('is-err'); st.textContent = String(e); }
208
+ }
209
+ });
210
+ actions.appendChild(btnDel);
211
+
212
+ header.appendChild(info);
213
+ header.appendChild(actions);
214
+
215
+ const editWrap = document.createElement('div');
216
+ editWrap.className = 'preset-edit-wrap';
217
+ editWrap.style.display = 'none';
218
+
219
+ const editStatus = document.createElement('div');
220
+ editStatus.className = 'status-line';
221
+
222
+ editWrap.innerHTML = presetFormHtml(p);
223
+ editWrap.appendChild(editStatus);
224
+ wirePresetForm(editWrap, p);
225
+
226
+ const toggleEdit = function(show) {
227
+ editWrap.style.display = show ? 'block' : 'none';
228
+ editStatus.textContent = '';
229
+ editStatus.classList.remove('is-err');
230
+ };
231
+ header.style.cursor = 'pointer';
232
+ header.addEventListener('click', function(e) {
233
+ if (e.target.closest('.btn') || e.target.closest('.preset-card__actions')) return;
234
+ const opening = editWrap.style.display !== 'block';
235
+ toggleEdit(opening);
236
+ if (opening) {
237
+ syncPresetFormFromProvider(editWrap, {
238
+ providerId: resolvePresetProviderId(p),
239
+ modelId: p.model || '',
240
+ useType: inferPresetUseType(p),
241
+ });
242
+ refreshPresetCopyFromOptions(editWrap);
243
+ updatePresetCapabilityHint(editWrap);
244
+ }
245
+ });
246
+
247
+ editWrap.querySelector('.preset-cancel-btn').addEventListener('click', function() { toggleEdit(false); });
248
+ wirePresetSaveAndTest(editWrap, editStatus, {
249
+ presetId: p.id,
250
+ onSaved: function() { toggleEdit(false); },
251
+ });
252
+
253
+ wrap.appendChild(header);
254
+ wrap.appendChild(editWrap);
255
+ return wrap;
256
+ }
257
+
258
+ function showNewPresetForm(preferredUseType, targetSection) {
259
+ const list = llmDom.list;
260
+ if (!list) return;
261
+
262
+ const existing = list.querySelector('.preset-card-wrap.is-new');
263
+ if (existing) existing.remove();
264
+
265
+ const useType = (preferredUseType || 'chat').trim();
266
+ const wrap = document.createElement('div');
267
+ wrap.className = 'preset-card-wrap is-new';
268
+
269
+ const editWrap = document.createElement('div');
270
+ editWrap.className = 'preset-edit-wrap';
271
+ editWrap.style.display = 'block';
272
+ const editStatus = document.createElement('div');
273
+ editStatus.className = 'status-line';
274
+
275
+ const seed = { provider: 'deepseek', provider_stored: 'deepseek', use_type: useType };
276
+ if (useType === 'vision' || useType === 'image' || useType === 'audio') {
277
+ seed.provider = 'ollama';
278
+ seed.provider_stored = 'ollama';
279
+ }
280
+
281
+ editWrap.innerHTML = presetFormHtml(seed);
282
+ editWrap.appendChild(editStatus);
283
+
284
+ editWrap.querySelector('.preset-cancel-btn').addEventListener('click', function() { wrap.remove(); });
285
+ wirePresetForm(editWrap, seed);
286
+ wirePresetSaveAndTest(editWrap, editStatus, {
287
+ onSaved: function() { wrap.remove(); },
288
+ });
289
+
290
+ wrap.appendChild(editWrap);
291
+
292
+ if (targetSection) {
293
+ const body = targetSection.querySelector('.preset-board-section__body');
294
+ const empty = body && body.querySelector('.preset-board-section__empty');
295
+ if (empty) empty.remove();
296
+ if (body) body.insertBefore(wrap, body.firstChild);
297
+ else list.insertBefore(wrap, list.firstChild);
298
+ } else if (list.firstChild) {
299
+ list.insertBefore(wrap, list.firstChild);
300
+ } else {
301
+ list.appendChild(wrap);
302
+ }
303
+
304
+ setSelectedUseType(editWrap, useType);
305
+ syncPresetFormFromProvider(editWrap, { useType: useType, providerId: resolvePresetProviderId(seed) });
306
+ wrap.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
307
+ }
308
+
309
+ (function () {
310
+ // 一次性填充 DOM 缓存(避免 8 处散落 getElementById)
311
+ [
312
+ ['list', 'llmPresetList'],
313
+ ['status', 'llmPresetStatus'],
314
+ ['btnAdd', 'btnLlmPresetAdd'],
315
+ ['btnRefresh', 'btnLlmPresetRefresh'],
316
+ ].forEach(function(pair) {
317
+ llmDom[pair[0]] = document.getElementById(pair[1]);
318
+ });
319
+ if (llmDom.btnAdd) llmDom.btnAdd.addEventListener('click', function() { showNewPresetForm('chat'); });
320
+ if (llmDom.btnRefresh) llmDom.btnRefresh.addEventListener('click', function () { loadLlmPresets(); });
321
+ loadLlmPresets();
322
+ })();