publishport-opencli 1.0.8 → 1.0.10

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 (58) hide show
  1. package/cli-manifest.json +442 -1
  2. package/clis/_shared/file-inject.js +41 -0
  3. package/clis/_shared/video-publish.js +4 -4
  4. package/clis/bilibili/upload.js +1 -1
  5. package/clis/chatgpt/utils.js +5 -5
  6. package/clis/claude/utils.js +1 -1
  7. package/clis/deepseek/utils.js +7 -7
  8. package/clis/douyin/draft.js +6 -6
  9. package/clis/douyin/publish-image.js +10 -31
  10. package/clis/facebook/feed.js +78 -5
  11. package/clis/facebook/post.js +9 -36
  12. package/clis/facebook/search.js +83 -22
  13. package/clis/instagram/post.js +19 -66
  14. package/clis/instagram/reel.js +11 -11
  15. package/clis/threads/post.js +15 -34
  16. package/clis/twitter/post.js +15 -42
  17. package/clis/twitter/utils.js +4 -36
  18. package/clis/wechat-channels/publish.js +29 -57
  19. package/clis/weibo/publish.js +8 -8
  20. package/clis/weixin/create-draft.js +7 -7
  21. package/clis/xianyu/collect.js +1 -0
  22. package/clis/xianyu/location.js +1 -0
  23. package/clis/xianyu/manage.js +1 -0
  24. package/clis/xianyu/mtop.js +47 -0
  25. package/clis/xianyu/order.js +1 -0
  26. package/clis/xianyu/publish.js +2 -2
  27. package/clis/xianyu/rate.js +1 -0
  28. package/clis/xianyu/user.js +1 -0
  29. package/clis/xiaohongshu/publish-video.js +9 -27
  30. package/clis/xiaohongshu/publish.js +32 -72
  31. package/dist/src/browser/base-page.d.ts +19 -0
  32. package/dist/src/browser/base-page.js +1 -1
  33. package/dist/src/browser/bridge-readiness.d.ts +1 -1
  34. package/dist/src/browser/daemon-client.d.ts +72 -1
  35. package/dist/src/browser/daemon-client.js +1 -1
  36. package/dist/src/browser/daemon-version.d.ts +1 -1
  37. package/dist/src/browser/errors.d.ts +2 -0
  38. package/dist/src/browser/errors.js +3 -3
  39. package/dist/src/browser/network-interceptor.d.ts +11 -0
  40. package/dist/src/browser/network-interceptor.js +1 -0
  41. package/dist/src/browser/target-resolver.d.ts +1 -0
  42. package/dist/src/browser/target-resolver.js +100 -6
  43. package/dist/src/cli.js +24 -24
  44. package/dist/src/commands/daemon.js +1 -1
  45. package/dist/src/daemon-utils.d.ts +1 -0
  46. package/dist/src/daemon-utils.js +1 -1
  47. package/dist/src/daemon.js +1 -1
  48. package/dist/src/doctor.d.ts +1 -1
  49. package/dist/src/doctor.js +7 -7
  50. package/dist/src/errors.d.ts +8 -0
  51. package/dist/src/errors.js +1 -1
  52. package/dist/src/execution.js +2 -2
  53. package/dist/src/external.js +1 -1
  54. package/dist/src/session-lease.d.ts +135 -0
  55. package/dist/src/session-lease.js +1 -0
  56. package/dist/src/session-lease.test.d.ts +1 -0
  57. package/dist/src/types.d.ts +3 -0
  58. package/package.json +1 -1
@@ -1,22 +1,83 @@
1
- import{cli as e}from"@jackwener/opencli/registry";e({site:"facebook",name:"search",access:"read",description:"Search Facebook for people, pages, or posts",domain:"www.facebook.com",args:[{name:"query",required:!0,positional:!0,help:"Search query"},{name:"limit",type:"int",default:10,help:"Number of results"}],columns:["index","title","text","url"],pipeline:[{navigate:"https://www.facebook.com"},{navigate:{url:"https://www.facebook.com/search/top?q=${{ args.query | urlencode }}",settleMs:4000}},{evaluate:`(async () => {
2
- const limit = \${{ args.limit }};
3
- // Search results are typically in role="article" or role="listitem"
4
- let items = document.querySelectorAll('[role="article"]');
5
- if (items.length === 0) {
6
- items = document.querySelectorAll('[role="listitem"]');
7
- }
8
- return Array.from(items)
9
- .filter(el => el.textContent.trim().length > 20)
10
- .slice(0, limit)
11
- .map((el, i) => {
12
- const link = el.querySelector('a[href*="facebook.com/"]');
13
- const heading = el.querySelector('h2, h3, h4, strong');
14
- return {
15
- index: i + 1,
16
- title: heading ? heading.textContent.trim().substring(0, 80) : '',
17
- text: el.textContent.trim().replace(/\\s+/g, ' ').substring(0, 150),
18
- url: link ? link.href.split('?')[0] : '',
19
- };
20
- });
21
- })()
22
- `}]});
1
+ import{ArgumentError as V,AuthRequiredError as j,CommandExecutionError as P,EmptyResultError as B}from"@jackwener/opencli/errors";import{cli as Q,Strategy as T}from"@jackwener/opencli/registry";const X="https://www.facebook.com",W=50;function Y(z){const D=Number(z);if(!Number.isInteger(D)||D<1||D>W)throw new V(`facebook search --limit must be an integer between 1 and ${W}`);return D}function Z(z){const D=String(z??"").trim();if(!D)throw new V("facebook search requires a non-empty query");return D}function F(z){if(z&&typeof z==="object"&&"data"in z)return z.data;return z}function $(z){return`(() => {
2
+ const limit = ${z};
3
+
4
+ function clean(value) {
5
+ return String(value || '')
6
+ .replace(/[\\u200b-\\u200f\\u202a-\\u202e\\u2060\\ufeff]/g, '')
7
+ .replace(/\\s+/g, ' ')
8
+ .trim();
9
+ }
10
+
11
+ // FB anti-scrape obfuscation: long spaceless digit tokens and spaced
12
+ // single-char strings ("a b c d e"). Real titles never look like this.
13
+ function isObfuscated(text) {
14
+ if (!text) return true;
15
+ if (/^\\d{8,}$/.test(text)) return true;
16
+ if (/^(?:\\S ){4,}\\S$/.test(text) && text.replace(/\\s/g, '').length <= 12) return true;
17
+ return false;
18
+ }
19
+
20
+ function isEntityHref(href) {
21
+ if (!href) return false;
22
+ let u;
23
+ try { u = new URL(href, 'https://www.facebook.com'); } catch (e) { return false; }
24
+ // drop hidden-domain .com spam — real results stay on facebook.com
25
+ if (!/(^|\\.)facebook\\.com$/i.test(u.hostname)) return false;
26
+ const p = u.pathname;
27
+ if (/^\\/search(\\/|$)/i.test(p)) return false; // decoy links back to search (incl. bare /search)
28
+ // chrome / non-result destinations that the catch-all below would keep
29
+ if (/^\\/(login|checkpoint|help|policies|privacy|settings|bookmarks|messages|notifications|marketplace|gaming|friends|requests|saved|me)\\b/i.test(p)) return false;
30
+ return /^\\/(profile\\.php|groups\\/|events\\/|watch\\/|reel\\/|pages\\/|permalink\\.php|story\\.php|[^/]+\\/posts\\/|[^/]+\\/videos\\/|[A-Za-z0-9.\\-]{2,}\\/?$)/i.test(p);
31
+ }
32
+
33
+ function isAuthPage() {
34
+ const path = window.location && window.location.pathname ? window.location.pathname : '';
35
+ const body = clean(document.body && document.body.textContent);
36
+ return /^\\/(login|checkpoint)(\\/|$|\\.php)/.test(path)
37
+ || /^(Log in to Facebook|Facebook登录|登录 Facebook)/i.test(body)
38
+ || /You must log in to continue/i.test(body);
39
+ }
40
+
41
+ if (isAuthPage()) return { status: 'auth', rows: [], diagnostics: {} };
42
+
43
+ const feed = document.querySelector('[role="feed"]')
44
+ || document.querySelector('[role="main"]')
45
+ || document.body;
46
+ const anchors = Array.from(feed.querySelectorAll('a[href]'));
47
+ const seen = new Set();
48
+ const rows = [];
49
+ for (const a of anchors) {
50
+ const rawHref = a.href || a.getAttribute('href') || '';
51
+ if (!isEntityHref(rawHref)) continue;
52
+ let key;
53
+ try { const u = new URL(rawHref, 'https://www.facebook.com'); key = u.origin + u.pathname; }
54
+ catch (e) { key = rawHref.split('?')[0].split('#')[0]; }
55
+ if (seen.has(key)) continue;
56
+
57
+ const title = clean(a.textContent).substring(0, 80);
58
+ if (!title || isObfuscated(title)) continue;
59
+
60
+ // climb a few levels for the surrounding card text
61
+ let card = a;
62
+ for (let i = 0; i < 4 && card.parentElement; i += 1) {
63
+ card = card.parentElement;
64
+ if (clean(card.textContent).length > title.length + 20) break;
65
+ }
66
+ const text = clean(card.textContent).substring(0, 150);
67
+ if (isObfuscated(text)) continue;
68
+
69
+ seen.add(key);
70
+ rows.push({ index: rows.length + 1, title, text, url: key });
71
+ if (rows.length >= limit) break;
72
+ }
73
+
74
+ return {
75
+ status: rows.length ? 'ok' : 'no_rows',
76
+ rows,
77
+ diagnostics: {
78
+ feedFound: !!document.querySelector('[role="feed"]'),
79
+ anchorCount: anchors.length,
80
+ mainTextLength: clean((document.querySelector('[role="main"]') || {}).textContent).length,
81
+ },
82
+ };
83
+ })()`}async function H(z,D){const U=Z(D.query),f=Y(D.limit??10);try{await z.goto(X);await z.goto(`https://www.facebook.com/search/top?q=${encodeURIComponent(U)}`,{settleMs:4000})}catch(J){throw new P(`Failed to open facebook search: ${J instanceof Error?J.message:J}`,"Check that facebook.com is reachable and the browser extension is connected.")}let G;try{G=F(await z.evaluate($(f)))}catch(J){throw new P(`Failed to read facebook search results: ${J instanceof Error?J.message:J}`,"Facebook may not have rendered or the search markup may have changed.")}if(!G||typeof G!=="object"||!Array.isArray(G.rows))throw new P("facebook search returned malformed extraction payload");if(G.status==="auth")throw new j("www.facebook.com","Open Chrome and log in to Facebook before retrying.");if(G.rows.length>0)return G.rows;const N=G.diagnostics||{};if(N.anchorCount||N.mainTextLength>200)throw new P("facebook search page rendered but no entity results could be extracted",`Diagnostics: feed=${!!N.feedFound}, anchors=${N.anchorCount||0}, mainTextLength=${N.mainTextLength||0}.`);throw new B("facebook search",`No Facebook results were visible for "${U}".`)}const K={site:"facebook",name:"search",access:"read",description:"Search Facebook for people, pages, or posts",domain:"www.facebook.com",strategy:T.COOKIE,browser:!0,navigateBefore:!1,args:[{name:"query",required:!0,positional:!0,help:"Search query"},{name:"limit",type:"int",default:10,help:"Number of results"}],columns:["index","title","text","url"],func:H};Q(K);export const __test__={buildSearchExtractScript:$,command:K,searchFacebook:H,requireLimit:Y,requireQuery:Z};
@@ -1,4 +1,4 @@
1
- import*as b from"node:fs";import*as W from"node:path";import{cli as r,Strategy as p}from"@jackwener/opencli/registry";import{ArgumentError as z,AuthRequiredError as R,CommandExecutionError as Y}from"@jackwener/opencli/errors";import{installInstagramProtocolCapture as a,readInstagramProtocolCapture as t}from"./_shared/protocol-capture.js";import{publishMediaViaPrivateApi as e,publishImagesViaPrivateApi as jj,resolveInstagramPrivatePublishConfig as Gj,isPublishOutcomeUncertain as Nj}from"./_shared/private-publish.js";import{resolveInstagramRuntimeInfo as Oj}from"./_shared/runtime-info.js";import{throwIfFileAccessDenied as Qj}from"../_shared/video-publish.js";const K="https://www.instagram.com/",Xj=new Set([".jpg",".jpeg",".png",".webp"]),Yj=new Set([".mp4"]),C=10,Zj="/tmp/instagram_post_protocol_trace.json";async function k(j,G=!1){if(G){await j.goto(`${K}?__opencli_reset=${Date.now()}`);await j.wait({time:1})}await j.goto(K)}export function buildEnsureComposerOpenJs(){return`
1
+ import*as P from"node:fs";import*as S from"node:path";import{cli as r,Strategy as p}from"@jackwener/opencli/registry";import{ArgumentError as H,AuthRequiredError as W,CommandExecutionError as T}from"@jackwener/opencli/errors";import{installInstagramProtocolCapture as a,readInstagramProtocolCapture as t}from"./_shared/protocol-capture.js";import{publishMediaViaPrivateApi as e,publishImagesViaPrivateApi as jj,resolveInstagramPrivatePublishConfig as Gj,isPublishOutcomeUncertain as Kj}from"./_shared/private-publish.js";import{resolveInstagramRuntimeInfo as Nj}from"./_shared/runtime-info.js";import{setInputFiles as Oj}from"../_shared/file-inject.js";const J="https://www.instagram.com/",Qj=new Set([".jpg",".jpeg",".png",".webp"]),Tj=new Set([".mp4"]),x=10,Xj="/tmp/instagram_post_protocol_trace.json";async function k(j,G=!1){if(G){await j.goto(`${J}?__opencli_reset=${Date.now()}`);await j.wait({time:1})}await j.goto(J)}export function buildEnsureComposerOpenJs(){return`
2
2
  (() => {
3
3
  const path = window.location?.pathname || '';
4
4
  const onLoginRoute = /\\/accounts\\/login\\/?/.test(path);
@@ -61,7 +61,7 @@ import*as b from"node:fs";import*as W from"node:path";import{cli as r,Strategy a
61
61
  const settled = !shared && !composerOpen && !/sharing/.test(visibleText);
62
62
  return { ok: shared, failed, settled, url: /\\/p\\//.test(url) ? url : '' };
63
63
  })()
64
- `}function _j(j){if(!j)throw new Y("Browser session required for instagram post");return j}function $j(j){if(!j.length)throw new z('Argument "media" is required.',"Provide --media /path/to/file.jpg or --media /path/a.jpg,/path/b.mp4");if(j.length>C)throw new z(`Too many media items: ${j.length}`,`Instagram carousel posts support at most ${C} items`);return j.map((N)=>{const O=W.resolve(String(N||"").trim());if(!O)throw new z("Media path cannot be empty");if(!b.existsSync(O))throw new z(`Media file not found: ${O}`);const Q=W.extname(O).toLowerCase();if(Xj.has(Q))return{type:"image",filePath:O};if(Yj.has(Q))return{type:"video",filePath:O};throw new z(`Unsupported media format: ${Q}`,"Supported formats: images (.jpg, .jpeg, .png, .webp) and videos (.mp4)")})}function qj(j){const G=String(j.media??"").trim();return $j(G.split(",").map((N)=>N.trim()).filter(Boolean))}function Hj(j){if(j.media===void 0)throw new z('Argument "media" is required.',"Provide --media /path/to/file.jpg or --media /path/a.jpg,/path/b.mp4")}function Jj(j){if(!(j instanceof Y))return!1;return j.message.startsWith("Instagram private publish")||j.message.startsWith("Instagram private route")}function x(j,G){return[{status:"✅ Posted",detail:Mj(j),url:G}]}function Tj(j,G){const N=j instanceof Error?j.message:String(j),O=G instanceof Error?G.message:String(G);return`Private route failed first: ${N}. UI fallback then failed: ${O}`}async function Vj(j){const G=await Gj(j.page),N=j.mediaItems.every((Q)=>Q.type==="image")?await jj({page:j.page,imagePaths:j.mediaItems.map((Q)=>Q.filePath),caption:j.content,apiContext:G.apiContext,jazoest:G.jazoest}):await e({page:j.page,mediaItems:j.mediaItems,caption:j.content,apiContext:G.apiContext,jazoest:G.jazoest}),O=N.code?new URL(`/p/${N.code}/`,K).toString():j.canDiffProfile?await w(j.page,j.existingPostPaths):"";return x(j.mediaItems,O)}async function zj(j){let G,N=null;for(let O=0;O<j.commandAttemptBudget;O++){let Q=!1;try{await k(j.page,j.forceFreshStart||O>0);await j.installProtocolCapture();await j.page.wait({time:2});await A(j.page);await y(j.page);const X=await v(j.page,j.mediaItems);if(j.preUploadDelaySeconds>0)await j.page.wait({time:j.preUploadDelaySeconds});let _=!1,Z=null;for(const q of X){let T=q;for(let L=0;L<j.uploadAttemptBudget;L++){await Aj(j.page,j.mediaItems,T);const B=await c(j.page,j.previewProbeWindowSeconds);if(B.state==="preview"){_=!0;break}if(B.state==="failed"){Z=D(B.detail);for(let F=0;F<j.inlineUploadRetryBudget;F++){if(!await Cj(j.page))break;await j.page.wait({time:3});const V=await c(j.page,Math.max(3,Math.floor(j.previewProbeWindowSeconds/2)));if(V.state==="preview"){_=!0;break}if(V.state!=="failed")break}if(_)break;await bj(j.page);await A(j.page);if(L<j.uploadAttemptBudget-1){try{await j.drainProtocolCapture();await k(j.page,!0);await j.installProtocolCapture();await j.page.wait({time:2});await A(j.page);await y(j.page);T=await I(j.page,T,j.mediaItems);if(j.preUploadDelaySeconds>0)await j.page.wait({time:j.preUploadDelaySeconds})}catch{throw Z}await j.page.wait({time:1.5});continue}break}break}if(_)break}if(!_){if(Z)throw Z;await kj(j.page,j.finalPreviewWaitSeconds)}try{await hj(j.page)}catch(q){await Ej(j.page,q)}if(j.content){await Sj(j.page,j.content);await vj(j.page,j.content)}if(j.preShareDelaySeconds>0)await j.page.wait({time:j.preShareDelaySeconds});await d(j.page,["Share","分享"],"caption");Q=!0;let $="";try{$=await g(j.page)}catch(q){if(q instanceof Y&&q.message==="Instagram post share failed"&&await Uj(j.page)){await j.page.wait({time:Math.max(2,j.preShareDelaySeconds)});$=await g(j.page)}else throw q}await j.drainProtocolCapture();if(!$&&j.canDiffProfile)$=await w(j.page,j.existingPostPaths);return x(j.mediaItems,$)}catch(X){G=X;if(X instanceof Y&&X.message!=="Failed to open Instagram post composer")N=X;if(X instanceof R)throw X;if(Q){let Z="";if(j.canDiffProfile)try{Z=await w(j.page,j.existingPostPaths)}catch{}if(Z)return x(j.mediaItems,Z);const $=X instanceof Error?X.message:String(X);throw new Y(`Instagram share was clicked but the outcome could not be confirmed: ${$}`,"The post may already be live. Do NOT rerun this command blindly — open the profile (or rerun after checking) and confirm no new post exists first; retrying on a false failure creates a duplicate post.")}if(!(X instanceof Y)||O===j.commandAttemptBudget-1){if(X instanceof Y&&X.message==="Failed to open Instagram post composer"&&N)throw N;throw X}let _=!1;if(j.mediaItems.length>=10&&j.page.closeWindow)try{await j.drainProtocolCapture();await j.page.closeWindow();_=!0}catch{}if(!_){await A(j.page);await j.page.wait({time:1})}}}throw G instanceof Error?G:new Y("Instagram post failed")}async function y(j){const G=await j.evaluate(buildEnsureComposerOpenJs());if(!G?.ok){if(G?.reason==="auth")throw new R("www.instagram.com","Instagram login required before posting");throw new Y("Failed to open Instagram post composer")}}async function A(j){for(let G=0;G<4;G++){if(!(await j.evaluate(`
64
+ `}function Yj(j){if(!j)throw new T("Browser session required for instagram post");return j}function Zj(j){if(!j.length)throw new H('Argument "media" is required.',"Provide --media /path/to/file.jpg or --media /path/a.jpg,/path/b.mp4");if(j.length>x)throw new H(`Too many media items: ${j.length}`,`Instagram carousel posts support at most ${x} items`);return j.map((K)=>{const N=S.resolve(String(K||"").trim());if(!N)throw new H("Media path cannot be empty");if(!P.existsSync(N))throw new H(`Media file not found: ${N}`);const O=S.extname(N).toLowerCase();if(Qj.has(O))return{type:"image",filePath:N};if(Tj.has(O))return{type:"video",filePath:N};throw new H(`Unsupported media format: ${O}`,"Supported formats: images (.jpg, .jpeg, .png, .webp) and videos (.mp4)")})}function _j(j){const G=String(j.media??"").trim();return Zj(G.split(",").map((K)=>K.trim()).filter(Boolean))}function $j(j){if(j.media===void 0)throw new H('Argument "media" is required.',"Provide --media /path/to/file.jpg or --media /path/a.jpg,/path/b.mp4")}function qj(j){if(!(j instanceof T))return!1;return j.message.startsWith("Instagram private publish")||j.message.startsWith("Instagram private route")}function R(j,G){return[{status:"✅ Posted",detail:Aj(j),url:G}]}function zj(j,G){const K=j instanceof Error?j.message:String(j),N=G instanceof Error?G.message:String(G);return`Private route failed first: ${K}. UI fallback then failed: ${N}`}async function Hj(j){const G=await Gj(j.page),K=j.mediaItems.every((O)=>O.type==="image")?await jj({page:j.page,imagePaths:j.mediaItems.map((O)=>O.filePath),caption:j.content,apiContext:G.apiContext,jazoest:G.jazoest}):await e({page:j.page,mediaItems:j.mediaItems,caption:j.content,apiContext:G.apiContext,jazoest:G.jazoest}),N=K.code?new URL(`/p/${K.code}/`,J).toString():j.canDiffProfile?await h(j.page,j.existingPostPaths):"";return R(j.mediaItems,N)}async function Jj(j){let G,K=null;for(let N=0;N<j.commandAttemptBudget;N++){let O=!1;try{await k(j.page,j.forceFreshStart||N>0);await j.installProtocolCapture();await j.page.wait({time:2});await A(j.page);await y(j.page);const Q=await v(j.page,j.mediaItems);if(j.preUploadDelaySeconds>0)await j.page.wait({time:j.preUploadDelaySeconds});let Y=!1,X=null;for(const q of Q){let V=q;for(let L=0;L<j.uploadAttemptBudget;L++){await Bj(j.page,j.mediaItems,V);const B=await c(j.page,j.previewProbeWindowSeconds);if(B.state==="preview"){Y=!0;break}if(B.state==="failed"){X=D(B.detail);for(let F=0;F<j.inlineUploadRetryBudget;F++){if(!await kj(j.page))break;await j.page.wait({time:3});const z=await c(j.page,Math.max(3,Math.floor(j.previewProbeWindowSeconds/2)));if(z.state==="preview"){Y=!0;break}if(z.state!=="failed")break}if(Y)break;await xj(j.page);await A(j.page);if(L<j.uploadAttemptBudget-1){try{await j.drainProtocolCapture();await k(j.page,!0);await j.installProtocolCapture();await j.page.wait({time:2});await A(j.page);await y(j.page);V=await I(j.page,V,j.mediaItems);if(j.preUploadDelaySeconds>0)await j.page.wait({time:j.preUploadDelaySeconds})}catch{throw X}await j.page.wait({time:1.5});continue}break}break}if(Y)break}if(!Y){if(X)throw X;await wj(j.page,j.finalPreviewWaitSeconds)}try{await Cj(j.page)}catch(q){await fj(j.page,q)}if(j.content){await Ej(j.page,j.content);await Sj(j.page,j.content)}if(j.preShareDelaySeconds>0)await j.page.wait({time:j.preShareDelaySeconds});await d(j.page,["Share","分享"],"caption");O=!0;let _="";try{_=await g(j.page)}catch(q){if(q instanceof T&&q.message==="Instagram post share failed"&&await bj(j.page)){await j.page.wait({time:Math.max(2,j.preShareDelaySeconds)});_=await g(j.page)}else throw q}await j.drainProtocolCapture();if(!_&&j.canDiffProfile)_=await h(j.page,j.existingPostPaths);return R(j.mediaItems,_)}catch(Q){G=Q;if(Q instanceof T&&Q.message!=="Failed to open Instagram post composer")K=Q;if(Q instanceof W)throw Q;if(O){let X="";if(j.canDiffProfile)try{X=await h(j.page,j.existingPostPaths)}catch{}if(X)return R(j.mediaItems,X);const _=Q instanceof Error?Q.message:String(Q);throw new T(`Instagram share was clicked but the outcome could not be confirmed: ${_}`,"The post may already be live. Do NOT rerun this command blindly — open the profile (or rerun after checking) and confirm no new post exists first; retrying on a false failure creates a duplicate post.")}if(!(Q instanceof T)||N===j.commandAttemptBudget-1){if(Q instanceof T&&Q.message==="Failed to open Instagram post composer"&&K)throw K;throw Q}let Y=!1;if(j.mediaItems.length>=10&&j.page.closeWindow)try{await j.drainProtocolCapture();await j.page.closeWindow();Y=!0}catch{}if(!Y){await A(j.page);await j.page.wait({time:1})}}}throw G instanceof Error?G:new T("Instagram post failed")}async function y(j){const G=await j.evaluate(buildEnsureComposerOpenJs());if(!G?.ok){if(G?.reason==="auth")throw new W("www.instagram.com","Instagram login required before posting");throw new T("Failed to open Instagram post composer")}}async function A(j){for(let G=0;G<4;G++){if(!(await j.evaluate(`
65
65
  (() => {
66
66
  const isVisible = (el) => {
67
67
  if (!(el instanceof HTMLElement)) return false;
@@ -105,7 +105,7 @@ import*as b from"node:fs";import*as W from"node:path";import{cli as r,Strategy a
105
105
 
106
106
  return { ok: false };
107
107
  })()
108
- `))?.ok)return;await j.wait({time:0.5})}}async function U(j,G){const N=G.some((Q)=>Q.type==="video"),O=await j.evaluate(`
108
+ `))?.ok)return;await j.wait({time:0.5})}}async function w(j,G){const K=G.some((O)=>O.type==="video"),N=await j.evaluate(`
109
109
  ((includesVideo) => {
110
110
  const isVisible = (el) => {
111
111
  if (!(el instanceof HTMLElement)) return false;
@@ -164,55 +164,8 @@ import*as b from"node:fs";import*as W from"node:path";import{cli as r,Strategy a
164
164
  return '[data-opencli-ig-upload-index="' + index + '"]';
165
165
  });
166
166
  return { ok: true, selectors };
167
- })(${JSON.stringify(N)})
168
- `);if(!O?.ok||!O.selectors?.length)throw new Y("Instagram upload input not found","Open the new-post composer in a logged-in browser session and retry");return O.selectors}async function v(j,G){try{return await U(j,G)}catch(N){if(!(N instanceof Y)||!N.message.includes("upload input not found"))throw N;await y(j);await j.wait({time:1.5});try{return await U(j,G)}catch(O){if(!(O instanceof Y)||!O.message.includes("upload input not found"))throw O;await k(j,!0);await j.wait({time:2});await A(j);await y(j);await j.wait({time:2});return U(j,G)}}}function Kj(j){const G=j.match(/data-opencli-ig-upload-index="(\d+)"/);if(!G)return null;const N=Number.parseInt(G[1]||"",10);return Number.isNaN(N)?null:N}async function I(j,G,N){const O=await v(j,N),Q=Kj(G);if(Q!==null&&O[Q])return O[Q];return O[0]||G}async function Lj(j,G,N){const O=G.map(($)=>{const q=W.extname($).toLowerCase(),T=q===".png"?"image/png":q===".webp"?"image/webp":"image/jpeg";return{name:W.basename($),type:T,base64:b.readFileSync($).toString("base64")}}),Q=`__opencliInstagramUpload_${Date.now()}_${Math.random().toString(36).slice(2)}`,X=262144;await j.evaluate(`
169
- (() => {
170
- window[${JSON.stringify(Q)}] = [];
171
- return { ok: true };
172
- })()
173
- `);const _=JSON.stringify(O);for(let $=0;$<_.length;$+=X){const q=_.slice($,$+X);await j.evaluate(`
174
- (() => {
175
- const key = ${JSON.stringify(Q)};
176
- const chunk = ${JSON.stringify(q)};
177
- const parts = Array.isArray(window[key]) ? window[key] : [];
178
- parts.push(chunk);
179
- window[key] = parts;
180
- return { ok: true, count: parts.length };
181
- })()
182
- `)}const Z=await j.evaluate(`
183
- (() => {
184
- const selector = ${JSON.stringify(N)};
185
- const key = ${JSON.stringify(Q)};
186
- const payload = JSON.parse(Array.isArray(window[key]) ? window[key].join('') : '[]');
187
-
188
- const cleanup = () => { try { delete window[key]; } catch {} };
189
- const input = document.querySelector(selector);
190
- if (!(input instanceof HTMLInputElement)) {
191
- cleanup();
192
- return { ok: false, error: 'File input not found for fallback injection' };
193
- }
194
-
195
- try {
196
- const dt = new DataTransfer();
197
- for (const img of payload) {
198
- const binary = atob(img.base64);
199
- const bytes = new Uint8Array(binary.length);
200
- for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
201
- const blob = new Blob([bytes], { type: img.type });
202
- const file = new File([blob], img.name, { type: img.type });
203
- dt.items.add(file);
204
- }
205
- Object.defineProperty(input, 'files', { value: dt.files, configurable: true });
206
- input.dispatchEvent(new Event('change', { bubbles: true }));
207
- input.dispatchEvent(new Event('input', { bubbles: true }));
208
- cleanup();
209
- return { ok: true, count: dt.files.length };
210
- } catch (error) {
211
- cleanup();
212
- return { ok: false, error: String(error) };
213
- }
214
- })()
215
- `);if(!Z?.ok)throw new Y(Z?.error||"Instagram fallback file injection failed")}async function Bj(j,G){await j.evaluate(`
167
+ })(${JSON.stringify(K)})
168
+ `);if(!N?.ok||!N.selectors?.length)throw new T("Instagram upload input not found","Open the new-post composer in a logged-in browser session and retry");return N.selectors}async function v(j,G){try{return await w(j,G)}catch(K){if(!(K instanceof T)||!K.message.includes("upload input not found"))throw K;await y(j);await j.wait({time:1.5});try{return await w(j,G)}catch(N){if(!(N instanceof T)||!N.message.includes("upload input not found"))throw N;await k(j,!0);await j.wait({time:2});await A(j);await y(j);await j.wait({time:2});return w(j,G)}}}function Vj(j){const G=j.match(/data-opencli-ig-upload-index="(\d+)"/);if(!G)return null;const K=Number.parseInt(G[1]||"",10);return Number.isNaN(K)?null:K}async function I(j,G,K){const N=await v(j,K),O=Vj(G);if(O!==null&&N[O])return N[O];return N[0]||G}async function Lj(j,G){await j.evaluate(`
216
169
  (() => {
217
170
  const input = document.querySelector(${JSON.stringify(G)});
218
171
  if (!(input instanceof HTMLInputElement)) return { ok: false };
@@ -255,7 +208,7 @@ import*as b from"node:fs";import*as W from"node:path";import{cli as r,Strategy a
255
208
  if (failed) return { state: 'failed', detail: dialogText || 'Something went wrong' };
256
209
  return { state: 'pending', detail: dialogText || '' };
257
210
  })()
258
- `}async function M(j){const G=await j.evaluate(buildInspectUploadStageJs());if(G?.state)return G;if(G?.ok===!0)return{state:"preview",detail:G.detail};return{state:"pending",detail:G?.detail}}function D(j){return new Y("Instagram image upload failed",j?`Instagram rejected the upload: ${j}`:"Instagram rejected the upload before the preview stage")}async function Aj(j,G,N){const O=G.map((X)=>X.filePath);if(!j.setFileInput)throw new Y("Instagram posting requires Browser Bridge file upload support","Use Browser Bridge or another browser mode that supports setFileInput");let Q=N;for(let X=0;X<2;X++)try{await j.setFileInput(O,Q);await Bj(j,Q);return}catch(_){const Z=_ instanceof Error?_.message:String(_);if((Z.includes("No element found matching selector")||Z.includes("Could not find node with given id")||Z.includes("No node with given id found"))&&X===0){Q=await I(j,Q,G);continue}if(!Z.includes("Unknown action")&&!Z.includes("set-file-input")&&!Z.includes("not supported")&&!Z.includes("Not allowed"))throw _;if(G.some((q)=>q.type==="video")){Qj(_);throw new Y("Instagram mixed-media posting requires Browser Bridge file upload support","Use Browser Bridge or another browser mode that supports setFileInput for image/video uploads")}await Lj(j,O,Q);return}}function Mj(j){if(j.every((G)=>G.type==="image"))return j.length===1?"Single image post shared successfully":`${j.length}-image carousel post shared successfully`;return j.length===1?"Single mixed-media post shared successfully":`${j.length}-item mixed-media carousel post shared successfully`}function Dj(j){if(j.length>=10)return 6;if(j.length>=5)return 4;return 3}function Fj(j){if(j.length>=10)return 3;if(j.length>=5)return 1.5;return 0}function Wj(j){if(j.length>=10)return 3;if(j.length>=5)return 3;return 2}function Rj(j){if(j.length>=10)return 6;if(j.length>=5)return 6;return 4}function xj(j){if(j.length>=10)return 12;if(j.length>=5)return 16;return 12}function yj(j){if(j.length>=10)return 4;if(j.length>=5)return 3;return 0}function wj(j){if(j.length>=10)return 3;if(j.length>=5)return 2;return 1}async function bj(j){return!!(await j.evaluate(`
211
+ `}async function M(j){const G=await j.evaluate(buildInspectUploadStageJs());if(G?.state)return G;if(G?.ok===!0)return{state:"preview",detail:G.detail};return{state:"pending",detail:G?.detail}}function D(j){return new T("Instagram image upload failed",j?`Instagram rejected the upload: ${j}`:"Instagram rejected the upload before the preview stage")}async function Bj(j,G,K){const N=G.map((Q)=>Q.filePath);let O=K;for(let Q=0;Q<2;Q++)try{if((await Oj(j,O,N)).method==="cdp")await Lj(j,O);return}catch(Y){const X=Y instanceof Error?Y.message:String(Y);if((X.includes("No element found matching selector")||X.includes("Could not find node with given id")||X.includes("No node with given id found")||X.includes("未找到可用的文件上传输入框"))&&Q===0){O=await I(j,O,G);continue}throw Y}}function Aj(j){if(j.every((G)=>G.type==="image"))return j.length===1?"Single image post shared successfully":`${j.length}-image carousel post shared successfully`;return j.length===1?"Single mixed-media post shared successfully":`${j.length}-item mixed-media carousel post shared successfully`}function Mj(j){if(j.length>=10)return 6;if(j.length>=5)return 4;return 3}function Dj(j){if(j.length>=10)return 3;if(j.length>=5)return 1.5;return 0}function Fj(j){if(j.length>=10)return 3;if(j.length>=5)return 3;return 2}function Wj(j){if(j.length>=10)return 6;if(j.length>=5)return 6;return 4}function Rj(j){if(j.length>=10)return 12;if(j.length>=5)return 16;return 12}function yj(j){if(j.length>=10)return 4;if(j.length>=5)return 3;return 0}function hj(j){if(j.length>=10)return 3;if(j.length>=5)return 2;return 1}async function xj(j){return!!(await j.evaluate(`
259
212
  (() => {
260
213
  const isVisible = (el) => {
261
214
  if (!(el instanceof HTMLElement)) return false;
@@ -278,7 +231,7 @@ import*as b from"node:fs";import*as W from"node:path";import{cli as r,Strategy a
278
231
  }
279
232
  return { ok: false };
280
233
  })()
281
- `))?.ok}async function Cj(j){return!!(await j.evaluate(`
234
+ `))?.ok}async function kj(j){return!!(await j.evaluate(`
282
235
  (() => {
283
236
  const isVisible = (el) => {
284
237
  if (!(el instanceof HTMLElement)) return false;
@@ -312,7 +265,7 @@ import*as b from"node:fs";import*as W from"node:path";import{cli as r,Strategy a
312
265
  }
313
266
  return { ok: false };
314
267
  })()
315
- `))?.ok}async function kj(j,G=12){const N=Math.max(1,Math.ceil(G));for(let O=0;O<N;O++){const Q=await M(j);if(Q.state==="preview")return;if(Q.state==="failed"){await j.screenshot({path:"/tmp/instagram_post_preview_debug.png"});throw D("Inspect /tmp/instagram_post_preview_debug.png. "+(Q.detail||""))}if(O<N-1)await j.wait({time:1})}await j.screenshot({path:"/tmp/instagram_post_preview_debug.png"});throw new Y("Instagram image preview did not appear after upload","The selected file input may not match the active composer; inspect /tmp/instagram_post_preview_debug.png")}async function c(j,G=4){const N=Math.max(1,Math.ceil(G*2));for(let O=0;O<N;O++){const Q=await M(j);if(Q.state!=="pending")return Q;if(O<N-1)await j.wait({time:0.5})}return{state:"pending"}}export function buildClickActionJs(j,G="any"){return`
268
+ `))?.ok}async function wj(j,G=12){const K=Math.max(1,Math.ceil(G));for(let N=0;N<K;N++){const O=await M(j);if(O.state==="preview")return;if(O.state==="failed"){await j.screenshot({path:"/tmp/instagram_post_preview_debug.png"});throw D("Inspect /tmp/instagram_post_preview_debug.png. "+(O.detail||""))}if(N<K-1)await j.wait({time:1})}await j.screenshot({path:"/tmp/instagram_post_preview_debug.png"});throw new T("Instagram image preview did not appear after upload","The selected file input may not match the active composer; inspect /tmp/instagram_post_preview_debug.png")}async function c(j,G=4){const K=Math.max(1,Math.ceil(G*2));for(let N=0;N<K;N++){const O=await M(j);if(O.state!=="pending")return O;if(N<K-1)await j.wait({time:0.5})}return{state:"pending"}}export function buildClickActionJs(j,G="any"){return`
316
269
  ((labels, scope) => {
317
270
  const isVisible = (el) => {
318
271
  if (!(el instanceof HTMLElement)) return false;
@@ -367,7 +320,7 @@ import*as b from"node:fs";import*as W from"node:path";import{cli as r,Strategy a
367
320
  }
368
321
  return { ok: false };
369
322
  })(${JSON.stringify(j)}, ${JSON.stringify(G)})
370
- `}async function d(j,G,N="any"){const O=await j.evaluate(buildClickActionJs(G,N));if(!O?.ok)throw new Y(`Instagram action button not found: ${G.join(" / ")}`);return O.label||G[0]}async function Uj(j){return!!(await j.evaluate(`
323
+ `}async function d(j,G,K="any"){const N=await j.evaluate(buildClickActionJs(G,K));if(!N?.ok)throw new T(`Instagram action button not found: ${G.join(" / ")}`);return N.label||G[0]}async function bj(j){return!!(await j.evaluate(`
371
324
  (() => {
372
325
  const isVisible = (el) => {
373
326
  if (!(el instanceof HTMLElement)) return false;
@@ -405,12 +358,12 @@ import*as b from"node:fs";import*as W from"node:path";import{cli as r,Strategy a
405
358
 
406
359
  return { ok: false };
407
360
  })()
408
- `))?.ok}async function l(j){return!!(await j.evaluate(`
361
+ `))?.ok}async function m(j){return!!(await j.evaluate(`
409
362
  (() => {
410
363
  const editable = document.querySelector('textarea, [contenteditable="true"]');
411
364
  return { ok: !!editable };
412
365
  })()
413
- `))?.ok}async function m(j){return!!(await j.evaluate(`
366
+ `))?.ok}async function l(j){return!!(await j.evaluate(`
414
367
  (() => {
415
368
  const editable = document.querySelector('textarea, [contenteditable="true"]');
416
369
  const dialogText = Array.from(document.querySelectorAll('[role="dialog"]'))
@@ -424,7 +377,7 @@ import*as b from"node:fs";import*as W from"node:path";import{cli as r,Strategy a
424
377
  || dialogText.includes('advanced settings'),
425
378
  };
426
379
  })()
427
- `))?.ok}async function hj(j){for(let G=0;G<3;G++){if(await m(j))return;try{await d(j,["Next","下一步"],"media")}catch(O){if(O instanceof Y){await j.wait({time:1.5});if(await m(j))return;const Q=await M(j);if(Q.state==="failed")throw D(Q.detail);if(G<2)continue}throw O}await j.wait({time:1.5});if(await l(j))return;const N=await M(j);if(N.state==="failed")throw D(N.detail)}await j.screenshot({path:"/tmp/instagram_post_caption_debug.png"});throw new Y("Instagram caption editor did not appear","Instagram may have changed the publish flow; inspect /tmp/instagram_post_caption_debug.png")}async function sj(j){if(!await l(j)){await j.screenshot({path:"/tmp/instagram_post_caption_debug.png"});throw new Y("Instagram caption editor did not appear","Instagram may have changed the publish flow; inspect /tmp/instagram_post_caption_debug.png")}}async function Ej(j,G){const N=await M(j);if(N.state==="failed")throw D(N.detail);throw G}async function fj(j){return!!(await j.evaluate(`
380
+ `))?.ok}async function Cj(j){for(let G=0;G<3;G++){if(await l(j))return;try{await d(j,["Next","下一步"],"media")}catch(N){if(N instanceof T){await j.wait({time:1.5});if(await l(j))return;const O=await M(j);if(O.state==="failed")throw D(O.detail);if(G<2)continue}throw N}await j.wait({time:1.5});if(await m(j))return;const K=await M(j);if(K.state==="failed")throw D(K.detail)}await j.screenshot({path:"/tmp/instagram_post_caption_debug.png"});throw new T("Instagram caption editor did not appear","Instagram may have changed the publish flow; inspect /tmp/instagram_post_caption_debug.png")}async function sj(j){if(!await m(j)){await j.screenshot({path:"/tmp/instagram_post_caption_debug.png"});throw new T("Instagram caption editor did not appear","Instagram may have changed the publish flow; inspect /tmp/instagram_post_caption_debug.png")}}async function fj(j,G){const K=await M(j);if(K.state==="failed")throw D(K.detail);throw G}async function Uj(j){return!!(await j.evaluate(`
428
381
  (() => {
429
382
  const textarea = document.querySelector('[aria-label="Write a caption..."], textarea');
430
383
  if (textarea instanceof HTMLTextAreaElement) {
@@ -484,7 +437,7 @@ import*as b from"node:fs";import*as W from"node:path";import{cli as r,Strategy a
484
437
 
485
438
  return { ok: true, kind: 'contenteditable' };
486
439
  })()
487
- `))?.ok}async function Sj(j,G){if(j.insertText&&await fj(j))try{await j.insertText(G);await j.wait({time:0.3});await j.evaluate(`
440
+ `))?.ok}async function Ej(j,G){if(j.insertText&&await Uj(j))try{await j.insertText(G);await j.wait({time:0.3});await j.evaluate(`
488
441
  (() => {
489
442
  const textarea = document.querySelector('[aria-label="Write a caption..."], textarea');
490
443
  if (textarea instanceof HTMLTextAreaElement) {
@@ -596,7 +549,7 @@ import*as b from"node:fs";import*as W from"node:path";import{cli as r,Strategy a
596
549
 
597
550
  return { ok: false };
598
551
  })(${JSON.stringify(G)})
599
- `))?.ok)throw new Y("Failed to fill Instagram caption")}async function Pj(j,G){return!!(await j.evaluate(`
552
+ `))?.ok)throw new T("Failed to fill Instagram caption")}async function Pj(j,G){return!!(await j.evaluate(`
600
553
  ((content) => {
601
554
  const normalized = content.trim();
602
555
  const readLexicalText = (node) => {
@@ -650,10 +603,10 @@ import*as b from"node:fs";import*as W from"node:path";import{cli as r,Strategy a
650
603
 
651
604
  return { ok: false };
652
605
  })(${JSON.stringify(G)})
653
- `))?.ok}async function vj(j,G){for(let N=0;N<6;N++){if(await Pj(j,G))return;if(N<5)await j.wait({time:0.5})}await j.screenshot({path:"/tmp/instagram_post_caption_fill_debug.png"});throw new Y("Instagram caption did not stick before sharing","Inspect /tmp/instagram_post_caption_fill_debug.png for the caption editor state")}async function g(j){let G=0;for(let N=0;N<90;N++){const O=await j.evaluate(buildPublishStatusProbeJs());if(O?.failed){await j.screenshot({path:"/tmp/instagram_post_share_debug.png"});throw new Y("Instagram post share failed","Inspect /tmp/instagram_post_share_debug.png for the share failure state")}if(O?.ok)return O.url||"";if(O?.settled){G+=1;if(G>=3)return""}else G=0;if(N<89)await j.wait({time:1})}await j.screenshot({path:"/tmp/instagram_post_share_debug.png"});throw new Y("Instagram post share confirmation did not appear","Inspect /tmp/instagram_post_share_debug.png for the final publish state")}async function o(j){return(await j.getCookies({domain:"instagram.com"})).find((N)=>N.name==="ds_user_id")?.value||""}async function s(j,G=""){if(G){const O=await Oj(j),Q=await j.evaluate(`
606
+ `))?.ok}async function Sj(j,G){for(let K=0;K<6;K++){if(await Pj(j,G))return;if(K<5)await j.wait({time:0.5})}await j.screenshot({path:"/tmp/instagram_post_caption_fill_debug.png"});throw new T("Instagram caption did not stick before sharing","Inspect /tmp/instagram_post_caption_fill_debug.png for the caption editor state")}async function g(j){let G=0;for(let K=0;K<90;K++){const N=await j.evaluate(buildPublishStatusProbeJs());if(N?.failed){await j.screenshot({path:"/tmp/instagram_post_share_debug.png"});throw new T("Instagram post share failed","Inspect /tmp/instagram_post_share_debug.png for the share failure state")}if(N?.ok)return N.url||"";if(N?.settled){G+=1;if(G>=3)return""}else G=0;if(K<89)await j.wait({time:1})}await j.screenshot({path:"/tmp/instagram_post_share_debug.png"});throw new T("Instagram post share confirmation did not appear","Inspect /tmp/instagram_post_share_debug.png for the final publish state")}async function s(j){return(await j.getCookies({domain:"instagram.com"})).find((K)=>K.name==="ds_user_id")?.value||""}async function o(j,G=""){if(G){const N=await Nj(j),O=await j.evaluate(`
654
607
  (async () => {
655
608
  const userId = ${JSON.stringify(G)};
656
- const appId = ${JSON.stringify(O.appId||"")};
609
+ const appId = ${JSON.stringify(N.appId||"")};
657
610
  try {
658
611
  const res = await fetch(
659
612
  'https://www.instagram.com/api/v1/users/' + encodeURIComponent(userId) + '/info/',
@@ -670,7 +623,7 @@ import*as b from"node:fs";import*as W from"node:path";import{cli as r,Strategy a
670
623
  return { ok: false };
671
624
  }
672
625
  })()
673
- `);if(Q?.ok&&Q.username)return new URL(`/${Q.username}/`,K).toString()}const N=await j.evaluate(`
626
+ `);if(O?.ok&&O.username)return new URL(`/${O.username}/`,J).toString()}const K=await j.evaluate(`
674
627
  (() => {
675
628
  const isVisible = (el) => {
676
629
  if (!(el instanceof HTMLElement)) return false;
@@ -695,7 +648,7 @@ import*as b from"node:fs";import*as W from"node:path";import{cli as r,Strategy a
695
648
  const path = explicitProfile;
696
649
  return { ok: !!path, path };
697
650
  })()
698
- `);if(!N?.ok||!N.path)return"";return new URL(N.path,K).toString()}async function n(j){const G=await j.evaluate(`
651
+ `);if(!K?.ok||!K.path)return"";return new URL(K.path,J).toString()}async function n(j){const G=await j.evaluate(`
699
652
  (() => {
700
653
  const isVisible = (el) => {
701
654
  if (!(el instanceof HTMLElement)) return false;
@@ -715,4 +668,4 @@ import*as b from"node:fs";import*as W from"node:path";import{cli as r,Strategy a
715
668
 
716
669
  return { ok: hrefs.length > 0, hrefs };
717
670
  })()
718
- `);return Array.isArray(G?.hrefs)?G.hrefs.filter(Boolean):[]}async function Ij(j){const G=await o(j);if(!G)return null;const N=await s(j,G);if(!N)return null;try{await j.goto(N);await j.wait({time:3});return new Set(await n(j))}catch{return null}}async function w(j,G){const N=await j.getCurrentUrl?.();if(N&&/\/p\//.test(N))return N;const O=await o(j),Q=await s(j,O);if(!Q)return"";await j.goto(Q);await j.wait({time:4});for(let X=0;X<8;X++){const Z=(await n(j)).find(($)=>!G.has($))||"";if(Z)return new URL(Z,K).toString();if(X<7)await j.wait({time:1})}return""}r({site:"instagram",name:"post",access:"write",description:"Post an Instagram feed image or mixed-media carousel",domain:"www.instagram.com",strategy:p.UI,browser:!0,args:[{name:"media",required:!1,valueRequired:!0,help:`Comma-separated media paths (images/videos, up to ${C})`},{name:"content",positional:!0,required:!1,help:"Caption text"},{name:"timeout",type:"int",required:!1,default:300,help:"Max seconds for the overall command (default: 300)"}],columns:["status","detail","url"],validateArgs:Hj,func:async(j,G)=>{const N=_j(j),O=qj(G),Q=String(G.content??"").trim(),X=await Ij(N),_=X!==null,Z=X??new Set,$=Dj(O),q=Fj(O),T=Wj(O),L=Rj(O),B=xj(O),F=yj(O),h=wj(O),V=process.env.OPENCLI_INSTAGRAM_CAPTURE==="1",E=[],f=[],u=async()=>{if(!V)return;await a(N)},S=async()=>{if(!V)return;const H=await t(N);if(H.data.length)E.push(...H.data);if(H.errors.length)f.push(...H.errors)};try{try{return await Vj({page:N,mediaItems:O,content:Q,existingPostPaths:Z,canDiffProfile:_})}catch(H){if(H instanceof R)throw H;if(Nj(H)){let J="",P=!1;if(_)try{J=await w(N,Z);P=!0}catch{}if(J)return x(O,J);if(!P){const i=H instanceof Error?H.message:String(H);throw new Y(`Instagram publish outcome uncertain: ${i}`,"The post may already be live. Do NOT rerun this command blindly — check the profile for a new post first; retrying on a false failure creates a duplicate post.")}}if(!Jj(H))throw H;try{return await zj({page:N,mediaItems:O,content:Q,existingPostPaths:Z,canDiffProfile:_,commandAttemptBudget:$,preUploadDelaySeconds:q,uploadAttemptBudget:T,previewProbeWindowSeconds:L,finalPreviewWaitSeconds:B,preShareDelaySeconds:F,inlineUploadRetryBudget:h,installProtocolCapture:u,drainProtocolCapture:S,forceFreshStart:!0})}catch(J){if(J instanceof R)throw J;if(J instanceof Y)throw new Y(J.message,Tj(H,J));throw J}}}finally{if(V){try{await S()}catch{}b.writeFileSync(Zj,JSON.stringify({data:E,errors:f},null,2))}}}});
671
+ `);return Array.isArray(G?.hrefs)?G.hrefs.filter(Boolean):[]}async function vj(j){const G=await s(j);if(!G)return null;const K=await o(j,G);if(!K)return null;try{await j.goto(K);await j.wait({time:3});return new Set(await n(j))}catch{return null}}async function h(j,G){const K=await j.getCurrentUrl?.();if(K&&/\/p\//.test(K))return K;const N=await s(j),O=await o(j,N);if(!O)return"";await j.goto(O);await j.wait({time:4});for(let Q=0;Q<8;Q++){const X=(await n(j)).find((_)=>!G.has(_))||"";if(X)return new URL(X,J).toString();if(Q<7)await j.wait({time:1})}return""}r({site:"instagram",name:"post",access:"write",description:"Post an Instagram feed image or mixed-media carousel",domain:"www.instagram.com",strategy:p.UI,browser:!0,args:[{name:"media",required:!1,valueRequired:!0,help:`Comma-separated media paths (images/videos, up to ${x})`},{name:"content",positional:!0,required:!1,help:"Caption text"},{name:"timeout",type:"int",required:!1,default:300,help:"Max seconds for the overall command (default: 300)"}],columns:["status","detail","url"],validateArgs:$j,func:async(j,G)=>{const K=Yj(j),N=_j(G),O=String(G.content??"").trim(),Q=await vj(K),Y=Q!==null,X=Q??new Set,_=Mj(N),q=Dj(N),V=Fj(N),L=Wj(N),B=Rj(N),F=yj(N),b=hj(N),z=process.env.OPENCLI_INSTAGRAM_CAPTURE==="1",C=[],f=[],u=async()=>{if(!z)return;await a(K)},U=async()=>{if(!z)return;const Z=await t(K);if(Z.data.length)C.push(...Z.data);if(Z.errors.length)f.push(...Z.errors)};try{try{return await Hj({page:K,mediaItems:N,content:O,existingPostPaths:X,canDiffProfile:Y})}catch(Z){if(Z instanceof W)throw Z;if(Kj(Z)){let $="",E=!1;if(Y)try{$=await h(K,X);E=!0}catch{}if($)return R(N,$);if(!E){const i=Z instanceof Error?Z.message:String(Z);throw new T(`Instagram publish outcome uncertain: ${i}`,"The post may already be live. Do NOT rerun this command blindly — check the profile for a new post first; retrying on a false failure creates a duplicate post.")}}if(!qj(Z))throw Z;try{return await Jj({page:K,mediaItems:N,content:O,existingPostPaths:X,canDiffProfile:Y,commandAttemptBudget:_,preUploadDelaySeconds:q,uploadAttemptBudget:V,previewProbeWindowSeconds:L,finalPreviewWaitSeconds:B,preShareDelaySeconds:F,inlineUploadRetryBudget:b,installProtocolCapture:u,drainProtocolCapture:U,forceFreshStart:!0})}catch($){if($ instanceof W)throw $;if($ instanceof T)throw new T($.message,zj(Z,$));throw $}}}finally{if(z){try{await U()}catch{}P.writeFileSync(Xj,JSON.stringify({data:C,errors:f},null,2))}}}});
@@ -1,4 +1,4 @@
1
- import*as L from"node:fs";import*as E from"node:os";import*as F from"node:path";import{Page as A}from"@jackwener/opencli/browser/page";import{cli as b,Strategy as I}from"@jackwener/opencli/registry";import{ArgumentError as G,AuthRequiredError as R,CommandExecutionError as Z}from"@jackwener/opencli/errors";import{buildClickActionJs as W,buildEnsureComposerOpenJs as x,buildInspectUploadStageJs as S}from"./post.js";import{resolveInstagramRuntimeInfo as U}from"./_shared/runtime-info.js";const H="https://www.instagram.com/",f=new Set([".mp4"]),C=600;function h(j){if(!j)throw new Z("Browser session required for instagram reel");return j}async function m(j,z=!1){if(z){await j.goto(`${H}?__opencli_reset=${Date.now()}`);await j.wait({time:1})}await j.goto(H)}function v(j){const z=F.resolve(String(j||"").trim());if(!z)throw new G("Video path cannot be empty");if(!L.existsSync(z))throw new G(`Video file not found: ${z}`);const B=F.extname(z).toLowerCase();if(!f.has(B))throw new G(`Unsupported video format: ${B}`,"Supported formats: .mp4");return z}function u(j){if(j.video===void 0)throw new G('Argument "video" is required.',"Provide --video /path/to/file.mp4")}function P(j){return[{status:"✅ Posted",detail:"Single reel shared successfully",url:j}]}function n(j){if(!(j instanceof Z))return!1;return j.message==="Instagram reel upload input not found"||j.message==="Instagram reel preview did not appear after upload"||j.message==="Instagram reel upload failed"}function d(j){const z=F.extname(j).toLowerCase()||".mp4";return F.join(E.tmpdir(),`opencli-instagram-video-real${z}`)}function c(j){const z=F.basename(j);if(/^[a-zA-Z0-9._-]+$/.test(z))return{originalPath:j,uploadPath:j};const B=d(j);L.copyFileSync(j,B);return{originalPath:j,uploadPath:B,cleanupPath:B}}async function o(j){const z=await j.evaluate(x());if(!z?.ok){if(z?.reason==="auth")throw new R("www.instagram.com","Instagram login required before posting a reel");throw new Z("Failed to open Instagram reel composer")}for(let B=0;B<12;B+=1){if((await j.evaluate(`
1
+ import*as L from"node:fs";import*as E from"node:os";import*as F from"node:path";import{Page as A}from"@jackwener/opencli/browser/page";import{cli as b,Strategy as I}from"@jackwener/opencli/registry";import{ArgumentError as G,AuthRequiredError as R,CommandExecutionError as Z}from"@jackwener/opencli/errors";import{buildClickActionJs as W,buildEnsureComposerOpenJs as x,buildInspectUploadStageJs as S}from"./post.js";import{resolveInstagramRuntimeInfo as U}from"./_shared/runtime-info.js";import{setInputFiles as f}from"../_shared/file-inject.js";const H="https://www.instagram.com/",h=new Set([".mp4"]),C=600;function m(j){if(!j)throw new Z("Browser session required for instagram reel");return j}async function v(j,z=!1){if(z){await j.goto(`${H}?__opencli_reset=${Date.now()}`);await j.wait({time:1})}await j.goto(H)}function u(j){const z=F.resolve(String(j||"").trim());if(!z)throw new G("Video path cannot be empty");if(!L.existsSync(z))throw new G(`Video file not found: ${z}`);const B=F.extname(z).toLowerCase();if(!h.has(B))throw new G(`Unsupported video format: ${B}`,"Supported formats: .mp4");return z}function P(j){if(j.video===void 0)throw new G('Argument "video" is required.',"Provide --video /path/to/file.mp4")}function n(j){return[{status:"✅ Posted",detail:"Single reel shared successfully",url:j}]}function d(j){if(!(j instanceof Z))return!1;return j.message==="Instagram reel upload input not found"||j.message==="Instagram reel preview did not appear after upload"||j.message==="Instagram reel upload failed"}function c(j){const z=F.extname(j).toLowerCase()||".mp4";return F.join(E.tmpdir(),`opencli-instagram-video-real${z}`)}function o(j){const z=F.basename(j);if(/^[a-zA-Z0-9._-]+$/.test(z))return{originalPath:j,uploadPath:j};const B=c(j);L.copyFileSync(j,B);return{originalPath:j,uploadPath:B,cleanupPath:B}}async function s(j){const z=await j.evaluate(x());if(!z?.ok){if(z?.reason==="auth")throw new R("www.instagram.com","Instagram login required before posting a reel");throw new Z("Failed to open Instagram reel composer")}for(let B=0;B<12;B+=1){if((await j.evaluate(`
2
2
  (() => {
3
3
  const isVisible = (el) => {
4
4
  if (!(el instanceof HTMLElement)) return false;
@@ -17,7 +17,7 @@ import*as L from"node:fs";import*as E from"node:os";import*as F from"node:path";
17
17
  });
18
18
  return { ok: inputs.length > 0 };
19
19
  })()
20
- `))?.ok)return;if(B<11)await j.wait({time:0.5})}throw new Z("Instagram reel upload input not found","Open the new-post composer in a logged-in browser session and retry")}async function s(j){for(let z=0;z<4;z+=1){if(!(await j.evaluate(`
20
+ `))?.ok)return;if(B<11)await j.wait({time:0.5})}throw new Z("Instagram reel upload input not found","Open the new-post composer in a logged-in browser session and retry")}async function l(j){for(let z=0;z<4;z+=1){if(!(await j.evaluate(`
21
21
  (() => {
22
22
  const isVisible = (el) => {
23
23
  if (!(el instanceof HTMLElement)) return false;
@@ -55,7 +55,7 @@ import*as L from"node:fs";import*as E from"node:os";import*as F from"node:path";
55
55
  }
56
56
  return { ok: false };
57
57
  })()
58
- `))?.ok)return;await j.wait({time:0.5})}}async function l(j){const z=await j.evaluate(`
58
+ `))?.ok)return;await j.wait({time:0.5})}}async function i(j){const z=await j.evaluate(`
59
59
  (() => {
60
60
  const isVisible = (el) => {
61
61
  if (!(el instanceof HTMLElement)) return false;
@@ -87,13 +87,13 @@ import*as L from"node:fs";import*as E from"node:os";import*as F from"node:path";
87
87
 
88
88
  return { ok: selectors.length > 0, selectors };
89
89
  })()
90
- `);if(!z?.ok||!Array.isArray(z.selectors)||z.selectors.length===0)throw new Z("Instagram reel upload input not found","Open the new-post composer in a logged-in browser session and retry");return z.selectors}async function i(j,z,B){if(!j.setFileInput)throw new Z("Instagram reel upload requires Browser Bridge file upload support","Use Browser Bridge or another browser mode that supports setFileInput");await j.setFileInput([z],B)}async function g(j,z){const B=await j.evaluate(`
90
+ `);if(!z?.ok||!Array.isArray(z.selectors)||z.selectors.length===0)throw new Z("Instagram reel upload input not found","Open the new-post composer in a logged-in browser session and retry");return z.selectors}async function g(j,z,B){await f(j,B,[z])}async function p(j,z){const B=await j.evaluate(`
91
91
  (() => {
92
92
  const input = document.querySelector(${JSON.stringify(z)});
93
93
  if (!(input instanceof HTMLInputElement)) return { count: null };
94
94
  return { count: input.files?.length || 0 };
95
95
  })()
96
- `);if(B?.count===null||B?.count===void 0)return null;return Number(B.count)}async function p(j,z=20){let B="";for(let Q=0;Q<z*2;Q+=1){const Y=await j.evaluate(S());B=String(Y?.detail||"").trim();if(Y?.state==="preview")return;if(Y?.state==="failed")throw new Z("Instagram reel upload failed",Y.detail?`Instagram rejected the reel upload: ${Y.detail}`:"Instagram rejected the reel upload before the preview stage");if(Q<z*2-1)await j.wait({time:0.5})}await j.screenshot({path:"/tmp/instagram_reel_preview_debug.png"});throw new Z("Instagram reel preview did not appear after upload",B?`Inspect /tmp/instagram_reel_preview_debug.png. Last visible dialog text: ${B}`:"Inspect /tmp/instagram_reel_preview_debug.png for the upload state")}async function D(j,z,B="any"){const Q=await j.evaluate(W(z,B));if(!Q?.ok)throw new Z(`Instagram action button not found: ${z.join(" / ")}`);return Q.label||z[0]||""}async function r(j,z,B="any"){return!!(await j.evaluate(W(z,B)))?.ok}function t(){return`
96
+ `);if(B?.count===null||B?.count===void 0)return null;return Number(B.count)}async function r(j,z=20){let B="";for(let Q=0;Q<z*2;Q+=1){const Y=await j.evaluate(S());B=String(Y?.detail||"").trim();if(Y?.state==="preview")return;if(Y?.state==="failed")throw new Z("Instagram reel upload failed",Y.detail?`Instagram rejected the reel upload: ${Y.detail}`:"Instagram rejected the reel upload before the preview stage");if(Q<z*2-1)await j.wait({time:0.5})}await j.screenshot({path:"/tmp/instagram_reel_preview_debug.png"});throw new Z("Instagram reel preview did not appear after upload",B?`Inspect /tmp/instagram_reel_preview_debug.png. Last visible dialog text: ${B}`:"Inspect /tmp/instagram_reel_preview_debug.png for the upload state")}async function D(j,z,B="any"){const Q=await j.evaluate(W(z,B));if(!Q?.ok)throw new Z(`Instagram action button not found: ${z.join(" / ")}`);return Q.label||z[0]||""}async function t(j,z,B="any"){return!!(await j.evaluate(W(z,B)))?.ok}function a(){return`
97
97
  (() => {
98
98
  const isVisible = (el) => {
99
99
  if (!(el instanceof HTMLElement)) return false;
@@ -127,7 +127,7 @@ import*as L from"node:fs";import*as E from"node:os";import*as F from"node:path";
127
127
  }
128
128
  return { state: 'pending', detail: text };
129
129
  })()
130
- `}async function O(j,z,B=20){for(let Q=0;Q<B*2;Q+=1){const Y=await j.evaluate(t());if(Y?.state===z)return;if(Y?.state==="failed")throw new Z("Instagram reel editor did not appear",Y.detail?`Instagram reel flow failed: ${Y.detail}`:"Instagram reel flow failed before the next editor stage");if(Q<B*2-1)await j.wait({time:0.5})}throw new Z(`Instagram reel ${z} editor did not appear`)}async function a(j){return!!(await j.evaluate(`
130
+ `}async function O(j,z,B=20){for(let Q=0;Q<B*2;Q+=1){const Y=await j.evaluate(a());if(Y?.state===z)return;if(Y?.state==="failed")throw new Z("Instagram reel editor did not appear",Y.detail?`Instagram reel flow failed: ${Y.detail}`:"Instagram reel flow failed before the next editor stage");if(Q<B*2-1)await j.wait({time:0.5})}throw new Z(`Instagram reel ${z} editor did not appear`)}async function e(j){return!!(await j.evaluate(`
131
131
  (() => {
132
132
  const isVisible = (el) => {
133
133
  if (!(el instanceof HTMLElement)) return false;
@@ -199,7 +199,7 @@ import*as L from"node:fs";import*as E from"node:os";import*as F from"node:path";
199
199
  }
200
200
  return { ok: false };
201
201
  })()
202
- `))?.ok}async function e(j,z){return!!(await j.evaluate(`
202
+ `))?.ok}async function jj(j,z){return!!(await j.evaluate(`
203
203
  (() => {
204
204
  const target = ${JSON.stringify(z.trim())}.replace(/\\u00a0/g, ' ').replace(/\\s+/g, ' ').trim();
205
205
  const isVisible = (el) => {
@@ -253,7 +253,7 @@ import*as L from"node:fs";import*as E from"node:os";import*as F from"node:path";
253
253
  }
254
254
  return { ok: false };
255
255
  })()
256
- `))?.ok}async function jj(j,z){if(!await a(j))throw new Z("Instagram reel caption editor did not appear");if(j.insertText)try{await j.insertText(z);await j.wait({time:0.3});await j.evaluate(`
256
+ `))?.ok}async function zj(j,z){if(!await e(j))throw new Z("Instagram reel caption editor did not appear");if(j.insertText)try{await j.insertText(z);await j.wait({time:0.3});await j.evaluate(`
257
257
  (() => {
258
258
  const isVisible = (el) => {
259
259
  if (!(el instanceof HTMLElement)) return false;
@@ -383,7 +383,7 @@ import*as L from"node:fs";import*as E from"node:os";import*as F from"node:path";
383
383
  }
384
384
  return { ok: false };
385
385
  })(${JSON.stringify(z)})
386
- `)}async function zj(j,z){for(let B=0;B<6;B+=1){if(await e(j,z))return;if(B<5)await j.wait({time:0.5})}throw new Z("Instagram reel caption did not stick before sharing")}function Bj(){return`
386
+ `)}async function Bj(j,z){for(let B=0;B<6;B+=1){if(await jj(j,z))return;if(B<5)await j.wait({time:0.5})}throw new Z("Instagram reel caption did not stick before sharing")}function Kj(){return`
387
387
  (() => {
388
388
  const isVisible = (el) => {
389
389
  if (!(el instanceof HTMLElement)) return false;
@@ -411,7 +411,7 @@ import*as L from"node:fs";import*as E from"node:os";import*as F from"node:path";
411
411
  const settled = !shared && !composerOpen && !sharingVisible;
412
412
  return { ok: shared, failed, settled, url: /\\/reel\\//.test(url) ? url : '' };
413
413
  })()
414
- `}async function Kj(j){let z=0;for(let B=0;B<120;B+=1){const Q=await j.evaluate(Bj());if(Q?.failed)throw new Z("Instagram reel share failed");if(Q?.ok)return Q.url||"";if(Q?.settled){z+=1;if(z>=3)return""}else z=0;if(B<119)await j.wait({time:1})}throw new Z("Instagram reel share confirmation did not appear")}async function _(j){return(await j.getCookies({domain:"instagram.com"})).find((B)=>B.name==="ds_user_id")?.value||""}async function w(j,z=""){if(z){const B=await U(j),Q=await j.evaluate(`
414
+ `}async function Qj(j){let z=0;for(let B=0;B<120;B+=1){const Q=await j.evaluate(Kj());if(Q?.failed)throw new Z("Instagram reel share failed");if(Q?.ok)return Q.url||"";if(Q?.settled){z+=1;if(z>=3)return""}else z=0;if(B<119)await j.wait({time:1})}throw new Z("Instagram reel share confirmation did not appear")}async function _(j){return(await j.getCookies({domain:"instagram.com"})).find((B)=>B.name==="ds_user_id")?.value||""}async function w(j,z=""){if(z){const B=await U(j),Q=await j.evaluate(`
415
415
  (async () => {
416
416
  const userId = ${JSON.stringify(z)};
417
417
  const appId = ${JSON.stringify(B.appId||"")};
@@ -449,4 +449,4 @@ import*as L from"node:fs";import*as E from"node:os";import*as F from"node:path";
449
449
  .filter((href, index, arr) => arr.indexOf(href) === index);
450
450
  return { hrefs };
451
451
  })()
452
- `);return Array.isArray(z?.hrefs)?z.hrefs.filter(Boolean):[]}async function Qj(j){const z=await _(j);if(!z)return new Set;const B=await w(j,z);if(!B)return new Set;try{await j.goto(B);await j.wait({time:3});return new Set(await M(j))}catch{return new Set}}async function Yj(j,z){const B=await j.getCurrentUrl?.();if(B&&/\/reel\//.test(B))return B;const Q=await _(j),Y=await w(j,Q);if(!Y)return"";await j.goto(Y);await j.wait({time:4});for(let q=0;q<8;q+=1){const y=await M(j),K=y.find(($)=>$.includes("/reel/")&&!z.has($))||y.find(($)=>!z.has($))||"";if(K)return new URL(K,H).toString();if(q<7)await j.wait({time:1})}return""}b({site:"instagram",name:"reel",access:"write",description:"Post an Instagram reel video",domain:"www.instagram.com",strategy:I.UI,browser:!0,args:[{name:"video",required:!1,valueRequired:!0,help:"Path to a single .mp4 video file"},{name:"content",positional:!0,required:!1,help:"Caption text"},{name:"timeout",type:"int",required:!1,default:C,help:`Max seconds for the overall command (default: ${C})`}],columns:["status","detail","url"],validateArgs:u,func:async(j,z)=>{const B=h(j),Q=v(z.video),Y=String(z.content??"").trim(),q=c(Q),y=async(K,$=new Set)=>{if(typeof K.startNetworkCapture==="function")await K.startNetworkCapture("/rupload_igvideo/|/api/v1/|/reel/|/clips/|/media/|/configure|/upload");await m(K,!0);await K.wait({time:2});await s(K);await o(K);await K.wait({time:2});const X=await l(K);let V=!1,J;for(const N of X)try{await i(K,q.uploadPath,N);if(await g(K,N)===0)throw new Z("Instagram reel upload failed","The selected reel input never received the video file");await p(K,10);V=!0;break}catch(T){J=T}if(!V)throw J instanceof Error?J:new Z("Instagram reel preview did not appear after upload");await r(K,["OK"],"any");await D(K,["Next","下一步"],"media");await O(K,"edit",20);await D(K,["Next","下一步"],"media");await O(K,"composer",20);if(Y){await jj(K,Y);await zj(K,Y)}await D(K,["Share","分享"],"caption");const k=await Kj(K)||await Yj(K,$);return P(k)};try{if(!process.env.VITEST){const $=async()=>{const X=new A(`site:instagram-reel-${Date.now()}`);try{return await y(X,new Set)}finally{await X.closeWindow?.()}};try{return await $()}catch(X){if(!n(X))throw X;return await $()}}const K=await Qj(B);return await y(B,K)}finally{if(q.cleanupPath)L.rmSync(q.cleanupPath,{force:!0})}}});
452
+ `);return Array.isArray(z?.hrefs)?z.hrefs.filter(Boolean):[]}async function Yj(j){const z=await _(j);if(!z)return new Set;const B=await w(j,z);if(!B)return new Set;try{await j.goto(B);await j.wait({time:3});return new Set(await M(j))}catch{return new Set}}async function Zj(j,z){const B=await j.getCurrentUrl?.();if(B&&/\/reel\//.test(B))return B;const Q=await _(j),Y=await w(j,Q);if(!Y)return"";await j.goto(Y);await j.wait({time:4});for(let q=0;q<8;q+=1){const y=await M(j),K=y.find(($)=>$.includes("/reel/")&&!z.has($))||y.find(($)=>!z.has($))||"";if(K)return new URL(K,H).toString();if(q<7)await j.wait({time:1})}return""}b({site:"instagram",name:"reel",access:"write",description:"Post an Instagram reel video",domain:"www.instagram.com",strategy:I.UI,browser:!0,args:[{name:"video",required:!1,valueRequired:!0,help:"Path to a single .mp4 video file"},{name:"content",positional:!0,required:!1,help:"Caption text"},{name:"timeout",type:"int",required:!1,default:C,help:`Max seconds for the overall command (default: ${C})`}],columns:["status","detail","url"],validateArgs:P,func:async(j,z)=>{const B=m(j),Q=u(z.video),Y=String(z.content??"").trim(),q=o(Q),y=async(K,$=new Set)=>{if(typeof K.startNetworkCapture==="function")await K.startNetworkCapture("/rupload_igvideo/|/api/v1/|/reel/|/clips/|/media/|/configure|/upload");await v(K,!0);await K.wait({time:2});await l(K);await s(K);await K.wait({time:2});const X=await i(K);let V=!1,J;for(const N of X)try{await g(K,q.uploadPath,N);if(await p(K,N)===0)throw new Z("Instagram reel upload failed","The selected reel input never received the video file");await r(K,10);V=!0;break}catch(T){J=T}if(!V)throw J instanceof Error?J:new Z("Instagram reel preview did not appear after upload");await t(K,["OK"],"any");await D(K,["Next","下一步"],"media");await O(K,"edit",20);await D(K,["Next","下一步"],"media");await O(K,"composer",20);if(Y){await zj(K,Y);await Bj(K,Y)}await D(K,["Share","分享"],"caption");const k=await Qj(K)||await Zj(K,$);return n(k)};try{if(!process.env.VITEST){const $=async()=>{const X=new A(`site:instagram-reel-${Date.now()}`);try{return await y(X,new Set)}finally{await X.closeWindow?.()}};try{return await $()}catch(X){if(!d(X))throw X;return await $()}}const K=await Yj(B);return await y(B,K)}finally{if(q.cleanupPath)L.rmSync(q.cleanupPath,{force:!0})}}});