openclaw-openagent 1.0.9 → 1.0.11

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.
@@ -14,6 +14,26 @@
14
14
  const fs = require('fs');
15
15
  const path = require('path');
16
16
 
17
+ // ── 读取 OpenClaw 版本(用于注入到产物中)──
18
+ function resolveHostVersion() {
19
+ // 优先使用环境变量
20
+ if (process.env.OPENCLAW_HOST_VERSION) return process.env.OPENCLAW_HOST_VERSION;
21
+
22
+ // 从 package.json devDependencies 读取
23
+ try {
24
+ var pkgPath = path.join(__dirname, '..', 'package.json');
25
+ if (fs.existsSync(pkgPath)) {
26
+ var pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
27
+ var ver = (pkg.devDependencies && pkg.devDependencies.openclaw) || '';
28
+ // 去掉 ^ 前缀: "^2026.4.22" → "2026.4.22"
29
+ ver = String(ver).replace(/^[\^~>=<]+/, '').trim();
30
+ if (ver) return ver;
31
+ }
32
+ } catch (e) {}
33
+
34
+ return '2026.4.22'; // 默认 fallback
35
+ }
36
+
17
37
  // ═══════════════════════════════════════════════════════════════
18
38
  // MANIFEST — 显式构建顺序,不要用 readdir+sort
19
39
  // 新增模块必须在此注册,否则不进产物
@@ -58,7 +78,10 @@ const MANIFEST = [
58
78
  // ═══════════════════════════════════════════════════════════════
59
79
 
60
80
  const modulesDir = path.join(__dirname, 'modules');
61
- const outFile = path.join(__dirname, 'assets', 'openagent-override.js');
81
+ const assetsDir = path.join(__dirname, 'assets');
82
+ const outFile = path.join(assetsDir, 'openagent-override.js');
83
+ const iconFile = path.join(assetsDir, 'icon.png');
84
+ const bgFile = path.join(assetsDir, 'bg.png');
62
85
 
63
86
  const HEADER = `/**
64
87
  * OpenAgent UI Override — Auto-generated, do not edit directly!
@@ -107,7 +130,9 @@ function build() {
107
130
  return;
108
131
  }
109
132
 
110
- const output = HEADER + body + FOOTER;
133
+ // ── 不做构建时版本注入,由运行时 DOM/CSS 特征检测 ──
134
+ // (build.cjs 无法知道实际运行的 OpenClaw 版本)
135
+ var output = HEADER + body + FOOTER;
111
136
 
112
137
  fs.mkdirSync(path.dirname(outFile), { recursive: true });
113
138
  fs.writeFileSync(outFile, output, 'utf-8');
@@ -123,11 +148,19 @@ function build() {
123
148
 
124
149
  const DEPLOY_TARGETS = [
125
150
  // 插件安装目录(Gateway 启动时从这里读取并复制到 control-ui)
126
- // 注意:安装目录仍使用旧路径 src/inject/,下次 npm publish 后才会变
127
151
  path.join(homedir, '.openclaw-docker/extensions/openclaw-openagent/src/inject/assets/openagent-override.js'),
128
152
  path.join(homedir, '.openclaw-docker/extensions/openclaw-openagent/src/plugin-ui/assets/openagent-override.js'),
129
153
  path.join(homedir, '.openclaw/extensions/openclaw-openagent/src/inject/assets/openagent-override.js'),
130
154
  path.join(homedir, '.openclaw/extensions/openclaw-openagent/src/plugin-ui/assets/openagent-override.js'),
155
+ // 本地开发 dist/ 目录
156
+ path.join(__dirname, '..', '..', 'dist', 'src', 'plugin-ui', 'assets', 'openagent-override.js'),
157
+ // 本地 node_modules 中的 openclaw control-ui(Gateway 实际运行路径)
158
+ path.join(__dirname, '..', '..', 'node_modules', 'openclaw', 'dist', 'control-ui', 'openagent-override.js'),
159
+ // npm 全局安装 + 项目缓存(Gateway 可能从这些路径加载)
160
+ path.join(homedir, '.openclaw/npm/projects/openclaw-openagent/node_modules/openclaw-openagent/src/plugin-ui/assets/openagent-override.js'),
161
+ path.join(homedir, '.openclaw/npm/projects/openclaw-openagent/node_modules/openclaw-openagent/dist/src/plugin-ui/assets/openagent-override.js'),
162
+ path.join(homedir, '.nvm/versions/node/v22.21.1/lib/node_modules/openclaw-openagent/src/plugin-ui/assets/openagent-override.js'),
163
+ path.join(homedir, '.nvm/versions/node/v22.21.1/lib/node_modules/openclaw-openagent/dist/src/plugin-ui/assets/openagent-override.js'),
131
164
  ];
132
165
 
133
166
  // 动态发现 control-ui 目录(通过 node 可执行文件路径推断)
@@ -149,10 +182,52 @@ function build() {
149
182
  }
150
183
 
151
184
  if (deployed > 0) {
152
- console.log(`✅ Auto-deployed to ${deployed} target(s)`);
185
+ console.log(`✅ Auto-deployed override to ${deployed} target(s)`);
153
186
  } else {
154
187
  console.log('ℹ️ No deploy targets found (standalone build)');
155
188
  }
189
+
190
+ // ── Shared asset deploy targets (control-ui + extension dirs) ──
191
+ const ASSET_DEPLOY_TARGETS = [
192
+ path.join(homedir, '.openclaw-docker/extensions/openclaw-openagent/src/inject/assets'),
193
+ path.join(homedir, '.openclaw-docker/extensions/openclaw-openagent/src/plugin-ui/assets'),
194
+ path.join(homedir, '.openclaw/extensions/openclaw-openagent/src/inject/assets'),
195
+ path.join(homedir, '.openclaw/extensions/openclaw-openagent/src/plugin-ui/assets'),
196
+ path.join(__dirname, '..', '..', 'dist', 'src', 'plugin-ui', 'assets'),
197
+ path.join(__dirname, '..', '..', 'node_modules', 'openclaw', 'dist', 'control-ui'),
198
+ path.join(homedir, '.openclaw/npm/projects/openclaw-openagent/node_modules/openclaw-openagent/src/plugin-ui/assets'),
199
+ path.join(homedir, '.openclaw/npm/projects/openclaw-openagent/node_modules/openclaw-openagent/dist/src/plugin-ui/assets'),
200
+ path.join(homedir, '.nvm/versions/node/v22.21.1/lib/node_modules/openclaw-openagent/src/plugin-ui/assets'),
201
+ path.join(homedir, '.nvm/versions/node/v22.21.1/lib/node_modules/openclaw-openagent/dist/src/plugin-ui/assets'),
202
+ ];
203
+
204
+ try {
205
+ const nodeDir = path.dirname(process.execPath);
206
+ ASSET_DEPLOY_TARGETS.push(path.resolve(path.join(nodeDir, '..', 'lib', 'node_modules', 'openclaw', 'dist', 'control-ui')));
207
+ } catch {}
208
+
209
+ // ── Deploy image assets (icon.png, bg.png) ──
210
+ const IMAGE_ASSETS = [
211
+ { file: iconFile, name: 'icon.png' },
212
+ { file: bgFile, name: 'bg.png' },
213
+ ];
214
+
215
+ for (const asset of IMAGE_ASSETS) {
216
+ if (!fs.existsSync(asset.file)) continue;
217
+ let deployed = 0;
218
+ for (const dir of ASSET_DEPLOY_TARGETS) {
219
+ try {
220
+ const dest = path.join(dir, asset.name);
221
+ if (fs.existsSync(dir)) {
222
+ fs.copyFileSync(asset.file, dest);
223
+ deployed++;
224
+ }
225
+ } catch {}
226
+ }
227
+ if (deployed > 0) {
228
+ console.log(`✅ Auto-deployed ${asset.name} to ${deployed} target(s)`);
229
+ }
230
+ }
156
231
  }
157
232
 
158
233
  // ── Execution ──
@@ -45,9 +45,9 @@ panel.innerHTML = `
45
45
  <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
46
  <path d="M27 25.5L32.5 21" stroke="#12CCF6" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
47
47
  </svg>
48
- <span class="panel-title-text">Agent Book</span>
48
+ <span class="panel-title-text">OpenAgent</span>
49
49
  </span>
50
- <button class="openagent-panel-close">✕</button>
50
+ <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
51
  </div>
52
52
  <hr class="openagent-panel-divider" />
53
53
  <div class="openagent-agent-list">
@@ -60,6 +60,15 @@ panel.querySelector('.openagent-panel-close').addEventListener('click', () => {
60
60
  closePanel();
61
61
  });
62
62
 
63
+
64
+ // 提示栏关闭按钮
65
+ const hintClose = panel.querySelector('.openagent-hint-bar__close');
66
+ if (hintClose) {
67
+ hintClose.addEventListener('click', () => {
68
+ const hintBar = panel.querySelector('.openagent-hint-bar');
69
+ if (hintBar) hintBar.style.display = 'none';
70
+ });
71
+ }
63
72
  // 挂到 body(与 backdrop 同级,z-index 自然生效)
64
73
  document.body.appendChild(panel);
65
74
  return panel;
@@ -98,6 +107,12 @@ return textarea.value.replace(/@/g, ' ').replace(/\s+/g, ' ').trim();
98
107
  }
99
108
 
100
109
  function openPanel(textarea) {
110
+ // 清除上次的空状态弹窗
111
+ var oldToast = document.querySelector('.openagent-empty-toast');
112
+ if (oldToast) oldToast.remove();
113
+ var oldEmpty = document.querySelector('.openagent-empty-state');
114
+ if (oldEmpty) oldEmpty.remove();
115
+
101
116
  const p = ensurePanel();
102
117
  _positionPanel(); // 动态定位到 input 上方
103
118
  p.classList.add('visible');
@@ -281,14 +296,82 @@ function _appendSearchResults(container, agents, textarea, renderedAgents) {
281
296
  container.appendChild(list);
282
297
  }
283
298
 
299
+ /**
300
+ * 空状态组件(Figma 144:3444)— 未匹配到 Agent 时显示
301
+ */
302
+ /** 关闭已有空状态浮层 */
303
+ function _dismissEmptyToast() {
304
+ var existing = document.querySelector('.openagent-empty-toast');
305
+ if (existing) existing.remove();
306
+ }
307
+
308
+ /** 独立浮层空状态(不在面板内) */
309
+ function _showEmptyToast(query) {
310
+ _dismissEmptyToast();
311
+ var toast = _el('div', 'openagent-empty-toast');
312
+
313
+ var iconWrap = _el('div', 'openagent-empty-state__icon');
314
+ iconWrap.innerHTML = '<svg width="14" height="14" viewBox="0 0 14 14" fill="none">' +
315
+ '<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"/>' +
316
+ '</svg>';
317
+ toast.appendChild(iconWrap);
318
+
319
+ toast.appendChild(_text('span', 'openagent-empty-state__text',
320
+ query ? '暂未匹配到您想要的Agent 我们将持续上新~' : '暂无在线 Agent,请输入关键词搜索'));
321
+
322
+ var closeBtn = _el('button', 'openagent-empty-state__close');
323
+ closeBtn.innerHTML = '<svg width="12" height="12" viewBox="0 0 12 12" fill="none">' +
324
+ '<path d="M1 1L11 11M11 1L1 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/>' +
325
+ '</svg>';
326
+ closeBtn.addEventListener('click', function() { toast.remove(); });
327
+ toast.appendChild(closeBtn);
328
+
329
+ // 定位到输入框上方
330
+ if (inputWrapperRef) {
331
+ var rect = inputWrapperRef.getBoundingClientRect();
332
+ toast.style.position = 'fixed';
333
+ toast.style.left = Math.max(16, rect.left) + 'px';
334
+ toast.style.width = Math.min(rect.width, window.innerWidth - 32) + 'px';
335
+ toast.style.bottom = (window.innerHeight - rect.top + 8) + 'px';
336
+ toast.style.zIndex = '100000';
337
+ }
338
+ document.body.appendChild(toast);
339
+ }
340
+
341
+ function _createEmptyState(query) {
342
+ var wrapper = _el('div', 'openagent-empty-state');
343
+ var row = _el('div', 'openagent-empty-state__row');
344
+
345
+ var iconWrap = _el('div', 'openagent-empty-state__icon');
346
+ iconWrap.innerHTML = '<svg width="14" height="14" viewBox="0 0 14 14" fill="none">' +
347
+ '<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"/>' +
348
+ '</svg>';
349
+ row.appendChild(iconWrap);
350
+
351
+ var text = _text('span', 'openagent-empty-state__text',
352
+ query ? '暂未匹配到您想要的Agent 我们将持续上新~' : '暂无在线 Agent,请输入关键词搜索');
353
+ row.appendChild(text);
354
+
355
+ var closeBtn = _el('button', 'openagent-empty-state__close');
356
+ closeBtn.innerHTML = '<svg width="12" height="12" viewBox="0 0 12 12" fill="none">' +
357
+ '<path d="M1 1L11 11M11 1L1 11" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/>' +
358
+ '</svg>';
359
+ closeBtn.addEventListener('click', function() {
360
+ wrapper.style.display = 'none';
361
+ });
362
+ row.appendChild(closeBtn);
363
+
364
+ wrapper.appendChild(row);
365
+ return wrapper;
366
+ }
367
+
284
368
  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;
369
+ if (!agents.length) {
370
+ _currentAgents = [];
371
+ _currentTextarea = textarea;
372
+ closePanel();
373
+ _showEmptyToast(query);
374
+ return;
292
375
  }
293
376
 
294
377
  console.log('[openagent] renderAgentList:', agents.length, 'agents, textarea:', !!textarea);
@@ -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;' };
@@ -220,6 +220,8 @@ function tryInject() {
220
220
  const pos = ta.selectionStart;
221
221
  // 如果光标前已经是 @,不重复插入
222
222
  if (pos > 0 && val[pos - 1] === '@') {
223
+ // 按钮主动触发 → 清除 dismissed 状态,确保弹窗能打开
224
+ if (typeof resetMention === 'function') resetMention();
223
225
  _handleStateChange(ta);
224
226
  return;
225
227
  }
@@ -278,9 +280,53 @@ function tryInject() {
278
280
 
279
281
  console.log('[openagent] ✅ Agent Book UI injected (v3 hook-driven)');
280
282
 
283
+ // ── 提示栏(Figma 141:3293):页面加载即显示 ──
284
+ _injectHintBar(inputContainer || textarea.parentElement);
285
+
281
286
  return true;
282
287
  }
283
288
 
289
+ /** 注入提示栏到输入区域上方 */
290
+ function _injectHintBar(anchorEl) {
291
+ if (!anchorEl || document.querySelector('.openagent-hint-bar')) return;
292
+
293
+ const hintBar = document.createElement('div');
294
+ hintBar.className = 'openagent-hint-bar';
295
+ hintBar.innerHTML = '' +
296
+ '<div class="openagent-hint-bar__content">' +
297
+ '<div class="openagent-hint-bar__icon">' +
298
+ '<svg xmlns="http://www.w3.org/2000/svg" width="27" height="27" viewBox="0 0 27 27" fill="none">' +
299
+ '<rect width="27" height="27" rx="6" fill="url(#paint0_linear_141_3277)" fill-opacity="0.1"/>' +
300
+ '<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)"/>' +
301
+ '<defs>' +
302
+ '<linearGradient id="paint0_linear_141_3277" x1="0" y1="13.5" x2="27" y2="13.5" gradientUnits="userSpaceOnUse">' +
303
+ '<stop stop-color="#8274FF"/>' +
304
+ '<stop offset="1" stop-color="#3890FF"/>' +
305
+ '</linearGradient>' +
306
+ '<linearGradient id="paint1_linear_141_3277" x1="7.5" y1="13.8759" x2="20.9999" y2="13.8759" gradientUnits="userSpaceOnUse">' +
307
+ '<stop stop-color="#8274FF"/>' +
308
+ '<stop offset="1" stop-color="#3890FF"/>' +
309
+ '</linearGradient>' +
310
+ '</defs>' +
311
+ '</svg>' +
312
+ '</div>' +
313
+ '<span class="openagent-hint-bar__text">输入你的需求,调配远端Agent为你解决</span>' +
314
+ '</div>' +
315
+ '<button class="openagent-hint-bar__close">' +
316
+ '<svg xmlns="http://www.w3.org/2000/svg" width="21" height="21" viewBox="0 0 21 21" fill="none">' +
317
+ '<path d="M5.625 5.625L15.375 15.375" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>' +
318
+ '<path d="M15.375 5.625L5.625 15.375" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>' +
319
+ '</svg>' +
320
+ '</button>';
321
+
322
+ hintBar.querySelector('.openagent-hint-bar__close').addEventListener('click', () => {
323
+ hintBar.style.display = 'none';
324
+ });
325
+
326
+ // 插入到 wrapper 外面、上方
327
+ anchorEl.parentElement.insertBefore(hintBar, anchorEl);
328
+ }
329
+
284
330
  // ════════════════════════════════════════════════════════════════
285
331
  // ── window.__clMention — OC 注入钩子的桥接对象 ──
286
332
  // ════════════════════════════════════════════════════════════════