@lightcone-ai/daemon 0.9.65 → 0.9.66

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.
@@ -24,6 +24,7 @@ const REQUIREMENTS = {
24
24
  };
25
25
 
26
26
  const PUBLISH_URL = 'https://creator.xiaohongshu.com/publish/publish';
27
+ const IMAGE_PUBLISH_URL = 'https://creator.xiaohongshu.com/publish/publish?target=image';
27
28
  const VIDEO_PUBLISH_URL = 'https://creator.xiaohongshu.com/publish/publish?source=video';
28
29
 
29
30
  const CREATOR_HOME_URL = 'https://creator.xiaohongshu.com/new/home';
@@ -135,13 +136,21 @@ export class XhsAdapter {
135
136
  async _openPublishComposer(kind) {
136
137
  const targetTabText = kind === 'image' ? '上传图文' : '上传视频';
137
138
  const inputSelector = kind === 'image' ? IMAGE_FILE_INPUT_SELECTOR : VIDEO_FILE_INPUT_SELECTOR;
138
- const url = kind === 'video' ? VIDEO_PUBLISH_URL : PUBLISH_URL;
139
+ const url = kind === 'video' ? VIDEO_PUBLISH_URL : IMAGE_PUBLISH_URL;
139
140
 
140
141
  await this._cdp.send('Page.navigate', { url });
141
142
  await this._waitForCreatorShell(20_000);
142
143
  await this._assertReadyForPublish();
143
144
 
144
- await this._clickVisibleByText(targetTabText, '.creator-tab, button, [role="button"], span, div');
145
+ if (await this._hasSelector(inputSelector)) return;
146
+
147
+ const clicked = await this._clickVisibleByText(targetTabText, '.creator-tab, button, [role="button"], span, div', { throwOnMissing: false });
148
+ if (clicked) {
149
+ await this._waitForAny([inputSelector], 15_000);
150
+ return;
151
+ }
152
+
153
+ await this._cdp.send('Page.navigate', { url: kind === 'image' ? `${PUBLISH_URL}?from=tab_switch&target=image` : VIDEO_PUBLISH_URL });
145
154
  await this._waitForAny([inputSelector], 15_000);
146
155
  }
147
156
 
@@ -186,6 +195,14 @@ export class XhsAdapter {
186
195
  throw new Error(`Timeout waiting for any of: ${combined}`);
187
196
  }
188
197
 
198
+ async _hasSelector(selector) {
199
+ const result = await this._cdp.send('Runtime.evaluate', {
200
+ expression: `!!document.querySelector(${JSON.stringify(selector)})`,
201
+ returnByValue: true,
202
+ });
203
+ return result.result?.value === true;
204
+ }
205
+
189
206
  async _waitForText(text, timeoutMs = 8000) {
190
207
  const deadline = Date.now() + timeoutMs;
191
208
  while (Date.now() < deadline) {
@@ -364,7 +381,7 @@ export class XhsAdapter {
364
381
  await sleep(500);
365
382
  }
366
383
 
367
- async _clickVisibleByText(text, selector) {
384
+ async _clickVisibleByText(text, selector, { throwOnMissing = true } = {}) {
368
385
  const result = await this._cdp.send('Runtime.evaluate', {
369
386
  expression: `
370
387
  (function() {
@@ -374,7 +391,11 @@ export class XhsAdapter {
374
391
  return r.width > 0 && r.height > 0 && r.left > -100 && s.display !== 'none' && s.visibility !== 'hidden';
375
392
  };
376
393
  const els = [...document.querySelectorAll(${JSON.stringify(selector)})].filter(visible);
377
- const el = els.find(e => (e.innerText || e.textContent || '').trim() === ${JSON.stringify(text)});
394
+ const targetText = ${JSON.stringify(text)};
395
+ const el = els.find(e => {
396
+ const t = (e.innerText || e.textContent || '').trim();
397
+ return t === targetText || t.split(/\\s+/).includes(targetText) || t.includes(targetText);
398
+ });
378
399
  const target = el?.closest('.creator-tab, button, [role="button"]') || el;
379
400
  if (target) { target.click(); return true; }
380
401
  return false;
@@ -382,8 +403,10 @@ export class XhsAdapter {
382
403
  `,
383
404
  returnByValue: true,
384
405
  });
385
- if (result.result?.value !== true) throw new Error(`PUBLISH_FAILED: 找不到小红书发布入口:${text}`);
386
- await sleep(1000);
406
+ const clicked = result.result?.value === true;
407
+ if (!clicked && throwOnMissing) throw new Error(`PUBLISH_FAILED: 找不到小红书发布入口:${text}`);
408
+ if (clicked) await sleep(1000);
409
+ return clicked;
387
410
  }
388
411
 
389
412
  async _clickByText(text) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightcone-ai/daemon",
3
- "version": "0.9.65",
3
+ "version": "0.9.66",
4
4
  "type": "module",
5
5
  "main": "src/index.js",
6
6
  "bin": {