openclaw-openagent 1.0.13 → 1.0.14

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 (128) hide show
  1. package/dist/src/messaging/executor.d.ts +2 -3
  2. package/dist/src/messaging/executor.js +4 -31
  3. package/dist/src/plugin-ui/assets/openagent-override.js +4 -5
  4. package/dist/src/runtime/update-checker.d.ts +1 -1
  5. package/dist/src/runtime/update-checker.js +9 -46
  6. package/package.json +1 -3
  7. package/src/app/channel-tools.ts +0 -249
  8. package/src/app/discovery-tools.ts +0 -273
  9. package/src/app/download-file-tool.ts +0 -133
  10. package/src/app/hooks.ts +0 -144
  11. package/src/app/index.ts +0 -84
  12. package/src/app/messaging-tools.ts +0 -79
  13. package/src/app/ops-tools.ts +0 -155
  14. package/src/app/remote-agent-tool.ts +0 -762
  15. package/src/app/types.ts +0 -68
  16. package/src/app/upload-file-tool.ts +0 -411
  17. package/src/app/verbose-preflight.ts +0 -190
  18. package/src/auth/config.ts +0 -266
  19. package/src/auth/credential-manager.ts +0 -146
  20. package/src/auth/index.ts +0 -24
  21. package/src/auth/verify.ts +0 -99
  22. package/src/channel.ts +0 -566
  23. package/src/compat.ts +0 -94
  24. package/src/config/config-schema.ts +0 -45
  25. package/src/messaging/aggregator.ts +0 -120
  26. package/src/messaging/collector.ts +0 -89
  27. package/src/messaging/executor.ts +0 -72
  28. package/src/messaging/inbound.ts +0 -150
  29. package/src/messaging/index.ts +0 -11
  30. package/src/messaging/mention-protocol.ts +0 -94
  31. package/src/messaging/process-c2c-request.ts +0 -564
  32. package/src/messaging/process-message.ts +0 -373
  33. package/src/messaging/scheduler.ts +0 -55
  34. package/src/messaging/types.ts +0 -38
  35. package/src/plugin-ui/adapters/oc-2026-04.js +0 -103
  36. package/src/plugin-ui/adapters/oc-2026-05.js +0 -125
  37. package/src/plugin-ui/adapters/oc-2026-06.js +0 -125
  38. package/src/plugin-ui/adapters/oc-unknown.js +0 -48
  39. package/src/plugin-ui/assets/agentbook-icon.svg +0 -5
  40. package/src/plugin-ui/assets/bg.png +0 -0
  41. package/src/plugin-ui/assets/icon.png +0 -0
  42. package/src/plugin-ui/assets/magic.svg +0 -5
  43. package/src/plugin-ui/assets/openagent-override.js +0 -11263
  44. package/src/plugin-ui/build.cjs +0 -463
  45. package/src/plugin-ui/index.ts +0 -18
  46. package/src/plugin-ui/modules/agent-book/panel/agent-book.js +0 -570
  47. package/src/plugin-ui/modules/agent-book/panel/agent-card.js +0 -170
  48. package/src/plugin-ui/modules/agent-book/panel/agent-data.js +0 -643
  49. package/src/plugin-ui/modules/agent-book/panel/inject-ui.js +0 -665
  50. package/src/plugin-ui/modules/agent-book/panel/mention-state.js +0 -206
  51. package/src/plugin-ui/modules/agent-book/panel/styles.js +0 -832
  52. package/src/plugin-ui/modules/agent-book/panel/theme-adapter.js +0 -86
  53. package/src/plugin-ui/modules/agent-book/remote-agent-tool/components-core.js +0 -295
  54. package/src/plugin-ui/modules/agent-book/remote-agent-tool/thought-chain-card.js +0 -211
  55. package/src/plugin-ui/modules/agent-book/scanner.js +0 -131
  56. package/src/plugin-ui/modules/agent-book/travelcard/travel-cards.js +0 -500
  57. package/src/plugin-ui/modules/agent-book/travelcard/travel-engine.js +0 -652
  58. package/src/plugin-ui/modules/agent-book/travelcard/travel-styles.js +0 -262
  59. package/src/plugin-ui/modules/loader/bootstrap.js +0 -133
  60. package/src/plugin-ui/modules/loader/shared-state.js +0 -838
  61. package/src/plugin-ui/modules/loader/ws-intercept.js +0 -199
  62. package/src/plugin-ui/modules/remote-agent/chunk-parser.js +0 -161
  63. package/src/plugin-ui/modules/remote-agent/execution-card.js +0 -530
  64. package/src/plugin-ui/modules/remote-agent/markdown-renderer.js +0 -256
  65. package/src/plugin-ui/modules/remote-agent/media-links.js +0 -151
  66. package/src/plugin-ui/modules/remote-agent/native-style-adapter.js +0 -134
  67. package/src/plugin-ui/modules/remote-agent/output-card.js +0 -342
  68. package/src/plugin-ui/modules/remote-agent/progress-store.js +0 -363
  69. package/src/plugin-ui/modules/remote-agent/render-hooks.js +0 -1700
  70. package/src/plugin-ui/modules/remote-agent/styles.js +0 -903
  71. package/src/plugin-ui/modules/remote-agent/tool-card-model.js +0 -130
  72. package/src/plugin-ui/postinstall-deploy.cjs +0 -52
  73. package/src/plugin-ui/ui-extension-loader/backup.ts +0 -92
  74. package/src/plugin-ui/ui-extension-loader/index.ts +0 -276
  75. package/src/plugin-ui/ui-extension-loader/locator.ts +0 -152
  76. package/src/plugin-ui/ui-extension-loader/manifest.ts +0 -57
  77. package/src/plugin-ui/ui-extension-loader/registry-regex.ts +0 -944
  78. package/src/plugin-ui/ui-extension-loader/removed-extensions.ts +0 -70
  79. package/src/plugin-ui/ui-extension-loader/types.ts +0 -72
  80. package/src/proxy/auth-proxy.ts +0 -414
  81. package/src/runtime/account.ts +0 -549
  82. package/src/runtime/index.ts +0 -7
  83. package/src/runtime/plugin-runtime.ts +0 -94
  84. package/src/runtime/registry.ts +0 -71
  85. package/src/runtime/update-checker.ts +0 -286
  86. package/src/sdk/CLASS_MAP.md +0 -143
  87. package/src/sdk/index.d.ts +0 -126
  88. package/src/sdk/index.js +0 -23990
  89. package/src/sdk/modules/cloud-search-module.js +0 -1117
  90. package/src/sdk/modules/follow-module.js +0 -1069
  91. package/src/sdk/modules/group-module.js +0 -7397
  92. package/src/sdk/modules/relationship-module.js +0 -2269
  93. package/src/sdk/modules/signaling-module.js +0 -1468
  94. package/src/sdk/modules/tim-upload-plugin.js +0 -730
  95. package/src/sdk/node-env/http-request.js +0 -90
  96. package/src/sdk/node-env/index.js +0 -57
  97. package/src/sdk/node-env/storage.js +0 -114
  98. package/src/sdk/package.json +0 -10
  99. package/src/sdk/tsconfig.json +0 -16
  100. package/src/state/pending-invocation-store.ts +0 -43
  101. package/src/state/store.ts +0 -756
  102. package/src/tim/c2c.ts +0 -451
  103. package/src/tim/channels.ts +0 -364
  104. package/src/tim/client.ts +0 -330
  105. package/src/tim/index.ts +0 -18
  106. package/src/tim/messages.ts +0 -166
  107. package/src/tim/sdk-logger-init.ts +0 -50
  108. package/src/tools.ts +0 -10
  109. package/src/transport/factory.ts +0 -95
  110. package/src/transport/oasn/index.ts +0 -17
  111. package/src/transport/oasn/oasn-agent-card.ts +0 -111
  112. package/src/transport/oasn/oasn-discovery.ts +0 -108
  113. package/src/transport/oasn/oasn-files.ts +0 -210
  114. package/src/transport/oasn/oasn-http.ts +0 -529
  115. package/src/transport/oasn/oasn-invocation.ts +0 -604
  116. package/src/transport/oasn/oasn-normalize.ts +0 -133
  117. package/src/transport/oasn/oasn-register.ts +0 -33
  118. package/src/transport/oasn/oasn-transport.ts +0 -318
  119. package/src/transport/oasn/oasn-types.ts +0 -404
  120. package/src/transport/tim/index.ts +0 -8
  121. package/src/transport/tim/tim-transport.ts +0 -515
  122. package/src/transport/types.ts +0 -538
  123. package/src/types/openclaw-plugin-sdk-media-store.d.ts +0 -9
  124. package/src/types/openclaw.d.ts +0 -97
  125. package/src/types/tencentcloud-chat.d.ts +0 -15
  126. package/src/util/http.ts +0 -113
  127. package/src/util/logger.ts +0 -131
  128. package/src/util/url-resolver.ts +0 -77
@@ -1,570 +0,0 @@
1
-
2
-
3
- // ── UI 构建 ──
4
-
5
- let panel = null;
6
- let backdrop = null;
7
-
8
- let inputWrapperRef = null; // 保存输入框包裹层引用
9
- let panelPositionResizeObserver = null;
10
-
11
- // ── 键盘导航状态(§1.5)──
12
- // 对标 TIM index.ts:13 "let selectedIndex: number = 0"
13
- let selectedIndex = 0;
14
- let _currentAgents = []; // 当前列表中的 agents(供键盘选中使用)
15
- let _currentTextarea = null; // 当前关联的 textarea
16
-
17
- function ensurePanel() {
18
- if (panel) return panel;
19
-
20
- // 背景遮罩(点击关闭)
21
- backdrop = document.createElement('div');
22
- backdrop.className = 'openagent-panel-backdrop';
23
- backdrop.addEventListener('click', () => {
24
- console.log('[openagent] 🔲 backdrop clicked → closePanel (dismissed)');
25
- // backdrop 关闭 = 用户主动关闭 → 触发 dismissed(同 ESC 意图)
26
- setDismissed();
27
- closePanel();
28
- });
29
- document.body.appendChild(backdrop);
30
-
31
- // 全局点击诊断(捕获阶段,看最先点到什么)
32
- document.addEventListener('click', (e) => {
33
- if (panel && panel.classList.contains('visible')) {
34
- console.log('[openagent] 🔍 global click capture:', e.target.tagName, e.target.className, 'composedPath[0]:', e.composedPath()[0]?.tagName);
35
- }
36
- }, true); // 捕获阶段
37
-
38
- // 面板 — 独立浮动卡片
39
- panel = document.createElement('div');
40
- panel.className = 'openagent-agent-panel';
41
- panel.innerHTML = `
42
- <div class="openagent-panel-head">
43
- <span class="openagent-panel-title">
44
- <svg class="openagent-panel-title-icon" width="24" height="24" viewBox="0 0 56 56" fill="none">
45
- <path d="M28 25H32C34.2091 25 36 26.7909 36 29V39C36 41.2091 34.2091 43 32 43H14C11.7909 43 10 41.2091 10 39V29C10 26.7909 11.7909 25 14 25H15" stroke="#12CCF6" stroke-width="3.3" stroke-linecap="round"/>
46
- <path d="M39 31H42C44.2091 31 46 29.2091 46 27V17C46 14.7909 44.2091 13 42 13H24C21.7909 13 20 14.7909 20 17V27C20 29.2091 21.7909 31 24 31H30.0652C30.236 31 30.3282 31.2004 30.217 31.3302L27.5 34.5" stroke="#12CCF6" stroke-width="3.3" stroke-linecap="round"/>
47
- <path d="M27 25.5L32.5 21" stroke="#12CCF6" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
48
- </svg>
49
- <span class="panel-title-text">OpenAgent</span>
50
- </span>
51
- <button class="openagent-panel-close"><svg xmlns="http://www.w3.org/2000/svg" width="21" height="21" viewBox="0 0 21 21" fill="none"><path d="M5.625 5.625L15.375 15.375" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M15.375 5.625L5.625 15.375" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg></button>
52
- </div>
53
- <hr class="openagent-panel-divider" />
54
- <div class="openagent-agent-list">
55
- <div class="openagent-loading">加载中...</div>
56
- </div>
57
- `;
58
- panel.querySelector('.openagent-panel-close').addEventListener('click', () => {
59
- // ✕ 按钮关闭 = 用户主动关闭 → 触发 dismissed(同 ESC 意图)
60
- setDismissed();
61
- closePanel();
62
- });
63
-
64
-
65
- // 提示栏关闭按钮
66
- const hintClose = panel.querySelector('.openagent-hint-bar__close');
67
- if (hintClose) {
68
- hintClose.addEventListener('click', () => {
69
- const hintBar = panel.querySelector('.openagent-hint-bar');
70
- if (hintBar) hintBar.style.display = 'none';
71
- });
72
- }
73
- // 挂到 body(与 backdrop 同级,z-index 自然生效)
74
- document.body.appendChild(panel);
75
- return panel;
76
- }
77
-
78
- /** 根据 inputWrapper 位置动态定位 panel */
79
- function _positionPanel() {
80
- if (!panel || !inputWrapperRef) return;
81
- const rect = inputWrapperRef.getBoundingClientRect();
82
- const viewportPadding = 16;
83
- const width = Math.min(rect.width, window.innerWidth - viewportPadding * 2);
84
- const left = Math.max(viewportPadding, Math.min(rect.left, window.innerWidth - width - viewportPadding));
85
- panel.style.left = left + 'px';
86
- panel.style.width = width + 'px';
87
- const toolbar = _findPanelToolbar();
88
- const isComposerWrapper = inputWrapperRef.classList
89
- && inputWrapperRef.classList.contains('agent-chat__composer-combobox');
90
- if (isComposerWrapper) {
91
- panel.style.bottom = (_readElementHeight(inputWrapperRef) + _readElementHeight(toolbar) + 35) + 'px';
92
- } else {
93
- panel.style.bottom = (window.innerHeight - rect.top + 8) + 'px';
94
- }
95
- }
96
-
97
- /** resize 时实时跟随输入框 */
98
- function _onResize() { _positionPanel(); }
99
-
100
- function _findPanelToolbar() {
101
- if (!inputWrapperRef) return null;
102
- var chatInput = inputWrapperRef.closest && inputWrapperRef.closest('.agent-chat__input');
103
- if (chatInput) {
104
- var toolbar = chatInput.querySelector('.agent-chat__toolbar');
105
- if (toolbar) return toolbar;
106
- }
107
-
108
- var parentEl = inputWrapperRef.parentElement;
109
- if (parentEl) {
110
- for (var i = 0; i < parentEl.children.length; i++) {
111
- var child = parentEl.children[i];
112
- if (child !== inputWrapperRef && child.className && String(child.className).indexOf('agent-chat__toolbar') !== -1) {
113
- return child;
114
- }
115
- }
116
- }
117
- return null;
118
- }
119
-
120
- function _readElementHeight(el) {
121
- if (!el) return 0;
122
- var rect = el.getBoundingClientRect ? el.getBoundingClientRect() : null;
123
- if (rect && rect.height > 0) return rect.height;
124
- return typeof el.offsetHeight === 'number' ? el.offsetHeight : 0;
125
- }
126
-
127
- function _schedulePanelPosition() {
128
- window.requestAnimationFrame
129
- ? window.requestAnimationFrame(_positionPanel)
130
- : setTimeout(_positionPanel, 0);
131
- }
132
-
133
- function _installPanelPositionObservers() {
134
- if (panelPositionResizeObserver) {
135
- panelPositionResizeObserver.disconnect();
136
- panelPositionResizeObserver = null;
137
- }
138
- if (typeof ResizeObserver !== 'function' || !inputWrapperRef) return;
139
-
140
- panelPositionResizeObserver = new ResizeObserver(_schedulePanelPosition);
141
- panelPositionResizeObserver.observe(inputWrapperRef);
142
- var toolbar = _findPanelToolbar();
143
- if (toolbar) panelPositionResizeObserver.observe(toolbar);
144
- }
145
-
146
- function _teardownPanelPositionObservers() {
147
- if (!panelPositionResizeObserver) return;
148
- panelPositionResizeObserver.disconnect();
149
- panelPositionResizeObserver = null;
150
- }
151
-
152
- // 搜索状态管理
153
- let currentAbort = null; // AbortController for in-flight search
154
- let searchDebounceId = null;
155
-
156
- // ── @mention → systemProvenanceReceipt 状态 ──
157
- // 当用户从 Agent Book 选中一个 agent 时,保存其 metadata。
158
- // 下次 chat.send 时作为 systemProvenanceReceipt 注入,发送后清空。
159
-
160
- /**
161
- * 提取输入框文本作为搜索词(对齐 openagent-frontend NewChatPanel L82)
162
- * 去掉所有 @ 符号,合并空白
163
- */
164
- function extractSearchQuery(textarea) {
165
- if (!textarea) return '';
166
- return textarea.value.replace(/@/g, ' ').replace(/\s+/g, ' ').trim();
167
- }
168
-
169
- function openPanel(textarea) {
170
- // 清除上次的空状态弹窗
171
- var oldToast = document.querySelector('.openagent-empty-toast');
172
- if (oldToast) oldToast.remove();
173
- var oldEmpty = document.querySelector('.openagent-empty-state');
174
- if (oldEmpty) oldEmpty.remove();
175
-
176
- const p = ensurePanel();
177
- _positionPanel(); // 动态定位到 input 上方
178
- _installPanelPositionObservers();
179
- p.classList.add('visible');
180
- backdrop.classList.add('visible');
181
- window.addEventListener('resize', _onResize);
182
-
183
- const list = p.querySelector('.openagent-agent-list');
184
- list.innerHTML = '<div class="openagent-loading">加载中...</div>';
185
-
186
- // 提取当前输入文本作为搜索词
187
- const query = extractSearchQuery(textarea);
188
- console.log('[openagent] openPanel with search query:', JSON.stringify(query));
189
-
190
- if (query) {
191
- // 有输入文本 → 语义搜索
192
- searchAgents(query).then(agents => {
193
- if (!p.classList.contains('visible')) return;
194
- renderAgentList(list, agents, textarea, query);
195
- });
196
- } else {
197
- // 空输入 → 全量列表
198
- fetchAgentSections().then(agents => {
199
- if (!p.classList.contains('visible')) return;
200
- renderAgentList(list, agents, textarea, query);
201
- });
202
- }
203
- }
204
- /**
205
- * 实时搜索更新(debounce 300ms,对齐 MentionPickerPopup)
206
- * 当面板打开时,textarea 每次输入都会触发
207
- */
208
- function updatePanelSearch(textarea) {
209
- if (!panel || !panel.classList.contains('visible')) return;
210
-
211
- // 取消前一个请求
212
- if (currentAbort) currentAbort.abort();
213
- if (searchDebounceId) clearTimeout(searchDebounceId);
214
-
215
- const query = extractSearchQuery(textarea);
216
- const list = panel.querySelector('.openagent-agent-list');
217
-
218
- searchDebounceId = setTimeout(() => {
219
- currentAbort = new AbortController();
220
- const signal = currentAbort.signal;
221
-
222
- list.innerHTML = '<div class="openagent-loading">搜索中...</div>';
223
-
224
-
225
- const doSearch = query
226
- ? searchAgents(query, signal)
227
- : fetchAgentSections();
228
-
229
- doSearch.then(agents => {
230
- if (signal.aborted) return;
231
- if (!panel.classList.contains('visible')) return;
232
- renderAgentList(list, agents, textarea, query);
233
- });
234
- }, 300);
235
- }
236
-
237
- function closePanel() {
238
- if (panel) panel.classList.remove('visible');
239
- if (backdrop) backdrop.classList.remove('visible');
240
- window.removeEventListener('resize', _onResize);
241
- _teardownPanelPositionObservers();
242
- // 清理搜索状态
243
- if (currentAbort) { currentAbort.abort(); currentAbort = null; }
244
- if (searchDebounceId) { clearTimeout(searchDebounceId); searchDebounceId = null; }
245
- // 同步状态机(如果 dismissed 已由 setDismissed() 设置则不覆盖)
246
- closeMention();
247
- }
248
-
249
- // ── 键盘导航函数(§1.5)──
250
- // 对标 TIM index.ts:158-173 upHandler/downHandler/enterHandler
251
-
252
- function moveSelectionUp() {
253
- const len = _currentAgents.length;
254
- if (!len) return;
255
- selectedIndex = (selectedIndex + len - 1) % len;
256
- _highlightItem(selectedIndex);
257
- _scrollItemIntoView(selectedIndex);
258
- }
259
-
260
- function moveSelectionDown() {
261
- const len = _currentAgents.length;
262
- if (!len) return;
263
- selectedIndex = (selectedIndex + 1) % len;
264
- _highlightItem(selectedIndex);
265
- _scrollItemIntoView(selectedIndex);
266
- }
267
-
268
- function selectHighlightedAgent(textarea) {
269
- const agent = _currentAgents[selectedIndex];
270
- const ta = textarea || _currentTextarea;
271
- if (agent && ta) {
272
- insertMention(ta, agent.name, agent);
273
- resetMention(); // 选中 Agent = 正常完成,清空一切(不触发 dismissed)
274
- closePanel();
275
- }
276
- }
277
-
278
- function _highlightItem(index) {
279
- if (!panel) return;
280
- const cards = panel.querySelectorAll('.openagent-agent-list .agent-card');
281
- cards.forEach((c, i) => {
282
- c.classList.toggle('openagent-card-selected', i === index);
283
- });
284
- }
285
-
286
- function _scrollItemIntoView(index) {
287
- if (!panel) return;
288
- const cards = panel.querySelectorAll('.openagent-agent-list .agent-card');
289
- if (cards[index]) {
290
- cards[index].scrollIntoView({ block: 'nearest', behavior: 'smooth' });
291
- }
292
- }
293
-
294
- function _appendParentSection(container, parentTitle, children, textarea, renderedAgents) {
295
- const parentSec = _el('section', 'openagent-parent-section');
296
- children.forEach(function(child) {
297
- if (child.agents && child.agents.length > 0) {
298
- _appendAgentSection(parentSec, child.title, child.agents, textarea, renderedAgents);
299
- }
300
- });
301
- container.appendChild(parentSec);
302
- }
303
-
304
- function _appendAgentSection(container, title, agents, textarea, renderedAgents) {
305
- if (!agents.length) return;
306
- const section = _el('section', 'openagent-agent-section');
307
- section.appendChild(_text('div', 'openagent-section-heading', title));
308
-
309
- const grid = _el('div', 'openagent-section-grid');
310
- agents.forEach((a) => {
311
- const displayIndex = renderedAgents.length;
312
- const card = AgentCard(a, {
313
- mode: 'mention',
314
- onAction: () => {
315
- console.log('[openagent] onAction fired for:', a.name);
316
- insertMention(textarea, a.name, a);
317
- resetMention(); // 点击选中 = 正常完成,清空一切
318
- closePanel();
319
- }
320
- });
321
- card.dataset.tag = a.tag || '';
322
- card.dataset.name = a.name || '';
323
- card.dataset.index = displayIndex;
324
- grid.appendChild(card);
325
- renderedAgents.push(a);
326
-
327
- card.addEventListener('mousedown', () => console.log('[openagent] 🖱 mousedown on card:', a.name));
328
- const tryBtn = card.querySelector('.agent-card__action');
329
- if (tryBtn) {
330
- tryBtn.addEventListener('mousedown', (e) => {
331
- console.log('[openagent] 🖱 mousedown on Try btn:', a.name, 'target:', e.target.tagName, e.target.className);
332
- });
333
- }
334
- });
335
- section.appendChild(grid);
336
- container.appendChild(section);
337
- }
338
-
339
- function _appendSearchResults(container, agents, textarea, renderedAgents) {
340
- const list = _el('div', 'openagent-search-results');
341
- agents.forEach((a) => {
342
- const displayIndex = renderedAgents.length;
343
- const card = AgentCard(a, {
344
- mode: 'search',
345
- onAction: () => {
346
- insertMention(textarea, a.name, a);
347
- resetMention();
348
- closePanel();
349
- }
350
- });
351
- card.dataset.tag = a.tag || '';
352
- card.dataset.name = a.name || '';
353
- card.dataset.index = displayIndex;
354
- list.appendChild(card);
355
- renderedAgents.push(a);
356
- });
357
- container.appendChild(list);
358
- }
359
-
360
- /**
361
- * 空状态组件(Figma 144:3444)— 未匹配到 Agent 时显示
362
- */
363
- /** 关闭已有空状态浮层 */
364
- function _dismissEmptyToast() {
365
- var existing = document.querySelector('.openagent-empty-toast');
366
- if (existing) existing.remove();
367
- }
368
-
369
- /** 独立浮层空状态(不在面板内) */
370
- function _getEmptyMessage(query) {
371
- return CL.agentBookLastError ||
372
- (query ? '暂未匹配到您想要的Agent 我们将持续上新~' : '暂无在线 Agent,请输入关键词搜索');
373
- }
374
-
375
- function _showEmptyToast(query, message) {
376
- _dismissEmptyToast();
377
- var toast = _el('div', 'openagent-empty-toast');
378
-
379
- var iconWrap = _el('div', 'openagent-empty-state__icon');
380
- iconWrap.innerHTML = '<svg width="14" height="14" viewBox="0 0 14 14" fill="none">' +
381
- '<path d="M7 1.5C10.0376 1.5 12.5 3.96243 12.5 7C12.5 8.69527 11.7389 10.2145 10.5237 11.2559L13.0303 13.7626C13.3232 14.0555 13.3232 14.5303 13.0303 14.8232C12.7374 15.1161 12.2626 15.1161 11.9697 14.8232L9.38402 12.2376C8.53401 12.7803 7.49507 13.1079 6.37793 13.1079L7 12.5C6.99363 12.5008 6.98726 12.5012 6.98089 12.5012C3.9368 12.5307 1.46927 10.0632 1.49878 7.01908C1.52829 3.97499 3.99398 1.50537 7.03789 1.5H7ZM7 3C4.79086 3 3 4.79086 3 7C3 9.20914 4.79086 11 7 11C9.20914 11 11 9.20914 11 7C11 4.79086 9.20914 3 7 3Z" fill="#8274ff" fill-opacity="0.6"/>' +
382
- '</svg>';
383
- toast.appendChild(iconWrap);
384
-
385
- toast.appendChild(_text('span', 'openagent-empty-state__text', message || _getEmptyMessage(query)));
386
-
387
- var closeBtn = _el('button', 'openagent-empty-state__close');
388
- closeBtn.innerHTML = '<svg width="12" height="12" viewBox="0 0 12 12" fill="none">' +
389
- '<path d="M1 1L11 11M11 1L1 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/>' +
390
- '</svg>';
391
- closeBtn.addEventListener('click', function() { toast.remove(); });
392
- toast.appendChild(closeBtn);
393
-
394
- // 定位到输入框上方
395
- if (inputWrapperRef) {
396
- var rect = inputWrapperRef.getBoundingClientRect();
397
- toast.style.position = 'fixed';
398
- toast.style.left = Math.max(16, rect.left) + 'px';
399
- toast.style.width = Math.min(rect.width, window.innerWidth - 32) + 'px';
400
- toast.style.bottom = (window.innerHeight - rect.top + 8) + 'px';
401
- // ── V2 版本兼容:v1 bottom 固定 117px ──
402
- var isV2Toast = typeof _clIsHostVersionGte === 'function' && _clIsHostVersionGte('2026.6.9');
403
- if (!isV2Toast) {
404
- toast.style.bottom = '117px';
405
- }
406
- toast.style.zIndex = '100000';
407
- }
408
- document.body.appendChild(toast);
409
- }
410
-
411
- function _createEmptyState(query, message) {
412
- var wrapper = _el('div', 'openagent-empty-state');
413
- var row = _el('div', 'openagent-empty-state__row');
414
-
415
- var iconWrap = _el('div', 'openagent-empty-state__icon');
416
- iconWrap.innerHTML = '<svg width="14" height="14" viewBox="0 0 14 14" fill="none">' +
417
- '<path d="M7 1.5C10.0376 1.5 12.5 3.96243 12.5 7C12.5 8.69527 11.7389 10.2145 10.5237 11.2559L13.0303 13.7626C13.3232 14.0555 13.3232 14.5303 13.0303 14.8232C12.7374 15.1161 12.2626 15.1161 11.9697 14.8232L9.38402 12.2376C8.53401 12.7803 7.49507 13.1079 6.37793 13.1079L7 12.5C6.99363 12.5008 6.98726 12.5012 6.98089 12.5012C3.9368 12.5307 1.46927 10.0632 1.49878 7.01908C1.52829 3.97499 3.99398 1.50537 7.03789 1.5H7ZM7 3C4.79086 3 3 4.79086 3 7C3 9.20914 4.79086 11 7 11C9.20914 11 11 9.20914 11 7C11 4.79086 9.20914 3 7 3Z" fill="#8274ff" fill-opacity="0.6"/>' +
418
- '</svg>';
419
- row.appendChild(iconWrap);
420
-
421
- var text = _text('span', 'openagent-empty-state__text', message || _getEmptyMessage(query));
422
- row.appendChild(text);
423
-
424
- var closeBtn = _el('button', 'openagent-empty-state__close');
425
- closeBtn.innerHTML = '<svg width="12" height="12" viewBox="0 0 12 12" fill="none">' +
426
- '<path d="M1 1L11 11M11 1L1 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/>' +
427
- '</svg>';
428
- closeBtn.addEventListener('click', function() {
429
- wrapper.style.display = 'none';
430
- });
431
- row.appendChild(closeBtn);
432
-
433
- wrapper.appendChild(row);
434
- return wrapper;
435
- }
436
-
437
- function renderAgentList(container, agents, textarea, query) {
438
- if (!agents.length) {
439
- var emptyMessage = _getEmptyMessage(query);
440
- _currentAgents = [];
441
- _currentTextarea = textarea;
442
- closePanel();
443
- _showEmptyToast(query, emptyMessage);
444
- return;
445
- }
446
-
447
- console.log('[openagent] renderAgentList:', agents.length, 'agents, textarea:', !!textarea);
448
-
449
- container.innerHTML = '';
450
- _currentTextarea = textarea;
451
-
452
- const renderedAgents = [];
453
- const normalizedQuery = (query || '').trim();
454
- if (normalizedQuery) {
455
- _appendSearchResults(container, agents, textarea, renderedAgents);
456
- } else {
457
- agents.forEach(section => {
458
- if (section.children && section.children.length > 0) {
459
- _appendParentSection(container, section.title, section.children, textarea, renderedAgents);
460
- } else {
461
- _appendAgentSection(container, section.title, section.agents || [], textarea, renderedAgents);
462
- }
463
- });
464
- }
465
-
466
- // 保存 DOM 顺序中的 agents 列表,供键盘导航使用
467
- _currentAgents = renderedAgents;
468
-
469
- // 默认高亮第一项(§1.5 默认选中)
470
- // 对标 TIM index.ts:13 "selectedIndex = 0" + index.vue:32 ":class=[index===selectedIndex&&'selected']"
471
- selectedIndex = 0;
472
- _highlightItem(0);
473
- }
474
-
475
- /**
476
- * 选中 Agent 后插入 @name 到 textarea
477
- * 对齐 openagent-frontend NewChatPanel L92-105:
478
- * 找到最后一个 @,替换其后内容为 @agentName
479
- */
480
- function _pickMentionAgentDescription(agent) {
481
- if (!agent || typeof agent !== 'object') return '';
482
- if (CL && typeof CL.pickAgentIdentityDescription === 'function') {
483
- return CL.pickAgentIdentityDescription(agent);
484
- }
485
- const keys = ['agent_bio', 'agentBio', 'bio', 'description', 'desc', 'agent_description', 'agentDescription', 'MOM', 'mom'];
486
- for (let i = 0; i < keys.length; i++) {
487
- const value = agent[keys[i]];
488
- if (typeof value === 'string' && value.trim()) return value.trim();
489
- }
490
- return '';
491
- }
492
-
493
- function insertMention(textarea, agentName, agentData) {
494
- // 重新查找 textarea(Lit 可能重新渲染导致引用失效)
495
- const liveTextarea = document.querySelector(
496
- 'textarea[placeholder*="Message"]'
497
- ) || document.querySelector(
498
- 'textarea[placeholder*="Enter to send"]'
499
- ) || textarea;
500
-
501
- console.log('[openagent] insertMention:', agentName,
502
- 'textarea found:', !!liveTextarea,
503
- 'same ref:', liveTextarea === textarea);
504
-
505
- if (!liveTextarea) return;
506
- liveTextarea.focus();
507
-
508
- // 存储 agent 信息,发送时替换为 {openagent:...} 标记
509
- const agentId = agentData?.agent_id || agentData?.agentId || agentData?.id || agentData?.tag ||
510
- agentData?.user_id || agentData?.userId || agentData?.identifier || agentData?.tim_user_id || agentData?.timUserId || '';
511
- const agentAvatar = agentData?.avatar || agentData?.avatar_url || agentData?.avatarUrl || agentData?.image || agentData?.logo || agentData?.photo || null;
512
- const agentBio = _pickMentionAgentDescription(agentData);
513
- console.log('[cl-diag][mention-select]', {
514
- agentName,
515
- resolvedAgentId: agentId || null,
516
- hasAgentBio: !!agentBio,
517
- rawKeys: Object.keys(agentData || {}),
518
- rawAgent: agentData,
519
- });
520
- if (!agentId) {
521
- CL.pendingMention = null;
522
- console.warn('[openagent] mention skipped: missing agent identifier for', agentName, agentData);
523
- return;
524
- }
525
- CL.pendingMention = { agent_id: agentId, name: agentName, avatar: agentAvatar, agent_bio: agentBio };
526
- if (CL && typeof CL.storeAgentIdentity === 'function') {
527
- CL.storeAgentIdentity(Object.assign({}, agentData || {}, {
528
- agent_id: agentId,
529
- name: agentName,
530
- avatar: agentAvatar,
531
- agent_bio: agentBio,
532
- }));
533
- }
534
- console.log('[openagent] mention stored:', CL.pendingMention);
535
-
536
- // textarea 显示 @agentName(用户友好)
537
- const val = liveTextarea.value;
538
- const lastAtIndex = val.lastIndexOf('@');
539
- let newValue;
540
- if (lastAtIndex !== -1) {
541
- const before = val.slice(0, lastAtIndex).trimEnd();
542
- newValue = before ? `${before} @${agentName} ` : `@${agentName} `;
543
- } else {
544
- newValue = `${val}@${agentName} `;
545
- }
546
-
547
- // 设置值
548
- const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
549
- HTMLTextAreaElement.prototype, 'value'
550
- )?.set;
551
- if (nativeInputValueSetter) {
552
- nativeInputValueSetter.call(liveTextarea, newValue);
553
- } else {
554
- liveTextarea.value = newValue;
555
- }
556
-
557
- // 光标到末尾
558
- liveTextarea.selectionStart = liveTextarea.selectionEnd = newValue.length;
559
-
560
- // 触发事件让 Lit 识别变化
561
- liveTextarea.dispatchEvent(new Event('input', { bubbles: true }));
562
- liveTextarea.dispatchEvent(new Event('change', { bubbles: true }));
563
-
564
- // 标记替换由 window.__clMention.onKeyDown 在 OC 注入钩子中处理
565
- // 不再需要独立的 _installSendInterceptor
566
- }
567
-
568
- // _installSendInterceptor 已移除(v3)
569
- // 标记替换逻辑迁移到 inject-ui.js → window.__clMention.onKeyDown
570
- // 在 OC 的 handleKeyDown 钩子中执行,优先级在 slash menu 之后、Enter 发送之前