openclaw-openagent 1.0.0

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 (113) hide show
  1. package/index.ts +114 -0
  2. package/openclaw.plugin.json +159 -0
  3. package/package.json +79 -0
  4. package/skills/clawlink/SKILL.md +145 -0
  5. package/skills/clawlink/SKILL.md.bak +165 -0
  6. package/src/app/channel-tools.ts +249 -0
  7. package/src/app/discovery-tools.ts +273 -0
  8. package/src/app/hooks.ts +60 -0
  9. package/src/app/index.ts +78 -0
  10. package/src/app/messaging-tools.ts +79 -0
  11. package/src/app/ops-tools.ts +155 -0
  12. package/src/app/remote-agent-tool.ts +476 -0
  13. package/src/app/types.ts +67 -0
  14. package/src/app/verbose-preflight.ts +190 -0
  15. package/src/auth/config.ts +197 -0
  16. package/src/auth/credential-manager.ts +146 -0
  17. package/src/auth/index.ts +24 -0
  18. package/src/auth/verify.ts +99 -0
  19. package/src/channel.ts +565 -0
  20. package/src/compat.ts +82 -0
  21. package/src/config/config-schema.ts +39 -0
  22. package/src/messaging/aggregator.ts +120 -0
  23. package/src/messaging/collector.ts +89 -0
  24. package/src/messaging/executor.ts +72 -0
  25. package/src/messaging/inbound.ts +150 -0
  26. package/src/messaging/index.ts +11 -0
  27. package/src/messaging/mention-protocol.ts +94 -0
  28. package/src/messaging/process-c2c-request.ts +564 -0
  29. package/src/messaging/process-message.ts +373 -0
  30. package/src/messaging/scheduler.ts +55 -0
  31. package/src/messaging/types.ts +38 -0
  32. package/src/plugin-ui/assets/agentbook-icon.svg +5 -0
  33. package/src/plugin-ui/assets/magic.svg +5 -0
  34. package/src/plugin-ui/assets/openagent-override.js +9329 -0
  35. package/src/plugin-ui/build.cjs +175 -0
  36. package/src/plugin-ui/index.ts +18 -0
  37. package/src/plugin-ui/modules/agent-book/panel/agent-book.js +458 -0
  38. package/src/plugin-ui/modules/agent-book/panel/agent-card.js +154 -0
  39. package/src/plugin-ui/modules/agent-book/panel/agent-data.js +644 -0
  40. package/src/plugin-ui/modules/agent-book/panel/inject-ui.js +456 -0
  41. package/src/plugin-ui/modules/agent-book/panel/mention-state.js +206 -0
  42. package/src/plugin-ui/modules/agent-book/panel/styles.js +670 -0
  43. package/src/plugin-ui/modules/agent-book/remote-agent-tool/components-core.js +293 -0
  44. package/src/plugin-ui/modules/agent-book/remote-agent-tool/thought-chain-card.js +208 -0
  45. package/src/plugin-ui/modules/agent-book/scanner.js +119 -0
  46. package/src/plugin-ui/modules/agent-book/travelcard/travel-cards.js +500 -0
  47. package/src/plugin-ui/modules/agent-book/travelcard/travel-engine.js +652 -0
  48. package/src/plugin-ui/modules/agent-book/travelcard/travel-styles.js +251 -0
  49. package/src/plugin-ui/modules/loader/bootstrap.js +38 -0
  50. package/src/plugin-ui/modules/loader/shared-state.js +560 -0
  51. package/src/plugin-ui/modules/loader/ws-intercept.js +199 -0
  52. package/src/plugin-ui/modules/remote-agent/chunk-parser.js +161 -0
  53. package/src/plugin-ui/modules/remote-agent/execution-card.js +269 -0
  54. package/src/plugin-ui/modules/remote-agent/markdown-renderer.js +256 -0
  55. package/src/plugin-ui/modules/remote-agent/native-style-adapter.js +146 -0
  56. package/src/plugin-ui/modules/remote-agent/output-card.js +259 -0
  57. package/src/plugin-ui/modules/remote-agent/progress-store.js +363 -0
  58. package/src/plugin-ui/modules/remote-agent/render-hooks.js +1609 -0
  59. package/src/plugin-ui/modules/remote-agent/styles.js +668 -0
  60. package/src/plugin-ui/modules/remote-agent/tool-card-model.js +56 -0
  61. package/src/plugin-ui/ui-extension-loader/backup.ts +92 -0
  62. package/src/plugin-ui/ui-extension-loader/index.ts +276 -0
  63. package/src/plugin-ui/ui-extension-loader/locator.ts +152 -0
  64. package/src/plugin-ui/ui-extension-loader/manifest.ts +57 -0
  65. package/src/plugin-ui/ui-extension-loader/registry-regex.ts +729 -0
  66. package/src/plugin-ui/ui-extension-loader/removed-extensions.ts +70 -0
  67. package/src/plugin-ui/ui-extension-loader/types.ts +68 -0
  68. package/src/proxy/auth-proxy.ts +356 -0
  69. package/src/runtime/account.ts +572 -0
  70. package/src/runtime/index.ts +7 -0
  71. package/src/runtime/plugin-runtime.ts +94 -0
  72. package/src/runtime/registry.ts +71 -0
  73. package/src/sdk/CLASS_MAP.md +143 -0
  74. package/src/sdk/index.d.ts +126 -0
  75. package/src/sdk/index.js +23990 -0
  76. package/src/sdk/modules/cloud-search-module.js +1117 -0
  77. package/src/sdk/modules/follow-module.js +1069 -0
  78. package/src/sdk/modules/group-module.js +7397 -0
  79. package/src/sdk/modules/relationship-module.js +2269 -0
  80. package/src/sdk/modules/signaling-module.js +1468 -0
  81. package/src/sdk/modules/tim-upload-plugin.js +730 -0
  82. package/src/sdk/node-env/http-request.js +90 -0
  83. package/src/sdk/node-env/index.js +57 -0
  84. package/src/sdk/node-env/storage.js +114 -0
  85. package/src/sdk/package.json +10 -0
  86. package/src/sdk/tsconfig.json +16 -0
  87. package/src/state/pending-invocation-store.ts +43 -0
  88. package/src/state/store.ts +676 -0
  89. package/src/tim/c2c.ts +451 -0
  90. package/src/tim/channels.ts +364 -0
  91. package/src/tim/client.ts +330 -0
  92. package/src/tim/index.ts +18 -0
  93. package/src/tim/messages.ts +166 -0
  94. package/src/tim/sdk-logger-init.ts +50 -0
  95. package/src/tools.ts +10 -0
  96. package/src/transport/factory.ts +95 -0
  97. package/src/transport/oasn/index.ts +17 -0
  98. package/src/transport/oasn/oasn-agent-card.ts +111 -0
  99. package/src/transport/oasn/oasn-discovery.ts +108 -0
  100. package/src/transport/oasn/oasn-files.ts +210 -0
  101. package/src/transport/oasn/oasn-http.ts +483 -0
  102. package/src/transport/oasn/oasn-invocation.ts +527 -0
  103. package/src/transport/oasn/oasn-normalize.ts +159 -0
  104. package/src/transport/oasn/oasn-register.ts +106 -0
  105. package/src/transport/oasn/oasn-transport.ts +341 -0
  106. package/src/transport/oasn/oasn-types.ts +353 -0
  107. package/src/transport/tim/index.ts +8 -0
  108. package/src/transport/tim/tim-transport.ts +515 -0
  109. package/src/transport/types.ts +541 -0
  110. package/src/types/openclaw.d.ts +97 -0
  111. package/src/types/tencentcloud-chat.d.ts +15 -0
  112. package/src/util/http.ts +113 -0
  113. package/src/util/logger.ts +131 -0
@@ -0,0 +1,560 @@
1
+ // ══════════════════════════════════════════════════════════════
2
+ // CL — OpenAgent 共享状态与跨模块 hooks
3
+ // 所有跨模块依赖必须注册在此,禁止隐式闭包共享
4
+ // ══════════════════════════════════════════════════════════════
5
+ const CL = {
6
+ // ── 数据 ──
7
+ agentCache: [], // Agent 列表缓存
8
+ lastFetchTime: 0, // 上次拉取时间戳
9
+
10
+ // ── Mention 状态 ──
11
+ pendingMention: null, // 待注入的 @mention 数据
12
+ panel: null, // Agent Book 面板 DOM
13
+ escKeyBound: false, // ESC 键是否已绑定
14
+
15
+ // ── Trip 数据 ──
16
+ tripCardData: null, // 行程卡片 JSON 数据
17
+ tripCardDataScoped: null, // 按 toolCallId / routeId / cardId 存储的行程卡片缓存
18
+ tripCardDataFetchPromise: null, // trip-card-data.json 的全局单次请求
19
+ tripCardDataFetchFailed: false, // 文件不存在时避免扫描器重复 404
20
+
21
+ // ── Scanner ──
22
+ clScanCount: 0, // 通用 DOM 扫描计数器
23
+
24
+ // ── Agent Identity(跨链路传递) ──
25
+ lastMentionAgentId: null, // 用户选择 Agent 时保留的 agent_id(100% 可靠)
26
+ agentIdentityCache: {}, // 按 id/name 缓存完整身份,避免用 UUID 走搜索接口查头像
27
+ remoteSendInFlight: false, // Agent Book remote call 发送锁,避免 async patch 期间重复发送
28
+
29
+ // ── Hooks(前向引用安全) ──
30
+ // 占位函数,由后续模块赋值覆盖真实实现
31
+ handleDelegateWsEvent: function(msg) {},
32
+ processCustomCards: function(bubble) {},
33
+
34
+ // ── 配置 ──
35
+ OPENAGENT_API: 'https://api.openagent.club',
36
+ AUTH_API: '/plugins/openagent', // Proxied via Gateway registerHttpRoute (see src/proxy/auth-proxy.ts)
37
+ POLL_INTERVAL: 800,
38
+ MAX_POLL: 30,
39
+ CACHE_TTL: 30000,
40
+ };
41
+
42
+ // 暴露到 window 供控制台调试/测试
43
+ window.__CL = CL;
44
+
45
+ CL._agentIdentityStorageKey = 'openagent.agentIdentityCache.v1';
46
+
47
+ CL._agentIdentityCacheLoaded = false;
48
+
49
+ CL._tripCardScopedStorageKey = 'openagent.tripCardData.scoped.v1';
50
+ CL._tripCardScopedLoaded = false;
51
+ CL._tripCardScopedMaxEntries = 240;
52
+
53
+ CL._loadAgentIdentityCache = function() {
54
+ if (CL._agentIdentityCacheLoaded) return;
55
+ CL._agentIdentityCacheLoaded = true;
56
+ try {
57
+ var raw = window.localStorage && window.localStorage.getItem(CL._agentIdentityStorageKey);
58
+ if (!raw) return;
59
+ var parsed = JSON.parse(raw);
60
+ if (parsed && typeof parsed === 'object') {
61
+ CL.agentIdentityCache = parsed;
62
+ }
63
+ } catch (err) {
64
+ CL.agentIdentityCache = CL.agentIdentityCache || {};
65
+ }
66
+ };
67
+
68
+ CL._saveAgentIdentityCache = function() {
69
+ try {
70
+ if (!window.localStorage) return;
71
+ window.localStorage.setItem(CL._agentIdentityStorageKey, JSON.stringify(CL.agentIdentityCache || {}));
72
+ } catch (err) {}
73
+ };
74
+
75
+ CL.storeAgentIdentity = function(agent, fallbackName) {
76
+ if (!agent || typeof agent !== 'object') return null;
77
+ CL._loadAgentIdentityCache();
78
+
79
+ var id = agent.agent_id || agent.agentId || agent.id || agent.tag ||
80
+ agent.user_id || agent.userId || agent.identifier || agent.tim_user_id || agent.timUserId || '';
81
+ var name = agent.name || agent.agent_name || agent.agentName || fallbackName || '';
82
+ var avatar = agent.avatar || agent.avatar_url || agent.avatarUrl || agent.image || agent.logo || agent.photo || '';
83
+ var record = {
84
+ id: id,
85
+ agent_id: id,
86
+ tag: agent.tag || id,
87
+ name: name,
88
+ avatar: avatar || null,
89
+ };
90
+
91
+ var keys = [id, record.tag, name, fallbackName].filter(Boolean);
92
+ if (keys.length === 0) return null;
93
+ for (var i = 0; i < keys.length; i++) {
94
+ CL.agentIdentityCache[String(keys[i])] = record;
95
+ }
96
+ CL._saveAgentIdentityCache();
97
+ return record;
98
+ };
99
+
100
+ CL.getAgentIdentity = function(identifier, fallbackName) {
101
+ CL._loadAgentIdentityCache();
102
+ var keys = [identifier, fallbackName].filter(Boolean);
103
+ for (var i = 0; i < keys.length; i++) {
104
+ var hit = CL.agentIdentityCache && CL.agentIdentityCache[String(keys[i])];
105
+ if (hit) return hit;
106
+ }
107
+ return null;
108
+ };
109
+
110
+ CL.getOpenClawApp = function() {
111
+ var app = document.querySelector('openclaw-app');
112
+ if (app) return app;
113
+ var nodes = document.querySelectorAll('*');
114
+ for (var i = 0; i < nodes.length; i++) {
115
+ if (typeof nodes[i].handleSendChat === 'function' && nodes[i].client) {
116
+ return nodes[i];
117
+ }
118
+ }
119
+ return null;
120
+ };
121
+
122
+ CL.getCurrentSessionKey = function(app) {
123
+ var key = app && typeof app.sessionKey === 'string' ? app.sessionKey : '';
124
+ if (!key) {
125
+ try {
126
+ key = new URL(window.location.href).searchParams.get('session') || '';
127
+ } catch (err) {}
128
+ }
129
+ if (key === 'main') return 'agent:main:main';
130
+ return key;
131
+ };
132
+
133
+ CL.sendRemoteAgentMessage = async function(message) {
134
+ var app = CL.getOpenClawApp();
135
+ if (!app || typeof app.handleSendChat !== 'function') {
136
+ throw new Error('OpenClaw send handler is not available');
137
+ }
138
+ await app.handleSendChat(message);
139
+ };
140
+
141
+ CL.createEmptyTripCardData = function() {
142
+ return { unitContexts: {}, dayList: [], foodData: null, budgetData: null };
143
+ };
144
+
145
+ CL.cloneTripCardData = function(data) {
146
+ if (!data || typeof data !== 'object') return null;
147
+ try {
148
+ return JSON.parse(JSON.stringify(data));
149
+ } catch (err) {
150
+ var clone = CL.createEmptyTripCardData();
151
+ clone.unitContexts = data.unitContexts && typeof data.unitContexts === 'object'
152
+ ? Object.assign({}, data.unitContexts)
153
+ : {};
154
+ clone.dayList = Array.isArray(data.dayList) ? data.dayList.slice() : [];
155
+ clone.foodData = data.foodData || null;
156
+ clone.budgetData = data.budgetData || data.budget || null;
157
+ return clone;
158
+ }
159
+ };
160
+
161
+ CL.extractTripCardRefsFromText = function(text) {
162
+ var result = {
163
+ routeIds: [],
164
+ cardRefs: [],
165
+ cardIds: [],
166
+ unitIds: []
167
+ };
168
+ if (!text) return result;
169
+
170
+ var source = String(text);
171
+ var routeSeen = Object.create(null);
172
+ var cardSeen = Object.create(null);
173
+ var unitSeen = Object.create(null);
174
+
175
+ function addRoute(id) {
176
+ id = String(id || '').trim();
177
+ if (!id || routeSeen[id]) return;
178
+ routeSeen[id] = true;
179
+ result.routeIds.push(id);
180
+ }
181
+
182
+ function addCard(tag, id) {
183
+ tag = String(tag || '').toLowerCase().trim();
184
+ id = String(id || '').trim();
185
+ if (!tag || !id) return;
186
+ if (tag === 'la_card') return;
187
+ var ref = tag + ':' + id;
188
+ if (!cardSeen[ref]) {
189
+ cardSeen[ref] = true;
190
+ result.cardRefs.push(ref);
191
+ result.cardIds.push(id);
192
+ }
193
+ if ((tag === 'tr_card' || tag === 'i_card') && !unitSeen[id]) {
194
+ unitSeen[id] = true;
195
+ result.unitIds.push(id);
196
+ }
197
+ if (tag === 'sh_card') {
198
+ var prefix = id.match(/^([A-Za-z0-9-]+)(?:[_:])/);
199
+ if (prefix && prefix[1]) addRoute(prefix[1]);
200
+ }
201
+ }
202
+
203
+ var routeMatch;
204
+ var routeRegex = /[?&]routeId=([A-Za-z0-9_-]+)/g;
205
+ while ((routeMatch = routeRegex.exec(source))) {
206
+ addRoute(routeMatch[1]);
207
+ }
208
+
209
+ var tagMatch;
210
+ var tagRegex = /(?:&lt;|<)(sh_card|tr_card|i_card|la_card|fr_card|bg_card|time_data_card)(?:&gt;|>)([\s\S]*?)(?:&lt;|<)\/\1(?:&gt;|>)/gi;
211
+ while ((tagMatch = tagRegex.exec(source))) {
212
+ addCard(tagMatch[1], tagMatch[2]);
213
+ }
214
+
215
+ return result;
216
+ };
217
+
218
+ CL.normalizeTripScope = function(scope) {
219
+ scope = scope && typeof scope === 'object' ? scope : {};
220
+ var normalized = {
221
+ toolCallId: String(scope.toolCallId || scope.tcid || '').trim(),
222
+ routeIds: [],
223
+ cardRefs: [],
224
+ cardIds: [],
225
+ unitIds: []
226
+ };
227
+ var routeSeen = Object.create(null);
228
+ var cardSeen = Object.create(null);
229
+ var cardIdSeen = Object.create(null);
230
+ var unitSeen = Object.create(null);
231
+
232
+ function addList(target, seen, value) {
233
+ if (Array.isArray(value)) {
234
+ for (var i = 0; i < value.length; i++) addList(target, seen, value[i]);
235
+ return;
236
+ }
237
+ if (typeof value === 'string' && value.indexOf(',') !== -1) {
238
+ var parts = value.split(',');
239
+ for (var pi = 0; pi < parts.length; pi++) addList(target, seen, parts[pi]);
240
+ return;
241
+ }
242
+ var item = String(value || '').trim();
243
+ if (!item || seen[item]) return;
244
+ seen[item] = true;
245
+ target.push(item);
246
+ }
247
+
248
+ addList(normalized.routeIds, routeSeen, scope.routeIds || scope.routeId || '');
249
+ addList(normalized.cardRefs, cardSeen, scope.cardRefs || scope.cardRef || '');
250
+ addList(normalized.cardIds, cardIdSeen, scope.cardIds || scope.cardId || '');
251
+ addList(normalized.unitIds, unitSeen, scope.unitIds || scope.unitId || '');
252
+
253
+ var rawRefs = CL.extractTripCardRefsFromText(scope.rawText || scope.html || scope.text || '');
254
+ addList(normalized.routeIds, routeSeen, rawRefs.routeIds);
255
+ addList(normalized.cardRefs, cardSeen, rawRefs.cardRefs);
256
+ addList(normalized.cardIds, cardIdSeen, rawRefs.cardIds);
257
+ addList(normalized.unitIds, unitSeen, rawRefs.unitIds);
258
+
259
+ for (var ci = 0; ci < normalized.cardRefs.length; ci++) {
260
+ var refParts = normalized.cardRefs[ci].split(':');
261
+ if (refParts.length >= 2) {
262
+ addList(normalized.cardIds, cardIdSeen, refParts.slice(1).join(':'));
263
+ var tag = refParts[0];
264
+ var id = refParts.slice(1).join(':');
265
+ if (tag === 'tr_card' || tag === 'i_card') {
266
+ addList(normalized.unitIds, unitSeen, id);
267
+ }
268
+ }
269
+ }
270
+
271
+ return normalized;
272
+ };
273
+
274
+ CL.getTripCardScopeKeys = function(scope) {
275
+ var normalized = CL.normalizeTripScope(scope);
276
+ var keys = [];
277
+ var seen = Object.create(null);
278
+
279
+ function add(key) {
280
+ key = String(key || '').trim();
281
+ if (!key || seen[key]) return;
282
+ seen[key] = true;
283
+ keys.push(key);
284
+ }
285
+
286
+ if (normalized.toolCallId) add('tool:' + normalized.toolCallId);
287
+ for (var ri = 0; ri < normalized.routeIds.length; ri++) add('route:' + normalized.routeIds[ri]);
288
+ for (var cr = 0; cr < normalized.cardRefs.length; cr++) add('card:' + normalized.cardRefs[cr]);
289
+ for (var ci = 0; ci < normalized.cardIds.length; ci++) add('card-id:' + normalized.cardIds[ci]);
290
+ for (var ui = 0; ui < normalized.unitIds.length; ui++) add('unit:' + normalized.unitIds[ui]);
291
+ return keys;
292
+ };
293
+
294
+ CL._loadTripCardScopedCache = function() {
295
+ if (CL._tripCardScopedLoaded) return;
296
+ CL._tripCardScopedLoaded = true;
297
+ CL.tripCardDataScoped = { version: 1, entries: {} };
298
+ try {
299
+ var raw = window.localStorage && window.localStorage.getItem(CL._tripCardScopedStorageKey);
300
+ if (!raw) return;
301
+ var parsed = JSON.parse(raw);
302
+ if (parsed && parsed.entries && typeof parsed.entries === 'object') {
303
+ CL.tripCardDataScoped = parsed;
304
+ }
305
+ } catch (err) {
306
+ CL.tripCardDataScoped = { version: 1, entries: {} };
307
+ }
308
+ };
309
+
310
+ CL._saveTripCardScopedCache = function() {
311
+ try {
312
+ if (!window.localStorage || !CL.tripCardDataScoped) return;
313
+ var entries = CL.tripCardDataScoped.entries || {};
314
+ var keys = Object.keys(entries);
315
+ if (keys.length > CL._tripCardScopedMaxEntries) {
316
+ keys.sort(function(a, b) {
317
+ return ((entries[b] && entries[b].updatedAt) || 0) - ((entries[a] && entries[a].updatedAt) || 0);
318
+ });
319
+ for (var i = CL._tripCardScopedMaxEntries; i < keys.length; i++) {
320
+ delete entries[keys[i]];
321
+ }
322
+ }
323
+ window.localStorage.setItem(CL._tripCardScopedStorageKey, JSON.stringify(CL.tripCardDataScoped));
324
+ } catch (err) {}
325
+ };
326
+
327
+ CL.getScopedTripCardData = function(scope) {
328
+ var keys = CL.getTripCardScopeKeys(scope);
329
+ if (keys.length === 0) return null;
330
+ CL._loadTripCardScopedCache();
331
+ var entries = (CL.tripCardDataScoped && CL.tripCardDataScoped.entries) || {};
332
+ for (var i = 0; i < keys.length; i++) {
333
+ var entry = entries[keys[i]];
334
+ if (entry && entry.data && typeof entry.data === 'object') {
335
+ console.log('[trip-cache] hit', keys[i]);
336
+ return CL.cloneTripCardData(entry.data);
337
+ }
338
+ }
339
+ console.log('[trip-cache] miss', keys.join(','));
340
+ return null;
341
+ };
342
+
343
+ CL.saveScopedTripCardData = function(data, scope) {
344
+ if (!data || typeof data !== 'object') return false;
345
+ var keys = CL.getTripCardScopeKeys(scope);
346
+ if (keys.length === 0) return false;
347
+
348
+ CL._loadTripCardScopedCache();
349
+ var normalized = CL.normalizeTripScope(scope);
350
+ var entry = {
351
+ version: 1,
352
+ updatedAt: Date.now(),
353
+ keys: keys,
354
+ meta: normalized,
355
+ data: CL.cloneTripCardData(data)
356
+ };
357
+ if (!entry.data) return false;
358
+
359
+ CL.tripCardDataScoped.entries = CL.tripCardDataScoped.entries || {};
360
+ for (var i = 0; i < keys.length; i++) {
361
+ CL.tripCardDataScoped.entries[keys[i]] = entry;
362
+ }
363
+ CL._saveTripCardScopedCache();
364
+ console.log('[trip-cache] saved', keys.join(','));
365
+ return true;
366
+ };
367
+
368
+ CL._mergeTripDataIntoTarget = function(target, data, replaceDayList) {
369
+ if (!target || !data || typeof data !== 'object') return false;
370
+ if (!target.unitContexts || typeof target.unitContexts !== 'object') target.unitContexts = {};
371
+ if (!Array.isArray(target.dayList)) target.dayList = [];
372
+
373
+ var changed = false;
374
+
375
+ if (data.unitContexts && typeof data.unitContexts === 'object') {
376
+ var ids = Object.keys(data.unitContexts);
377
+ for (var i = 0; i < ids.length; i++) {
378
+ target.unitContexts[ids[i]] = data.unitContexts[ids[i]];
379
+ }
380
+ if (ids.length > 0) changed = true;
381
+ }
382
+
383
+ if (data.unitContext && data.unitContext.id) {
384
+ target.unitContexts[data.unitContext.id] = data.unitContext;
385
+ changed = true;
386
+ }
387
+
388
+ if (Array.isArray(data.dayList) && (replaceDayList || target.dayList.length === 0)) {
389
+ target.dayList = data.dayList;
390
+ changed = true;
391
+ }
392
+
393
+ if (data.foodData) {
394
+ target.foodData = data.foodData;
395
+ changed = true;
396
+ }
397
+
398
+ var incomingBudget = data.budgetData
399
+ || data.budget
400
+ || (data.result && (data.result.budgetData || data.result.budget));
401
+ if (incomingBudget) {
402
+ target.budgetData = incomingBudget;
403
+ changed = true;
404
+ }
405
+
406
+ return changed;
407
+ };
408
+
409
+ CL.mergeScopedTripCardData = function(data, scope, options) {
410
+ if (!data || typeof data !== 'object') return false;
411
+ var keys = CL.getTripCardScopeKeys(scope);
412
+ if (keys.length === 0) return false;
413
+
414
+ var existing = CL.getScopedTripCardData(scope);
415
+ var target = existing || CL.createEmptyTripCardData();
416
+ var changed = CL._mergeTripDataIntoTarget(target, data, !!(options && options.replaceDayList));
417
+ if (changed) {
418
+ CL.saveScopedTripCardData(target, scope);
419
+ }
420
+ return changed;
421
+ };
422
+
423
+ CL.tripCardDataMatchesScope = function(data, scope) {
424
+ if (!data || typeof data !== 'object') return false;
425
+ var normalized = CL.normalizeTripScope(scope);
426
+ var hasScope = !!(normalized.toolCallId || normalized.routeIds.length || normalized.cardRefs.length || normalized.cardIds.length || normalized.unitIds.length);
427
+ if (!hasScope) return true;
428
+
429
+ var unitContexts = data.unitContexts || {};
430
+ for (var i = 0; i < normalized.unitIds.length; i++) {
431
+ if (!unitContexts[normalized.unitIds[i]]) return false;
432
+ }
433
+
434
+ var needsDayList = normalized.cardRefs.some(function(ref) { return ref.indexOf('sh_card:') === 0; });
435
+ if (needsDayList && (!Array.isArray(data.dayList) || data.dayList.length === 0)) return false;
436
+
437
+ var needsFood = normalized.cardRefs.some(function(ref) { return ref.indexOf('fr_card:') === 0; });
438
+ if (needsFood && !data.foodData) return false;
439
+
440
+ var needsBudget = normalized.cardRefs.some(function(ref) { return ref.indexOf('bg_card:') === 0; });
441
+ if (needsBudget && !(data.budgetData || data.budget || (data.result && (data.result.budgetData || data.result.budget)))) return false;
442
+
443
+ return normalized.unitIds.length > 0 || needsDayList || needsFood || needsBudget;
444
+ };
445
+
446
+ CL.ensureTripCardData = function() {
447
+ if (!CL.tripCardData || typeof CL.tripCardData !== 'object') {
448
+ CL.tripCardData = CL.createEmptyTripCardData();
449
+ }
450
+ if (!CL.tripCardData.unitContexts || typeof CL.tripCardData.unitContexts !== 'object') {
451
+ CL.tripCardData.unitContexts = {};
452
+ }
453
+ if (!Array.isArray(CL.tripCardData.dayList)) {
454
+ CL.tripCardData.dayList = [];
455
+ }
456
+ return CL.tripCardData;
457
+ };
458
+
459
+ CL.mergeTripCardData = function(data, options) {
460
+ if (!data || typeof data !== 'object') return false;
461
+
462
+ var target = CL.ensureTripCardData();
463
+ var replaceDayList = !!(options && options.replaceDayList);
464
+ var changed = CL._mergeTripDataIntoTarget(target, data, replaceDayList);
465
+ var scope = options && (options.scope || options.meta);
466
+ var scopedChanged = scope ? CL.mergeScopedTripCardData(data, scope, options) : false;
467
+
468
+ if (changed) {
469
+ CL.tripCardDataFetchFailed = false;
470
+ try {
471
+ localStorage.setItem('openagent_tripCardData', JSON.stringify(target));
472
+ } catch (e) {}
473
+ }
474
+
475
+ return changed || scopedChanged;
476
+ };
477
+
478
+ CL.diagCardSeq = 0;
479
+
480
+ CL.diagMarkCard = function(node, source, meta) {
481
+ if (!node || !node.dataset) return '';
482
+ var uid = 'clc-' + (++CL.diagCardSeq) + '-' + Date.now().toString(36);
483
+ var tcid = (meta && meta.tcid) || '';
484
+ node.dataset.clCardUid = uid;
485
+ node.dataset.clCardSource = source || '';
486
+ node.dataset.clCardTcid = tcid;
487
+ node.__clCardUid = uid;
488
+ node.__clCardSource = source || '';
489
+ console.log('[cl-diag][card-create] uid=' + uid
490
+ + ' source=' + (source || '')
491
+ + ' tcid=' + String(tcid).substring(0, 8));
492
+ return uid;
493
+ };
494
+
495
+ CL.diagHtmlRewrite = function(label, el, extra) {
496
+ try {
497
+ if (!el || !el.querySelectorAll) return;
498
+ var cards = Array.from(el.querySelectorAll('.cl-remote-agent-card'));
499
+ if (el.classList && el.classList.contains('cl-remote-agent-card')) {
500
+ cards.unshift(el);
501
+ }
502
+ if (cards.length === 0) return;
503
+
504
+ var cardInfo = cards.map(function(card) {
505
+ var uid = card.dataset ? (card.dataset.clCardUid || '') : '';
506
+ var jsUid = card.__clCardUid || '';
507
+ var img = card.querySelector && card.querySelector('.cl-agent-pill-avatar');
508
+ return {
509
+ uid: uid,
510
+ jsUid: jsUid,
511
+ alive: !!uid && uid === jsUid,
512
+ tcid: card.dataset ? (card.dataset.clCardTcid || '') : '',
513
+ imgAlt: img ? img.getAttribute('alt') : null,
514
+ imgSrc: img ? img.getAttribute('src') : null,
515
+ text: (card.textContent || '').replace(/\s+/g, ' ').trim().slice(0, 120)
516
+ };
517
+ });
518
+
519
+ console.warn('[cl-diag][html-write] ' + label + ' ' + JSON.stringify({
520
+ target: el.className || el.tagName,
521
+ extra: extra || null,
522
+ cards: cardInfo
523
+ }));
524
+ console.warn('[cl-diag][html-stack] ' + label + '\n'
525
+ + (new Error().stack || '').split('\n').slice(1, 8).join('\n'));
526
+ } catch (err) {
527
+ console.warn('[cl-diag][html-write-error] ' + label + ' ' + err.message);
528
+ }
529
+ };
530
+
531
+ if (!window.__clDiagClickProbeInstalled) {
532
+ window.__clDiagClickProbeInstalled = true;
533
+ document.addEventListener('click', function(evt) {
534
+ var target = evt.target;
535
+ if (!target || !target.closest) return;
536
+ var header = target.closest('.cl-tools-collapse-header');
537
+ if (!header) return;
538
+ var card = header.closest('.cl-remote-agent-card');
539
+ if (!card) return;
540
+
541
+ var body = card.querySelector('.cl-tools-collapse-body');
542
+ var title = card.querySelector('.cl-tools-collapse-header-title');
543
+ var uid = card.dataset ? (card.dataset.clCardUid || '') : '';
544
+ var jsUid = card.__clCardUid || '';
545
+ console.log('[cl-diag][click-probe] before uid=' + uid
546
+ + ' jsUid=' + jsUid
547
+ + ' alive=' + (!!uid && uid === jsUid)
548
+ + ' title=' + JSON.stringify(title ? title.textContent.trim() : '')
549
+ + ' bodyClass=' + (body ? body.className : '')
550
+ + ' steps=' + (body ? body.querySelectorAll('.cl-tools-collapse-step').length : 0));
551
+
552
+ setTimeout(function() {
553
+ var afterBody = card.querySelector('.cl-tools-collapse-body');
554
+ console.log('[cl-diag][click-probe] after uid=' + uid
555
+ + ' jsUid=' + (card.__clCardUid || '')
556
+ + ' bodyClass=' + (afterBody ? afterBody.className : '')
557
+ + ' steps=' + (afterBody ? afterBody.querySelectorAll('.cl-tools-collapse-step').length : 0));
558
+ }, 0);
559
+ }, true);
560
+ }