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
@@ -31,14 +31,26 @@ function _clRenderOutputCard(model, onOpenSidebar) {
31
31
  ? _clStripOpenagentMediaLines(chunk.text)
32
32
  : chunk.text;
33
33
  if (_clShouldRenderOutputText(textChunk)) resultTexts.push(textChunk);
34
+ } else if (chunk.type === 'error') {
35
+ var errorText = chunk.text || model.rawText || '远端 Agent 调用失败';
36
+ if (_clShouldRenderOutputText(errorText)) resultTexts.push(errorText);
34
37
  }
35
38
  }
36
39
 
40
+ // ── V2 版本判断 ──
41
+ var isV2 = typeof _clIsHostVersionGte === 'function' && _clIsHostVersionGte('2026.6.9');
42
+
37
43
  if (resultTexts.length === 0 && mediaLinks.length === 0) {
38
44
  var placeholder = document.createElement('span');
39
45
  placeholder.className = 'cl-remote-agent-card cl-remote-agent-output-placeholder';
40
46
  placeholder.style.display = 'none';
41
47
  placeholder.__clEmptyOutput = true;
48
+ // 防止 OpenClaw native 代码读 .textContent 报 undefined.trim()
49
+ var hiddenText = document.createElement('span');
50
+ hiddenText.className = 'chat-text';
51
+ hiddenText.style.display = 'none';
52
+ hiddenText.textContent = '';
53
+ placeholder.appendChild(hiddenText);
42
54
  if (model.toolCallId) {
43
55
  placeholder.dataset.clCardTcid = model.toolCallId;
44
56
  }
@@ -47,34 +59,54 @@ function _clRenderOutputCard(model, onOpenSidebar) {
47
59
  }
48
60
 
49
61
  var container = document.createElement('div');
50
- container.className = 'cl-remote-agent-card cl-thought-chain cl-output-card'
62
+ var cardClasses = 'cl-remote-agent-card cl-thought-chain cl-output-card'
51
63
  + (resultTexts.length > 0 ? ' cl-output-card--pending' : '');
64
+ if (isV2) cardClasses += ' cl-exec-v2';
65
+ container.className = cardClasses;
52
66
  container.dataset.clCardRole = 'output';
67
+ // 防止 OpenClaw native 代码读 .textContent 报 undefined.trim()
68
+ var safetyText = document.createElement('div');
69
+ safetyText.className = 'chat-text';
70
+ safetyText.style.display = 'none';
71
+ safetyText.textContent = '';
72
+ container.appendChild(safetyText);
73
+ if (model.toolCallId) container.dataset.clCardTcid = model.toolCallId;
74
+ // 阻止点击冒泡到原生 tool card handler
75
+ container.addEventListener('click', function(e) { e.stopPropagation(); });
53
76
  if (CL && typeof CL.diagMarkCard === 'function') {
54
77
  CL.diagMarkCard(container, 'output', { tcid: model.toolCallId || '' });
55
78
  }
56
79
 
57
- var shellHeader = _clCreateOpenAgentHeader(model);
58
- container.appendChild(shellHeader);
59
- if (typeof _clSetOpenAgentHeaderAgent === 'function') {
60
- _clSetOpenAgentHeaderAgent(container, model.agentName || model.agentId || 'Remote Agent');
80
+ model._outputMode = true;
81
+ model.status = model.isError ? 'failed' : 'completed';
82
+ if (isV2) {
83
+ var v2Header = _clCreateOpenAgentHeaderV2(model);
84
+ v2Header.classList.remove('cl-openagent-header--output');
85
+ container.appendChild(v2Header);
86
+ if (typeof _clUpdateAgentStatusTextV2 === 'function') {
87
+ _clUpdateAgentStatusTextV2(container, model.status);
88
+ }
89
+ } else {
90
+ var shellHeader = _clCreateOpenAgentHeader(model);
91
+ container.appendChild(shellHeader);
92
+ if (typeof _clSetOpenAgentHeaderAgent === 'function') {
93
+ _clSetOpenAgentHeaderAgent(container, model.agentName || model.agentId || 'Remote Agent');
94
+ }
61
95
  }
62
96
 
63
97
  var content = document.createElement('div');
64
98
  content.className = 'cl-thought-chain-content';
65
99
  container.appendChild(content);
66
100
 
67
- // ── Agent Pill ──
68
- var pillSlot = document.createElement('div');
69
- pillSlot.className = 'cl-thought-chain-pill-slot';
70
- var pill = _clCreateAgentPill(model.agentName, model.agentId, model.agentAvatar);
71
- pillSlot.appendChild(pill);
72
- content.appendChild(pillSlot);
73
-
74
- // ── 分隔线 ──
75
- var divider = document.createElement('div');
76
- divider.className = 'cl-thought-chain-divider';
77
- content.appendChild(divider);
101
+ // ── V2 Agent 详情卡片 ──
102
+ if (isV2) {
103
+ try {
104
+ var detailCard = _clCreateAgentDetailCardV2(model);
105
+ content.appendChild(detailCard);
106
+ } catch(e) {
107
+ console.warn('[cl-output-v2] detail card creation failed:', e);
108
+ }
109
+ }
78
110
 
79
111
  // ── 附件下载链接 ──
80
112
  if (mediaLinks.length > 0 && typeof _clCreateOpenagentMediaLinksSection === 'function') {
@@ -119,12 +151,23 @@ function _clRenderOutputCard(model, onOpenSidebar) {
119
151
  }
120
152
 
121
153
  // ── onOpenSidebar 支持:点击展开到侧边栏 ──
122
- if (onOpenSidebar && model.rawText) {
154
+ // 宿主 sidebar 渲染器要求 content 为 { kind: 'markdown', content, rawText } 对象,
155
+ // kind 必须为 'markdown' 才会进入 markdown 渲染路径,否则显示 "No previewable markdown content."。
156
+ // travel card 标签(<sh_card>等)sidebar 原生 markdown 解析不认,先 strip 再传。
157
+ var sidebarRaw = resultText || model.rawText || '';
158
+ var sidebarText = String(sidebarRaw).replace(/<\/?[a-z]+_card[^>]*>/gi, '');
159
+ if (typeof _clStripSuppressedTravelTags === 'function') {
160
+ sidebarText = _clStripSuppressedTravelTags(sidebarText);
161
+ }
162
+ if (onOpenSidebar && sidebarText.trim()) {
123
163
  container.style.cursor = 'pointer';
124
164
  container.addEventListener('click', function(e) {
125
- // 不拦截折叠/展开点击
126
165
  if (e.target.closest('.cl-tools-collapse-header')) return;
127
- onOpenSidebar(model.rawText);
166
+ onOpenSidebar({ kind: 'markdown', content: sidebarText, rawText: sidebarText });
167
+ setTimeout(function() {
168
+ var titleEl = document.querySelector('.chat-sidebar .sidebar-title');
169
+ if (titleEl) titleEl.textContent = 'OpenAgent @' + (model.agentName || 'Remote Agent');
170
+ }, 100);
128
171
  });
129
172
  }
130
173
 
@@ -132,26 +175,47 @@ function _clRenderOutputCard(model, onOpenSidebar) {
132
175
  if ((model.agentId || model.agentName) && typeof fetchAgentById === 'function') {
133
176
  fetchAgentById(model.agentId, model.agentName).then(function(agent) {
134
177
  if (!agent) return;
135
- var pa = container.querySelector('.cl-agent-pill-avatar');
136
- var pn = container.querySelector('.cl-agent-pill-name');
137
- if (pa && typeof avatarUrl === 'function') {
138
- var resolvedAvatar = avatarUrl(agent);
139
- console.log('[cl-diag][pill] fetch-update agentId=' + JSON.stringify(model.agentId)
140
- + ' name=' + JSON.stringify(agent.name || model.agentName)
141
- + ' src=' + JSON.stringify(resolvedAvatar));
142
- pa.src = resolvedAvatar;
143
- pa.style.display = '';
178
+ if (isV2) {
179
+ var avatarElV2 = container.querySelector('.cl-exec-agent-avatar-v2');
180
+ var nameElV2 = container.querySelector('.cl-exec-agent-name-v2');
181
+ var bioElV2 = container.querySelector('.cl-exec-agent-bio-v2');
182
+ var agentBioV2 = typeof _clGetAgentDescriptionText === 'function'
183
+ ? _clGetAgentDescriptionText(agent)
184
+ : (agent.bio || agent.description || '');
185
+ if (nameElV2) nameElV2.textContent = agent.name || model.agentName;
186
+ if (bioElV2 && agentBioV2) bioElV2.textContent = agentBioV2;
187
+ var starsElV2 = container.querySelector('.cl-exec-star-count-v2');
188
+ if (starsElV2 && agent.claws) starsElV2.textContent = _cl_formatStarCount(agent.claws);
189
+ if (starsElV2 && agent.stars && !agent.claws) starsElV2.textContent = _cl_formatStarCount(agent.stars);
190
+ } else {
191
+ _clSetOpenAgentHeaderAgent(container, agent.name || model.agentName);
144
192
  }
145
- _clSetAgentPillName(container, agent.name || model.agentName);
146
- _clSetOpenAgentHeaderAgent(container, agent.name || model.agentName);
147
193
  }).catch(function() {});
148
194
  }
149
195
 
196
+ // ── Footer ──
197
+ if (isV2) {
198
+ var footerV2 = document.createElement('div');
199
+ footerV2.className = 'cl-output-footer cl-output-footer-v2';
200
+ footerV2.innerHTML = '<span class="cl-output-footer-text">-由' + (model.agentName || 'Remote Agent') + '完成</span>'
201
+ + '<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>'
202
+ + '<span class="cl-output-footer-count">' + (model.agentStars || '3.2万') + '</span>';
203
+ container.appendChild(footerV2);
204
+ } else {
205
+ // ── Footer(Figma 131:2091) ──
206
+ var footer = document.createElement('div');
207
+ footer.className = 'cl-output-footer';
208
+ footer.innerHTML = '<span class="cl-output-footer-text">-由' + (model.agentName || 'Remote Agent') + '完成</span>'
209
+ + '<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>'
210
+ + '<span class="cl-output-footer-count">' + (model.agentStars || '3.2万') + '</span>';
211
+ container.appendChild(footer);
212
+ }
213
+
150
214
  if (typeof _cl_applyCardUiState === 'function') {
151
215
  _cl_applyCardUiState(container, model);
152
216
  }
153
217
 
154
- console.log('[cl-output] ✅ output card built: results=' + resultTexts.length);
218
+ console.log('[cl-output] ✅ output card built: results=' + resultTexts.length + ' v2=' + isV2);
155
219
  return container;
156
220
  }
157
221
 
@@ -274,3 +338,5 @@ function _clScheduleOutputCardProcessing(resultSection, model) {
274
338
 
275
339
  setTimeout(run, 0);
276
340
  }
341
+
342
+ // ── Sidebar Figma 145:5712 内联样式 ──
@@ -13,8 +13,14 @@ var __cl_toolStates = new Map();
13
13
  // 每个 entry: { steps: [], phase: 'active'|'completed', cardNode: null, args: {} }
14
14
 
15
15
  var __cl_lastCallModel = null; // 同一 render cycle 里 call card 的 model(供 result card 读取 agent 身份)
16
- var __cl_outputCardCache = new Map(); // toolCallId → cached output DOM
17
- var __cl_cardUiStates = new Map(); // execution/output 展开状态,避免 OpenClaw rerender 覆盖用户操作
16
+ var __cl_outputCardCache = new Map(); // toolCallId → cached output DOM
17
+ var __cl_executionCardCache = new Map(); // toolCallId cached historical execution DOM
18
+ var __cl_cardUiStates = new Map(); // execution/output 展开状态,避免 OpenClaw rerender 覆盖用户操作
19
+ var __cl_progressMessageMap = new Map(); // toolCallId → 动态进度文字(来自 response.progress?.safe_status_message)
20
+
21
+ // ── 诊断:渲染频率计数器 ──
22
+ var __clDiag = { renderCalls: 0, lastDiagTs: 0, version: 'v4-oneshot-20260630' };
23
+ console.log('[cl-diag] render-hooks loaded, version=' + __clDiag.version);
18
24
 
19
25
  var CL_REMOTE_AGENT_PROGRESS_MODE_TRAVEL_TITLE = 'travel-title';
20
26
  var CL_REMOTE_AGENT_PROGRESS_MODE_GENERIC_STREAM = 'generic-stream';
@@ -310,6 +316,16 @@ function _cl_ensureRemoteToolState(toolCallId, data, rawText) {
310
316
  // ═══════════════════════════════════════════════════════════════
311
317
 
312
318
  window.__openagentRenderToolCard = function(card, onOpenSidebar) {
319
+ // ── 诊断:渲染频率计数器 ──
320
+ __clDiag.renderCalls++;
321
+ var diagNow = Date.now();
322
+ if (diagNow - __clDiag.lastDiagTs > 2000) {
323
+ var rps = (__clDiag.renderCalls / ((diagNow - __clDiag.lastDiagTs) / 1000)).toFixed(1);
324
+ console.log('[cl-diag] render rate: ' + rps + ' calls/sec, total=' + __clDiag.renderCalls + ', version=' + __clDiag.version);
325
+ __clDiag.renderCalls = 0;
326
+ __clDiag.lastDiagTs = diagNow;
327
+ }
328
+
313
329
  var n = (card && card.name || '').toLowerCase();
314
330
  var cardTcid = card && (card.toolCallId || '');
315
331
  var cardKind = typeof _clInferToolCardKind === 'function' ? _clInferToolCardKind(card) : (card && card.kind || '');
@@ -347,19 +363,34 @@ window.__openagentRenderToolCard = function(card, onOpenSidebar) {
347
363
  }
348
364
  if (state.phase === 'active') {
349
365
  model.status = 'executing';
366
+ if (typeof _clUpdateAgentStatusTextV2 === 'function' && state.cardNode && state.cardNode.classList.contains('cl-exec-v2')) {
367
+ _clUpdateAgentStatusTextV2(state.cardNode, 'executing');
368
+ } else if (typeof _clUpdateAgentStatusText === 'function') {
369
+ _clUpdateAgentStatusText(state.cardNode, 'executing');
370
+ }
350
371
  }
351
372
  // 有 streaming 状态 — 复用或新建
352
373
  if (state.cardNode) {
353
374
  // Lit 重复调用会复用同一个 DOM 节点;但 OpenClaw 外层 native
354
375
  // <details> 可能被 rerender 成 closed。这里重新打开的是外层原生
355
- // details,不影响卡片内部的“思考中/思考完成”折叠状态。
376
+ // details,不影响卡片内部的”思考中/思考完成”折叠状态。
356
377
  _cl_applyCardUiState(state.cardNode, { toolCallId: tcid, cardKind: 'call' });
357
378
  if (state.phase === 'active') {
358
379
  _cl_autoOpenStepsIfUncontrolled(state.cardNode);
359
380
  }
360
- _cl_forceOpenNativeToolDetails(state.cardNode, 'execution-cache', tcid);
361
- if (typeof _cl_scheduleHostShellMark === 'function') _cl_scheduleHostShellMark(state.cardNode);
362
- _cl_hideHostRawText(state.cardNode);
381
+ // ── 更新进度文字:来自 response.progress?.safe_status_message ──
382
+ var progressEl = state.cardNode.querySelector('.cl-exec-progress-text');
383
+ if (progressEl && model.rawText) {
384
+ var msg = (model.rawText || '').trim();
385
+ if (msg) progressEl.textContent = msg;
386
+ }
387
+ // ── 一次性外壳初始化:首次渲染时打开 native details + 隐藏 raw text,之后永久跳过 ──
388
+ if (!state.cardNode.__clShellReady) {
389
+ state.cardNode.__clShellReady = true;
390
+ _cl_forceOpenNativeToolDetails(state.cardNode, 'execution-cache', tcid);
391
+ if (typeof _cl_scheduleHostShellMark === 'function') _cl_scheduleHostShellMark(state.cardNode);
392
+ _cl_hideHostRawText(state.cardNode);
393
+ }
363
394
  return state.cardNode;
364
395
  }
365
396
 
@@ -397,6 +428,20 @@ window.__openagentRenderToolCard = function(card, onOpenSidebar) {
397
428
 
398
429
  // 无状态 → 刷新/历史态。前端 store 如果有同一 toolCallId 的卡片快照,
399
430
  // 就用快照参数重建 steps;没有 store 时仍展示完成态外壳。
431
+
432
+ // 缓存:历史态 execution card 只创建一次,Lit 重复调用时复用(与 output card 逻辑一致)
433
+ var cachedExecution = tcid ? __cl_executionCardCache.get(tcid) : null;
434
+ if (cachedExecution && cachedExecution.isConnected) {
435
+ _cl_applyCardUiState(cachedExecution, { toolCallId: tcid, cardKind: 'call' });
436
+ if (!cachedExecution.__clShellReady) {
437
+ cachedExecution.__clShellReady = true;
438
+ _cl_forceOpenNativeToolDetails(cachedExecution, 'execution-history-cache', tcid);
439
+ if (typeof _cl_scheduleHostShellMark === 'function') _cl_scheduleHostShellMark(cachedExecution);
440
+ _cl_hideHostRawText(cachedExecution);
441
+ }
442
+ return cachedExecution;
443
+ }
444
+
400
445
  var storedCallRecord = tcid && typeof _clRemoteAgentProgressStore !== 'undefined' && _clRemoteAgentProgressStore
401
446
  ? _clRemoteAgentProgressStore.get(tcid)
402
447
  : null;
@@ -413,10 +458,16 @@ window.__openagentRenderToolCard = function(card, onOpenSidebar) {
413
458
  model.cardKind = 'call';
414
459
  model.status = 'completed';
415
460
  var historyNode = _clRenderExecutionCard(model);
461
+ if (historyNode && historyNode.classList && historyNode.classList.contains('cl-exec-v2')) {
462
+ if (typeof _clUpdateAgentStatusTextV2 === 'function') _clUpdateAgentStatusTextV2(historyNode, 'completed');
463
+ } else if (typeof _clUpdateAgentStatusText === 'function') {
464
+ _clUpdateAgentStatusText(historyNode, 'completed');
465
+ }
416
466
  _cl_finalizeCard(historyNode, model._bufferedSteps || []);
417
467
  _cl_forceOpenNativeToolDetails(historyNode, 'execution-history', tcid);
418
468
  if (typeof _cl_scheduleHostShellMark === 'function') _cl_scheduleHostShellMark(historyNode);
419
469
  _cl_hideHostRawText(historyNode);
470
+ if (tcid) __cl_executionCardCache.set(tcid, historyNode);
420
471
  console.log('[cl-render] 🗂️ built historical call card, tcid=' + tcid.substring(0, 8));
421
472
  return historyNode;
422
473
  }
@@ -464,14 +515,27 @@ window.__openagentRenderToolCard = function(card, onOpenSidebar) {
464
515
 
465
516
  model.toolCallId = resTcid;
466
517
  model.cardKind = 'result';
518
+ if (model.isError) {
519
+ var executionNodeForResult = (resState && resState.cardNode)
520
+ || (resTcid ? __cl_executionCardCache.get(resTcid) : null);
521
+ if (executionNodeForResult && executionNodeForResult.classList && executionNodeForResult.classList.contains('cl-exec-v2')) {
522
+ if (typeof _clUpdateAgentStatusTextV2 === 'function') _clUpdateAgentStatusTextV2(executionNodeForResult, 'failed');
523
+ } else if (executionNodeForResult && typeof _clUpdateAgentStatusText === 'function') {
524
+ _clUpdateAgentStatusText(executionNodeForResult, 'failed');
525
+ }
526
+ }
467
527
 
468
528
  // 缓存:同一 toolCallId 的 output card 只创建一次,Lit 重复调用时复用
469
529
  var cachedOutput = resTcid ? __cl_outputCardCache.get(resTcid) : null;
470
530
  if (cachedOutput && cachedOutput.isConnected) {
471
531
  _cl_applyCardUiState(cachedOutput, { toolCallId: resTcid, cardKind: 'result' });
472
- _cl_forceOpenNativeToolDetails(cachedOutput, 'output-cache', resTcid);
473
- if (typeof _cl_scheduleHostShellMark === 'function') _cl_scheduleHostShellMark(cachedOutput);
474
- _cl_hideHostRawText(cachedOutput);
532
+ // ── 一次性外壳初始化:首次渲染时打开 native details + 隐藏 raw text,之后永久跳过 ──
533
+ if (!cachedOutput.__clShellReady) {
534
+ cachedOutput.__clShellReady = true;
535
+ _cl_forceOpenNativeToolDetails(cachedOutput, 'output-cache', resTcid);
536
+ if (typeof _cl_scheduleHostShellMark === 'function') _cl_scheduleHostShellMark(cachedOutput);
537
+ _cl_hideHostRawText(cachedOutput);
538
+ }
475
539
  return cachedOutput;
476
540
  }
477
541
 
@@ -554,6 +618,8 @@ function _cl_replayBufferedSteps(toolCallId, state) {
554
618
 
555
619
  function _cl_hideHostRawText(cardNode) {
556
620
  if (!cardNode) return;
621
+ // 幂等性守卫:如果父链已经标记为隐藏,跳过重复操作
622
+ if (cardNode.closest && cardNode.closest('.cl-remote-agent-raw-hidden')) return;
557
623
  function hide() {
558
624
  var hosts = _cl_collectRawTextHosts(cardNode);
559
625
  for (var h = 0; h < hosts.length; h++) {
@@ -563,10 +629,7 @@ function _cl_hideHostRawText(cardNode) {
563
629
  hide();
564
630
  if (typeof requestAnimationFrame === 'function') requestAnimationFrame(hide);
565
631
  setTimeout(hide, 0);
566
- setTimeout(hide, 80);
567
- setTimeout(hide, 250);
568
- setTimeout(hide, 800);
569
- setTimeout(hide, 2000);
632
+ setTimeout(hide, 200);
570
633
  }
571
634
 
572
635
  function _cl_isRemoteToolNameText(text) {
@@ -585,26 +648,32 @@ function _cl_isRemoteRawTextContent(text) {
585
648
  return false;
586
649
  }
587
650
 
651
+ function _cl_getHostAdapter() {
652
+ return (typeof CL !== 'undefined' && CL.hostAdapter) ? CL.hostAdapter : {};
653
+ }
654
+
588
655
  function _cl_collectRawTextHosts(node) {
589
656
  var hosts = [];
657
+ var adapter = _cl_getHostAdapter();
658
+ var selectors = adapter.selectors && adapter.selectors.rawTextHostClosest;
590
659
  function add(host) {
591
660
  if (!host || hosts.indexOf(host) !== -1) return;
592
661
  hosts.push(host);
593
662
  }
594
663
  add(node.parentElement);
595
- if (node.closest) {
596
- add(node.closest('.chat-tools-collapse__body'));
597
- add(node.closest('.chat-tool-msg-body'));
598
- add(node.closest('.chat-tool-card__detail'));
599
- add(node.closest('.chat-bubble'));
664
+ if (node.closest && Array.isArray(selectors)) {
665
+ for (var i = 0; i < selectors.length; i++) {
666
+ add(node.closest(selectors[i]));
667
+ }
600
668
  }
601
669
  return hosts;
602
670
  }
603
671
 
604
672
  function _cl_hideRawTextInHost(host) {
605
673
  if (!host || !host.querySelectorAll) return;
674
+ var adapter = _cl_getHostAdapter();
606
675
  host.classList.add('cl-remote-agent-raw-hidden');
607
- if (host.classList.contains('chat-tools-collapse__body') || host.classList.contains('chat-tool-msg-body')) {
676
+ if (adapter.isToolBody && adapter.isToolBody(host)) {
608
677
  host.classList.add('cl-remote-agent-host-shell');
609
678
  }
610
679
  var texts = host.querySelectorAll(':scope > .chat-text');
@@ -615,16 +684,11 @@ function _cl_hideRawTextInHost(host) {
615
684
  }
616
685
 
617
686
  function _cl_findRemoteNativeToolShell(node) {
687
+ var adapter = _cl_getHostAdapter();
618
688
  var cur = node && (node.nodeType === 1 ? node : node.parentElement);
619
689
  var hops = 0;
620
690
  while (cur && cur !== document.body && hops < 12) {
621
- if (cur.matches && cur.matches(
622
- 'details.chat-tools-collapse,' +
623
- 'details.chat-tool-msg-collapse,' +
624
- '.chat-tools-collapse,' +
625
- '.chat-tool-msg-collapse,' +
626
- '.chat-tool-card'
627
- )) {
691
+ if (adapter.isRemoteNativeToolShellCandidate && adapter.isRemoteNativeToolShellCandidate(cur)) {
628
692
  if (_cl_isRemoteNativeToolShell(cur)) return cur;
629
693
  }
630
694
  cur = cur.parentElement;
@@ -635,14 +699,12 @@ function _cl_findRemoteNativeToolShell(node) {
635
699
 
636
700
  function _cl_isRemoteNativeToolShell(shell) {
637
701
  if (!shell) return false;
702
+ var adapter = _cl_getHostAdapter();
703
+ var summarySelector = adapter.selectors && adapter.selectors.summary;
638
704
  var summaryText = '';
639
- var summary = shell.querySelector && shell.querySelector(
640
- ':scope > summary,' +
641
- ':scope > .chat-tools-summary,' +
642
- ':scope > .chat-tool-msg-summary,' +
643
- '.chat-tools-summary,' +
644
- '.chat-tool-msg-summary'
645
- );
705
+ var summary = shell.querySelector && summarySelector
706
+ ? shell.querySelector(summarySelector)
707
+ : null;
646
708
  if (summary) summaryText = summary.textContent || '';
647
709
  if (_cl_isRemoteToolNameText(summaryText)) return true;
648
710
 
@@ -683,27 +745,23 @@ function _cl_tryHideRemoteRawTextNode(node) {
683
745
 
684
746
  var shell = _cl_findRemoteNativeToolShell(node);
685
747
  if (shell && shell.querySelectorAll) {
686
- var hosts = shell.querySelectorAll('.chat-tools-collapse__body, .chat-tool-msg-body, .chat-tool-card__detail, .chat-bubble');
687
- for (var h = 0; h < hosts.length; h++) {
688
- _cl_hideRawTextInHost(hosts[h]);
748
+ var adapter = _cl_getHostAdapter();
749
+ var hostSelector = adapter.selectors && adapter.selectors.rawTextHostsWithinShell;
750
+ if (hostSelector) {
751
+ var hosts = shell.querySelectorAll(hostSelector);
752
+ for (var h = 0; h < hosts.length; h++) {
753
+ _cl_hideRawTextInHost(hosts[h]);
754
+ }
689
755
  }
690
756
  }
691
757
  }
692
758
 
693
759
  function _cl_findNearestToolLikeShell(node) {
760
+ var adapter = _cl_getHostAdapter();
694
761
  var cur = node && (node.nodeType === 1 ? node : node.parentElement);
695
762
  var hops = 0;
696
763
  while (cur && cur !== document.body && hops < 12) {
697
- if (cur.matches && cur.matches(
698
- 'details.chat-tools-collapse,' +
699
- 'details.chat-tool-msg-collapse,' +
700
- '.chat-tools-collapse,' +
701
- '.chat-tool-msg-collapse,' +
702
- '.chat-tool-card,' +
703
- '.chat-tools-collapse__body,' +
704
- '.chat-tool-msg-body,' +
705
- '.chat-tool-card__detail'
706
- )) {
764
+ if (adapter.isToolLikeShell && adapter.isToolLikeShell(cur)) {
707
765
  return cur;
708
766
  }
709
767
  cur = cur.parentElement;
@@ -752,15 +810,11 @@ _cl_installRemoteRawTextObserver();
752
810
  // ── 局部打开最近宿主 wrapper(不做全局扫描)──
753
811
 
754
812
  function _cl_findNearestNativeToolShell(node) {
813
+ var adapter = _cl_getHostAdapter();
755
814
  var cur = node && node.parentElement;
756
815
  var hops = 0;
757
816
  while (cur && cur !== document.body && hops < 10) {
758
- if (cur.matches && cur.matches(
759
- 'details.chat-tools-collapse,' +
760
- 'details.chat-tool-msg-collapse,' +
761
- '.chat-tools-collapse,' +
762
- '.chat-tool-msg-collapse'
763
- )) {
817
+ if (adapter.isNativeToolShell && adapter.isNativeToolShell(cur)) {
764
818
  return cur;
765
819
  }
766
820
  cur = cur.parentElement;
@@ -788,7 +842,9 @@ function _cl_forceOpenNativeToolDetails(node, source, tcid) {
788
842
 
789
843
  if (shell.classList && !shell.classList.contains('is-open')) {
790
844
  shell.classList.add('is-open');
791
- var header = shell.querySelector('.chat-tool-msg-summary, .chat-tools-summary');
845
+ var adapter = _cl_getHostAdapter();
846
+ var headerSelector = (adapter.selectors && adapter.selectors.forceOpenHeader) || '';
847
+ var header = headerSelector ? shell.querySelector(headerSelector) : null;
792
848
  if (header) header.setAttribute('aria-expanded', 'true');
793
849
  console.log('[cl-render] 🔓 opened native collapse source=' + source
794
850
  + ' tcid=' + String(tcid || '').substring(0, 8));
@@ -800,8 +856,6 @@ function _cl_forceOpenNativeToolDetails(node, source, tcid) {
800
856
  // openNearest 是幂等的(已 open 不重复操作),不需要防抖。
801
857
  openNearest();
802
858
  if (typeof requestAnimationFrame === 'function') requestAnimationFrame(openNearest);
803
- setTimeout(openNearest, 0);
804
- setTimeout(openNearest, 80);
805
859
  setTimeout(openNearest, 300); // 兜底:慢速 Lit render / 异步 wrapper 挂载
806
860
  }
807
861
 
@@ -866,6 +920,9 @@ function _cl_applyCardUiState(container, modelOrNode) {
866
920
  content.classList.remove('cl-content-collapsed');
867
921
  if (caret) caret.textContent = '▼';
868
922
  }
923
+ if (typeof _clSyncOutputFooterVisibility === 'function') {
924
+ _clSyncOutputFooterVisibility(container, state.contentCollapsed);
925
+ }
869
926
  }
870
927
 
871
928
  var body = container.querySelector('.cl-tools-collapse-body');
@@ -895,6 +952,14 @@ function _cl_applyStoredRecordToModel(model, record) {
895
952
  if (!model.agentAvatar) {
896
953
  model.agentAvatar = args.agent_avatar || args.agentAvatar || args.avatar || args.avatar_url || args.avatarUrl || null;
897
954
  }
955
+ if (!model.agentBio) {
956
+ model.agentBio = typeof _clPickAgentDescription === 'function'
957
+ ? _clPickAgentDescription(args)
958
+ : (args.agent_bio || args.agentBio || args.description || args.agent_description || args.MOM || '');
959
+ }
960
+ if (!model.agentStars) {
961
+ model.agentStars = args.agent_stars || args.agentStars || '3.2万';
962
+ }
898
963
  var identity = CL && typeof CL.getAgentIdentity === 'function'
899
964
  ? CL.getAgentIdentity(model.agentId, model.agentName)
900
965
  : null;
@@ -902,6 +967,11 @@ function _cl_applyStoredRecordToModel(model, record) {
902
967
  model.agentId = model.agentId || identity.id || identity.agent_id;
903
968
  model.agentName = (model.agentName && model.agentName !== 'Remote Agent') ? model.agentName : (identity.name || model.agentName);
904
969
  model.agentAvatar = model.agentAvatar || identity.avatar || null;
970
+ if (!model.agentBio) {
971
+ model.agentBio = typeof _clPickAgentDescription === 'function'
972
+ ? _clPickAgentDescription(identity)
973
+ : (identity.bio || identity.description || identity.agent_bio || identity.agentBio || identity.MOM || '');
974
+ }
905
975
  }
906
976
  model.taskText = model.taskText || args.task || args.message || args.instruction || '';
907
977
  }
@@ -1300,8 +1370,6 @@ function _cl_updateCardSteps(card, steps) {
1300
1370
  var stepEl = _clCreateStepElement(steps[i], i === steps.length - 1);
1301
1371
  body.appendChild(stepEl);
1302
1372
  }
1303
-
1304
- _cl_forceOpenNativeToolDetails(card, 'steps-update', card.dataset && card.dataset.clCardTcid || '');
1305
1373
  }
1306
1374
 
1307
1375
  function _cl_autoOpenStepsIfUncontrolled(card) {
@@ -1309,7 +1377,11 @@ function _cl_autoOpenStepsIfUncontrolled(card) {
1309
1377
  var uiState = _cl_getCardUiState(card);
1310
1378
  if (uiState && uiState.stepsExpanded !== undefined) return;
1311
1379
 
1312
- var body = card.querySelector('.cl-tools-collapse-body');
1380
+ // 缓存 body 引用,避免 5-16Hz Lit rerender 时重复 querySelector
1381
+ if (!card.__clStepsBody) {
1382
+ card.__clStepsBody = card.querySelector('.cl-tools-collapse-body');
1383
+ }
1384
+ var body = card.__clStepsBody;
1313
1385
  if (!body) return;
1314
1386
 
1315
1387
  body.classList.remove('cl-collapsed');
@@ -1364,6 +1436,11 @@ function _cl_countChunkTypes(chunks) {
1364
1436
  }
1365
1437
 
1366
1438
  function _cl_finalizeCard(card, steps) {
1439
+ if (card && card.classList && card.classList.contains('cl-exec-v2')) {
1440
+ if (typeof _clUpdateAgentStatusTextV2 === 'function') _clUpdateAgentStatusTextV2(card, 'completed');
1441
+ } else if (typeof _clUpdateAgentStatusText === 'function') {
1442
+ _clUpdateAgentStatusText(card, 'completed');
1443
+ }
1367
1444
  var header = card.querySelector('.cl-tools-collapse-header-title');
1368
1445
  if (header) {
1369
1446
  header.textContent = '思考完成';
@@ -1374,6 +1451,20 @@ function _cl_finalizeCard(card, steps) {
1374
1451
  dots[i].className = 'cl-tools-collapse-step-check';
1375
1452
  }
1376
1453
 
1454
+ // 执行完成后隐藏第一个 chat-bubble(execution card),仅保留 output card
1455
+ // 仅 V2 启用:V1 的 output card 布局不同,不宜隐藏 execution bubble
1456
+ var isV2Finalize = typeof _clIsHostVersionGte === 'function' && _clIsHostVersionGte('2026.6.9');
1457
+ if (isV2Finalize && card && !card.__clBubbleHidden) {
1458
+ card.__clBubbleHidden = true;
1459
+ var bubble = card.closest && card.closest('.chat-bubble');
1460
+ if (bubble) {
1461
+ // 延迟隐藏,等 output card(第二个 bubble)渲染完毕
1462
+ setTimeout(function() {
1463
+ bubble.style.display = 'none';
1464
+ }, 500);
1465
+ }
1466
+ }
1467
+
1377
1468
  // Finalize 只负责把 execution card 标记为完成态。
1378
1469
  // 不在这里强制折叠 steps:OpenClaw 会周期性 rerender,若 finalize 每次都
1379
1470
  // 写 cl-collapsed,会覆盖用户手动展开后的状态。