openclaw-openagent 1.0.9 → 1.0.12

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 (64) hide show
  1. package/dist/index.js +1 -1
  2. package/dist/src/app/remote-agent-tool.js +110 -14
  3. package/dist/src/app/types.d.ts +2 -2
  4. package/dist/src/plugin-ui/adapters/adapters/oc-2026-04.js +103 -0
  5. package/dist/src/plugin-ui/adapters/adapters/oc-2026-05.js +125 -0
  6. package/dist/src/plugin-ui/adapters/adapters/oc-2026-06.js +125 -0
  7. package/dist/src/plugin-ui/adapters/adapters/oc-unknown.js +48 -0
  8. package/dist/src/plugin-ui/adapters/oc-2026-04.js +103 -0
  9. package/dist/src/plugin-ui/adapters/oc-2026-05.js +125 -0
  10. package/dist/src/plugin-ui/adapters/oc-2026-06.js +125 -0
  11. package/dist/src/plugin-ui/adapters/oc-unknown.js +48 -0
  12. package/dist/src/plugin-ui/assets/bg.png +0 -0
  13. package/dist/src/plugin-ui/assets/icon.png +0 -0
  14. package/dist/src/plugin-ui/assets/openagent-override.js +2480 -1004
  15. package/dist/src/plugin-ui/index.d.ts +1 -1
  16. package/dist/src/plugin-ui/index.js +2 -2
  17. package/dist/src/plugin-ui/ui-extension-loader/index.d.ts +2 -1
  18. package/dist/src/plugin-ui/ui-extension-loader/index.js +5 -5
  19. package/dist/src/plugin-ui/ui-extension-loader/registry-regex.js +128 -13
  20. package/dist/src/plugin-ui/ui-extension-loader/types.d.ts +4 -1
  21. package/dist/src/state/store.d.ts +21 -0
  22. package/dist/src/state/store.js +54 -0
  23. package/dist/src/transport/oasn/oasn-invocation.d.ts +3 -0
  24. package/dist/src/transport/oasn/oasn-invocation.js +28 -12
  25. package/dist/src/transport/oasn/oasn-types.d.ts +8 -4
  26. package/index.ts +1 -1
  27. package/openclaw.plugin.json +1 -1
  28. package/package.json +5 -4
  29. package/src/app/remote-agent-tool.ts +131 -16
  30. package/src/app/types.ts +2 -2
  31. package/src/plugin-ui/adapters/oc-2026-04.js +103 -0
  32. package/src/plugin-ui/adapters/oc-2026-05.js +125 -0
  33. package/src/plugin-ui/adapters/oc-2026-06.js +125 -0
  34. package/src/plugin-ui/adapters/oc-unknown.js +48 -0
  35. package/src/plugin-ui/assets/bg.png +0 -0
  36. package/src/plugin-ui/assets/icon.png +0 -0
  37. package/src/plugin-ui/assets/openagent-override.js +2480 -1004
  38. package/src/plugin-ui/build.cjs +309 -23
  39. package/src/plugin-ui/index.ts +2 -2
  40. package/src/plugin-ui/modules/agent-book/panel/agent-book.js +187 -14
  41. package/src/plugin-ui/modules/agent-book/panel/agent-card.js +26 -10
  42. package/src/plugin-ui/modules/agent-book/panel/agent-data.js +1 -1
  43. package/src/plugin-ui/modules/agent-book/panel/inject-ui.js +149 -1
  44. package/src/plugin-ui/modules/agent-book/panel/styles.js +352 -210
  45. package/src/plugin-ui/modules/agent-book/remote-agent-tool/components-core.js +4 -2
  46. package/src/plugin-ui/modules/agent-book/remote-agent-tool/thought-chain-card.js +4 -1
  47. package/src/plugin-ui/modules/agent-book/scanner.js +17 -5
  48. package/src/plugin-ui/modules/agent-book/travelcard/travel-styles.js +5 -0
  49. package/src/plugin-ui/modules/loader/bootstrap.js +1 -1
  50. package/src/plugin-ui/modules/loader/shared-state.js +278 -0
  51. package/src/plugin-ui/modules/remote-agent/execution-card.js +385 -124
  52. package/src/plugin-ui/modules/remote-agent/native-style-adapter.js +5 -23
  53. package/src/plugin-ui/modules/remote-agent/output-card.js +97 -31
  54. package/src/plugin-ui/modules/remote-agent/render-hooks.js +149 -58
  55. package/src/plugin-ui/modules/remote-agent/styles.js +690 -523
  56. package/src/plugin-ui/modules/remote-agent/tool-card-model.js +77 -3
  57. package/src/plugin-ui/postinstall-deploy.cjs +52 -0
  58. package/src/plugin-ui/ui-extension-loader/index.ts +6 -6
  59. package/src/plugin-ui/ui-extension-loader/registry-regex.ts +131 -14
  60. package/src/plugin-ui/ui-extension-loader/types.ts +5 -1
  61. package/src/state/store.ts +80 -0
  62. package/src/transport/oasn/oasn-invocation.ts +47 -12
  63. package/src/transport/oasn/oasn-types.ts +6 -2
  64. package/src/types/openclaw-plugin-sdk-media-store.d.ts +9 -0
@@ -6,6 +6,7 @@ let panel = null;
6
6
  let backdrop = null;
7
7
 
8
8
  let inputWrapperRef = null; // 保存输入框包裹层引用
9
+ let panelPositionResizeObserver = null;
9
10
 
10
11
  // ── 键盘导航状态(§1.5)──
11
12
  // 对标 TIM index.ts:13 "let selectedIndex: number = 0"
@@ -40,14 +41,14 @@ panel.className = 'openagent-agent-panel';
40
41
  panel.innerHTML = `
41
42
  <div class="openagent-panel-head">
42
43
  <span class="openagent-panel-title">
43
- <svg class="openagent-panel-title-icon" width="28" height="28" viewBox="0 0 56 56" fill="none">
44
+ <svg class="openagent-panel-title-icon" width="24" height="24" viewBox="0 0 56 56" fill="none">
44
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"/>
45
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"/>
46
47
  <path d="M27 25.5L32.5 21" stroke="#12CCF6" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
47
48
  </svg>
48
- <span class="panel-title-text">Agent Book</span>
49
+ <span class="panel-title-text">OpenAgent</span>
49
50
  </span>
50
- <button class="openagent-panel-close">✕</button>
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>
51
52
  </div>
52
53
  <hr class="openagent-panel-divider" />
53
54
  <div class="openagent-agent-list">
@@ -60,6 +61,15 @@ panel.querySelector('.openagent-panel-close').addEventListener('click', () => {
60
61
  closePanel();
61
62
  });
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
+ }
63
73
  // 挂到 body(与 backdrop 同级,z-index 自然生效)
64
74
  document.body.appendChild(panel);
65
75
  return panel;
@@ -74,12 +84,71 @@ const width = Math.min(rect.width, window.innerWidth - viewportPadding * 2);
74
84
  const left = Math.max(viewportPadding, Math.min(rect.left, window.innerWidth - width - viewportPadding));
75
85
  panel.style.left = left + 'px';
76
86
  panel.style.width = width + 'px';
77
- panel.style.bottom = (window.innerHeight - rect.top + 8) + '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
+ }
78
95
  }
79
96
 
80
97
  /** resize 时实时跟随输入框 */
81
98
  function _onResize() { _positionPanel(); }
82
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
+
83
152
  // 搜索状态管理
84
153
  let currentAbort = null; // AbortController for in-flight search
85
154
  let searchDebounceId = null;
@@ -98,8 +167,15 @@ return textarea.value.replace(/@/g, ' ').replace(/\s+/g, ' ').trim();
98
167
  }
99
168
 
100
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
+
101
176
  const p = ensurePanel();
102
177
  _positionPanel(); // 动态定位到 input 上方
178
+ _installPanelPositionObservers();
103
179
  p.classList.add('visible');
104
180
  backdrop.classList.add('visible');
105
181
  window.addEventListener('resize', _onResize);
@@ -162,6 +238,7 @@ function closePanel() {
162
238
  if (panel) panel.classList.remove('visible');
163
239
  if (backdrop) backdrop.classList.remove('visible');
164
240
  window.removeEventListener('resize', _onResize);
241
+ _teardownPanelPositionObservers();
165
242
  // 清理搜索状态
166
243
  if (currentAbort) { currentAbort.abort(); currentAbort = null; }
167
244
  if (searchDebounceId) { clearTimeout(searchDebounceId); searchDebounceId = null; }
@@ -216,7 +293,6 @@ function _scrollItemIntoView(index) {
216
293
 
217
294
  function _appendParentSection(container, parentTitle, children, textarea, renderedAgents) {
218
295
  const parentSec = _el('section', 'openagent-parent-section');
219
- parentSec.appendChild(_text('div', 'openagent-parent-heading', parentTitle));
220
296
  children.forEach(function(child) {
221
297
  if (child.agents && child.agents.length > 0) {
222
298
  _appendAgentSection(parentSec, child.title, child.agents, textarea, renderedAgents);
@@ -281,14 +357,91 @@ function _appendSearchResults(container, agents, textarea, renderedAgents) {
281
357
  container.appendChild(list);
282
358
  }
283
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
+
284
437
  function renderAgentList(container, agents, textarea, query) {
285
- if (!agents.length) {
286
- const message = CL.agentBookLastError || '暂无在线 Agent';
287
- container.innerHTML = '';
288
- container.appendChild(_text('div', 'openagent-loading', message));
289
- _currentAgents = [];
290
- _currentTextarea = textarea;
291
- return;
438
+ if (!agents.length) {
439
+ var emptyMessage = _getEmptyMessage(query);
440
+ _currentAgents = [];
441
+ _currentTextarea = textarea;
442
+ closePanel();
443
+ _showEmptyToast(query, emptyMessage);
444
+ return;
292
445
  }
293
446
 
294
447
  console.log('[openagent] renderAgentList:', agents.length, 'agents, textarea:', !!textarea);
@@ -324,6 +477,19 @@ _highlightItem(0);
324
477
  * 对齐 openagent-frontend NewChatPanel L92-105:
325
478
  * 找到最后一个 @,替换其后内容为 @agentName
326
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
+
327
493
  function insertMention(textarea, agentName, agentData) {
328
494
  // 重新查找 textarea(Lit 可能重新渲染导致引用失效)
329
495
  const liveTextarea = document.querySelector(
@@ -343,9 +509,11 @@ liveTextarea.focus();
343
509
  const agentId = agentData?.agent_id || agentData?.agentId || agentData?.id || agentData?.tag ||
344
510
  agentData?.user_id || agentData?.userId || agentData?.identifier || agentData?.tim_user_id || agentData?.timUserId || '';
345
511
  const agentAvatar = agentData?.avatar || agentData?.avatar_url || agentData?.avatarUrl || agentData?.image || agentData?.logo || agentData?.photo || null;
512
+ const agentBio = _pickMentionAgentDescription(agentData);
346
513
  console.log('[cl-diag][mention-select]', {
347
514
  agentName,
348
515
  resolvedAgentId: agentId || null,
516
+ hasAgentBio: !!agentBio,
349
517
  rawKeys: Object.keys(agentData || {}),
350
518
  rawAgent: agentData,
351
519
  });
@@ -354,9 +522,14 @@ if (!agentId) {
354
522
  console.warn('[openagent] mention skipped: missing agent identifier for', agentName, agentData);
355
523
  return;
356
524
  }
357
- CL.pendingMention = { agent_id: agentId, name: agentName, avatar: agentAvatar };
525
+ CL.pendingMention = { agent_id: agentId, name: agentName, avatar: agentAvatar, agent_bio: agentBio };
358
526
  if (CL && typeof CL.storeAgentIdentity === 'function') {
359
- CL.storeAgentIdentity({ agent_id: agentId, name: agentName, avatar: agentAvatar });
527
+ CL.storeAgentIdentity(Object.assign({}, agentData || {}, {
528
+ agent_id: agentId,
529
+ name: agentName,
530
+ avatar: agentAvatar,
531
+ agent_bio: agentBio,
532
+ }));
360
533
  }
361
534
  console.log('[openagent] mention stored:', CL.pendingMention);
362
535
 
@@ -44,17 +44,23 @@ function AgentCard(agent, opts = {}) {
44
44
  info.appendChild(_text('div', 'agent-card__name', agent.name || ''));
45
45
  info.appendChild(_text('div', 'agent-card__bio', agent.bio || '暂无简介'));
46
46
  const stats = _el('div', 'agent-card__stats');
47
- stats.appendChild(_text('span', 'agent-card__stat agent-card__stat--claws', `${formatNumber(agent.claws)}☆`));
47
+ // 星标 + 数字 紧密组合(Figma gap 1.5px)
48
+ const statGroup = _el('span', 'agent-card__stat-group');
49
+ var starIcon = _el('span', 'agent-card__stat-icon');
50
+ starIcon.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M5.94531 0.525391C6.08953 0.525551 6.20334 0.604267 6.25098 0.701172L7.59668 3.43262L7.71875 3.68066L7.99121 3.7207L11.0859 4.16992V4.1709H11.0869C11.1865 4.18536 11.2656 4.2375 11.3135 4.30371L11.3506 4.37402C11.3752 4.44422 11.3691 4.52183 11.3301 4.58984L11.2803 4.6543L9.01172 6.86914L8.81543 7.06152L8.86133 7.33301L9.3877 10.4043C9.40428 10.501 9.36472 10.6085 9.26172 10.6797C9.20158 10.7197 9.13 10.7412 9.05762 10.7412C9.00017 10.7412 8.94132 10.7275 8.8877 10.7002L6.18945 9.2793L5.94531 9.15039L5.7002 9.2793L3.00684 10.6982C2.95198 10.7266 2.89097 10.7412 2.83203 10.7412C2.77821 10.7412 2.72454 10.7298 2.67578 10.707L2.62891 10.6797C2.52556 10.6083 2.48649 10.5012 2.50293 10.4053V10.4043L3.0293 7.33301L3.0752 7.06152L2.87793 6.86914L0.611328 4.6543L0.610352 4.65332L0.560547 4.58984C0.521516 4.522 0.515166 4.44401 0.540039 4.37305L0.539062 4.37207C0.573747 4.27569 0.671018 4.18999 0.803711 4.1709L0.804688 4.16992L3.89844 3.7207L4.17188 3.68066L4.29395 3.43262L5.63867 0.702148C5.68788 0.603278 5.80274 0.525391 5.94531 0.525391Z" stroke="#666666" stroke-width="1.05"/></svg>';
51
+ statGroup.appendChild(starIcon);
52
+ statGroup.appendChild(_text('span', 'agent-card__stat agent-card__stat--claws', formatNumber(agent.claws)));
53
+ stats.appendChild(statGroup);
48
54
  if (agent.owner) {
49
- stats.appendChild(_text('span', 'agent-card__stat agent-card__stat--owner', ` · owner${agent.owner}`));
55
+ stats.appendChild(_text('span', 'agent-card__stat agent-card__stat--owner', ` · ${agent.owner}`));
50
56
  }
51
57
  info.appendChild(stats);
52
58
  contentGroup.appendChild(info);
53
59
 
54
60
  row1.appendChild(contentGroup);
55
61
 
56
- // @Try 按钮
57
- const defaultLabel = 'Try';
62
+ // @召唤 按钮
63
+ const defaultLabel = '@召唤';
58
64
  const btn = _text('button', 'agent-card__action', actionLabel || defaultLabel);
59
65
  if (onAction) {
60
66
  btn.addEventListener('click', (e) => {
@@ -90,14 +96,19 @@ function AgentCard(agent, opts = {}) {
90
96
  body.appendChild(_text('div', 'agent-card__bio', agent.bio || '暂无简介'));
91
97
 
92
98
  const stats = _el('div', 'agent-card__stats');
93
- stats.appendChild(_text('span', 'agent-card__stat agent-card__stat--claws', `${formatNumber(agent.claws)}☆`));
99
+ const statGroup = _el('span', 'agent-card__stat-group');
100
+ var starIcon = _el('span', 'agent-card__stat-icon');
101
+ starIcon.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M5.94531 0.525391C6.08953 0.525551 6.20334 0.604267 6.25098 0.701172L7.59668 3.43262L7.71875 3.68066L7.99121 3.7207L11.0859 4.16992V4.1709H11.0869C11.1865 4.18536 11.2656 4.2375 11.3135 4.30371L11.3506 4.37402C11.3752 4.44422 11.3691 4.52183 11.3301 4.58984L11.2803 4.6543L9.01172 6.86914L8.81543 7.06152L8.86133 7.33301L9.3877 10.4043C9.40428 10.501 9.36472 10.6085 9.26172 10.6797C9.20158 10.7197 9.13 10.7412 9.05762 10.7412C9.00017 10.7412 8.94132 10.7275 8.8877 10.7002L6.18945 9.2793L5.94531 9.15039L5.7002 9.2793L3.00684 10.6982C2.95198 10.7266 2.89097 10.7412 2.83203 10.7412C2.77821 10.7412 2.72454 10.7298 2.67578 10.707L2.62891 10.6797C2.52556 10.6083 2.48649 10.5012 2.50293 10.4053V10.4043L3.0293 7.33301L3.0752 7.06152L2.87793 6.86914L0.611328 4.6543L0.610352 4.65332L0.560547 4.58984C0.521516 4.522 0.515166 4.44401 0.540039 4.37305L0.539062 4.37207C0.573747 4.27569 0.671018 4.18999 0.803711 4.1709L0.804688 4.16992L3.89844 3.7207L4.17188 3.68066L4.29395 3.43262L5.63867 0.702148C5.68788 0.603278 5.80274 0.525391 5.94531 0.525391Z" stroke="#666666" stroke-width="1.05"/></svg>';
102
+ statGroup.appendChild(starIcon);
103
+ statGroup.appendChild(_text('span', 'agent-card__stat agent-card__stat--claws', formatNumber(agent.claws)));
104
+ stats.appendChild(statGroup);
94
105
  if (agent.owner) {
95
- stats.appendChild(_text('span', 'agent-card__stat agent-card__stat--owner', ` · owner${agent.owner}`));
106
+ stats.appendChild(_text('span', 'agent-card__stat agent-card__stat--owner', ` · ${agent.owner}`));
96
107
  }
97
108
  body.appendChild(stats);
98
109
  card.appendChild(body);
99
110
 
100
- const btn = _text('button', 'agent-card__action', actionLabel || 'Try');
111
+ const btn = _text('button', 'agent-card__action', actionLabel || '@召唤');
101
112
  if (onAction) {
102
113
  btn.addEventListener('click', (e) => {
103
114
  e.stopPropagation();
@@ -134,14 +145,19 @@ function AgentCard(agent, opts = {}) {
134
145
  body.appendChild(_text('div', 'agent-card__bio', agent.bio || '暂无简介'));
135
146
 
136
147
  const stats = _el('div', 'agent-card__stats');
137
- stats.appendChild(_text('span', 'agent-card__stat agent-card__stat--claws', `${formatNumber(agent.claws)}☆`));
148
+ const statGroup = _el('span', 'agent-card__stat-group');
149
+ var starIcon = _el('span', 'agent-card__stat-icon');
150
+ starIcon.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M5.94531 0.525391C6.08953 0.525551 6.20334 0.604267 6.25098 0.701172L7.59668 3.43262L7.71875 3.68066L7.99121 3.7207L11.0859 4.16992V4.1709H11.0869C11.1865 4.18536 11.2656 4.2375 11.3135 4.30371L11.3506 4.37402C11.3752 4.44422 11.3691 4.52183 11.3301 4.58984L11.2803 4.6543L9.01172 6.86914L8.81543 7.06152L8.86133 7.33301L9.3877 10.4043C9.40428 10.501 9.36472 10.6085 9.26172 10.6797C9.20158 10.7197 9.13 10.7412 9.05762 10.7412C9.00017 10.7412 8.94132 10.7275 8.8877 10.7002L6.18945 9.2793L5.94531 9.15039L5.7002 9.2793L3.00684 10.6982C2.95198 10.7266 2.89097 10.7412 2.83203 10.7412C2.77821 10.7412 2.72454 10.7298 2.67578 10.707L2.62891 10.6797C2.52556 10.6083 2.48649 10.5012 2.50293 10.4053V10.4043L3.0293 7.33301L3.0752 7.06152L2.87793 6.86914L0.611328 4.6543L0.610352 4.65332L0.560547 4.58984C0.521516 4.522 0.515166 4.44401 0.540039 4.37305L0.539062 4.37207C0.573747 4.27569 0.671018 4.18999 0.803711 4.1709L0.804688 4.16992L3.89844 3.7207L4.17188 3.68066L4.29395 3.43262L5.63867 0.702148C5.68788 0.603278 5.80274 0.525391 5.94531 0.525391Z" stroke="#666666" stroke-width="1.05"/></svg>';
151
+ statGroup.appendChild(starIcon);
152
+ statGroup.appendChild(_text('span', 'agent-card__stat agent-card__stat--claws', formatNumber(agent.claws)));
153
+ stats.appendChild(statGroup);
138
154
  if (agent.owner) {
139
- stats.appendChild(_text('span', 'agent-card__stat agent-card__stat--owner', ` · owner${agent.owner}`));
155
+ stats.appendChild(_text('span', 'agent-card__stat agent-card__stat--owner', ` · ${agent.owner}`));
140
156
  }
141
157
  body.appendChild(stats);
142
158
  card.appendChild(body);
143
159
 
144
- const btn = _text('button', 'agent-card__action', actionLabel || '@ Chat');
160
+ const btn = _text('button', 'agent-card__action', actionLabel || '@召唤');
145
161
  if (onAction) {
146
162
  btn.addEventListener('click', (e) => { e.stopPropagation(); onAction(agent); });
147
163
  card.addEventListener('click', (e) => { e.stopPropagation(); onAction(agent); });
@@ -619,7 +619,7 @@ function avatarUrl(agent) {
619
619
  if (agent.avatar.startsWith('http')) return agent.avatar;
620
620
  return CL.AUTH_API + '/' + agent.avatar;
621
621
  }
622
- return `https://ui-avatars.com/api/?name=${encodeURIComponent(agent.name)}&background=random&size=64`;
622
+ return './icon.png';
623
623
  }
624
624
 
625
625
  const ESC_MAP = { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' };
@@ -34,12 +34,27 @@ function _setTextareaValue(textarea, value) {
34
34
  textarea.dispatchEvent(new Event('input', { bubbles: true }));
35
35
  }
36
36
 
37
+ function _escapeRemoteAgentMarkerValue(value) {
38
+ return String(value || '')
39
+ .replace(/\s+/g, ' ')
40
+ .trim()
41
+ .replace(/"/g, "'");
42
+ }
43
+
37
44
  function _buildRemoteAgentMarker(mention, userText) {
38
45
  const hasChinese = /[\u4e00-\u9fff]/.test(userText || '');
39
46
  const instruction = hasChinese
40
47
  ? '请调用 openagent_call_remote_agent 工具将此请求转发给远端 Agent 处理'
41
48
  : 'Please invoke the openagent_call_remote_agent tool to forward this request to the remote agent';
42
- return `{openagent_call_remote_agent:agent_id="${mention.agent_id}",agent_name="${mention.name}",instruction="${instruction}"}`;
49
+ const attrs = [
50
+ `agent_id="${_escapeRemoteAgentMarkerValue(mention.agent_id)}"`,
51
+ `agent_name="${_escapeRemoteAgentMarkerValue(mention.name)}"`,
52
+ ];
53
+ if (mention.agent_bio) {
54
+ attrs.push(`agent_bio="${_escapeRemoteAgentMarkerValue(mention.agent_bio)}"`);
55
+ }
56
+ attrs.push(`instruction="${_escapeRemoteAgentMarkerValue(instruction)}"`);
57
+ return `{openagent_call_remote_agent:${attrs.join(',')}}`;
43
58
  }
44
59
 
45
60
  function _composeRemoteAgentMessage(textarea, mention) {
@@ -220,6 +235,8 @@ function tryInject() {
220
235
  const pos = ta.selectionStart;
221
236
  // 如果光标前已经是 @,不重复插入
222
237
  if (pos > 0 && val[pos - 1] === '@') {
238
+ // 按钮主动触发 → 清除 dismissed 状态,确保弹窗能打开
239
+ if (typeof resetMention === 'function') resetMention();
223
240
  _handleStateChange(ta);
224
241
  return;
225
242
  }
@@ -278,9 +295,140 @@ function tryInject() {
278
295
 
279
296
  console.log('[openagent] ✅ Agent Book UI injected (v3 hook-driven)');
280
297
 
298
+ // ── 提示栏(Figma 141:3293):页面加载即显示 ──
299
+ _injectHintBar(inputContainer || textarea.parentElement, toolbarRow);
300
+
281
301
  return true;
282
302
  }
283
303
 
304
+ /** 注入提示栏到输入区域上方 */
305
+ function _injectHintBar(anchorEl, toolbarEl) {
306
+ if (!anchorEl || document.querySelector('.openagent-hint-bar')) return;
307
+
308
+ const hintBar = document.createElement('div');
309
+ hintBar.className = 'openagent-hint-bar';
310
+ hintBar.innerHTML = '' +
311
+ '<div class="openagent-hint-bar__content">' +
312
+ '<div class="openagent-hint-bar__icon">' +
313
+ '<svg xmlns="http://www.w3.org/2000/svg" width="27" height="27" viewBox="0 0 27 27" fill="none">' +
314
+ '<rect width="27" height="27" rx="6" fill="url(#paint0_linear_141_3277)" fill-opacity="0.1"/>' +
315
+ '<path d="M13.5 6.75098C16.8137 6.75098 19.5 9.43727 19.5 12.751C19.5 14.3288 18.8894 15.7629 17.8936 16.834L20.7803 19.7207C21.0732 20.0136 21.0732 20.4884 20.7803 20.7812C20.4874 21.0741 20.0126 21.0741 19.7197 20.7812L16.7383 17.7998C15.8038 18.4004 14.6933 18.751 13.5 18.751C10.1863 18.751 7.5 16.0647 7.5 12.751C7.5 9.43727 10.1863 6.75098 13.5 6.75098ZM13.5 8.25098C11.0147 8.25098 9 10.2657 9 12.751C9 15.2363 11.0147 17.251 13.5 17.251C15.9853 17.251 18 15.2363 18 12.751C18 10.2657 15.9853 8.25098 13.5 8.25098Z" fill="url(#paint1_linear_141_3277)"/>' +
316
+ '<defs>' +
317
+ '<linearGradient id="paint0_linear_141_3277" x1="0" y1="13.5" x2="27" y2="13.5" gradientUnits="userSpaceOnUse">' +
318
+ '<stop stop-color="#8274FF"/>' +
319
+ '<stop offset="1" stop-color="#3890FF"/>' +
320
+ '</linearGradient>' +
321
+ '<linearGradient id="paint1_linear_141_3277" x1="7.5" y1="13.8759" x2="20.9999" y2="13.8759" gradientUnits="userSpaceOnUse">' +
322
+ '<stop stop-color="#8274FF"/>' +
323
+ '<stop offset="1" stop-color="#3890FF"/>' +
324
+ '</linearGradient>' +
325
+ '</defs>' +
326
+ '</svg>' +
327
+ '</div>' +
328
+ '<span class="openagent-hint-bar__text">输入你的需求,调配远端Agent为你解决</span>' +
329
+ '</div>' +
330
+ '<button class="openagent-hint-bar__close">' +
331
+ '<svg xmlns="http://www.w3.org/2000/svg" width="21" height="21" viewBox="0 0 21 21" fill="none">' +
332
+ '<path d="M5.625 5.625L15.375 15.375" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>' +
333
+ '<path d="M15.375 5.625L5.625 15.375" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>' +
334
+ '</svg>' +
335
+ '</button>';
336
+
337
+ hintBar.querySelector('.openagent-hint-bar__close').addEventListener('click', () => {
338
+ hintBar.style.display = 'none';
339
+ });
340
+
341
+ // ── V2 版本兼容:≥ 2026.6.9 使用 absolute 定位,bottom 动态跟随输入区高度 ──
342
+ var isV2 = typeof _clIsHostVersionGte === 'function' && _clIsHostVersionGte('2026.6.9');
343
+ if (isV2) {
344
+ hintBar.style.position = 'absolute';
345
+ }
346
+
347
+ // 插入到 wrapper 外面、上方
348
+ anchorEl.parentElement.insertBefore(hintBar, anchorEl);
349
+
350
+ function _findHintBarToolbar() {
351
+ if (toolbarEl) return toolbarEl;
352
+ var parentEl = anchorEl.parentElement;
353
+ if (parentEl) {
354
+ for (var i = 0; i < parentEl.children.length; i++) {
355
+ var child = parentEl.children[i];
356
+ if (child !== anchorEl && child.className && String(child.className).indexOf('agent-chat__toolbar') !== -1) {
357
+ return child;
358
+ }
359
+ }
360
+ }
361
+ return anchorEl.closest && anchorEl.closest('.agent-chat__input')
362
+ ? anchorEl.closest('.agent-chat__input').querySelector('.agent-chat__toolbar')
363
+ : null;
364
+ }
365
+
366
+ function _readElementHeight(el) {
367
+ if (!el) return 0;
368
+ var rect = el.getBoundingClientRect ? el.getBoundingClientRect() : null;
369
+ if (rect && rect.height > 0) return rect.height;
370
+ return typeof el.offsetHeight === 'number' ? el.offsetHeight : 0;
371
+ }
372
+
373
+ // 跟随 composer wrapper 的实际尺寸。侧栏拖拽/布局重排不一定触发 window resize。
374
+ function _syncHintBarLayout() {
375
+ var rect = anchorEl.getBoundingClientRect();
376
+ if (rect.width > 0) {
377
+ hintBar.style.width = rect.width + 'px';
378
+ var rootStyle = document.documentElement && document.documentElement.style;
379
+ if (rootStyle) {
380
+ rootStyle.setProperty('--openagent-input-wrapper-right-offset', Math.max(0, window.innerWidth - rect.right) + 'px');
381
+ rootStyle.setProperty('--openagent-input-wrapper-right-edge', Math.max(0, rect.right) + 'px');
382
+ rootStyle.setProperty('--openagent-input-wrapper-width', rect.width + 'px');
383
+ }
384
+ _syncSidebarRightEdge(rect);
385
+ }
386
+ if (isV2) {
387
+ var toolbar = _findHintBarToolbar();
388
+ var bottom = _readElementHeight(anchorEl) + _readElementHeight(toolbar) + 6;
389
+ hintBar.style.bottom = bottom + 'px';
390
+ }
391
+ }
392
+
393
+ function _syncSidebarRightEdge(inputRect) {
394
+ var sidebars = document.querySelectorAll('.chat-sidebar');
395
+ for (var i = 0; i < sidebars.length; i++) {
396
+ var sidebar = sidebars[i];
397
+ var sidebarRect = sidebar.getBoundingClientRect();
398
+ if (!sidebarRect || sidebarRect.width <= 0) continue;
399
+ var left = Math.max(0, sidebarRect.left);
400
+ var targetRight = Math.min(window.innerWidth, Math.max(0, inputRect.right));
401
+ var targetWidth = Math.floor(targetRight - left);
402
+ if (targetWidth <= 0) continue;
403
+ sidebar.style.setProperty('--openagent-sidebar-target-width', targetWidth + 'px');
404
+ sidebar.style.setProperty('width', targetWidth + 'px', 'important');
405
+ sidebar.style.setProperty('max-width', targetWidth + 'px', 'important');
406
+ sidebar.style.setProperty('flex-basis', targetWidth + 'px', 'important');
407
+ sidebar.style.setProperty('margin-right', '0px', 'important');
408
+ }
409
+ }
410
+
411
+ function _scheduleHintBarLayoutSync() {
412
+ window.requestAnimationFrame
413
+ ? window.requestAnimationFrame(_syncHintBarLayout)
414
+ : setTimeout(_syncHintBarLayout, 0);
415
+ }
416
+
417
+ _syncHintBarLayout();
418
+ _scheduleHintBarLayoutSync();
419
+ window.addEventListener('resize', _scheduleHintBarLayoutSync);
420
+ if (typeof ResizeObserver === 'function') {
421
+ var hintBarResizeObserver = new ResizeObserver(_scheduleHintBarLayoutSync);
422
+ hintBarResizeObserver.observe(anchorEl);
423
+ var toolbarForResize = _findHintBarToolbar();
424
+ if (toolbarForResize) hintBarResizeObserver.observe(toolbarForResize);
425
+ }
426
+ if (typeof MutationObserver === 'function' && document.body) {
427
+ var sidebarLayoutObserver = new MutationObserver(_scheduleHintBarLayoutSync);
428
+ sidebarLayoutObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['class'] });
429
+ }
430
+ }
431
+
284
432
  // ════════════════════════════════════════════════════════════════
285
433
  // ── window.__clMention — OC 注入钩子的桥接对象 ──
286
434
  // ════════════════════════════════════════════════════════════════