@lightcone-ai/daemon 0.15.24 → 0.15.26
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.
|
@@ -781,7 +781,7 @@ function pickSlotKeysForMode({ mode, slots }) {
|
|
|
781
781
|
return ordered.filter(key => slotHasValue(slots[key])).slice(0, 3);
|
|
782
782
|
}
|
|
783
783
|
if (mode === 'job_alert') {
|
|
784
|
-
const ordered = ['job_directions', 'locations', 'cohort'
|
|
784
|
+
const ordered = ['job_directions', 'locations', 'cohort'];
|
|
785
785
|
return ordered.filter(key => slotHasValue(slots[key])).slice(0, 1);
|
|
786
786
|
}
|
|
787
787
|
if (mode === 'info_summary') {
|
|
@@ -1013,7 +1013,7 @@ export function planVideo({
|
|
|
1013
1013
|
semantic_slot: ctaSlotKey,
|
|
1014
1014
|
focus_region: ctaAnchor?.y_range ?? null,
|
|
1015
1015
|
confidence: ctaSlot ? Number(clampNumber(ctaSlot.confidence, 0, 1, 0).toFixed(2)) : null,
|
|
1016
|
-
guidance: '
|
|
1016
|
+
guidance: '收尾自然收口(如"感兴趣去原文查看"),禁止提及任何 URL、网址、二维码或投递入口',
|
|
1017
1017
|
});
|
|
1018
1018
|
|
|
1019
1019
|
const cappedPlan = phasePlan.slice(0, 5);
|
|
@@ -1139,24 +1139,24 @@ function buildPhaseSentence({ phase, strategy, phaseIndex }) {
|
|
|
1139
1139
|
if (role === 'cta') {
|
|
1140
1140
|
if (mode === 'job_intel_broadcast') {
|
|
1141
1141
|
return ensureSentenceLength(
|
|
1142
|
-
|
|
1142
|
+
`感兴趣的同学去原文查看完整岗位要求和截止时间,对照自己情况再决定要不要投。`
|
|
1143
1143
|
);
|
|
1144
1144
|
}
|
|
1145
1145
|
|
|
1146
1146
|
if (mode === 'job_alert') {
|
|
1147
1147
|
return ensureSentenceLength(
|
|
1148
|
-
|
|
1148
|
+
`细节不完整,建议收藏原文,等正式公告发布后再核对岗位方向、城市和流程再决定。`
|
|
1149
1149
|
);
|
|
1150
1150
|
}
|
|
1151
1151
|
|
|
1152
1152
|
if (mode === 'refuse_auto_broadcast') {
|
|
1153
1153
|
return ensureSentenceLength(
|
|
1154
|
-
'
|
|
1154
|
+
'页面信息不完整,暂不播报。建议直接去官方渠道确认公司、岗位和发布时间后再做判断。'
|
|
1155
1155
|
);
|
|
1156
1156
|
}
|
|
1157
1157
|
|
|
1158
1158
|
return ensureSentenceLength(
|
|
1159
|
-
|
|
1159
|
+
'具体要求和截止时间见原文,建议直接查看官方公告,避免依赖摘要信息做投递判断。'
|
|
1160
1160
|
);
|
|
1161
1161
|
}
|
|
1162
1162
|
|
package/package.json
CHANGED
|
@@ -157,6 +157,26 @@ async function scrollToTop(page) {
|
|
|
157
157
|
});
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
+
function scalePhaseY(phase, zoom) {
|
|
161
|
+
if (!phase || typeof phase !== 'object') return phase;
|
|
162
|
+
const scale = (v) => (Number.isFinite(Number(v)) ? Math.round(Number(v) * zoom) : v);
|
|
163
|
+
const scaledVisualAction = phase.visual_action && typeof phase.visual_action === 'object'
|
|
164
|
+
? {
|
|
165
|
+
...phase.visual_action,
|
|
166
|
+
...(phase.visual_action.target_y != null ? { target_y: scale(phase.visual_action.target_y) } : {}),
|
|
167
|
+
...(phase.visual_action.to_y != null ? { to_y: scale(phase.visual_action.to_y) } : {}),
|
|
168
|
+
...(phase.visual_action.from_y != null ? { from_y: scale(phase.visual_action.from_y) } : {}),
|
|
169
|
+
}
|
|
170
|
+
: phase.visual_action;
|
|
171
|
+
return {
|
|
172
|
+
...phase,
|
|
173
|
+
...(phase.target_y != null ? { target_y: scale(phase.target_y) } : {}),
|
|
174
|
+
...(phase.to_y != null ? { to_y: scale(phase.to_y) } : {}),
|
|
175
|
+
...(phase.from_y != null ? { from_y: scale(phase.from_y) } : {}),
|
|
176
|
+
...(scaledVisualAction !== phase.visual_action ? { visual_action: scaledVisualAction } : {}),
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
160
180
|
export async function recordUrlNarration({
|
|
161
181
|
plan,
|
|
162
182
|
output_path,
|
|
@@ -167,6 +187,7 @@ export async function recordUrlNarration({
|
|
|
167
187
|
viewport = DEFAULT_VIEWPORT,
|
|
168
188
|
fps = DEFAULT_FPS,
|
|
169
189
|
settle_ms = 4000,
|
|
190
|
+
page_zoom = 1.1,
|
|
170
191
|
displayPool = defaultDisplayPool,
|
|
171
192
|
ffmpegDurationBufferSec = 8,
|
|
172
193
|
startupProbeMs = 1200,
|
|
@@ -174,7 +195,9 @@ export async function recordUrlNarration({
|
|
|
174
195
|
xvfbStopTimeoutMs = 5000,
|
|
175
196
|
postPlanTailMs = 600,
|
|
176
197
|
} = {}) {
|
|
177
|
-
const
|
|
198
|
+
const zoom = Number.isFinite(Number(page_zoom)) && Number(page_zoom) > 0 ? Number(page_zoom) : 1.0;
|
|
199
|
+
const rawPhases = normalizePlanPhases(plan);
|
|
200
|
+
const phases = zoom !== 1.0 ? rawPhases.map(p => scalePhaseY(p, zoom)) : rawPhases;
|
|
178
201
|
const executablePlan = {
|
|
179
202
|
...(plan && typeof plan === 'object' ? plan : {}),
|
|
180
203
|
phases,
|
|
@@ -220,6 +243,13 @@ export async function recordUrlNarration({
|
|
|
220
243
|
settleMs: settle_ms,
|
|
221
244
|
});
|
|
222
245
|
|
|
246
|
+
if (zoom !== 1.0) {
|
|
247
|
+
await browserSession.page.evaluate((z) => {
|
|
248
|
+
document.documentElement.style.zoom = String(z);
|
|
249
|
+
}, zoom);
|
|
250
|
+
await browserSession.page.waitForTimeout(300);
|
|
251
|
+
}
|
|
252
|
+
|
|
223
253
|
const estimatedDurationMs = estimatePlanDurationMs(executablePlan);
|
|
224
254
|
const estimatedDurationSec = Math.max(
|
|
225
255
|
5,
|
|
@@ -204,6 +204,55 @@ async function extractStructure(page, { binHeight, minBinChars }) {
|
|
|
204
204
|
return rangeFromMatches(matches, root.scrollHeight);
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
+
function trimNoiseFromBottom(range, pageHeight, detectionStrategy) {
|
|
208
|
+
// Site-specific selectors already point to the exact content element — trust them.
|
|
209
|
+
if (detectionStrategy && detectionStrategy.startsWith('site:')) return range;
|
|
210
|
+
|
|
211
|
+
const [coreTop, rawBottom] = range;
|
|
212
|
+
const minContentHeight = 600; // always keep at least 600px of core content
|
|
213
|
+
|
|
214
|
+
// Selectors that reliably identify non-article noise below the body text.
|
|
215
|
+
const noiseSelectors = [
|
|
216
|
+
// Comment sections
|
|
217
|
+
'[class*="comment-list"]', '[class*="comment-wrap"]', '[class*="commentList"]',
|
|
218
|
+
'[id*="comment"]', '[class*="discuss"]', '[class*="reply-list"]',
|
|
219
|
+
// Related / recommended articles
|
|
220
|
+
'[class*="related-read"]', '[class*="related-article"]', '[class*="relatedArticle"]',
|
|
221
|
+
'[class*="recommend"]', '[class*="more-article"]', '[class*="further-reading"]',
|
|
222
|
+
// Article footer / bottom toolbars
|
|
223
|
+
'[class*="article-footer"]', '[class*="post-footer"]', '[class*="article-bottom"]',
|
|
224
|
+
// Social sharing bars that sit below the body
|
|
225
|
+
'[class*="share-bar"]', '[class*="share-wrap"]', '[class*="article-share"]',
|
|
226
|
+
// Generic page footer inside the core element
|
|
227
|
+
'footer',
|
|
228
|
+
];
|
|
229
|
+
|
|
230
|
+
const root = document.scrollingElement || document.documentElement;
|
|
231
|
+
let trimBottom = rawBottom;
|
|
232
|
+
|
|
233
|
+
for (const sel of noiseSelectors) {
|
|
234
|
+
try {
|
|
235
|
+
const elements = document.querySelectorAll(sel);
|
|
236
|
+
for (const el of elements) {
|
|
237
|
+
if (!isVisibleEnough(el, 40)) continue;
|
|
238
|
+
const rect = el.getBoundingClientRect();
|
|
239
|
+
const elTop = Math.round(rect.top + root.scrollTop);
|
|
240
|
+
if (
|
|
241
|
+
elTop > coreTop + minContentHeight
|
|
242
|
+
&& elTop < trimBottom
|
|
243
|
+
&& rect.height > 60
|
|
244
|
+
) {
|
|
245
|
+
trimBottom = elTop;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
} catch {
|
|
249
|
+
// ignore selector errors for individual sites
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return [coreTop, trimBottom];
|
|
254
|
+
}
|
|
255
|
+
|
|
207
256
|
function collectTextBins({ range, coreElement }) {
|
|
208
257
|
const [rangeTop, rangeBottom] = range;
|
|
209
258
|
const root = document.scrollingElement || document.documentElement;
|
|
@@ -353,6 +402,10 @@ async function extractStructure(page, { binHeight, minBinChars }) {
|
|
|
353
402
|
strategy = `${strategy}:range_fixed`;
|
|
354
403
|
}
|
|
355
404
|
|
|
405
|
+
// Trim coreBottom to exclude footer noise (comments, related articles, recommendations)
|
|
406
|
+
// that commonly appear below the article body.
|
|
407
|
+
coreRange = trimNoiseFromBottom(coreRange, totalHeight, strategy);
|
|
408
|
+
|
|
356
409
|
const bins = collectTextBins({ range: coreRange, coreElement });
|
|
357
410
|
const focusRange = (() => {
|
|
358
411
|
const span = coreRange[1] - coreRange[0];
|
package/src/chat-bridge.js
CHANGED
|
@@ -1480,6 +1480,7 @@ server.tool('record_url_narration',
|
|
|
1480
1480
|
}).optional().describe('Default 1080x1920 (mobile portrait). Override only if the plan requires a different shape.'),
|
|
1481
1481
|
fps: z.number().optional().describe('Default 30. Do not change unless needed.'),
|
|
1482
1482
|
settle_ms: z.number().optional().describe('Default 4000. Settle wait after navigation before recording starts.'),
|
|
1483
|
+
page_zoom: z.number().optional().describe('Browser zoom factor applied before recording. Default 1.1 (10% zoom in). Set to 1.0 to disable. Plan Y coordinates are automatically scaled by this factor.'),
|
|
1483
1484
|
},
|
|
1484
1485
|
async (args) => {
|
|
1485
1486
|
if (isBlockedCvmaxEditorVideoTool('record_url_narration')) {
|