@lightcone-ai/daemon 0.9.29 → 0.9.31

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.
@@ -42,11 +42,22 @@ export class XhsAdapter {
42
42
 
43
43
  // Navigate to publish page
44
44
  await cdp.send('Page.navigate', { url: 'https://creator.xiaohongshu.com/publish/publish' });
45
- await this._waitForSelector('[class*="upload"]', 10000);
45
+ await sleep(3000);
46
+
47
+ // Check if we got redirected away (login expired)
48
+ const urlAfterNav = await this._getUrl();
49
+ if (!urlAfterNav.includes('creator.xiaohongshu.com/publish')) {
50
+ throw new Error(`LOGIN_EXPIRED: 跳转到了 ${urlAfterNav},请重新扫码连接小红书`);
51
+ }
46
52
 
47
- // Check login
48
- const loggedIn = await this.checkLoginStatus();
49
- if (!loggedIn) throw new Error('LOGIN_EXPIRED: 小红书登录已过期,请重新扫码连接');
53
+ // Wait for upload area with multiple fallback selectors
54
+ await this._waitForAny([
55
+ 'input[type="file"]',
56
+ '[class*="upload"]',
57
+ '[class*="Upload"]',
58
+ '[class*="uploader"]',
59
+ '.upload-input',
60
+ ], 15000);
50
61
 
51
62
  // Upload images first (if any)
52
63
  if (images.length > 0) {
@@ -99,10 +110,19 @@ export class XhsAdapter {
99
110
  const cdp = this._cdp;
100
111
 
101
112
  await cdp.send('Page.navigate', { url: 'https://creator.xiaohongshu.com/publish/publish?source=video' });
102
- await this._waitForSelector('[class*="upload"]', 10000);
113
+ await sleep(3000);
103
114
 
104
- const loggedIn = await this.checkLoginStatus();
105
- if (!loggedIn) throw new Error('LOGIN_EXPIRED: 小红书登录已过期,请重新扫码连接');
115
+ const urlAfterNav = await this._getUrl();
116
+ if (!urlAfterNav.includes('creator.xiaohongshu.com/publish')) {
117
+ throw new Error(`LOGIN_EXPIRED: 跳转到了 ${urlAfterNav},请重新扫码连接小红书`);
118
+ }
119
+
120
+ await this._waitForAny([
121
+ 'input[type="file"]',
122
+ '[class*="upload"]',
123
+ '[class*="Upload"]',
124
+ '[class*="uploader"]',
125
+ ], 15000);
106
126
 
107
127
  // Upload video
108
128
  await this._uploadFiles([video], 'video');
@@ -143,6 +163,20 @@ export class XhsAdapter {
143
163
  throw new Error(`Timeout waiting for selector: ${selector}`);
144
164
  }
145
165
 
166
+ async _waitForAny(selectors, timeoutMs = 15000) {
167
+ const combined = selectors.join(', ');
168
+ const deadline = Date.now() + timeoutMs;
169
+ while (Date.now() < deadline) {
170
+ const result = await this._cdp.send('Runtime.evaluate', {
171
+ expression: `!!document.querySelector(${JSON.stringify(combined)})`,
172
+ returnByValue: true,
173
+ });
174
+ if (result.result?.value) return;
175
+ await sleep(500);
176
+ }
177
+ throw new Error(`Timeout waiting for any of: ${combined}`);
178
+ }
179
+
146
180
  async _waitForText(text, timeoutMs = 8000) {
147
181
  const deadline = Date.now() + timeoutMs;
148
182
  while (Date.now() < deadline) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightcone-ai/daemon",
3
- "version": "0.9.29",
3
+ "version": "0.9.31",
4
4
  "type": "module",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -439,9 +439,12 @@ server.tool('execute_approved_action',
439
439
  const data = await api('POST', `/actions/${action_id}/execute`, {});
440
440
  if (data.error) return { isError: true, content: [{ type: 'text', text: `Failed: ${data.error}` }] };
441
441
  return { content: [{ type: 'text', text:
442
- `Action executed successfully.\n` +
442
+ `Action approved. Now call the appropriate platform tool to actually perform the operation.\n` +
443
443
  `actionType=${data.actionType} platform=${data.platform}\n` +
444
- `Payload confirmed: ${JSON.stringify(data.payload)}`
444
+ `Payload: ${JSON.stringify(data.payload)}\n\n` +
445
+ `For xhs_post: call publish_content(platform="xhs", ...) with the payload fields above.\n` +
446
+ `For douyin_post: call publish_content(platform="douyin", ...).\n` +
447
+ `For x_post: call post_tweet(...).`
445
448
  }]};
446
449
  } catch (err) {
447
450
  return { isError: true, content: [{ type: 'text', text: `Error: ${err.message}` }] };