openclaw-openagent 1.0.13 → 1.0.14
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.
- package/dist/src/messaging/executor.d.ts +2 -3
- package/dist/src/messaging/executor.js +4 -31
- package/dist/src/plugin-ui/assets/openagent-override.js +4 -5
- package/dist/src/runtime/update-checker.d.ts +1 -1
- package/dist/src/runtime/update-checker.js +9 -46
- package/package.json +1 -3
- package/src/app/channel-tools.ts +0 -249
- package/src/app/discovery-tools.ts +0 -273
- package/src/app/download-file-tool.ts +0 -133
- package/src/app/hooks.ts +0 -144
- package/src/app/index.ts +0 -84
- package/src/app/messaging-tools.ts +0 -79
- package/src/app/ops-tools.ts +0 -155
- package/src/app/remote-agent-tool.ts +0 -762
- package/src/app/types.ts +0 -68
- package/src/app/upload-file-tool.ts +0 -411
- package/src/app/verbose-preflight.ts +0 -190
- package/src/auth/config.ts +0 -266
- package/src/auth/credential-manager.ts +0 -146
- package/src/auth/index.ts +0 -24
- package/src/auth/verify.ts +0 -99
- package/src/channel.ts +0 -566
- package/src/compat.ts +0 -94
- package/src/config/config-schema.ts +0 -45
- package/src/messaging/aggregator.ts +0 -120
- package/src/messaging/collector.ts +0 -89
- package/src/messaging/executor.ts +0 -72
- package/src/messaging/inbound.ts +0 -150
- package/src/messaging/index.ts +0 -11
- package/src/messaging/mention-protocol.ts +0 -94
- package/src/messaging/process-c2c-request.ts +0 -564
- package/src/messaging/process-message.ts +0 -373
- package/src/messaging/scheduler.ts +0 -55
- package/src/messaging/types.ts +0 -38
- package/src/plugin-ui/adapters/oc-2026-04.js +0 -103
- package/src/plugin-ui/adapters/oc-2026-05.js +0 -125
- package/src/plugin-ui/adapters/oc-2026-06.js +0 -125
- package/src/plugin-ui/adapters/oc-unknown.js +0 -48
- package/src/plugin-ui/assets/agentbook-icon.svg +0 -5
- package/src/plugin-ui/assets/bg.png +0 -0
- package/src/plugin-ui/assets/icon.png +0 -0
- package/src/plugin-ui/assets/magic.svg +0 -5
- package/src/plugin-ui/assets/openagent-override.js +0 -11263
- package/src/plugin-ui/build.cjs +0 -463
- package/src/plugin-ui/index.ts +0 -18
- package/src/plugin-ui/modules/agent-book/panel/agent-book.js +0 -570
- package/src/plugin-ui/modules/agent-book/panel/agent-card.js +0 -170
- package/src/plugin-ui/modules/agent-book/panel/agent-data.js +0 -643
- package/src/plugin-ui/modules/agent-book/panel/inject-ui.js +0 -665
- package/src/plugin-ui/modules/agent-book/panel/mention-state.js +0 -206
- package/src/plugin-ui/modules/agent-book/panel/styles.js +0 -832
- package/src/plugin-ui/modules/agent-book/panel/theme-adapter.js +0 -86
- package/src/plugin-ui/modules/agent-book/remote-agent-tool/components-core.js +0 -295
- package/src/plugin-ui/modules/agent-book/remote-agent-tool/thought-chain-card.js +0 -211
- package/src/plugin-ui/modules/agent-book/scanner.js +0 -131
- package/src/plugin-ui/modules/agent-book/travelcard/travel-cards.js +0 -500
- package/src/plugin-ui/modules/agent-book/travelcard/travel-engine.js +0 -652
- package/src/plugin-ui/modules/agent-book/travelcard/travel-styles.js +0 -262
- package/src/plugin-ui/modules/loader/bootstrap.js +0 -133
- package/src/plugin-ui/modules/loader/shared-state.js +0 -838
- package/src/plugin-ui/modules/loader/ws-intercept.js +0 -199
- package/src/plugin-ui/modules/remote-agent/chunk-parser.js +0 -161
- package/src/plugin-ui/modules/remote-agent/execution-card.js +0 -530
- package/src/plugin-ui/modules/remote-agent/markdown-renderer.js +0 -256
- package/src/plugin-ui/modules/remote-agent/media-links.js +0 -151
- package/src/plugin-ui/modules/remote-agent/native-style-adapter.js +0 -134
- package/src/plugin-ui/modules/remote-agent/output-card.js +0 -342
- package/src/plugin-ui/modules/remote-agent/progress-store.js +0 -363
- package/src/plugin-ui/modules/remote-agent/render-hooks.js +0 -1700
- package/src/plugin-ui/modules/remote-agent/styles.js +0 -903
- package/src/plugin-ui/modules/remote-agent/tool-card-model.js +0 -130
- package/src/plugin-ui/postinstall-deploy.cjs +0 -52
- package/src/plugin-ui/ui-extension-loader/backup.ts +0 -92
- package/src/plugin-ui/ui-extension-loader/index.ts +0 -276
- package/src/plugin-ui/ui-extension-loader/locator.ts +0 -152
- package/src/plugin-ui/ui-extension-loader/manifest.ts +0 -57
- package/src/plugin-ui/ui-extension-loader/registry-regex.ts +0 -944
- package/src/plugin-ui/ui-extension-loader/removed-extensions.ts +0 -70
- package/src/plugin-ui/ui-extension-loader/types.ts +0 -72
- package/src/proxy/auth-proxy.ts +0 -414
- package/src/runtime/account.ts +0 -549
- package/src/runtime/index.ts +0 -7
- package/src/runtime/plugin-runtime.ts +0 -94
- package/src/runtime/registry.ts +0 -71
- package/src/runtime/update-checker.ts +0 -286
- package/src/sdk/CLASS_MAP.md +0 -143
- package/src/sdk/index.d.ts +0 -126
- package/src/sdk/index.js +0 -23990
- package/src/sdk/modules/cloud-search-module.js +0 -1117
- package/src/sdk/modules/follow-module.js +0 -1069
- package/src/sdk/modules/group-module.js +0 -7397
- package/src/sdk/modules/relationship-module.js +0 -2269
- package/src/sdk/modules/signaling-module.js +0 -1468
- package/src/sdk/modules/tim-upload-plugin.js +0 -730
- package/src/sdk/node-env/http-request.js +0 -90
- package/src/sdk/node-env/index.js +0 -57
- package/src/sdk/node-env/storage.js +0 -114
- package/src/sdk/package.json +0 -10
- package/src/sdk/tsconfig.json +0 -16
- package/src/state/pending-invocation-store.ts +0 -43
- package/src/state/store.ts +0 -756
- package/src/tim/c2c.ts +0 -451
- package/src/tim/channels.ts +0 -364
- package/src/tim/client.ts +0 -330
- package/src/tim/index.ts +0 -18
- package/src/tim/messages.ts +0 -166
- package/src/tim/sdk-logger-init.ts +0 -50
- package/src/tools.ts +0 -10
- package/src/transport/factory.ts +0 -95
- package/src/transport/oasn/index.ts +0 -17
- package/src/transport/oasn/oasn-agent-card.ts +0 -111
- package/src/transport/oasn/oasn-discovery.ts +0 -108
- package/src/transport/oasn/oasn-files.ts +0 -210
- package/src/transport/oasn/oasn-http.ts +0 -529
- package/src/transport/oasn/oasn-invocation.ts +0 -604
- package/src/transport/oasn/oasn-normalize.ts +0 -133
- package/src/transport/oasn/oasn-register.ts +0 -33
- package/src/transport/oasn/oasn-transport.ts +0 -318
- package/src/transport/oasn/oasn-types.ts +0 -404
- package/src/transport/tim/index.ts +0 -8
- package/src/transport/tim/tim-transport.ts +0 -515
- package/src/transport/types.ts +0 -538
- package/src/types/openclaw-plugin-sdk-media-store.d.ts +0 -9
- package/src/types/openclaw.d.ts +0 -97
- package/src/types/tencentcloud-chat.d.ts +0 -15
- package/src/util/http.ts +0 -113
- package/src/util/logger.ts +0 -131
- package/src/util/url-resolver.ts +0 -77
|
@@ -1,652 +0,0 @@
|
|
|
1
|
-
// ── 5. Card Data Extraction & Replacement Engine ──
|
|
2
|
-
|
|
3
|
-
function _findTripCardDataInDom(root) {
|
|
4
|
-
const scopes = [];
|
|
5
|
-
if (root) scopes.push(root);
|
|
6
|
-
if (typeof document !== 'undefined') scopes.push(document);
|
|
7
|
-
|
|
8
|
-
const seen = new Set();
|
|
9
|
-
for (const scope of scopes) {
|
|
10
|
-
if (!scope || seen.has(scope)) continue;
|
|
11
|
-
seen.add(scope);
|
|
12
|
-
|
|
13
|
-
const codeEls = scope.querySelectorAll ? scope.querySelectorAll('code') : [];
|
|
14
|
-
for (const code of codeEls) {
|
|
15
|
-
const text = (code.textContent || '').trim();
|
|
16
|
-
if (!text.startsWith('{') || !/(unitContexts|dayList|foodData|budgetData|budget)/.test(text)) continue;
|
|
17
|
-
try {
|
|
18
|
-
const cleaned = text.replace(/[\x00-\x1f]/g, (ch) => {
|
|
19
|
-
if (ch === '\n') return '\\n';
|
|
20
|
-
if (ch === '\r') return '\\r';
|
|
21
|
-
if (ch === '\t') return '\\t';
|
|
22
|
-
return '';
|
|
23
|
-
});
|
|
24
|
-
const parsed = JSON.parse(cleaned);
|
|
25
|
-
if (parsed && (parsed.unitContexts || parsed.dayList || parsed.foodData || parsed.budgetData || parsed.budget)) {
|
|
26
|
-
if (code.parentElement) code.parentElement.style.display = 'none';
|
|
27
|
-
return parsed;
|
|
28
|
-
}
|
|
29
|
-
} catch (e) {
|
|
30
|
-
console.warn('[trip-cards] code block fallback failed:', e.message);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function _fetchTripCardDataForCards(force, scope) {
|
|
39
|
-
if (typeof CL.fetchTripCardDataOnce === 'function') {
|
|
40
|
-
return CL.fetchTripCardDataOnce('card-processor', { force: !!force, scope: scope });
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
if (scope && typeof CL.getScopedTripCardData === 'function') {
|
|
44
|
-
var scoped = CL.getScopedTripCardData(scope);
|
|
45
|
-
if (scoped && !force) return Promise.resolve(scoped);
|
|
46
|
-
}
|
|
47
|
-
if (CL.tripCardData && !force && (!scope || (typeof CL.tripCardDataMatchesScope === 'function' && CL.tripCardDataMatchesScope(CL.tripCardData, scope)))) {
|
|
48
|
-
return Promise.resolve(CL.tripCardData);
|
|
49
|
-
}
|
|
50
|
-
if (CL.tripCardDataFetchPromise) return CL.tripCardDataFetchPromise;
|
|
51
|
-
if (CL.tripCardDataFetchFailed) return Promise.resolve(null);
|
|
52
|
-
|
|
53
|
-
CL.tripCardDataFetchPromise = fetch('./trip-card-data.json?t=' + Date.now())
|
|
54
|
-
.then(r => {
|
|
55
|
-
if (!r.ok) throw new Error('HTTP ' + r.status);
|
|
56
|
-
return r.json();
|
|
57
|
-
})
|
|
58
|
-
.then(data => {
|
|
59
|
-
if (typeof CL.mergeTripCardData === 'function') {
|
|
60
|
-
CL.mergeTripCardData(data, { replaceDayList: true, scope: scope });
|
|
61
|
-
} else {
|
|
62
|
-
CL.tripCardData = data;
|
|
63
|
-
}
|
|
64
|
-
CL.tripCardDataFetchFailed = false;
|
|
65
|
-
return data;
|
|
66
|
-
})
|
|
67
|
-
.catch(err => {
|
|
68
|
-
CL.tripCardDataFetchFailed = true;
|
|
69
|
-
console.warn('[trip-cards] File fetch failed:', err.message);
|
|
70
|
-
return null;
|
|
71
|
-
})
|
|
72
|
-
.finally(() => {
|
|
73
|
-
CL.tripCardDataFetchPromise = null;
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
return CL.tripCardDataFetchPromise;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function _deriveDayListFromRenderedContent(root) {
|
|
80
|
-
if (!root || !root.querySelectorAll) return [];
|
|
81
|
-
|
|
82
|
-
var days = [];
|
|
83
|
-
var currentDay = null;
|
|
84
|
-
var seenInDay = null;
|
|
85
|
-
|
|
86
|
-
function startDay(title) {
|
|
87
|
-
currentDay = {
|
|
88
|
-
title: title || ('Day ' + (days.length + 1)),
|
|
89
|
-
districtInfos: [],
|
|
90
|
-
itineraryUnitList: []
|
|
91
|
-
};
|
|
92
|
-
seenInDay = Object.create(null);
|
|
93
|
-
days.push(currentDay);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function ensureDay() {
|
|
97
|
-
if (!currentDay) startDay('Day 1');
|
|
98
|
-
return currentDay;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
var nodes = root.querySelectorAll('h1,h2,h3,a');
|
|
102
|
-
for (var i = 0; i < nodes.length; i++) {
|
|
103
|
-
var node = nodes[i];
|
|
104
|
-
var text = (node.textContent || '').replace(/\s+/g, ' ').trim();
|
|
105
|
-
if (!text) continue;
|
|
106
|
-
|
|
107
|
-
if (/^H[1-3]$/.test(node.tagName) && /(?:^|\b)Day\s*\d+|第\s*\d+\s*天/i.test(text)) {
|
|
108
|
-
startDay(text);
|
|
109
|
-
continue;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
if (node.tagName !== 'A') continue;
|
|
113
|
-
var href = node.getAttribute('href') || '';
|
|
114
|
-
if (!/^(?:poi_|hotel_|lodgingArea_)/.test(href)) continue;
|
|
115
|
-
|
|
116
|
-
var day = ensureDay();
|
|
117
|
-
if (seenInDay[href]) continue;
|
|
118
|
-
seenInDay[href] = true;
|
|
119
|
-
|
|
120
|
-
day.itineraryUnitList.push({
|
|
121
|
-
id: href,
|
|
122
|
-
poiInfo: {
|
|
123
|
-
name: text,
|
|
124
|
-
basicInfo: {
|
|
125
|
-
poiName: text,
|
|
126
|
-
id: href
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return days.filter(function(day) {
|
|
133
|
-
return day.itineraryUnitList && day.itineraryUnitList.length > 0;
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function _lastAnchorInNode(node, predicate) {
|
|
138
|
-
if (!node) return null;
|
|
139
|
-
if (node.nodeType === 1 && node.matches && node.matches('a') && (!predicate || predicate(node))) {
|
|
140
|
-
return node;
|
|
141
|
-
}
|
|
142
|
-
if (!node.querySelectorAll) return null;
|
|
143
|
-
var anchors = Array.from(node.querySelectorAll('a'));
|
|
144
|
-
for (var i = anchors.length - 1; i >= 0; i--) {
|
|
145
|
-
if (!predicate || predicate(anchors[i])) return anchors[i];
|
|
146
|
-
}
|
|
147
|
-
return null;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
function _firstAnchorInNode(node, predicate) {
|
|
151
|
-
if (!node) return null;
|
|
152
|
-
if (node.nodeType === 1 && node.matches && node.matches('a') && (!predicate || predicate(node))) {
|
|
153
|
-
return node;
|
|
154
|
-
}
|
|
155
|
-
if (!node.querySelectorAll) return null;
|
|
156
|
-
var anchors = Array.from(node.querySelectorAll('a'));
|
|
157
|
-
for (var i = 0; i < anchors.length; i++) {
|
|
158
|
-
if (!predicate || predicate(anchors[i])) return anchors[i];
|
|
159
|
-
}
|
|
160
|
-
return null;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
function _findPreviousAnchorForCardTag(tagEl, root, predicate, preferFirstInBlock) {
|
|
164
|
-
var current = tagEl;
|
|
165
|
-
while (current && current !== root) {
|
|
166
|
-
var sibling = current.previousSibling;
|
|
167
|
-
while (sibling) {
|
|
168
|
-
var anchor = preferFirstInBlock
|
|
169
|
-
? _firstAnchorInNode(sibling, predicate)
|
|
170
|
-
: _lastAnchorInNode(sibling, predicate);
|
|
171
|
-
if (anchor) return anchor;
|
|
172
|
-
sibling = sibling.previousSibling;
|
|
173
|
-
}
|
|
174
|
-
current = current.parentNode;
|
|
175
|
-
}
|
|
176
|
-
return null;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
function _cleanFallbackCardText(text) {
|
|
180
|
-
return String(text || '')
|
|
181
|
-
.replace(/<[^>]+>/g, ' ')
|
|
182
|
-
.replace(/(?:sh_card|tr_card|i_card|fr_card|bg_card|time_data_card)_[^\s]*/g, ' ')
|
|
183
|
-
.replace(/\s+/g, ' ')
|
|
184
|
-
.trim();
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
function _stripLodgingAreaCardTagsFromHtml(html) {
|
|
188
|
-
return String(html || '')
|
|
189
|
-
.replace(/<la_card(?:\s[^>]*)?>[\s\S]*?<\/la_card>/gi, '')
|
|
190
|
-
.replace(/<la_card(?:\s[\s\S]*?)?>[\s\S]*?<\/la_card>/gi, '')
|
|
191
|
-
.replace(/<la_card(?:\s[^>]*)?\/?>/gi, '')
|
|
192
|
-
.replace(/<la_card(?:\s[\s\S]*?)?\/?>/gi, '');
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
function _getTripCardScopeFromBubble(bubble) {
|
|
196
|
-
var scope = {
|
|
197
|
-
toolCallId: '',
|
|
198
|
-
routeIds: [],
|
|
199
|
-
cardRefs: [],
|
|
200
|
-
cardIds: [],
|
|
201
|
-
unitIds: [],
|
|
202
|
-
html: bubble && bubble.innerHTML || ''
|
|
203
|
-
};
|
|
204
|
-
if (!bubble) return scope;
|
|
205
|
-
|
|
206
|
-
if (bubble.dataset) {
|
|
207
|
-
scope.toolCallId = bubble.dataset.clToolCallId || bubble.dataset.clCardTcid || '';
|
|
208
|
-
scope.routeIds = bubble.dataset.clRouteIds || '';
|
|
209
|
-
scope.cardRefs = bubble.dataset.clCardRefs || '';
|
|
210
|
-
scope.cardIds = bubble.dataset.clCardIds || '';
|
|
211
|
-
scope.unitIds = bubble.dataset.clUnitIds || '';
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
var owner = bubble.closest && bubble.closest('.cl-output-card, .cl-remote-agent-card');
|
|
215
|
-
if (owner && owner.dataset && !scope.toolCallId) {
|
|
216
|
-
scope.toolCallId = owner.dataset.clCardTcid || '';
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
if (CL && typeof CL.normalizeTripScope === 'function') {
|
|
220
|
-
return CL.normalizeTripScope(scope);
|
|
221
|
-
}
|
|
222
|
-
return scope;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
function _hasTripCardScopeIdentity(scope) {
|
|
226
|
-
return !!(scope && (scope.toolCallId
|
|
227
|
-
|| (scope.routeIds && scope.routeIds.length)
|
|
228
|
-
|| (scope.cardRefs && scope.cardRefs.length)
|
|
229
|
-
|| (scope.cardIds && scope.cardIds.length)
|
|
230
|
-
|| (scope.unitIds && scope.unitIds.length)));
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
function _extractTextAroundAnchor(anchor, root) {
|
|
234
|
-
if (!anchor) return '';
|
|
235
|
-
var block = anchor.closest && anchor.closest('li,p,div');
|
|
236
|
-
if (!block || (root && !root.contains(block))) block = anchor.parentElement;
|
|
237
|
-
return _cleanFallbackCardText(block ? block.textContent : anchor.textContent);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
function _extractDescriptionFromAnchor(anchor, name, root) {
|
|
241
|
-
var text = _extractTextAroundAnchor(anchor, root);
|
|
242
|
-
if (!text) return '';
|
|
243
|
-
|
|
244
|
-
var cleanedName = _cleanFallbackCardText(name);
|
|
245
|
-
if (cleanedName && text.indexOf(cleanedName) === 0) {
|
|
246
|
-
text = text.slice(cleanedName.length);
|
|
247
|
-
}
|
|
248
|
-
text = text.replace(/^[\s::,,.。-]+/, '').trim();
|
|
249
|
-
return text.length > 160 ? text.slice(0, 157) + '...' : text;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
function _deriveFallbackUnitContextsFromRenderedContent(root) {
|
|
253
|
-
var contexts = {};
|
|
254
|
-
if (!root || !root.querySelectorAll) return contexts;
|
|
255
|
-
|
|
256
|
-
root.querySelectorAll('i_card,tr_card').forEach(function(tagEl) {
|
|
257
|
-
var cardTag = String(tagEl.tagName || '').toLowerCase();
|
|
258
|
-
var id = (tagEl.textContent || '').trim();
|
|
259
|
-
if (!id || contexts[id]) return;
|
|
260
|
-
|
|
261
|
-
if (cardTag === 'i_card') {
|
|
262
|
-
var poiAnchor = _findPreviousAnchorForCardTag(tagEl, root, function(a) {
|
|
263
|
-
return /^poi_/.test(a.getAttribute('href') || '');
|
|
264
|
-
}, true);
|
|
265
|
-
if (!poiAnchor) return;
|
|
266
|
-
var poiName = (poiAnchor.textContent || '').replace(/\s+/g, ' ').trim();
|
|
267
|
-
var poiId = poiAnchor.getAttribute('href') || '';
|
|
268
|
-
if (!poiName) return;
|
|
269
|
-
var poiDesc = _extractDescriptionFromAnchor(poiAnchor, poiName, root);
|
|
270
|
-
contexts[id] = {
|
|
271
|
-
id: id,
|
|
272
|
-
type: 'imageCard',
|
|
273
|
-
unitList: [{
|
|
274
|
-
unitType: 'poi',
|
|
275
|
-
poiInfo: {
|
|
276
|
-
id: poiId,
|
|
277
|
-
name: poiName,
|
|
278
|
-
poiName: poiName,
|
|
279
|
-
description: poiDesc,
|
|
280
|
-
summary: poiDesc,
|
|
281
|
-
imgs: [],
|
|
282
|
-
basicInfo: {
|
|
283
|
-
id: poiId,
|
|
284
|
-
poiName: poiName,
|
|
285
|
-
description: poiDesc,
|
|
286
|
-
summary: poiDesc
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
}]
|
|
290
|
-
};
|
|
291
|
-
return;
|
|
292
|
-
}
|
|
293
|
-
});
|
|
294
|
-
|
|
295
|
-
return contexts;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
function _processCustomCards(bubble) {
|
|
299
|
-
if (!bubble) return;
|
|
300
|
-
// 保护:bubble 自身或子节点是 RenderHook 活 DOM 时,只处理 .cl-output-result
|
|
301
|
-
if ((bubble.classList.contains('cl-remote-agent-card') || bubble.querySelector('.cl-remote-agent-card'))
|
|
302
|
-
&& !bubble.classList.contains('cl-output-result')) {
|
|
303
|
-
return;
|
|
304
|
-
}
|
|
305
|
-
var bubbleHtml = bubble.innerHTML || '';
|
|
306
|
-
var strippedBubbleHtml = _stripLodgingAreaCardTagsFromHtml(bubbleHtml);
|
|
307
|
-
if (strippedBubbleHtml !== bubbleHtml) {
|
|
308
|
-
bubble.innerHTML = strippedBubbleHtml;
|
|
309
|
-
bubbleHtml = strippedBubbleHtml;
|
|
310
|
-
}
|
|
311
|
-
var hasRawCardTags = /(?:<|<)(?:sh_card|tr_card|i_card|fr_card|bg_card|time_data_card)(?:>|>)/.test(bubbleHtml);
|
|
312
|
-
var tripScope = _getTripCardScopeFromBubble(bubble);
|
|
313
|
-
var hasScopedIdentity = _hasTripCardScopeIdentity(tripScope);
|
|
314
|
-
var scopedData = (hasScopedIdentity && CL && typeof CL.getScopedTripCardData === 'function')
|
|
315
|
-
? CL.getScopedTripCardData(tripScope)
|
|
316
|
-
: null;
|
|
317
|
-
var hasUsableGlobalData = !hasScopedIdentity
|
|
318
|
-
|| (CL && typeof CL.tripCardDataMatchesScope === 'function' && CL.tripCardDataMatchesScope(CL.tripCardData, tripScope));
|
|
319
|
-
var hasAnyCardData = !!(scopedData || (CL.tripCardData && hasUsableGlobalData));
|
|
320
|
-
// 已处理过的 .cl-output-result 且已有行程卡片 → 不重写(防止图片闪烁)
|
|
321
|
-
if (bubble.classList.contains('cl-output-result')
|
|
322
|
-
&& bubble.dataset.clProcessed === '1'
|
|
323
|
-
&& bubble.querySelector('.trip-img-card, .trip-tc-card, .trip-sh-card')) {
|
|
324
|
-
return;
|
|
325
|
-
}
|
|
326
|
-
if (bubble.dataset.clProcessed === '1') return;
|
|
327
|
-
if (bubble.dataset.clProcessed === 'loading' && !hasAnyCardData && !hasRawCardTags) return;
|
|
328
|
-
if (bubble.dataset.clProcessed === 'no-data' && !hasAnyCardData && !hasRawCardTags) return;
|
|
329
|
-
if ((bubble.dataset.clProcessed === 'loading' || bubble.dataset.clProcessed === 'no-data' || bubble.dataset.clProcessed === 'partial') && hasAnyCardData) {
|
|
330
|
-
bubble.dataset.clProcessed = '';
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
// 优先使用和当前 output 身份绑定的数据,避免刷新后读到“最后一次全局行程”。
|
|
334
|
-
let dataMap = scopedData;
|
|
335
|
-
if (dataMap && CL && typeof CL.saveScopedTripCardData === 'function') {
|
|
336
|
-
CL.saveScopedTripCardData(dataMap, tripScope);
|
|
337
|
-
}
|
|
338
|
-
if (!dataMap && CL.tripCardData && hasUsableGlobalData) {
|
|
339
|
-
dataMap = CL.tripCardData;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
// 回退 A:没有完整 JSON 时,先从当前 markdown 内容推导最小数据。
|
|
343
|
-
// 这样远端只返回 <sh_card>/<i_card> 标签时,也不会被 no-data 挡住。
|
|
344
|
-
if (!dataMap) {
|
|
345
|
-
const fallbackDayList = _deriveDayListFromRenderedContent(bubble);
|
|
346
|
-
const fallbackUcs = _deriveFallbackUnitContextsFromRenderedContent(bubble);
|
|
347
|
-
if (fallbackDayList.length > 0 || Object.keys(fallbackUcs).length > 0) {
|
|
348
|
-
dataMap = {
|
|
349
|
-
unitContexts: fallbackUcs,
|
|
350
|
-
dayList: fallbackDayList,
|
|
351
|
-
foodData: null,
|
|
352
|
-
budgetData: null
|
|
353
|
-
};
|
|
354
|
-
if (typeof CL.mergeTripCardData === 'function') {
|
|
355
|
-
CL.mergeTripCardData(dataMap, { replaceDayList: false, scope: tripScope });
|
|
356
|
-
}
|
|
357
|
-
bubble.dataset.clProcessed = '';
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
// 回退 B:从文件 HTTP 获取(tool 写入了 trip-card-data.json)
|
|
362
|
-
if (!dataMap) {
|
|
363
|
-
const foundData = _findTripCardDataInDom(bubble);
|
|
364
|
-
if (foundData) {
|
|
365
|
-
if (typeof CL.mergeTripCardData === 'function') {
|
|
366
|
-
CL.mergeTripCardData(foundData, { replaceDayList: true, scope: tripScope });
|
|
367
|
-
} else {
|
|
368
|
-
CL.tripCardData = foundData;
|
|
369
|
-
}
|
|
370
|
-
CL.tripCardDataFetchFailed = false;
|
|
371
|
-
bubble.dataset.clProcessed = '';
|
|
372
|
-
_processCustomCards(bubble);
|
|
373
|
-
return;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
bubble.dataset.clProcessed = 'loading';
|
|
377
|
-
_fetchTripCardDataForCards(false, tripScope)
|
|
378
|
-
.then(data => {
|
|
379
|
-
if (data) {
|
|
380
|
-
bubble.dataset.clProcessed = '';
|
|
381
|
-
_processCustomCards(bubble);
|
|
382
|
-
} else {
|
|
383
|
-
bubble.dataset.clCardFetchFailed = '1';
|
|
384
|
-
bubble.dataset.clProcessed = 'no-data';
|
|
385
|
-
console.log('[trip-cards] No data found in any format');
|
|
386
|
-
}
|
|
387
|
-
});
|
|
388
|
-
return; // 异步处理中,先返回
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
if (!dataMap) {
|
|
392
|
-
bubble.dataset.clProcessed = 'no-data'; // 标记已处理,避免死循环
|
|
393
|
-
return;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
var _hasMissing = 0;
|
|
397
|
-
// 暂不标记 clProcessed,处理完后根据是否有缺失决定
|
|
398
|
-
|
|
399
|
-
const ucs = dataMap.unitContexts || {};
|
|
400
|
-
const dayList = dataMap.dayList || [];
|
|
401
|
-
const foodData = dataMap.foodData || null;
|
|
402
|
-
const budgetData = dataMap.budgetData || dataMap.budget || (dataMap.result && (dataMap.result.budgetData || dataMap.result.budget)) || null;
|
|
403
|
-
const hasShoppingCard = /(?:<|<)sh_card(?:>|>)/.test(bubble.innerHTML);
|
|
404
|
-
const hasFoodCard = /(?:<|<)fr_card(?:>|>)/.test(bubble.innerHTML);
|
|
405
|
-
const hasBudgetCard = /(?:<|<)bg_card(?:>|>)/.test(bubble.innerHTML);
|
|
406
|
-
const derivedDayList = hasShoppingCard ? _deriveDayListFromRenderedContent(bubble) : [];
|
|
407
|
-
const effectiveDayList = derivedDayList.length > 0 ? derivedDayList : dayList;
|
|
408
|
-
const fallbackUcs = _deriveFallbackUnitContextsFromRenderedContent(bubble);
|
|
409
|
-
|
|
410
|
-
// 诊断:列出 bubble 中所有 card tag 引用的 ID
|
|
411
|
-
var _cardTagIds = [];
|
|
412
|
-
var _unitCardTagIds = [];
|
|
413
|
-
(bubble.innerHTML.match(/(?:<|<)(?:sh_card|tr_card|i_card|fr_card|bg_card|time_data_card)(?:>|>)([\s\S]*?)(?:<|<)\//g) || []).forEach(function(m) {
|
|
414
|
-
var tagMatch = m.match(/(?:<|<)([a-z_]+)(?:>|>)/i);
|
|
415
|
-
var idMatch = m.match(/(?:>|>)([\s\S]*?)(?:<|<)/);
|
|
416
|
-
if (!idMatch) return;
|
|
417
|
-
var tag = tagMatch ? tagMatch[1].toLowerCase() : '';
|
|
418
|
-
var id = idMatch[1].trim();
|
|
419
|
-
_cardTagIds.push(tag + ':' + id);
|
|
420
|
-
if (tag === 'tr_card' || tag === 'i_card') {
|
|
421
|
-
_unitCardTagIds.push(id);
|
|
422
|
-
}
|
|
423
|
-
});
|
|
424
|
-
var _missing = _unitCardTagIds.filter(function(id) { return !ucs[id]; });
|
|
425
|
-
const needsAggregateTripData = (hasShoppingCard && effectiveDayList.length === 0)
|
|
426
|
-
|| (hasFoodCard && !foodData)
|
|
427
|
-
|| (hasBudgetCard && !budgetData)
|
|
428
|
-
|| _missing.length > 0;
|
|
429
|
-
|
|
430
|
-
if (needsAggregateTripData && !bubble.dataset.clFullTripFetchTried && !CL.tripCardDataFetchFailed) {
|
|
431
|
-
bubble.dataset.clFullTripFetchTried = '1';
|
|
432
|
-
_fetchTripCardDataForCards(true, tripScope)
|
|
433
|
-
.then(data => {
|
|
434
|
-
if (!data) return;
|
|
435
|
-
bubble.dataset.clProcessed = '';
|
|
436
|
-
_processCustomCards(bubble);
|
|
437
|
-
});
|
|
438
|
-
}
|
|
439
|
-
var _tripLogKey = [
|
|
440
|
-
Object.keys(ucs).join(','),
|
|
441
|
-
_cardTagIds.join(','),
|
|
442
|
-
_missing.join(','),
|
|
443
|
-
effectiveDayList.length
|
|
444
|
-
].join('|');
|
|
445
|
-
var _tripLogChanged = bubble.dataset.clTripLogKey !== _tripLogKey;
|
|
446
|
-
if (_tripLogChanged) {
|
|
447
|
-
bubble.dataset.clTripLogKey = _tripLogKey;
|
|
448
|
-
console.log('[trip-cards] Processing cards:', Object.keys(ucs).length, 'unitContexts,', effectiveDayList.length, 'days');
|
|
449
|
-
console.log('[trip-cards] Available unitContext IDs:', Object.keys(ucs).join(', '));
|
|
450
|
-
console.log('[trip-cards] Card tags requesting IDs:', _cardTagIds.join(', '));
|
|
451
|
-
if (_missing.length > 0) {
|
|
452
|
-
console.warn('[trip-cards] ⚠️ MISSING unitContexts:', _missing.join(', '));
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
// Remove the [TRIP_CARDS_READY] marker from innerHTML before processing card tags
|
|
457
|
-
let processed = bubble.innerHTML;
|
|
458
|
-
processed = processed.replace(/\[TRIP_CARDS_READY\]/g, '');
|
|
459
|
-
processed = _stripLodgingAreaCardTagsFromHtml(processed);
|
|
460
|
-
|
|
461
|
-
function _keepPendingCard(match) {
|
|
462
|
-
_hasMissing++;
|
|
463
|
-
return match;
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
// <time_data_card>{"dayIndex":N}</time_data_card>
|
|
467
|
-
processed = processed.replace(/(?:<|<)time_data_card(?:>|>)([\s\S]*?)(?:<|<)\/time_data_card(?:>|>)/g, (match, content) => {
|
|
468
|
-
const el = _renderTimeDataCard(content);
|
|
469
|
-
return el ? el.outerHTML : '';
|
|
470
|
-
});
|
|
471
|
-
|
|
472
|
-
// <sh_card>id</sh_card>
|
|
473
|
-
processed = processed.replace(/(?:<|<)sh_card(?:>|>)([\s\S]*?)(?:<|<)\/sh_card(?:>|>)/g, (match) => {
|
|
474
|
-
const el = _renderShoppingCard(effectiveDayList);
|
|
475
|
-
return el ? el.outerHTML : _keepPendingCard(match);
|
|
476
|
-
});
|
|
477
|
-
|
|
478
|
-
// <tr_card>id</tr_card>
|
|
479
|
-
processed = processed.replace(/(?:<|<)tr_card(?:>|>)([\s\S]*?)(?:<|<)\/tr_card(?:>|>)/g, (match, id) => {
|
|
480
|
-
const uc = ucs[id.trim()] || fallbackUcs[id.trim()];
|
|
481
|
-
if (!uc) return _keepPendingCard(match);
|
|
482
|
-
const el = _renderTransportCard(uc);
|
|
483
|
-
return el ? el.outerHTML : _keepPendingCard(match);
|
|
484
|
-
});
|
|
485
|
-
|
|
486
|
-
// <i_card>id</i_card>
|
|
487
|
-
processed = processed.replace(/(?:<|<)i_card(?:>|>)([\s\S]*?)(?:<|<)\/i_card(?:>|>)/g, (match, id) => {
|
|
488
|
-
const uc = ucs[id.trim()] || fallbackUcs[id.trim()];
|
|
489
|
-
if (!uc) return _keepPendingCard(match);
|
|
490
|
-
const el = _renderImageCard(uc);
|
|
491
|
-
return el ? el.outerHTML : _keepPendingCard(match);
|
|
492
|
-
});
|
|
493
|
-
|
|
494
|
-
// <fr_card>id</fr_card>
|
|
495
|
-
processed = processed.replace(/(?:<|<)fr_card(?:>|>)([\s\S]*?)(?:<|<)\/fr_card(?:>|>)/g, (match) => {
|
|
496
|
-
const el = _renderFoodCard(foodData);
|
|
497
|
-
return el ? el.outerHTML : _keepPendingCard(match);
|
|
498
|
-
});
|
|
499
|
-
|
|
500
|
-
// <bg_card>id</bg_card>
|
|
501
|
-
processed = processed.replace(/(?:<|<)bg_card(?:>|>)([\s\S]*?)(?:<|<)\/bg_card(?:>|>)/g, (match) => {
|
|
502
|
-
const el = _renderBudgetCard(budgetData);
|
|
503
|
-
return el ? el.outerHTML : _keepPendingCard(match);
|
|
504
|
-
});
|
|
505
|
-
|
|
506
|
-
// 清理 emoji HTML 实体(🔗 = 🔗)
|
|
507
|
-
processed = processed.replace(/🔗( )?|🔗\s?/g, '');
|
|
508
|
-
|
|
509
|
-
if (CL && typeof CL.diagHtmlRewrite === 'function') {
|
|
510
|
-
CL.diagHtmlRewrite('travel.process.before', bubble, {
|
|
511
|
-
processed: bubble.dataset.clProcessed || '',
|
|
512
|
-
missing: _hasMissing
|
|
513
|
-
});
|
|
514
|
-
}
|
|
515
|
-
bubble.innerHTML = processed;
|
|
516
|
-
if (CL && typeof CL.diagHtmlRewrite === 'function') {
|
|
517
|
-
CL.diagHtmlRewrite('travel.process.after', bubble, {
|
|
518
|
-
processed: bubble.dataset.clProcessed || '',
|
|
519
|
-
missing: _hasMissing
|
|
520
|
-
});
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
// 根据是否有缺失的 unitContext 决定标记
|
|
524
|
-
if (_hasMissing > 0) {
|
|
525
|
-
bubble.dataset.clProcessed = 'partial';
|
|
526
|
-
if (_tripLogChanged) console.log('[trip-cards] ⏳', _hasMissing, 'cards pending data, will retry');
|
|
527
|
-
} else {
|
|
528
|
-
bubble.dataset.clProcessed = '1';
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
// ── 后处理 A:POI 链接 — 从 dayList 提取真实跳转 URL ──
|
|
532
|
-
// 构建 POI 名称 → curUrl 映射表
|
|
533
|
-
var poiUrlMap = {};
|
|
534
|
-
var poiIdMap = {};
|
|
535
|
-
function addDetailUrlCandidate(obj) {
|
|
536
|
-
if (!obj) return;
|
|
537
|
-
var name = obj.poiName || obj.name || obj.title || obj.hotelName || '';
|
|
538
|
-
var id = obj.id || obj.poiId || obj.poiID || obj.hotelId || obj.hotelID || '';
|
|
539
|
-
var url = (obj.detailUrl && (obj.detailUrl.curUrl || obj.detailUrl.url)) ||
|
|
540
|
-
(obj.url && (obj.url.curUrl || obj.url.url)) ||
|
|
541
|
-
obj.curUrl ||
|
|
542
|
-
(typeof obj.url === 'string' ? obj.url : '');
|
|
543
|
-
if (!url) return;
|
|
544
|
-
if (name) poiUrlMap[name] = url;
|
|
545
|
-
if (id) poiIdMap[String(id)] = url;
|
|
546
|
-
}
|
|
547
|
-
(effectiveDayList || []).forEach(function(day) {
|
|
548
|
-
(day.itineraryUnitList || []).forEach(function(unit) {
|
|
549
|
-
var bi = unit.poiInfo && unit.poiInfo.basicInfo;
|
|
550
|
-
addDetailUrlCandidate(bi);
|
|
551
|
-
addDetailUrlCandidate(unit.poiInfo);
|
|
552
|
-
addDetailUrlCandidate(unit.hotelInfo);
|
|
553
|
-
addDetailUrlCandidate(unit.hotel);
|
|
554
|
-
addDetailUrlCandidate(unit.lodgingArea);
|
|
555
|
-
});
|
|
556
|
-
});
|
|
557
|
-
|
|
558
|
-
bubble.querySelectorAll('a').forEach(function(a) {
|
|
559
|
-
var href = a.getAttribute('href') || '';
|
|
560
|
-
if (/(?:poi_|hotel_|lodgingArea_|ctx_)/.test(href)) {
|
|
561
|
-
var linkText = (a.textContent || '').trim();
|
|
562
|
-
var ids = [];
|
|
563
|
-
var idMatch;
|
|
564
|
-
var idRegex = /(?:poi_|hotel_|lodgingArea_|ctx_)([a-zA-Z0-9_-]+)/g;
|
|
565
|
-
while ((idMatch = idRegex.exec(href))) {
|
|
566
|
-
ids.push(idMatch[1]);
|
|
567
|
-
}
|
|
568
|
-
var realUrl = '';
|
|
569
|
-
for (var ii = ids.length - 1; ii >= 0; ii--) {
|
|
570
|
-
if (poiIdMap[ids[ii]]) {
|
|
571
|
-
realUrl = poiIdMap[ids[ii]];
|
|
572
|
-
break;
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
if (!realUrl) realUrl = poiUrlMap[linkText] || '';
|
|
576
|
-
if (realUrl) {
|
|
577
|
-
a.setAttribute('href', realUrl);
|
|
578
|
-
a.setAttribute('target', '_blank');
|
|
579
|
-
a.setAttribute('rel', 'noopener noreferrer');
|
|
580
|
-
a.style.cssText = 'color:#0066cc;font-weight:600;text-decoration:none;cursor:pointer;';
|
|
581
|
-
} else {
|
|
582
|
-
// 无匹配 URL,保持黑色文本不可点击
|
|
583
|
-
a.removeAttribute('href');
|
|
584
|
-
a.style.cssText = 'color:#111;font-weight:600;text-decoration:none;pointer-events:none;';
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
});
|
|
588
|
-
|
|
589
|
-
// ── 后处理 B:通过 CSS class 统一处理文字颜色 ──
|
|
590
|
-
// 普通文字灰色(#888),加粗/链接/标题保持黑色(#111)
|
|
591
|
-
bubble.classList.add('trip-styled');
|
|
592
|
-
|
|
593
|
-
// ── 后处理 C:Tips 去掉 emoji(🔗) ──
|
|
594
|
-
// 使用 TreeWalker 遍历文本节点,避免重置 innerHTML 导致 dataset 标记丢失
|
|
595
|
-
var walker = document.createTreeWalker(bubble, NodeFilter.SHOW_TEXT, null, false);
|
|
596
|
-
while (walker.nextNode()) {
|
|
597
|
-
var tn = walker.currentNode;
|
|
598
|
-
if (tn.textContent && (tn.textContent.includes('🔗') || tn.textContent.includes('\uD83D\uDD17'))) {
|
|
599
|
-
tn.textContent = tn.textContent.replace(/🔗\s?/g, '');
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
// ── 后处理 D:将 h3(上午/下午/晚上) + ul 转为带缩进的列表格式(图四) ──
|
|
604
|
-
bubble.querySelectorAll('h3').forEach(function(h3) {
|
|
605
|
-
var text = (h3.textContent || '').trim();
|
|
606
|
-
if (text !== '上午' && text !== '下午' && text !== '晚上') return;
|
|
607
|
-
|
|
608
|
-
var next = h3.nextElementSibling;
|
|
609
|
-
if (next && next.tagName === 'UL') {
|
|
610
|
-
// 将 h3 文字作为 li 的前缀,保持 ul 的缩进
|
|
611
|
-
var items = next.querySelectorAll('li');
|
|
612
|
-
if (items.length > 0) {
|
|
613
|
-
if (CL && typeof CL.diagHtmlRewrite === 'function') {
|
|
614
|
-
CL.diagHtmlRewrite('travel.heading-item.before', items[0], { text: text });
|
|
615
|
-
}
|
|
616
|
-
items[0].innerHTML = '<strong style="font-size:15px;">' + text + '</strong> ' + items[0].innerHTML;
|
|
617
|
-
if (CL && typeof CL.diagHtmlRewrite === 'function') {
|
|
618
|
-
CL.diagHtmlRewrite('travel.heading-item.after', items[0], { text: text });
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
next.style.cssText = 'list-style:disc;padding-left:20px;margin:6px 0;';
|
|
622
|
-
items.forEach(function(li) {
|
|
623
|
-
li.style.cssText = 'margin-bottom:6px;font-size:14px;line-height:1.7;color:#333;';
|
|
624
|
-
});
|
|
625
|
-
h3.remove();
|
|
626
|
-
} else if (next && (next.tagName === 'P' || next.tagName === 'DIV')) {
|
|
627
|
-
// 转成 ul>li 保持缩进
|
|
628
|
-
var ul = document.createElement('ul');
|
|
629
|
-
ul.style.cssText = 'list-style:disc;padding-left:20px;margin:6px 0;';
|
|
630
|
-
var li = document.createElement('li');
|
|
631
|
-
li.style.cssText = 'margin-bottom:6px;font-size:14px;line-height:1.7;color:#333;';
|
|
632
|
-
if (CL && typeof CL.diagHtmlRewrite === 'function') {
|
|
633
|
-
CL.diagHtmlRewrite('travel.heading-merge.before', li, { text: text });
|
|
634
|
-
}
|
|
635
|
-
li.innerHTML = '<strong style="font-size:15px;">' + text + '</strong> ' + next.innerHTML;
|
|
636
|
-
if (CL && typeof CL.diagHtmlRewrite === 'function') {
|
|
637
|
-
CL.diagHtmlRewrite('travel.heading-merge.after', li, { text: text });
|
|
638
|
-
}
|
|
639
|
-
ul.appendChild(li);
|
|
640
|
-
h3.parentNode.insertBefore(ul, h3);
|
|
641
|
-
next.remove();
|
|
642
|
-
h3.remove();
|
|
643
|
-
}
|
|
644
|
-
});
|
|
645
|
-
|
|
646
|
-
if (_tripLogChanged || !bubble.dataset.clTripRenderedLogged) {
|
|
647
|
-
bubble.dataset.clTripRenderedLogged = '1';
|
|
648
|
-
if (_hasMissing === 0) {
|
|
649
|
-
console.log('[trip-cards] ✅ Cards rendered');
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
}
|