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.
@@ -5,7 +5,7 @@ var _clObserverTarget = null;
5
5
 
6
6
  const _clObserver = new MutationObserver(() => {
7
7
  if (_clDebounceTimer) clearTimeout(_clDebounceTimer);
8
- _clDebounceTimer = setTimeout(_debouncedClScan, 50); // Reduced from 500ms to 50ms to fix UI flash
8
+ _clDebounceTimer = setTimeout(_debouncedClScan, 300); // Debounce to reduce DOM churn feedback loops
9
9
  });
10
10
 
11
11
  function _debouncedClScan() {
@@ -31,6 +31,9 @@ const CL = {
31
31
  handleDelegateWsEvent: function(msg) {},
32
32
  processCustomCards: function(bubble) {},
33
33
 
34
+ // ── Host 版本(构建时注入,fallback 运行时检测)──
35
+ hostVersion: '__OPENCLAW_HOST_VERSION__',
36
+
34
37
  // ── 配置 ──
35
38
  OPENAGENT_API: 'https://api.openagent.club',
36
39
  AUTH_API: '/plugins/openagent', // Proxied via Gateway registerHttpRoute (see src/proxy/auth-proxy.ts)
@@ -39,6 +42,57 @@ const CL = {
39
42
  CACHE_TTL: 30000,
40
43
  };
41
44
 
45
+ // ── 版本解析与比较(供 execution-card V2 分支使用)──
46
+
47
+ function _clParseHostVersion(v) {
48
+ if (!v) return [0, 0, 0];
49
+ var base = String(v).split('-')[0];
50
+ var parts = base.split('.');
51
+ if (parts.length !== 3) return [0, 0, 0];
52
+ var y = parseInt(parts[0], 10);
53
+ var m = parseInt(parts[1], 10);
54
+ var d = parseInt(parts[2], 10);
55
+ if (isNaN(y) || isNaN(m) || isNaN(d)) return [0, 0, 0];
56
+ return [y, m, d];
57
+ }
58
+
59
+ function _clIsHostVersionGte(minVer) {
60
+ var cur = _clParseHostVersion(CL.hostVersion || '');
61
+ var min = _clParseHostVersion(minVer);
62
+ for (var i = 0; i < 3; i++) {
63
+ if (cur[i] > min[i]) return true;
64
+ if (cur[i] < min[i]) return false;
65
+ }
66
+ return true;
67
+ }
68
+
69
+ // ─ 运行时 fallback:当构建时未注入版本,通过 CSS/DOM 特征检测 ──
70
+ // v5.x (2026.5+) 有 data-theme 属性和 --glass-surface CSS 变量
71
+ // v4.x (2026.3-4.x) 有 data-theme-mode 属性和 --vscode-* CSS 变量
72
+ if (CL.hostVersion === '__OPENCLAW_HOST_VERSION__' || !CL.hostVersion) {
73
+ try {
74
+ if (document.documentElement.hasAttribute('data-theme')) {
75
+ // v5.x (2026.5+) — 有 data-theme 属性
76
+ CL.hostVersion = '2026.6.9';
77
+ } else if (document.documentElement.hasAttribute('data-theme-mode')) {
78
+ // v4.x — 有 data-theme-mode 属性
79
+ CL.hostVersion = '2026.4.0';
80
+ } else {
81
+ var cs = getComputedStyle(document.documentElement);
82
+ if (cs.getPropertyValue('--glass-surface').trim()) {
83
+ CL.hostVersion = '2026.6.9';
84
+ } else if (cs.getPropertyValue('--vscode-editor-background').trim()) {
85
+ CL.hostVersion = '2026.4.0';
86
+ } else {
87
+ CL.hostVersion = '2026.3.0';
88
+ }
89
+ }
90
+ console.log('[cl-version] detected via DOM/CSS features: ' + CL.hostVersion);
91
+ } catch (e) {
92
+ CL.hostVersion = '2026.3.0';
93
+ }
94
+ }
95
+
42
96
  // 暴露到 window 供控制台调试/测试
43
97
  window.__CL = CL;
44
98
 
@@ -11,6 +11,11 @@
11
11
  // UI 结构使用 shared thought-chain styles,数据来源是 RenderHook model。
12
12
 
13
13
  function _clRenderExecutionCard(model) {
14
+ // ── V2 版本判断:≥ 2026.6.9 启用新版 UI ──
15
+ if (typeof _clIsHostVersionGte === 'function' && _clIsHostVersionGte('2026.6.9')) {
16
+ return _clRenderExecutionCardV2(model);
17
+ }
18
+
14
19
  var container = document.createElement('div');
15
20
  container.className = 'cl-remote-agent-card cl-thought-chain';
16
21
  if (CL && typeof CL.diagMarkCard === 'function') {
@@ -20,111 +25,45 @@ function _clRenderExecutionCard(model) {
20
25
  container.appendChild(_clCreateOpenAgentHeader(model));
21
26
 
22
27
  var content = document.createElement('div');
23
- content.className = 'cl-thought-chain-content cl-thought-chain-content--execution';
28
+ content.className = 'cl-thought-chain-content cl-thought-chain-content--execution cl-content-collapsed';
24
29
  container.appendChild(content);
25
30
 
26
- // ── Agent Pill ──
27
- console.log('[cl-exec] 🏷️ agentName=' + JSON.stringify(model.agentName) + ' agentId=' + JSON.stringify(model.agentId));
28
- var pillSlot = document.createElement('div');
29
- pillSlot.className = 'cl-thought-chain-pill-slot';
30
- var pill = _clCreateAgentPill(model.agentName, model.agentId, model.agentAvatar);
31
- pillSlot.appendChild(pill);
32
- content.appendChild(pillSlot);
33
-
34
- // ── 分隔线 ──
35
- var divider = document.createElement('div');
36
- divider.className = 'cl-thought-chain-divider';
37
- content.appendChild(divider);
38
-
39
- // ── 思考步骤区 ──
40
- var stepsSection = document.createElement('div');
41
- stepsSection.className = 'cl-thought-chain-steps-section';
42
-
43
- // 标题栏
44
- var header = document.createElement('div');
45
- header.className = 'cl-tools-collapse-header';
46
-
47
- var headerIcon = document.createElement('span');
48
- headerIcon.className = 'cl-tools-collapse-header-icon';
49
- headerIcon.textContent = '▼';
50
-
51
- var headerTitle = document.createElement('span');
52
- headerTitle.className = 'cl-tools-collapse-header-title';
53
-
54
- // 从 chunks 提取步骤
55
- var steps = [];
56
- for (var i = 0; i < model.chunks.length; i++) {
57
- var chunk = model.chunks[i];
58
- if (chunk.type === 'step') {
59
- steps.push({ title: chunk.title, detail: chunk.detail || '' });
60
- }
61
- }
62
-
63
- // 合并预缓冲步骤(WS 先于 Lit 渲染到达时)
64
- if (model._bufferedSteps && model._bufferedSteps.length > 0) {
65
- steps = model._bufferedSteps;
66
- }
67
- if (typeof _cl_compactThoughtSteps === 'function') {
68
- steps = _cl_compactThoughtSteps(steps);
31
+ // ── Agent 详情卡片(Figma 346:181) ──
32
+ try {
33
+ var detailCard = _clCreateAgentDetailCard(model);
34
+ content.appendChild(detailCard);
35
+ } catch(e) {
36
+ console.warn('[cl-exec] detail card creation failed:', e);
69
37
  }
70
38
 
71
- headerTitle.textContent = '思考中...';
72
-
73
- header.appendChild(headerIcon);
74
- header.appendChild(headerTitle);
75
-
76
- // 步骤列表(可折叠)
77
- var body = document.createElement('div');
78
- body.className = 'cl-tools-collapse-body cl-expanded';
79
-
80
- for (var si = 0; si < steps.length; si++) {
81
- var isLatest = (si === steps.length - 1);
82
- var stepEl = _clCreateStepElement(steps[si], isLatest);
83
- body.appendChild(stepEl);
84
- }
85
-
86
- // 折叠/展开
87
- header.style.cursor = 'pointer';
88
- header.addEventListener('click', function(evt) {
89
- evt.stopPropagation(); // 防止外层容器拦截
90
- var isExpanded = body.classList.contains('cl-expanded');
91
- console.log('[cl-exec] 🖱️ header click: expanded=' + isExpanded + ' bodyChildren=' + body.childElementCount);
92
- if (isExpanded) {
93
- body.classList.remove('cl-expanded');
94
- body.classList.add('cl-collapsed');
95
- headerIcon.classList.add('cl-collapsed');
96
- if (typeof _cl_setCardUiState === 'function') {
97
- _cl_setCardUiState(model, { stepsExpanded: false });
98
- }
99
- } else {
100
- body.classList.remove('cl-collapsed');
101
- body.classList.add('cl-expanded');
102
- headerIcon.classList.remove('cl-collapsed');
103
- if (typeof _cl_setCardUiState === 'function') {
104
- _cl_setCardUiState(model, { stepsExpanded: true });
105
- }
106
- }
107
- });
108
-
109
- stepsSection.appendChild(header);
110
- stepsSection.appendChild(body);
111
- content.appendChild(stepsSection);
39
+ // ── 进度文字(Figma 346:253) — 动态读取 response.progress?.safe_status_message ──
40
+ var progressRow = document.createElement('div');
41
+ progressRow.className = 'cl-exec-progress-row';
42
+ var progressText = document.createElement('p');
43
+ progressText.className = 'cl-exec-progress-text';
44
+ progressText.textContent = (model.progressMessage || model.rawText || '').trim() || '思考中,正在了解你的需求';
45
+ progressRow.appendChild(progressText);
46
+ // 箭头图标
47
+ var arrowIcon = document.createElement('span');
48
+ arrowIcon.className = 'cl-exec-progress-arrow';
49
+ arrowIcon.innerHTML = '<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M5 4L9 7L5 10" stroke="#555" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg>';
50
+ progressRow.appendChild(arrowIcon);
51
+ content.appendChild(progressRow);
52
+ if (model.status === 'completed') progressRow.style.display = 'none';
112
53
 
113
54
  // ── 异步更新真实 Agent 身份 ──
114
55
  if ((model.agentId || model.agentName) && typeof fetchAgentById === 'function') {
115
56
  fetchAgentById(model.agentId, model.agentName).then(function(agent) {
116
57
  if (!agent) return;
117
- var pa = container.querySelector('.cl-agent-pill-avatar');
118
- var pn = container.querySelector('.cl-agent-pill-name');
119
- if (pa && typeof avatarUrl === 'function') {
120
- var resolvedAvatar = avatarUrl(agent);
121
- console.log('[cl-diag][pill] fetch-update agentId=' + JSON.stringify(model.agentId)
122
- + ' name=' + JSON.stringify(agent.name || model.agentName)
123
- + ' src=' + JSON.stringify(resolvedAvatar));
124
- pa.src = resolvedAvatar;
125
- pa.style.display = '';
126
- }
127
- _clSetAgentPillName(container, agent.name || model.agentName);
58
+ var avatarEl = container.querySelector('.cl-exec-agent-avatar');
59
+ var nameEl = container.querySelector('.cl-exec-agent-name');
60
+ var bioEl = container.querySelector('.cl-exec-agent-bio');
61
+ // avatar 保持 icon.png,不覆盖
62
+ if (nameEl) nameEl.textContent = agent.name || model.agentName;
63
+ if (bioEl && (agent.bio || agent.description)) bioEl.textContent = agent.bio || agent.description;
64
+ var starsEl = container.querySelector('.cl-exec-star-count');
65
+ if (starsEl && agent.claws) starsEl.textContent = _cl_formatStarCount(agent.claws);
66
+ if (starsEl && agent.stars && !agent.claws) starsEl.textContent = _cl_formatStarCount(agent.stars);
128
67
  _clSetOpenAgentHeaderAgent(container, agent.name || model.agentName);
129
68
  }).catch(function() {});
130
69
  }
@@ -133,40 +72,103 @@ function _clRenderExecutionCard(model) {
133
72
  _cl_applyCardUiState(container, model);
134
73
  }
135
74
 
136
- console.log('[cl-exec] execution card built: steps=' + steps.length);
75
+ console.log('[cl-exec] execution card built');
137
76
  return container;
138
77
  }
139
78
 
79
+ // ── Agent 详情卡片(Figma 266:11136) ──
80
+ function _clCreateAgentDetailCard(model) {
81
+ var card = document.createElement('div');
82
+ card.className = 'cl-exec-detail-card';
83
+
84
+ var row = document.createElement('div');
85
+ row.className = 'cl-exec-detail-row';
86
+
87
+ // 头像 68×68
88
+ var avatar = document.createElement('img');
89
+ avatar.className = 'cl-exec-agent-avatar';
90
+ avatar.alt = model.agentName || '';
91
+ avatar.src = './icon.png';
92
+ avatar.onerror = function() { this.style.visibility = 'hidden'; };
93
+ row.appendChild(avatar);
94
+
95
+ // 信息列
96
+ var info = document.createElement('div');
97
+ info.className = 'cl-exec-detail-info';
98
+
99
+ // 名称行:名称 + 星级徽章
100
+ var nameRow = document.createElement('div');
101
+ nameRow.className = 'cl-exec-name-row';
102
+
103
+ var nameEl = document.createElement('p');
104
+ nameEl.className = 'cl-exec-agent-name';
105
+ nameEl.textContent = model.agentName || 'Remote Agent';
106
+ nameRow.appendChild(nameEl);
107
+
108
+ // 星级徽章
109
+ var starBadge = document.createElement('div');
110
+ starBadge.className = 'cl-exec-star-badge';
111
+ var starSvgOutline = '<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M7 1.16L8.356 5.33H12.78L9.195 7.94L10.565 12.1L7 9.51L3.435 12.1L4.805 7.94L1.22 5.33H5.644L7 1.16Z" stroke="#999" stroke-width="0.8"/></svg>';
112
+ starBadge.innerHTML = starSvgOutline +
113
+ '<span class="cl-exec-star-count">' + (model.agentStars || '3.2万') + '</span>';
114
+ nameRow.appendChild(starBadge);
115
+ info.appendChild(nameRow);
116
+
117
+ var bioEl = document.createElement('p');
118
+ bioEl.className = 'cl-exec-agent-bio';
119
+ bioEl.textContent = model.agentBio || '智能行程规划·定制每日行程·优化路线安排';
120
+ info.appendChild(bioEl);
121
+
122
+ row.appendChild(info);
123
+ card.appendChild(row);
124
+
125
+ return card;
126
+ }
127
+
140
128
  // ── 共用 DOM 构建函数 ──
141
129
 
142
130
  function _clCreateOpenAgentHeader(model) {
143
131
  var header = document.createElement('div');
144
132
  header.className = 'cl-openagent-header';
133
+ if (model._outputMode) header.classList.add('cl-openagent-header--output');
145
134
  header.style.cursor = 'pointer';
146
135
 
147
- var caret = document.createElement('span');
148
- caret.className = 'cl-openagent-header-caret';
149
- caret.textContent = '';
150
- header.appendChild(caret);
151
-
152
- var icon = document.createElement('span');
153
- icon.className = 'cl-openagent-header-icon';
154
- icon.setAttribute('aria-hidden', 'true');
155
- header.appendChild(icon);
156
-
157
- var title = document.createElement('div');
158
- title.className = 'cl-openagent-header-title';
159
-
160
- var primary = document.createElement('span');
161
- primary.className = 'cl-openagent-header-primary';
162
- primary.textContent = 'OpenAgent @' + (model.agentName || 'Remote Agent');
163
- title.appendChild(primary);
164
-
165
- var secondary = document.createElement('span');
166
- secondary.className = 'cl-openagent-header-secondary';
167
- title.appendChild(secondary);
168
-
169
- header.appendChild(title);
136
+ // 展开/收起图标
137
+ var expandIcon = document.createElement('span');
138
+ expandIcon.className = 'cl-openagent-expand-icon';
139
+ // 收起态三角(向右)
140
+ expandIcon.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 15 15" fill="none"><path d="M9.75 6.79978C10.0833 6.99223 10.0833 7.47336 9.75 7.66581L6.75 9.39786C6.41667 9.59031 6 9.34975 6 8.96485L6 5.50075C6 5.11585 6.41667 4.87528 6.75 5.06773L9.75 6.79978Z" fill="#666666"/></svg>';
141
+ // 展开态三角(向下)
142
+ var expandedSvg = '<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 15 15" fill="none"><path d="M8.43313 8.98291C8.24068 9.31624 7.75955 9.31624 7.5671 8.98291L5.83505 5.98291C5.6426 5.64958 5.88316 5.23291 6.26806 5.23291L9.73216 5.23291C10.1171 5.23291 10.3576 5.64958 10.1652 5.98291L8.43313 8.98291Z" fill="#666666"/></svg>';
143
+ header.appendChild(expandIcon);
144
+
145
+ // OASN 小图标
146
+ var oasnBadge = document.createElement('span');
147
+ oasnBadge.className = 'cl-openagent-badge';
148
+ oasnBadge.style.backgroundImage = "url(./icon.png)";
149
+ oasnBadge.style.backgroundSize = 'cover';
150
+ header.appendChild(oasnBadge);
151
+
152
+ // 文字行
153
+ var textRow = document.createElement('span');
154
+ textRow.className = 'cl-openagent-text-row';
155
+
156
+ var labelOpenAgent = document.createElement('span');
157
+ labelOpenAgent.className = 'cl-openagent-label';
158
+ labelOpenAgent.textContent = 'OpenAgent';
159
+ textRow.appendChild(labelOpenAgent);
160
+
161
+ var labelAgent = document.createElement('span');
162
+ labelAgent.className = 'cl-openagent-agent';
163
+ labelAgent.textContent = '@' + (model.agentName || 'Remote Agent');
164
+ textRow.appendChild(labelAgent);
165
+
166
+ var labelStatus = document.createElement('span');
167
+ labelStatus.className = 'cl-openagent-status';
168
+ labelStatus.textContent = (model.status === 'completed') ? '执行已完成' : '正在执行任务';
169
+ textRow.appendChild(labelStatus);
170
+
171
+ header.appendChild(textRow);
170
172
 
171
173
  // 点击 header 折叠/展开卡片内容
172
174
  header.addEventListener('click', function(e) {
@@ -176,7 +178,10 @@ function _clCreateOpenAgentHeader(model) {
176
178
  var content = card.querySelector('.cl-thought-chain-content');
177
179
  if (!content) return;
178
180
  var isCollapsed = content.classList.toggle('cl-content-collapsed');
179
- caret.textContent = isCollapsed ? '▶' : '▼';
181
+ // 切换图标
182
+ expandIcon.innerHTML = isCollapsed
183
+ ? '<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 15 15" fill="none"><path d="M9.75 6.79978C10.0833 6.99223 10.0833 7.47336 9.75 7.66581L6.75 9.39786C6.41667 9.59031 6 9.34975 6 8.96485L6 5.50075C6 5.11585 6.41667 4.87528 6.75 5.06773L9.75 6.79978Z" fill="#666666"/></svg>'
184
+ : '<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 15 15" fill="none"><path d="M8.43313 8.98291C8.24068 9.31624 7.75955 9.31624 7.5671 8.98291L5.83505 5.98291C5.6426 5.64958 5.88316 5.23291 6.26806 5.23291L9.73216 5.23291C10.1171 5.23291 10.3576 5.64958 10.1652 5.98291L8.43313 8.98291Z" fill="#666666"/></svg>';
180
185
  if (typeof _cl_setCardUiState === 'function') {
181
186
  _cl_setCardUiState(model, { contentCollapsed: isCollapsed });
182
187
  }
@@ -186,8 +191,8 @@ function _clCreateOpenAgentHeader(model) {
186
191
  }
187
192
 
188
193
  function _clSetOpenAgentHeaderAgent(container, agentName) {
189
- var title = container && container.querySelector('.cl-openagent-header-primary');
190
- if (title) title.textContent = 'OpenAgent @' + (agentName || 'Remote Agent');
194
+ var label = container && container.querySelector('.cl-openagent-agent');
195
+ if (label) label.textContent = '@' + (agentName || 'Remote Agent');
191
196
  }
192
197
 
193
198
  function _clCreateAgentPill(agentName, agentId, agentAvatar) {
@@ -209,7 +214,7 @@ function _clCreateAgentPill(agentName, agentId, agentAvatar) {
209
214
  console.log('[cl-diag][pill] create agentName=' + JSON.stringify(agentName || '')
210
215
  + ' agentId=' + JSON.stringify(agentId || '')
211
216
  + ' src=' + JSON.stringify(avatar.getAttribute('src')));
212
- avatar.onerror = function() { this.style.display = 'none'; };
217
+ avatar.onerror = function() { this.style.visibility = 'hidden'; };
213
218
  pill.appendChild(avatar);
214
219
 
215
220
  var nameEl = document.createElement('span');
@@ -267,3 +272,221 @@ function _clCreateStepElement(step, isLatest) {
267
272
 
268
273
  return item;
269
274
  }
275
+
276
+
277
+ // ── 动态更新 header 状态文字 ──
278
+ function _clUpdateAgentStatusText(cardNode, status) {
279
+ var label = cardNode && cardNode.querySelector('.cl-openagent-status');
280
+ if (label) label.textContent = (status === 'completed') ? '执行已完成' : '正在执行任务';
281
+ var progressRow = cardNode && cardNode.querySelector('.cl-exec-progress-row');
282
+ if (progressRow) progressRow.style.display = (status === 'completed') ? 'none' : '';
283
+ }
284
+
285
+ function _cl_formatStarCount(count) {
286
+ var n = Number(count);
287
+ if (!isFinite(n)) return '3.2万';
288
+ if (n >= 10000) return (n / 10000).toFixed(1).replace(/.0$/, '') + '万';
289
+ if (n >= 1000) return (n / 1000).toFixed(1).replace(/.0$/, '') + 'k';
290
+ return String(Math.floor(n));
291
+ }
292
+
293
+ // ═══════════════════════════════════════════════════════════════
294
+ // V2 执行卡片渲染(2026.6.9+ 新版 UI)
295
+ // ═══════════════════════════════════════════════════════════════
296
+
297
+ function _clRenderExecutionCardV2(model) {
298
+ var container = document.createElement('div');
299
+ container.className = 'cl-remote-agent-card cl-thought-chain cl-exec-v2';
300
+ if (CL && typeof CL.diagMarkCard === 'function') {
301
+ CL.diagMarkCard(container, 'execution', { tcid: model.toolCallId || '' });
302
+ }
303
+
304
+ container.appendChild(_clCreateOpenAgentHeaderV2(model));
305
+
306
+ var content = document.createElement('div');
307
+ content.className = 'cl-thought-chain-content cl-thought-chain-content--execution cl-content-collapsed';
308
+ container.appendChild(content);
309
+
310
+ // ── Agent 详情卡片 V2 ──
311
+ try {
312
+ var detailCard = _clCreateAgentDetailCardV2(model);
313
+ content.appendChild(detailCard);
314
+ } catch(e) {
315
+ console.warn('[cl-exec-v2] detail card creation failed:', e);
316
+ }
317
+
318
+ // ── 进度文字 V2 ──
319
+ var progressRow = document.createElement('div');
320
+ progressRow.className = 'cl-exec-progress-row cl-exec-progress-row-v2';
321
+ var progressText = document.createElement('p');
322
+ progressText.className = 'cl-exec-progress-text';
323
+ progressText.textContent = (model.progressMessage || model.rawText || '').trim() || '思考中,正在了解你的需求';
324
+ progressRow.appendChild(progressText);
325
+ var arrowIcon = document.createElement('span');
326
+ arrowIcon.className = 'cl-exec-progress-arrow';
327
+ arrowIcon.innerHTML = '<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M5 4L9 7L5 10" stroke="#555" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg>';
328
+ progressRow.appendChild(arrowIcon);
329
+ content.appendChild(progressRow);
330
+ if (model.status === 'completed') progressRow.style.display = 'none';
331
+
332
+ // ── 步骤列表容器(供 _cl_updateCardSteps 使用)──
333
+ var stepsHeader = document.createElement('div');
334
+ stepsHeader.className = 'cl-tools-collapse-header cl-tools-collapse-header-v2';
335
+ var stepsHeaderIcon = document.createElement('span');
336
+ stepsHeaderIcon.className = 'cl-tools-collapse-header-icon';
337
+ stepsHeaderIcon.textContent = '▼';
338
+ stepsHeader.appendChild(stepsHeaderIcon);
339
+ var stepsHeaderTitle = document.createElement('span');
340
+ stepsHeaderTitle.className = 'cl-tools-collapse-header-title cl-tools-collapse-header-title-v2';
341
+ stepsHeaderTitle.textContent = '思考中...';
342
+ stepsHeader.appendChild(stepsHeaderTitle);
343
+ content.appendChild(stepsHeader);
344
+
345
+ var stepsBody = document.createElement('div');
346
+ stepsBody.className = 'cl-tools-collapse-body cl-tools-collapse-body-v2 cl-expanded';
347
+ content.appendChild(stepsBody);
348
+
349
+ // ─ Footer(Figma: -由xxx完成 + 星级)──
350
+ var footer = document.createElement('div');
351
+ footer.className = 'cl-output-footer cl-output-footer-v2';
352
+ footer.innerHTML = '<span class="cl-output-footer-text">-由' + (model.agentName || 'Remote Agent') + '完成</span>'
353
+ + '<span class="cl-output-footer-star"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M7 1.16L8.356 5.33H12.78L9.195 7.94L10.565 12.1L7 9.51L3.435 12.1L4.805 7.94L1.22 5.33H5.644L7 1.16Z" stroke="#999" stroke-width="0.8"/></svg></span>'
354
+ + '<span class="cl-output-footer-count">' + (model.agentStars || '3.2万') + '</span>';
355
+ container.appendChild(footer);
356
+
357
+ // ── 异步更新真实 Agent 身份 ──
358
+ if ((model.agentId || model.agentName) && typeof fetchAgentById === 'function') {
359
+ fetchAgentById(model.agentId, model.agentName).then(function(agent) {
360
+ if (!agent) return;
361
+ var avatarEl = container.querySelector('.cl-exec-agent-avatar-v2');
362
+ var nameEl = container.querySelector('.cl-exec-agent-name-v2');
363
+ var bioEl = container.querySelector('.cl-exec-agent-bio-v2');
364
+ if (nameEl) nameEl.textContent = agent.name || model.agentName;
365
+ if (bioEl && (agent.bio || agent.description)) bioEl.textContent = agent.bio || agent.description;
366
+ var starsEl = container.querySelector('.cl-exec-star-count-v2');
367
+ if (starsEl && agent.claws) starsEl.textContent = _cl_formatStarCount(agent.claws);
368
+ if (starsEl && agent.stars && !agent.claws) starsEl.textContent = _cl_formatStarCount(agent.stars);
369
+ }).catch(function() {});
370
+ }
371
+
372
+ if (typeof _cl_applyCardUiState === 'function') {
373
+ _cl_applyCardUiState(container, model);
374
+ }
375
+
376
+ console.log('[cl-exec-v2] execution card built');
377
+ return container;
378
+ }
379
+
380
+ // ── V2 Header(粉色背景 + 圆形头像 + 无 @agentName)──
381
+ function _clCreateOpenAgentHeaderV2(model) {
382
+ var header = document.createElement('div');
383
+ header.className = 'cl-openagent-header cl-openagent-header-v2';
384
+ if (model._outputMode) header.classList.add('cl-openagent-header--output');
385
+ header.style.cursor = 'pointer';
386
+
387
+ // 展开/收起图标
388
+ var expandIcon = document.createElement('span');
389
+ expandIcon.className = 'cl-openagent-expand-icon';
390
+ expandIcon.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 15 15" fill="none"><path d="M9.75 6.79978C10.0833 6.99223 10.0833 7.47336 9.75 7.66581L6.75 9.39786C6.41667 9.59031 6 9.34975 6 8.96485L6 5.50075C6 5.11585 6.41667 4.87528 6.75 5.06773L9.75 6.79978Z" fill="#666666"/></svg>';
391
+ var expandedSvg = '<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 15 15" fill="none"><path d="M8.43313 8.98291C8.24068 9.31624 7.75955 9.31624 7.5671 8.98291L5.83505 5.98291C5.6426 5.64958 5.88316 5.23291 6.26806 5.23291L9.73216 5.23291C10.1171 5.23291 10.3576 5.64958 10.1652 5.98291L8.43313 8.98291Z" fill="#666666"/></svg>';
392
+ header.appendChild(expandIcon);
393
+
394
+ // 圆形灰色头像(替代小徽章)
395
+ var avatar = document.createElement('span');
396
+ avatar.className = 'cl-openagent-avatar-v2';
397
+ header.appendChild(avatar);
398
+
399
+ // 文字行:OpenAgent + 状态文字(去掉 @agentName)
400
+ var textRow = document.createElement('span');
401
+ textRow.className = 'cl-openagent-text-row';
402
+
403
+ var labelOpenAgent = document.createElement('span');
404
+ labelOpenAgent.className = 'cl-openagent-label';
405
+ labelOpenAgent.textContent = 'OpenAgent';
406
+ textRow.appendChild(labelOpenAgent);
407
+
408
+ var labelStatus = document.createElement('span');
409
+ labelStatus.className = 'cl-openagent-status';
410
+ labelStatus.textContent = (model.status === 'completed') ? '执行已完成' : '正在执行任务';
411
+ textRow.appendChild(labelStatus);
412
+
413
+ header.appendChild(textRow);
414
+
415
+ // 点击 header 折叠/展开卡片内容
416
+ header.addEventListener('click', function(e) {
417
+ e.stopPropagation();
418
+ var card = header.closest('.cl-remote-agent-card');
419
+ if (!card) return;
420
+ var content = card.querySelector('.cl-thought-chain-content');
421
+ if (!content) return;
422
+ var isCollapsed = content.classList.toggle('cl-content-collapsed');
423
+ expandIcon.innerHTML = isCollapsed
424
+ ? '<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 15 15" fill="none"><path d="M9.75 6.79978C10.0833 6.99223 10.0833 7.47336 9.75 7.66581L6.75 9.39786C6.41667 9.59031 6 9.34975 6 8.96485L6 5.50075C6 5.11585 6.41667 4.87528 6.75 5.06773L9.75 6.79978Z" fill="#666666"/></svg>'
425
+ : expandedSvg;
426
+ if (typeof _cl_setCardUiState === 'function') {
427
+ _cl_setCardUiState(model, { contentCollapsed: isCollapsed });
428
+ }
429
+ });
430
+
431
+ return header;
432
+ }
433
+
434
+ // ─ V2 Agent 详情卡片(大头像 + 右置星级 + 网格点背景)──
435
+ function _clCreateAgentDetailCardV2(model) {
436
+ var card = document.createElement('div');
437
+ card.className = 'cl-exec-detail-card cl-exec-detail-card-v2';
438
+
439
+ var row = document.createElement('div');
440
+ row.className = 'cl-exec-detail-row cl-exec-detail-row-v2';
441
+
442
+ // 大头像 80×80
443
+ var avatar = document.createElement('img');
444
+ avatar.className = 'cl-exec-agent-avatar cl-exec-agent-avatar-v2';
445
+ avatar.alt = model.agentName || '';
446
+ avatar.src = './icon.png';
447
+ avatar.onerror = function() { this.style.visibility = 'hidden'; };
448
+ row.appendChild(avatar);
449
+
450
+ // 信息列
451
+ var info = document.createElement('div');
452
+ info.className = 'cl-exec-detail-info cl-exec-detail-info-v2';
453
+
454
+ // 名称(无星级徽章,星级右置到卡片右上角)
455
+ var nameEl = document.createElement('p');
456
+ nameEl.className = 'cl-exec-agent-name cl-exec-agent-name-v2';
457
+ nameEl.textContent = model.agentName || 'Remote Agent';
458
+ info.appendChild(nameEl);
459
+
460
+ // 描述文字
461
+ var bioEl = document.createElement('p');
462
+ bioEl.className = 'cl-exec-agent-bio cl-exec-agent-bio-v2';
463
+ bioEl.textContent = model.agentBio || '智能行程规划·定制每日行程·优化路线安排';
464
+ info.appendChild(bioEl);
465
+
466
+ row.appendChild(info);
467
+ card.appendChild(row);
468
+
469
+ // 星级徽章右置到卡片右上角
470
+ var starBadge = document.createElement('div');
471
+ starBadge.className = 'cl-exec-star-badge cl-exec-star-badge-v2';
472
+ var starSvgOutline = '<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M7 1.16L8.356 5.33H12.78L9.195 7.94L10.565 12.1L7 9.51L3.435 12.1L4.805 7.94L1.22 5.33H5.644L7 1.16Z" stroke="#999" stroke-width="0.8"/></svg>';
473
+ starBadge.innerHTML = starSvgOutline +
474
+ '<span class="cl-exec-star-count cl-exec-star-count-v2">' + (model.agentStars || '3.2万') + '</span>';
475
+ card.appendChild(starBadge);
476
+
477
+ return card;
478
+ }
479
+
480
+ // ── V2 状态文字更新 ──
481
+ function _clUpdateAgentStatusTextV2(cardNode, status) {
482
+ var label = cardNode && cardNode.querySelector('.cl-openagent-status');
483
+ if (label) label.textContent = (status === 'completed') ? '执行已完成' : '正在执行任务';
484
+ // 进度文字行:完成后隐藏
485
+ var progressRow = cardNode && cardNode.querySelector('.cl-exec-progress-row-v2');
486
+ if (progressRow) progressRow.style.display = (status === 'completed') ? 'none' : '';
487
+ // 步骤列表:完成后隐藏
488
+ var stepsBody = cardNode && cardNode.querySelector('.cl-tools-collapse-body-v2');
489
+ if (stepsBody) stepsBody.style.display = (status === 'completed') ? 'none' : '';
490
+ var stepsHeader = cardNode && cardNode.querySelector('.cl-tools-collapse-header-v2');
491
+ if (stepsHeader) stepsHeader.style.display = (status === 'completed') ? 'none' : '';
492
+ }