@redreplier/cli 0.1.1 → 0.1.2

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/README.md CHANGED
@@ -16,7 +16,7 @@ npm install -g @redreplier/cli
16
16
  npx -p @redreplier/cli redreplier --help
17
17
 
18
18
  # macOS and Linux, standalone binary, no Node required
19
- brew install RedReplier/tap/redreplier
19
+ brew trust RedReplier/tap && brew install RedReplier/tap/redreplier
20
20
 
21
21
  # or
22
22
  curl -fsSL https://redreplier.com/install.sh | sh
@@ -24,6 +24,10 @@ curl -fsSL https://redreplier.com/install.sh | sh
24
24
 
25
25
  `npx @redreplier/cli` prompts instead of running, because npx resolves a bin named after the unscoped package. Use `npx -p @redreplier/cli redreplier`. There is no unscoped `redreplier` package, so plain `npx redreplier` will not find anything.
26
26
 
27
+ Homebrew 7 refuses to load a formula from a third-party tap until you trust it, which is
28
+ what `brew trust` does. Skip it and both `brew install` and `brew upgrade` stop with
29
+ "Refusing to load formula ... from untrusted tap".
30
+
27
31
  The install script downloads the release archive for your platform, verifies its checksum, and puts the binary in `~/.local/bin`. It never edits your shell rc files; it prints the `export PATH` line for you to add. Override the destination with `REDREPLIER_INSTALL_DIR`.
28
32
 
29
33
  Both bins run the same program. `rr` is the short one.
@@ -1 +1 @@
1
- import"./exit-codes-IaZq17dv.js";import{f as e}from"./errors-Dkv23Z0t.js";import"./version-CFnbqWhw.js";import"./color-BbAK7_Y7.js";import{c as t,f as n,g as r,i,o as a,p as o,r as s,s as c,v as l}from"./output-uP7GrsdR.js";import"./config-Bg2ls0gu.js";import{t as u}from"./product-CXL7Ga4M.js";import"./http-Bryxg3iu.js";import{a as d,f,i as p,t as m}from"./types-Bu8scNHe.js";import{C as h,S as g,f as _,m as v,v as y,x as b}from"./client-jT4mvZ9E.js";const x=`experimental, undocumented API`;function S(e){return e%1440==0?`${e/1440}d`:e%60==0?`${e/60}h`:`${e}m`}function C(t){let n=Number(t);if(!Number.isInteger(n)||!m.includes(n))throw e(`--cadence must be one of ${m.join(`, `)} minutes, got "${t}"`,`the server rejects anything else with a generic 400`);return n}function w(t){let n=Number(t);if(!Number.isInteger(n)||n<d||n>p)throw e(`--min-score must be a whole number between ${d} and ${p}, got "${t}"`);return n}async function T(e,t){let n=c()||a()?null:f(e);try{return await t()}finally{n?.stop()}}function E(e){n([[`enabled`,e.enabled?`yes`:`no`],[`cadence`,S(e.cadenceMinutes)],[`fastest`,`${S(e.minIntervalMinutes)} on this plan`],[`options`,e.availableCadences.join(`, `)]])}async function D(){let e=await T(`Reading alert settings…`,_);if(a()){o(`alerts.get`,e);return}E(e),i(`the full server list is ${m.join(`, `)}; yours is what the plan allows`)}async function O(t){if(t.on===!0&&t.off===!0)throw e(`Pass either --on or --off, not both`);if(t.on!==!0&&t.off!==!0)throw e(`Pass --on or --off`,`${u.binName} alerts set --on --cadence 60`);let n=t.cadence===void 0?void 0:C(t.cadence),s=await T(`Reading alert settings…`,_);n!==void 0&&!s.availableCadences.includes(n)&&l(`${S(n)} is not in this plan's cadences (${s.availableCadences.join(`, `)}), so the server may refuse it.`);let c=n??s.cadenceMinutes,d=await T(`Saving alert settings…`,()=>g({enabled:t.on===!0,cadenceMinutes:c}));if(a()){o(`alerts.set`,d);return}r(d.enabled?`Alerts on every ${S(d.cadenceMinutes)}`:`Alerts off (cadence ${n===void 0?`kept at`:`set to`} ${S(d.cadenceMinutes)})`),n===void 0&&i(`PUT /alert-settings is a full replace, so the current cadence was read and resent.`)}function k(e){let t=e.command(`alerts`).alias(`alert`).description(`email alert cadence for new mentions`);t.command(`get`).alias(`list`).description(`show the alert settings`).action(async()=>{await D()}),t.command(`set`).description(`turn alerts on or off and choose the cadence`).option(`--on`,`enable alerts`).option(`--off`,`disable alerts`).option(`--cadence <minutes>`,`one of ${m.join(`, `)}`).action(async e=>{await O(e)})}function A(e){n([[`enabled`,e.enabled?`yes`:`no`],[`min score`,String(e.minScore)],[`site`,e.websiteId===null?`every site`:s(e.websiteId)],[`profanity`,e.profanity?`yes`:`no`]])}async function j(){let e=await T(`Reading mean marketer config…`,v);if(a()){o(`mean-marketer.config`,e,{experimental:!0});return}A(e),i(x)}async function M(t){if(t.on===!0&&t.off===!0)throw e(`Pass either --on or --off, not both`);let n={};if(t.on===!0&&(n.enabled=!0),t.off===!0&&(n.enabled=!1),t.minScore!==void 0&&(n.minScore=w(t.minScore)),t.site!==void 0){let e=t.site.trim();n.websiteId=e===``||e.toLowerCase()===`none`?null:e}if(t.profanity!==void 0&&(n.profanity=t.profanity),Object.keys(n).length===0)throw e(`Nothing to change.`,`Pass at least one of --on, --off, --min-score, --site, --profanity or --no-profanity`);let s=await T(`Saving mean marketer config…`,()=>h(n));if(a()){o(`mean-marketer.config.set`,s,{experimental:!0});return}r(`Saved`),A(s),i(x)}function N(e){n([[`enabled`,e.enabled?`yes`:`no`],[`min score`,String(e.minScore)],[`mood`,e.beMean?`mean, tier ${e.tier}`:`civil, tier ${e.tier}`],[`strikes`,String(e.strikes)]]),e.previous&&(t(``),t(`previous opportunity`),n([[`id`,e.previous.id],[`status`,e.previous.status],[`triaged`,e.previous.triaged?`yes`:`no`],[`outstanding`,`${e.previous.hoursOutstanding}h`]],` `)),e.opportunity?(t(``),t(`new opportunity`),n([[`id`,e.opportunity.id],[`title`,e.opportunity.title??`—`],[`source`,e.opportunity.subreddit?`r/${e.opportunity.subreddit}`:e.opportunity.source],[`keyword`,e.opportunity.keyword??`—`],[`score`,e.opportunity.relevanceScore===null?`—`:String(e.opportunity.relevanceScore)],[`url`,e.opportunity.url??`—`]],` `),e.opportunity.relevanceReason&&(t(``),t(` ${e.opportunity.relevanceReason}`))):e.noNewOpportunity&&(t(``),t(`No new opportunity above the minimum score.`)),e.message&&(t(``),t(e.message))}async function P(){let e=await T(`Polling…`,y);if(a()){o(`mean-marketer.poll`,e,{experimental:!0});return}N(e),i(`${x}; this call advances the strike state`)}async function F(){let e=await T(`Resetting…`,b);if(a()){o(`mean-marketer.reset`,e,{experimental:!0});return}e.reset?r(`Strike state reset`):t(`Nothing to reset.`),i(x)}function I(e){let t=e.command(`mean-marketer`,{hidden:!0}).alias(`mm`).description(`nag yourself into replying (${x})`);t.command(`config`).description(`show the mean marketer config`).action(async()=>{await j()}).command(`set`).description(`change the mean marketer config`).option(`--on`,`enable it`).option(`--off`,`disable it`).option(`--min-score <n>`,`only nag about mentions scoring this or higher, ${d} to ${p}`).option(`--site <id>`,`restrict it to one site, or "none" for every site`).option(`--profanity`,`allow profanity`).option(`--no-profanity`,`keep it clean`).action(async e=>{await M(e)}),t.command(`poll`).description(`ask for the next opportunity and advance the strike state`).action(async()=>{await P()}),t.command(`reset`).description(`clear the strike state`).action(async()=>{await F()})}export{C as assertCadence,w as assertMinScore,S as formatCadence,k as registerAlertCommands,I as registerMeanMarketerCommands};
1
+ import"./exit-codes-IaZq17dv.js";import{f as e}from"./errors-Dkv23Z0t.js";import"./version-BPszCYbY.js";import"./color-BbAK7_Y7.js";import{c as t,f as n,g as r,i,o as a,p as o,r as s,s as c,v as l}from"./output-uP7GrsdR.js";import"./config-Bg2ls0gu.js";import{t as u}from"./product-CXL7Ga4M.js";import"./http-ZFrs1UcT.js";import{a as d,f,i as p,t as m}from"./types-Bu8scNHe.js";import{C as h,S as g,f as _,m as v,v as y,x as b}from"./client-CVesEwEU.js";const x=`experimental, undocumented API`;function S(e){return e%1440==0?`${e/1440}d`:e%60==0?`${e/60}h`:`${e}m`}function C(t){let n=Number(t);if(!Number.isInteger(n)||!m.includes(n))throw e(`--cadence must be one of ${m.join(`, `)} minutes, got "${t}"`,`the server rejects anything else with a generic 400`);return n}function w(t){let n=Number(t);if(!Number.isInteger(n)||n<d||n>p)throw e(`--min-score must be a whole number between ${d} and ${p}, got "${t}"`);return n}async function T(e,t){let n=c()||a()?null:f(e);try{return await t()}finally{n?.stop()}}function E(e){n([[`enabled`,e.enabled?`yes`:`no`],[`cadence`,S(e.cadenceMinutes)],[`fastest`,`${S(e.minIntervalMinutes)} on this plan`],[`options`,e.availableCadences.join(`, `)]])}async function D(){let e=await T(`Reading alert settings…`,_);if(a()){o(`alerts.get`,e);return}E(e),i(`the full server list is ${m.join(`, `)}; yours is what the plan allows`)}async function O(t){if(t.on===!0&&t.off===!0)throw e(`Pass either --on or --off, not both`);if(t.on!==!0&&t.off!==!0)throw e(`Pass --on or --off`,`${u.binName} alerts set --on --cadence 60`);let n=t.cadence===void 0?void 0:C(t.cadence),s=await T(`Reading alert settings…`,_);n!==void 0&&!s.availableCadences.includes(n)&&l(`${S(n)} is not in this plan's cadences (${s.availableCadences.join(`, `)}), so the server may refuse it.`);let c=n??s.cadenceMinutes,d=await T(`Saving alert settings…`,()=>g({enabled:t.on===!0,cadenceMinutes:c}));if(a()){o(`alerts.set`,d);return}r(d.enabled?`Alerts on every ${S(d.cadenceMinutes)}`:`Alerts off (cadence ${n===void 0?`kept at`:`set to`} ${S(d.cadenceMinutes)})`),n===void 0&&i(`PUT /alert-settings is a full replace, so the current cadence was read and resent.`)}function k(e){let t=e.command(`alerts`).alias(`alert`).description(`email alert cadence for new mentions`);t.command(`get`).alias(`list`).description(`show the alert settings`).action(async()=>{await D()}),t.command(`set`).description(`turn alerts on or off and choose the cadence`).option(`--on`,`enable alerts`).option(`--off`,`disable alerts`).option(`--cadence <minutes>`,`one of ${m.join(`, `)}`).action(async e=>{await O(e)})}function A(e){n([[`enabled`,e.enabled?`yes`:`no`],[`min score`,String(e.minScore)],[`site`,e.websiteId===null?`every site`:s(e.websiteId)],[`profanity`,e.profanity?`yes`:`no`]])}async function j(){let e=await T(`Reading mean marketer config…`,v);if(a()){o(`mean-marketer.config`,e,{experimental:!0});return}A(e),i(x)}async function M(t){if(t.on===!0&&t.off===!0)throw e(`Pass either --on or --off, not both`);let n={};if(t.on===!0&&(n.enabled=!0),t.off===!0&&(n.enabled=!1),t.minScore!==void 0&&(n.minScore=w(t.minScore)),t.site!==void 0){let e=t.site.trim();n.websiteId=e===``||e.toLowerCase()===`none`?null:e}if(t.profanity!==void 0&&(n.profanity=t.profanity),Object.keys(n).length===0)throw e(`Nothing to change.`,`Pass at least one of --on, --off, --min-score, --site, --profanity or --no-profanity`);let s=await T(`Saving mean marketer config…`,()=>h(n));if(a()){o(`mean-marketer.config.set`,s,{experimental:!0});return}r(`Saved`),A(s),i(x)}function N(e){n([[`enabled`,e.enabled?`yes`:`no`],[`min score`,String(e.minScore)],[`mood`,e.beMean?`mean, tier ${e.tier}`:`civil, tier ${e.tier}`],[`strikes`,String(e.strikes)]]),e.previous&&(t(``),t(`previous opportunity`),n([[`id`,e.previous.id],[`status`,e.previous.status],[`triaged`,e.previous.triaged?`yes`:`no`],[`outstanding`,`${e.previous.hoursOutstanding}h`]],` `)),e.opportunity?(t(``),t(`new opportunity`),n([[`id`,e.opportunity.id],[`title`,e.opportunity.title??`—`],[`source`,e.opportunity.subreddit?`r/${e.opportunity.subreddit}`:e.opportunity.source],[`keyword`,e.opportunity.keyword??`—`],[`score`,e.opportunity.relevanceScore===null?`—`:String(e.opportunity.relevanceScore)],[`url`,e.opportunity.url??`—`]],` `),e.opportunity.relevanceReason&&(t(``),t(` ${e.opportunity.relevanceReason}`))):e.noNewOpportunity&&(t(``),t(`No new opportunity above the minimum score.`)),e.message&&(t(``),t(e.message))}async function P(){let e=await T(`Polling…`,y);if(a()){o(`mean-marketer.poll`,e,{experimental:!0});return}N(e),i(`${x}; this call advances the strike state`)}async function F(){let e=await T(`Resetting…`,b);if(a()){o(`mean-marketer.reset`,e,{experimental:!0});return}e.reset?r(`Strike state reset`):t(`Nothing to reset.`),i(x)}function I(e){let t=e.command(`mean-marketer`,{hidden:!0}).alias(`mm`).description(`nag yourself into replying (${x})`);t.command(`config`).description(`show the mean marketer config`).action(async()=>{await j()}).command(`set`).description(`change the mean marketer config`).option(`--on`,`enable it`).option(`--off`,`disable it`).option(`--min-score <n>`,`only nag about mentions scoring this or higher, ${d} to ${p}`).option(`--site <id>`,`restrict it to one site, or "none" for every site`).option(`--profanity`,`allow profanity`).option(`--no-profanity`,`keep it clean`).action(async e=>{await M(e)}),t.command(`poll`).description(`ask for the next opportunity and advance the strike state`).action(async()=>{await P()}),t.command(`reset`).description(`clear the strike state`).action(async()=>{await F()})}export{C as assertCadence,w as assertMinScore,S as formatCadence,k as registerAlertCommands,I as registerMeanMarketerCommands};
@@ -1,3 +1,3 @@
1
- import{n as e,t}from"./exit-codes-IaZq17dv.js";import{f as n,n as r}from"./errors-Dkv23Z0t.js";import{i}from"./version-CFnbqWhw.js";import{S as a,x as o}from"./config-Bg2ls0gu.js";import{t as s}from"./product-CXL7Ga4M.js";import{readFile as c}from"node:fs/promises";const l=[`GET`,`POST`,`PATCH`,`PUT`,`DELETE`,`HEAD`],u=(e,t)=>[...t,e];async function d(){let e=[];for await(let t of process.stdin)e.push(t);return Buffer.concat(e).toString(`utf8`)}function f(e){let t=new URLSearchParams;for(let r of e){let e=r.indexOf(`=`);if(e<=0)throw n(`--query expects key=value, got "${r}".`,`${s.binName} api /mentions --query limit=5 --query statuses=NEW`);t.append(r.slice(0,e),r.slice(e+1))}return t}function p(e){let t={};for(let r of e){let e=r.indexOf(`:`);if(e<=0)throw n(`--header expects "Name: value", got "${r}".`);let i=r.slice(0,e).trim();if(i.toLowerCase()===`authorization`)throw n(`Authorization comes from the resolved profile and cannot be overridden.`,`Use --token or --profile to change which token is sent.`);t[i]=r.slice(e+1).trim()}return t}async function m(e,t,r){if(e!==void 0&&t!==void 0)throw n(`Pass either --data or --data-file, not both.`);let i;if(t!==void 0)i=t===`-`?await d():await c(t,`utf8`);else if(e!==void 0)i=e===`@-`?await d():e.startsWith(`@`)?await c(e.slice(1),`utf8`):e;else if(r!==`GET`&&r!==`HEAD`&&!process.stdin.isTTY){let e=await d();i=e.trim()===``?void 0:e}if(i!==void 0){try{JSON.parse(i)}catch{throw n(`The request body is not valid JSON.`)}return i}}function h(c){c.command(`api`).argument(`<path>`,`API path such as /mentions, or an HTTP method when a path follows`).argument(`[pathAfterMethod]`,`API path, when the first argument is an HTTP method`).description(`send an authenticated request to the ${s.displayName} API`).option(`-X, --method <method>`,`HTTP method`,`GET`).option(`-q, --query <key=value>`,`query parameter, repeat the key for arrays`,u,[]).option(`-d, --data <json|@file>`,`request body, @- reads stdin`).option(`--data-file <path>`,`request body read from a file, - reads stdin`).option(`-H, --header <name:value>`,`extra request header, repeatable`,u,[]).option(`-i, --include`,`print the status and response headers to stderr`).action(async(c,u,d)=>{let h=d.method.toUpperCase(),g=c;if(u!==void 0){if(!l.includes(c.toUpperCase()))throw n(`"${c}" is not an HTTP method.`,`Methods: ${l.join(`, `)}`);h=c.toUpperCase(),g=u}if(!l.includes(h))throw n(`"${d.method}" is not an HTTP method.`,`Methods: ${l.join(`, `)}`);if(/^[a-z][a-z0-9+.-]*:\/\//i.test(g))throw n(`api takes a path, not a URL.`,`This CLI only ever talks to the resolved API host. Try: ${s.binName} api /mentions`);let _=a(),v=f(d.query).toString(),y=`${_.apiUrl}${g.startsWith(`/`)?g:`/${g}`}${v?`?${v}`:``}`,b=await m(d.data,d.dataFile,h),x=o(),S={Accept:`application/json`,"User-Agent":i(s.id),...p(d.header),Authorization:`Bearer ${_.token}`};b!==void 0&&(S[`Content-Type`]=`application/json`),x&&(S[`x-language`]=x);let C;try{C=await fetch(y,{method:h,headers:S,body:b,signal:AbortSignal.timeout(12e4)})}catch(e){throw new r(`Could not reach ${_.apiUrl}: ${e instanceof Error?e.message:String(e)}`,{exitCode:t.NETWORK,cause:e})}if(d.include){process.stderr.write(`HTTP ${C.status} ${C.statusText}\n`);for(let[e,t]of[...C.headers].sort())process.stderr.write(`${e}: ${t}\n`);process.stderr.write(`
1
+ import{n as e,t}from"./exit-codes-IaZq17dv.js";import{f as n,n as r}from"./errors-Dkv23Z0t.js";import{i}from"./version-BPszCYbY.js";import{S as a,x as o}from"./config-Bg2ls0gu.js";import{t as s}from"./product-CXL7Ga4M.js";import{readFile as c}from"node:fs/promises";const l=[`GET`,`POST`,`PATCH`,`PUT`,`DELETE`,`HEAD`],u=(e,t)=>[...t,e];async function d(){let e=[];for await(let t of process.stdin)e.push(t);return Buffer.concat(e).toString(`utf8`)}function f(e){let t=new URLSearchParams;for(let r of e){let e=r.indexOf(`=`);if(e<=0)throw n(`--query expects key=value, got "${r}".`,`${s.binName} api /mentions --query limit=5 --query statuses=NEW`);t.append(r.slice(0,e),r.slice(e+1))}return t}function p(e){let t={};for(let r of e){let e=r.indexOf(`:`);if(e<=0)throw n(`--header expects "Name: value", got "${r}".`);let i=r.slice(0,e).trim();if(i.toLowerCase()===`authorization`)throw n(`Authorization comes from the resolved profile and cannot be overridden.`,`Use --token or --profile to change which token is sent.`);t[i]=r.slice(e+1).trim()}return t}async function m(e,t,r){if(e!==void 0&&t!==void 0)throw n(`Pass either --data or --data-file, not both.`);let i;if(t!==void 0)i=t===`-`?await d():await c(t,`utf8`);else if(e!==void 0)i=e===`@-`?await d():e.startsWith(`@`)?await c(e.slice(1),`utf8`):e;else if(r!==`GET`&&r!==`HEAD`&&!process.stdin.isTTY){let e=await d();i=e.trim()===``?void 0:e}if(i!==void 0){try{JSON.parse(i)}catch{throw n(`The request body is not valid JSON.`)}return i}}function h(c){c.command(`api`).argument(`<path>`,`API path such as /mentions, or an HTTP method when a path follows`).argument(`[pathAfterMethod]`,`API path, when the first argument is an HTTP method`).description(`send an authenticated request to the ${s.displayName} API`).option(`-X, --method <method>`,`HTTP method`,`GET`).option(`-q, --query <key=value>`,`query parameter, repeat the key for arrays`,u,[]).option(`-d, --data <json|@file>`,`request body, @- reads stdin`).option(`--data-file <path>`,`request body read from a file, - reads stdin`).option(`-H, --header <name:value>`,`extra request header, repeatable`,u,[]).option(`-i, --include`,`print the status and response headers to stderr`).action(async(c,u,d)=>{let h=d.method.toUpperCase(),g=c;if(u!==void 0){if(!l.includes(c.toUpperCase()))throw n(`"${c}" is not an HTTP method.`,`Methods: ${l.join(`, `)}`);h=c.toUpperCase(),g=u}if(!l.includes(h))throw n(`"${d.method}" is not an HTTP method.`,`Methods: ${l.join(`, `)}`);if(/^[a-z][a-z0-9+.-]*:\/\//i.test(g))throw n(`api takes a path, not a URL.`,`This CLI only ever talks to the resolved API host. Try: ${s.binName} api /mentions`);let _=a(),v=f(d.query).toString(),y=`${_.apiUrl}${g.startsWith(`/`)?g:`/${g}`}${v?`?${v}`:``}`,b=await m(d.data,d.dataFile,h),x=o(),S={Accept:`application/json`,"User-Agent":i(s.id),...p(d.header),Authorization:`Bearer ${_.token}`};b!==void 0&&(S[`Content-Type`]=`application/json`),x&&(S[`x-language`]=x);let C;try{C=await fetch(y,{method:h,headers:S,body:b,signal:AbortSignal.timeout(12e4)})}catch(e){throw new r(`Could not reach ${_.apiUrl}: ${e instanceof Error?e.message:String(e)}`,{exitCode:t.NETWORK,cause:e})}if(d.include){process.stderr.write(`HTTP ${C.status} ${C.statusText}\n`);for(let[e,t]of[...C.headers].sort())process.stderr.write(`${e}: ${t}\n`);process.stderr.write(`
2
2
  `)}let w=await C.text();if(!C.ok){let t=`${h} ${g} failed with ${C.status}`,n=null;try{let e=JSON.parse(w);n=e,Array.isArray(e.message)?t=e.message.join(`; `):typeof e.message==`string`&&(t=e.message)}catch{w.trim()!==``&&(t=w.trim())}throw new r(t,{exitCode:e(C.status),details:n})}if(w===``)return;let T=w;if(process.stdout.isTTY)try{T=JSON.stringify(JSON.parse(w),null,2)}catch{T=w}process.stdout.write(T.endsWith(`
3
3
  `)?T:`${T}\n`)})}export{h as registerApiCommand};
@@ -1 +1 @@
1
- import{t as e}from"./exit-codes-IaZq17dv.js";import{n as t}from"./errors-Dkv23Z0t.js";import"./version-CFnbqWhw.js";import"./color-BbAK7_Y7.js";import{c as n,f as r,g as i,i as a,p as o}from"./output-uP7GrsdR.js";import{C as s,F as c,I as l,L as u,M as d,N as f,P as p,S as m,b as h,l as g,m as _,p as v,s as y,v as b,x}from"./config-Bg2ls0gu.js";import{t as S}from"./product-CXL7Ga4M.js";import{c as C,l as w}from"./http-Bryxg3iu.js";import{n as T,r as E}from"./prompt-DR68wwvQ.js";import{t as D}from"./open-url-CovrlP9b.js";import{_ as O}from"./client-jT4mvZ9E.js";const k=S.tokenPrefixes[0];function A(e){return e.map(e=>e.domain).sort()}function j(e){return e.reduce((e,t)=>e+t.keywords.filter(e=>e.status===`ACTIVE`).length,0)}async function M(){let e=[];for await(let t of process.stdin)e.push(t);return Buffer.concat(e).toString(`utf8`)}function N(n){if(S.tokenPrefixes.some(e=>n.startsWith(e)))return;if(n.split(`.`).length===3)throw new t(`That looks like an OAuth JWT, not an API token.`,{exitCode:e.AUTH,code:`unsupported_token`,hint:`OAuth login is not supported yet. Create an API token at ${S.tokensUrl}`});let r=n.indexOf(`_`),i=r>0?n.slice(0,r+1):``;throw new t(i?`That token starts with ${i}. ${S.binName} expects ${k}.`:`That does not look like a ${S.displayName} API token, which starts with ${k}.`,{exitCode:e.AUTH,code:`wrong_token_prefix`,hint:`Create one at ${S.tokensUrl}`})}async function P(n,r){if(n){let n=(await M()).trim();if(n===``)throw new t(`Nothing arrived on stdin.`,{exitCode:e.USAGE,code:`empty_stdin`,hint:`echo "$${S.envPrefix}_API_TOKEN" | ${S.binName} login --token-stdin`});return n}return r.token&&r.token.trim()!==``?r.token.trim():(await E(`Token (starts with ${k})`,{hint:`Pass --token-stdin and pipe the token in, or set ${S.envPrefix}_API_TOKEN`})).trim()}function F(E){E.command(`login`).description(`store a ${S.displayName} API token on this machine`).option(`--token-stdin`,`read the token from stdin instead of prompting`).option(`--name <label>`,`human label stored with the profile`).action(async e=>{let t=v(),n=s(),c=h(t,p(n)?.apiUrl).url;!e.tokenStdin&&!t.token&&(a(`Opening ${S.tokensUrl} in your browser.`),a(`Create a token, then paste it here.`),a(`API tokens need a plan with API access, so the token page errors on the free plan.`),D(S.tokensUrl));let d=await P(!!e.tokenStdin,t);N(d),C({profile:{name:n,token:d,tokenSource:`flag`,apiUrl:c,defaults:b(n)},debug:_(),language:x(),quiet:t.quiet===!0});let{websites:f}=await O(),m=A(f),g=j(f);u(n,{token:d,apiUrl:c,label:e.name},{makeCurrent:!0}),o(`login`,{profile:n,apiUrl:c,tokenPrefix:l(d),label:e.name??null,sites:f.length,domains:m,activeKeywords:g,credentialsPath:y()}),i(`Token valid`),r([[`profile`,n],...e.name?[[`label`,e.name]]:[],[`api`,c],[`sites`,`${f.length} monitored`],...m.length>0?[[`domains`,m.join(`, `)]]:[],[`keywords`,`${g} active`],[`stored in`,`${y()} (0600)`]])}),E.command(`logout`).description(`remove a stored token`).option(`--all`,`remove every profile`).action(async r=>{let i=v(),a=c();if(a.length===0)throw new t(`There are no stored profiles to remove.`,{exitCode:e.NOT_FOUND,code:`no_profiles`,hint:`${S.binName} login`});let l=s(),u=r.all?a.map(e=>e.name):[l];if(!r.all&&!a.some(e=>e.name===l))throw new t(`No profile named "${l}".`,{exitCode:e.NOT_FOUND,code:`unknown_profile`,hint:`Stored profiles: ${a.map(e=>e.name).join(`, `)}`});if(!await T(r.all?`Remove all ${u.length} profiles?`:`Remove profile "${l}"?`,{assumeYes:i.yes===!0,initialValue:!1})){n(`Nothing removed.`);return}r.all?d():f(l),o(`logout`,{removed:u}),n(r.all?`Removed all ${u.length} profiles.`:`Removed profile "${l}".`),n(`The token is still valid, revoke it at ${S.tokensUrl}`)}),E.command(`whoami`).description(`show which token is in use and what it can see`).action(async()=>{let e=m(),{websites:t}=await O(),n=A(t),i=j(t),s=w();o(`whoami`,{profile:e.name,tokenPrefix:l(e.token),tokenSource:e.tokenSource,apiUrl:e.apiUrl,sites:t.length,domains:n,activeKeywords:i},s?.limit!==void 0&&s.remaining!==void 0?{rateLimit:{limit:s.limit,remaining:s.remaining,resetSeconds:s.reset??0}}:void 0),r([[`profile`,e.name],[`token`,`${l(e.token)} (from ${g(e.tokenSource)})`],[`api`,e.apiUrl],[`sites`,`${t.length} ${t.length===1?`site`:`sites`}${n.length>0?` (${n.join(`, `)})`:``}`],[`keywords`,`${i} active`],...typeof e.defaults.defaultSite==`string`?[[`default site`,`${e.defaults.defaultSite} (from config.json)`]]:[],...s?.remaining!==void 0&&s.limit!==void 0?[[`limits`,`${s.remaining} of ${s.limit} requests left this minute`]]:[]]),a(`There is no /me endpoint, so this is read back from your monitored sites.`)})}export{N as assertTokenShape,F as registerAuthCommands};
1
+ import{t as e}from"./exit-codes-IaZq17dv.js";import{n as t}from"./errors-Dkv23Z0t.js";import"./version-BPszCYbY.js";import"./color-BbAK7_Y7.js";import{c as n,f as r,g as i,i as a,p as o}from"./output-uP7GrsdR.js";import{C as s,F as c,I as l,L as u,M as d,N as f,P as p,S as m,b as h,l as g,m as _,p as v,s as y,v as b,x}from"./config-Bg2ls0gu.js";import{t as S}from"./product-CXL7Ga4M.js";import{c as C,l as w}from"./http-ZFrs1UcT.js";import{n as T,r as E}from"./prompt-DR68wwvQ.js";import{t as D}from"./open-url-CovrlP9b.js";import{_ as O}from"./client-CVesEwEU.js";const k=S.tokenPrefixes[0];function A(e){return e.map(e=>e.domain).sort()}function j(e){return e.reduce((e,t)=>e+t.keywords.filter(e=>e.status===`ACTIVE`).length,0)}async function M(){let e=[];for await(let t of process.stdin)e.push(t);return Buffer.concat(e).toString(`utf8`)}function N(n){if(S.tokenPrefixes.some(e=>n.startsWith(e)))return;if(n.split(`.`).length===3)throw new t(`That looks like an OAuth JWT, not an API token.`,{exitCode:e.AUTH,code:`unsupported_token`,hint:`OAuth login is not supported yet. Create an API token at ${S.tokensUrl}`});let r=n.indexOf(`_`),i=r>0?n.slice(0,r+1):``;throw new t(i?`That token starts with ${i}. ${S.binName} expects ${k}.`:`That does not look like a ${S.displayName} API token, which starts with ${k}.`,{exitCode:e.AUTH,code:`wrong_token_prefix`,hint:`Create one at ${S.tokensUrl}`})}async function P(n,r){if(n){let n=(await M()).trim();if(n===``)throw new t(`Nothing arrived on stdin.`,{exitCode:e.USAGE,code:`empty_stdin`,hint:`echo "$${S.envPrefix}_API_TOKEN" | ${S.binName} login --token-stdin`});return n}return r.token&&r.token.trim()!==``?r.token.trim():(await E(`Token (starts with ${k})`,{hint:`Pass --token-stdin and pipe the token in, or set ${S.envPrefix}_API_TOKEN`})).trim()}function F(E){E.command(`login`).description(`store a ${S.displayName} API token on this machine`).option(`--token-stdin`,`read the token from stdin instead of prompting`).option(`--name <label>`,`human label stored with the profile`).action(async e=>{let t=v(),n=s(),c=h(t,p(n)?.apiUrl).url;!e.tokenStdin&&!t.token&&(a(`Opening ${S.tokensUrl} in your browser.`),a(`Create a token, then paste it here.`),a(`API tokens need a plan with API access, so the token page errors on the free plan.`),D(S.tokensUrl));let d=await P(!!e.tokenStdin,t);N(d),C({profile:{name:n,token:d,tokenSource:`flag`,apiUrl:c,defaults:b(n)},debug:_(),language:x(),quiet:t.quiet===!0});let{websites:f}=await O(),m=A(f),g=j(f);u(n,{token:d,apiUrl:c,label:e.name},{makeCurrent:!0}),o(`login`,{profile:n,apiUrl:c,tokenPrefix:l(d),label:e.name??null,sites:f.length,domains:m,activeKeywords:g,credentialsPath:y()}),i(`Token valid`),r([[`profile`,n],...e.name?[[`label`,e.name]]:[],[`api`,c],[`sites`,`${f.length} monitored`],...m.length>0?[[`domains`,m.join(`, `)]]:[],[`keywords`,`${g} active`],[`stored in`,`${y()} (0600)`]])}),E.command(`logout`).description(`remove a stored token`).option(`--all`,`remove every profile`).action(async r=>{let i=v(),a=c();if(a.length===0)throw new t(`There are no stored profiles to remove.`,{exitCode:e.NOT_FOUND,code:`no_profiles`,hint:`${S.binName} login`});let l=s(),u=r.all?a.map(e=>e.name):[l];if(!r.all&&!a.some(e=>e.name===l))throw new t(`No profile named "${l}".`,{exitCode:e.NOT_FOUND,code:`unknown_profile`,hint:`Stored profiles: ${a.map(e=>e.name).join(`, `)}`});if(!await T(r.all?`Remove all ${u.length} profiles?`:`Remove profile "${l}"?`,{assumeYes:i.yes===!0,initialValue:!1})){n(`Nothing removed.`);return}r.all?d():f(l),o(`logout`,{removed:u}),n(r.all?`Removed all ${u.length} profiles.`:`Removed profile "${l}".`),n(`The token is still valid, revoke it at ${S.tokensUrl}`)}),E.command(`whoami`).description(`show which token is in use and what it can see`).action(async()=>{let e=m(),{websites:t}=await O(),n=A(t),i=j(t),s=w();o(`whoami`,{profile:e.name,tokenPrefix:l(e.token),tokenSource:e.tokenSource,apiUrl:e.apiUrl,sites:t.length,domains:n,activeKeywords:i},s?.limit!==void 0&&s.remaining!==void 0?{rateLimit:{limit:s.limit,remaining:s.remaining,resetSeconds:s.reset??0}}:void 0),r([[`profile`,e.name],[`token`,`${l(e.token)} (from ${g(e.tokenSource)})`],[`api`,e.apiUrl],[`sites`,`${t.length} ${t.length===1?`site`:`sites`}${n.length>0?` (${n.join(`, `)})`:``}`],[`keywords`,`${i} active`],...typeof e.defaults.defaultSite==`string`?[[`default site`,`${e.defaults.defaultSite} (from config.json)`]]:[],...s?.remaining!==void 0&&s.limit!==void 0?[[`limits`,`${s.remaining} of ${s.limit} requests left this minute`]]:[]]),a(`There is no /me endpoint, so this is read back from your monitored sites.`)})}export{N as assertTokenShape,F as registerAuthCommands};
package/dist/cli.js CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
2
  const e=`22.12.0`;function t(e,t){let n=e.split(`.`),r=t.split(`.`);for(let e=0;e<3;e+=1){let t=Number.parseInt(n[e]??`0`,10)||0,i=Number.parseInt(r[e]??`0`,10)||0;if(t!==i)return t<i}return!1}t(process.versions.node,e)&&(process.stderr.write(`redreplier needs Node ${e} or newer, this is Node ${process.versions.node}. Install a current Node from https://nodejs.org and try again.
3
- `),process.exit(2));const{Command:n,Option:r}=await import(`./esm-CIPTesEn.js`),{ExitCode:i}=await import(`./exit-codes-Dth9pkcT.js`),{PRODUCT:a,setGlobalOptions:o}=await import(`./config-_SbTs7a5.js`),{versionLine:s}=await import(`./version-BuvsdT20.js`),c=[[`-p, --profile <name>`,`credential profile to use`],[`--json`,`force machine-readable JSON output`],[`-q, --quiet`,`suppress spinners, hints and notices`],[`--no-color`,`strip ANSI colour from the output`],[`--debug`,`log every request to stderr`],[`--api-url <url>`,`override the API base URL`],[`--token <token>`,`use this token for one invocation`],[`-y, --yes`,`answer yes to every confirmation`],[`--no-input`,`never prompt, fail with exit 2 instead`],[`--lang <code>`,`language for the x-language header: en, fr, de, es, pt`],[`--full-ids`,`print identifiers in full instead of truncating`]],l=[`profile`,`json`,`quiet`,`color`,`debug`,`apiUrl`,`token`,`yes`,`input`,`lang`,`fullIds`],u=new Set([`-p`,`--profile`,`--api-url`,`--token`,`--lang`]),d=`--help-all`,f=[{names:[`login`,`logout`,`whoami`],load:async()=>(await import(`./auth-D19BQ05g.js`)).registerAuthCommands},{names:[`config`],load:async()=>(await import(`./config-DwEEtXDc.js`)).registerConfigCommands},{names:[`doctor`],load:async()=>(await import(`./doctor-HSsl2NYt.js`)).registerDoctorCommand},{names:[`completion`],load:async()=>(await import(`./completion-DueI7liE.js`)).registerCompletionCommand},{names:[`mcp`],load:async()=>(await import(`./mcp-9bwQeg1V.js`)).registerMcpCommand},{names:[`api`],load:async()=>(await import(`./api-BDXNkJhw.js`)).registerApiCommand},{names:[`open`],load:async()=>(await import(`./open-C4CQFd2q.js`)).registerOpenCommand},{names:[`site`,`sites`],load:async()=>(await import(`./site-Dr3rXpTi.js`)).registerSiteCommands},{names:[`keyword`,`keywords`,`kw`],load:async()=>(await import(`./keyword-De6XB38E.js`)).registerKeywordCommands},{names:[`mention`,`mentions`],load:async()=>(await import(`./mention-vhJcPP7M.js`)).registerMentionCommands},{names:[`alerts`,`alert`],load:async()=>(await import(`./alert-DU80w2Ar.js`)).registerAlertCommands},{names:[`mean-marketer`,`mm`],load:async()=>(await import(`./alert-DU80w2Ar.js`)).registerMeanMarketerCommands}];function p(e){for(let t=2;t<e.length;t+=1){let n=e[t];if(n===`--`)return;if(n.startsWith(`-`)){!n.includes(`=`)&&u.has(n)&&(t+=1);continue}return n}}function m(e,t){let n=e.slice(2);return n.includes(`-h`)||n.includes(`--help`)||n.includes(d)?!0:t===void 0?!n.includes(`-V`)&&!n.includes(`--version`):t===`help`||t===`completion`?!0:!f.some(e=>e.names.includes(t))}async function h(e,t){let n=p(t),r=m(t,n)?f:f.filter(e=>e.names.includes(n));for(let t of r)(await t.load())(e)}function g(e,t){for(let n of e.options)if(n.attributeName()===t.attributeName()||t.short&&(n.short===t.short||n.long===t.short)||t.long&&(n.long===t.long||n.short===t.long))return!0;return!1}function _(e){for(let[t,n]of c){let i=new r(t,n).hideHelp(e.parent!==null);g(e,i)||e.addOption(i)}for(let t of e.commands)_(t)}function v(e){let t=[];for(let n=e;n;n=n.parent)t.unshift(n);let n={};for(let e of t)for(let t of l){let r=e.getOptionValueSource(t);(r===`cli`||r===`env`)&&(n[t]=e.getOptionValue(t))}return n.color===void 0&&(n.color=!0),n.input===void 0&&(n.input=!!process.stdin.isTTY),n}function y(e){let t=[];for(let n=e;n&&n.parent;n=n.parent)t.unshift(n.name());return t.join(`.`)||e.name()}let b=a.binName,x={},S=``;function C(e){if(!(e instanceof Error))return!1;let t=e.code;return typeof t==`string`&&t.startsWith(`commander.`)}async function w(e){let{isMachine:t,printError:n}=await import(`./output-CwNjSyRl.js`);if(C(e)){if(e.code===`commander.version`||e.code===`commander.helpDisplayed`)return process.stdout.write(S),i.OK;if(e.code===`commander.help`)return process.stderr.write(S),i.USAGE;if(t()){let{usageError:t}=await import(`./errors-DZ-S25mn.js`);return n(t(S.trim()||e.message),b)}return process.stderr.write(S),i.USAGE}return process.stderr.write(S),n(e,b)}process.on(`SIGINT`,()=>{process.stderr.write(`
4
- `),process.exit(i.CANCELLED)});const T=new n;T.name(a.binName).description(`${a.displayName} from your terminal`).version(s(a.binName),`-V, --version`,`print the version, node and platform`).helpOption(`-h, --help`,`show help for a command`).showSuggestionAfterError(!0).enablePositionalOptions().exitOverride().configureOutput({writeErr:e=>{S+=e},writeOut:e=>{S+=e}}),T.hook(`preAction`,async(e,t)=>{let n=v(t),r=y(t);b=r,x=n,o(n);let{detectColorEnabled:i,setColorEnabled:s}=await import(`./color-D6__4GPX.js`),{setInteractive:c}=await import(`./prompt-BMmbLZHM.js`),{configureHttp:l}=await import(`./http-DAEdGtuv.js`);s(i({noColor:n.color===!1})),E({json:n.json,quiet:n.quiet,fullIds:n.fullIds,command:r,envPrefix:a.envPrefix}),c(n.input!==!1),l(n)});for(let[e,t]of c)T.addOption(new r(e,t));T.addOption(new r(d,`show help including the experimental commands`)),await h(T,process.argv),_(T);const{initOutput:E}=await import(`./output-CwNjSyRl.js`);E({json:process.argv.includes(`--json`),envPrefix:a.envPrefix}),process.argv.includes(d)&&(T.configureHelp({visibleCommands:e=>[...e.commands]}),process.stdout.write(T.helpInformation()),process.exit(i.OK));try{await T.parseAsync(process.argv),process.stdout.write(S),S=``;let{runUpdateCheck:e}=await import(`./update-check-CIiMuXEG.js`);await e({quiet:x.quiet===!0}),process.exitCode===void 0&&(process.exitCode=i.OK)}catch(e){process.exitCode=await w(e)}export{};
3
+ `),process.exit(2));const{Command:n,Option:r}=await import(`./esm-CIPTesEn.js`),{ExitCode:i}=await import(`./exit-codes-Dth9pkcT.js`),{PRODUCT:a,setGlobalOptions:o}=await import(`./config-_SbTs7a5.js`),{versionLine:s}=await import(`./version-BmirVYxq.js`),c=[[`-p, --profile <name>`,`credential profile to use`],[`--json`,`force machine-readable JSON output`],[`-q, --quiet`,`suppress spinners, hints and notices`],[`--no-color`,`strip ANSI colour from the output`],[`--debug`,`log every request to stderr`],[`--api-url <url>`,`override the API base URL`],[`--token <token>`,`use this token for one invocation`],[`-y, --yes`,`answer yes to every confirmation`],[`--no-input`,`never prompt, fail with exit 2 instead`],[`--lang <code>`,`language for the x-language header: en, fr, de, es, pt`],[`--full-ids`,`print identifiers in full instead of truncating`]],l=[`profile`,`json`,`quiet`,`color`,`debug`,`apiUrl`,`token`,`yes`,`input`,`lang`,`fullIds`],u=new Set([`-p`,`--profile`,`--api-url`,`--token`,`--lang`]),d=`--help-all`,f=[{names:[`login`,`logout`,`whoami`],load:async()=>(await import(`./auth-BHJTFHTY.js`)).registerAuthCommands},{names:[`config`],load:async()=>(await import(`./config-DwEEtXDc.js`)).registerConfigCommands},{names:[`doctor`],load:async()=>(await import(`./doctor-DLsQi2B2.js`)).registerDoctorCommand},{names:[`completion`],load:async()=>(await import(`./completion-DueI7liE.js`)).registerCompletionCommand},{names:[`mcp`],load:async()=>(await import(`./mcp-9bwQeg1V.js`)).registerMcpCommand},{names:[`api`],load:async()=>(await import(`./api-COvamcn1.js`)).registerApiCommand},{names:[`open`],load:async()=>(await import(`./open-C4CQFd2q.js`)).registerOpenCommand},{names:[`site`,`sites`],load:async()=>(await import(`./site-DfMgDeXm.js`)).registerSiteCommands},{names:[`keyword`,`keywords`,`kw`],load:async()=>(await import(`./keyword-CiFeVNhI.js`)).registerKeywordCommands},{names:[`mention`,`mentions`],load:async()=>(await import(`./mention-07d3f4jl.js`)).registerMentionCommands},{names:[`alerts`,`alert`],load:async()=>(await import(`./alert-CRWrCjRD.js`)).registerAlertCommands},{names:[`mean-marketer`,`mm`],load:async()=>(await import(`./alert-CRWrCjRD.js`)).registerMeanMarketerCommands}];function p(e){for(let t=2;t<e.length;t+=1){let n=e[t];if(n===`--`)return;if(n.startsWith(`-`)){!n.includes(`=`)&&u.has(n)&&(t+=1);continue}return n}}function m(e,t){let n=e.slice(2);return n.includes(`-h`)||n.includes(`--help`)||n.includes(d)?!0:t===void 0?!n.includes(`-V`)&&!n.includes(`--version`):t===`help`||t===`completion`?!0:!f.some(e=>e.names.includes(t))}async function h(e,t){let n=p(t),r=m(t,n)?f:f.filter(e=>e.names.includes(n));for(let t of r)(await t.load())(e)}function g(e,t){for(let n of e.options)if(n.attributeName()===t.attributeName()||t.short&&(n.short===t.short||n.long===t.short)||t.long&&(n.long===t.long||n.short===t.long))return!0;return!1}function _(e){for(let[t,n]of c){let i=new r(t,n).hideHelp(e.parent!==null);g(e,i)||e.addOption(i)}for(let t of e.commands)_(t)}function v(e){let t=[];for(let n=e;n;n=n.parent)t.unshift(n);let n={};for(let e of t)for(let t of l){let r=e.getOptionValueSource(t);(r===`cli`||r===`env`)&&(n[t]=e.getOptionValue(t))}return n.color===void 0&&(n.color=!0),n.input===void 0&&(n.input=!!process.stdin.isTTY),n}function y(e){let t=[];for(let n=e;n&&n.parent;n=n.parent)t.unshift(n.name());return t.join(`.`)||e.name()}let b=a.binName,x={},S=``;function C(e){if(!(e instanceof Error))return!1;let t=e.code;return typeof t==`string`&&t.startsWith(`commander.`)}async function w(e){let{isMachine:t,printError:n}=await import(`./output-CwNjSyRl.js`);if(C(e)){if(e.code===`commander.version`||e.code===`commander.helpDisplayed`)return process.stdout.write(S),i.OK;if(e.code===`commander.help`)return process.stderr.write(S),i.USAGE;if(t()){let{usageError:t}=await import(`./errors-DZ-S25mn.js`);return n(t(S.trim()||e.message),b)}return process.stderr.write(S),i.USAGE}return process.stderr.write(S),n(e,b)}process.on(`SIGINT`,()=>{process.stderr.write(`
4
+ `),process.exit(i.CANCELLED)});const T=new n;T.name(a.binName).description(`${a.displayName} from your terminal`).version(s(a.binName),`-V, --version`,`print the version, node and platform`).helpOption(`-h, --help`,`show help for a command`).showSuggestionAfterError(!0).enablePositionalOptions().exitOverride().configureOutput({writeErr:e=>{S+=e},writeOut:e=>{S+=e}}),T.hook(`preAction`,async(e,t)=>{let n=v(t),r=y(t);b=r,x=n,o(n);let{detectColorEnabled:i,setColorEnabled:s}=await import(`./color-D6__4GPX.js`),{setInteractive:c}=await import(`./prompt-BMmbLZHM.js`),{configureHttp:l}=await import(`./http-CzW-4IIw.js`);s(i({noColor:n.color===!1})),E({json:n.json,quiet:n.quiet,fullIds:n.fullIds,command:r,envPrefix:a.envPrefix}),c(n.input!==!1),l(n)});for(let[e,t]of c)T.addOption(new r(e,t));T.addOption(new r(d,`show help including the experimental commands`)),await h(T,process.argv),_(T);const{initOutput:E}=await import(`./output-CwNjSyRl.js`);E({json:process.argv.includes(`--json`),envPrefix:a.envPrefix}),process.argv.includes(d)&&(T.configureHelp({visibleCommands:e=>[...e.commands]}),process.stdout.write(T.helpInformation()),process.exit(i.OK));try{await T.parseAsync(process.argv),process.stdout.write(S),S=``;let{runUpdateCheck:e}=await import(`./update-check-ZHdg1yHI.js`);await e({quiet:x.quiet===!0}),process.exitCode===void 0&&(process.exitCode=i.OK)}catch(e){process.exitCode=await w(e)}export{};
@@ -1 +1 @@
1
- import{d as e}from"./http-Bryxg3iu.js";const t=e=>encodeURIComponent(e),n=()=>e({method:`GET`,path:`/websites`}),r=n=>e({method:`GET`,path:`/websites/${t(n)}`}),i=t=>e({method:`POST`,path:`/websites`,body:t}),a=(n,r)=>e({method:`PATCH`,path:`/websites/${t(n)}`,body:r}),o=n=>e({method:`DELETE`,path:`/websites/${t(n)}`}),s=t=>e({method:`POST`,path:`/websites/analyze-description`,body:t}),c=(n,r)=>e({method:`POST`,path:`/websites/${t(n)}/keywords`,body:r}),l=(n,r)=>e({method:`PATCH`,path:`/keywords/${t(n)}`,body:r}),u=n=>e({method:`POST`,path:`/keywords/${t(n)}/disable`,idempotent:!0}),d=n=>e({method:`POST`,path:`/keywords/${t(n)}/enable`,idempotent:!0}),f=n=>e({method:`DELETE`,path:`/keywords/${t(n)}`}),p=()=>e({method:`POST`,path:`/keywords/activate-pending`,idempotent:!0}),m=()=>e({method:`GET`,path:`/keywords/activate-pending/preview`}),h=t=>e({method:`GET`,path:`/keywords/billing-preview`,query:t}),g=()=>e({method:`GET`,path:`/keywords/change-usage`}),_=(t={})=>e({method:`GET`,path:`/mentions`,query:t}),v=(t={})=>e({method:`GET`,path:`/mentions/count`,query:t}),y=(n,r)=>e({method:`PATCH`,path:`/mentions/${t(n)}/status`,body:r}),b=n=>e({method:`POST`,path:`/mentions/${t(n)}/explain`,idempotent:!0}),x=()=>e({method:`GET`,path:`/alert-settings`}),S=t=>e({method:`PUT`,path:`/alert-settings`,body:t}),C=()=>e({method:`GET`,path:`/mean-marketer/config`}),w=t=>e({method:`PUT`,path:`/mean-marketer/config`,body:t}),T=()=>e({method:`POST`,path:`/mean-marketer/poll`}),E=()=>e({method:`POST`,path:`/mean-marketer/reset`,idempotent:!0});export{w as C,S,a as T,n as _,i as a,h as b,u as c,b as d,x as f,_ as g,r as h,v as i,l,C as m,c as n,f as o,g as p,s as r,o as s,p as t,d as u,T as v,y as w,E as x,m as y};
1
+ import{d as e}from"./http-ZFrs1UcT.js";const t=e=>encodeURIComponent(e),n=()=>e({method:`GET`,path:`/websites`}),r=n=>e({method:`GET`,path:`/websites/${t(n)}`}),i=t=>e({method:`POST`,path:`/websites`,body:t}),a=(n,r)=>e({method:`PATCH`,path:`/websites/${t(n)}`,body:r}),o=n=>e({method:`DELETE`,path:`/websites/${t(n)}`}),s=t=>e({method:`POST`,path:`/websites/analyze-description`,body:t}),c=(n,r)=>e({method:`POST`,path:`/websites/${t(n)}/keywords`,body:r}),l=(n,r)=>e({method:`PATCH`,path:`/keywords/${t(n)}`,body:r}),u=n=>e({method:`POST`,path:`/keywords/${t(n)}/disable`,idempotent:!0}),d=n=>e({method:`POST`,path:`/keywords/${t(n)}/enable`,idempotent:!0}),f=n=>e({method:`DELETE`,path:`/keywords/${t(n)}`}),p=()=>e({method:`POST`,path:`/keywords/activate-pending`,idempotent:!0}),m=()=>e({method:`GET`,path:`/keywords/activate-pending/preview`}),h=t=>e({method:`GET`,path:`/keywords/billing-preview`,query:t}),g=()=>e({method:`GET`,path:`/keywords/change-usage`}),_=(t={})=>e({method:`GET`,path:`/mentions`,query:t}),v=(t={})=>e({method:`GET`,path:`/mentions/count`,query:t}),y=(n,r)=>e({method:`PATCH`,path:`/mentions/${t(n)}/status`,body:r}),b=n=>e({method:`POST`,path:`/mentions/${t(n)}/explain`,idempotent:!0}),x=()=>e({method:`GET`,path:`/alert-settings`}),S=t=>e({method:`PUT`,path:`/alert-settings`,body:t}),C=()=>e({method:`GET`,path:`/mean-marketer/config`}),w=t=>e({method:`PUT`,path:`/mean-marketer/config`,body:t}),T=()=>e({method:`POST`,path:`/mean-marketer/poll`}),E=()=>e({method:`POST`,path:`/mean-marketer/reset`,idempotent:!0});export{w as C,S,a as T,n as _,i as a,h as b,u as c,b as d,x as f,_ as g,r as h,v as i,l,C as m,c as n,f as o,g as p,s as r,o as s,p as t,d as u,T as v,y as w,E as x,m as y};
@@ -1 +1 @@
1
- import{t as e}from"./exit-codes-IaZq17dv.js";import"./errors-Dkv23Z0t.js";import{i as t,r as n}from"./version-CFnbqWhw.js";import{a as r,c as i,i as a,r as o}from"./color-BbAK7_Y7.js";import{c as s,d as c,o as l}from"./output-uP7GrsdR.js";import{A as u,I as d,S as f,b as p,c as m,i as h,j as g,l as _,o as v,p as y,s as b}from"./config-Bg2ls0gu.js";import{t as x}from"./product-CXL7Ga4M.js";import{a as S,o as C}from"./update-check-CkjowHze.js";import{statSync as w}from"node:fs";const T=`22.12.0`,E=(e,t,n,r=null)=>({id:e,status:t,detail:n,fix:r});function D(){let e=process.versions.node;return S(e,T)>=0?E(`node`,`pass`,`v${e} (>= ${T})`):E(`node`,`fail`,`v${e} is below ${T}`,`Install Node 22.12 or newer from https://nodejs.org`)}async function O(){let e;try{e=await C()}catch{return E(`cli`,`warn`,`${n} (could not reach the npm registry)`)}return e?S(e,n)>0?E(`cli`,`warn`,`${n} (${e} is published)`,`npm i -g ${x.npmPackage}`):E(`cli`,`pass`,`${n} (latest)`):E(`cli`,`warn`,`${n} (no published release to compare against)`)}function k(e){try{return w(e).mode&511}catch{return}}function A(){let e=h(),t=k(e);if(t===void 0)return E(`config dir`,`warn`,`${e} does not exist yet`,`${x.binName} login`);let n=t.toString(8).padStart(4,`0`);return process.platform!==`win32`&&t&63?E(`config dir`,`warn`,`${e} is mode ${n}`,`chmod 700 ${e}`):E(`config dir`,`pass`,`${e} (${n})`)}function j(){let e=v(),t=k(e);return t===void 0?E(`config file`,`warn`,`${e} does not exist yet`):E(`config file`,`pass`,`${e} (${t.toString(8).padStart(4,`0`)})`)}function M(){let e=b();if(!u())return E(`credentials`,`warn`,`${e} does not exist yet`,`${x.binName} login`);let t=g()??0,n=t.toString(8).padStart(4,`0`);return process.platform!==`win32`&&t&63?E(`credentials`,`fail`,`${e} is mode ${n}, other users can read your token`,`chmod 600 ${e}`):E(`credentials`,`pass`,`${e} (${n})`)}function N(){for(let e of[`HTTPS_PROXY`,`https_proxy`,`HTTP_PROXY`,`http_proxy`]){let t=process.env[e];if(t)return E(`proxy`,`warn`,`${e} is set to ${t}`)}return null}async function P(e,n){if(!n)return[E(`api`,`warn`,`skipped, no token to authenticate with`,`${x.binName} login`)];let r=Date.now(),i;try{i=await fetch(`${e}${x.verifyPath}`,{headers:{Authorization:`Bearer ${n}`,Accept:`application/json`,"User-Agent":t(x.id)},signal:AbortSignal.timeout(15e3)})}catch(t){return[E(`api`,`fail`,`${e} unreachable: ${t instanceof Error?t.message:String(t)}`,`Check your network, a proxy, or --api-url`)]}let a=Date.now()-r,o=[];i.status===401||i.status===403?o.push(E(`api`,`fail`,`${e} answered ${i.status}, the token was rejected`,`${x.binName} login`)):i.ok?o.push(E(`api`,`pass`,`${e} ${a} ms`)):o.push(E(`api`,`fail`,`${e} answered ${i.status}`));let s=Number(i.headers.get(`ratelimit-limit`)),c=Number(i.headers.get(`ratelimit-remaining`)),l=Number(i.headers.get(`ratelimit-reset`));if(i.headers.has(`ratelimit-limit`)&&Number.isFinite(s)&&Number.isFinite(c)){let e=Number.isFinite(l)?`, resets in ${l}s`:``;o.push(E(`rate limit`,c<=20?`warn`:`pass`,`${c} of ${s} left${e}`))}else o.push(E(`rate limit`,`warn`,`the API sent no RateLimit headers`));let u=i.headers.get(`date`);if(u){let e=Math.round((Date.now()-Date.parse(u))/1e3),t=Math.abs(e);o.push(t>60?E(`clock`,`fail`,`this machine is ${t}s ${e>0?`ahead of`:`behind`} the server`,`Turn on network time sync on this machine`):E(`clock`,`pass`,`${t}s from the server clock`))}else o.push(E(`clock`,`warn`,`the API sent no Date header`));return await i.arrayBuffer().catch(()=>void 0),o}async function F(e){try{let t=await fetch(`${e}/openapi.json`,{headers:{Accept:`application/json`},signal:AbortSignal.timeout(1e4)});return t.ok?E(`openapi`,`pass`,`reachable, version ${(await t.json()).info?.version??`unknown`}`):E(`openapi`,`warn`,`answered ${t.status}`)}catch{return E(`openapi`,`warn`,`not reachable`)}}const I={pass:`✓`,warn:`⚠`,fail:`✗`};function L(e,t){return e===`pass`?a(t):e===`warn`?i(t):r(t)}function R(t){t.command(`doctor`).description(`check this machine, the config files and the API`).action(async()=>{let t=y(),n=[D(),await O(),A(),j(),M()],r,i=p().url,a=`default`;try{let e=f();r=e.token,i=e.apiUrl,a=e.name,n.push(E(`token`,`pass`,`${d(e.token)} from ${_(e.tokenSource)}`))}catch(e){a=t.profile??a,n.push(E(`token`,`fail`,e instanceof Error?e.message:String(e),`${x.binName} login`))}n.push(E(`api url`,`pass`,`${i} (from ${m(p().source)})`)),n.push(...await P(i,r)),n.push(await F(i));let u=N();u&&n.push(u);let h=n.filter(e=>e.status===`fail`);if(l()){c({ok:h.length===0,command:`doctor`,data:{profile:a,checks:n}}),h.length>0&&(process.exitCode=e.GENERIC);return}let g=Math.max(...n.map(e=>e.id.length));for(let e of n)s(` ${L(e.status,I[e.status])} ${e.id.padEnd(g)} ${e.detail}`),e.fix&&s(` ${` `.repeat(g)} ${o(`fix: ${e.fix}`)}`);s(``),s(h.length===0?`No problems found.`:`${h.length} ${h.length===1?`problem`:`problems`} found.`),h.length>0&&(process.exitCode=e.GENERIC)})}export{R as registerDoctorCommand};
1
+ import{t as e}from"./exit-codes-IaZq17dv.js";import"./errors-Dkv23Z0t.js";import{i as t,r as n}from"./version-BPszCYbY.js";import{a as r,c as i,i as a,r as o}from"./color-BbAK7_Y7.js";import{c as s,d as c,o as l}from"./output-uP7GrsdR.js";import{A as u,I as d,S as f,b as p,c as m,i as h,j as g,l as _,o as v,p as y,s as b}from"./config-Bg2ls0gu.js";import{t as x}from"./product-CXL7Ga4M.js";import{a as S,o as C}from"./update-check-CALr-1_t.js";import{statSync as w}from"node:fs";const T=`22.12.0`,E=(e,t,n,r=null)=>({id:e,status:t,detail:n,fix:r});function D(){let e=process.versions.node;return S(e,T)>=0?E(`node`,`pass`,`v${e} (>= ${T})`):E(`node`,`fail`,`v${e} is below ${T}`,`Install Node 22.12 or newer from https://nodejs.org`)}async function O(){let e;try{e=await C()}catch{return E(`cli`,`warn`,`${n} (could not reach the npm registry)`)}return e?S(e,n)>0?E(`cli`,`warn`,`${n} (${e} is published)`,`npm i -g ${x.npmPackage}`):E(`cli`,`pass`,`${n} (latest)`):E(`cli`,`warn`,`${n} (no published release to compare against)`)}function k(e){try{return w(e).mode&511}catch{return}}function A(){let e=h(),t=k(e);if(t===void 0)return E(`config dir`,`warn`,`${e} does not exist yet`,`${x.binName} login`);let n=t.toString(8).padStart(4,`0`);return process.platform!==`win32`&&t&63?E(`config dir`,`warn`,`${e} is mode ${n}`,`chmod 700 ${e}`):E(`config dir`,`pass`,`${e} (${n})`)}function j(){let e=v(),t=k(e);return t===void 0?E(`config file`,`warn`,`${e} does not exist yet`):E(`config file`,`pass`,`${e} (${t.toString(8).padStart(4,`0`)})`)}function M(){let e=b();if(!u())return E(`credentials`,`warn`,`${e} does not exist yet`,`${x.binName} login`);let t=g()??0,n=t.toString(8).padStart(4,`0`);return process.platform!==`win32`&&t&63?E(`credentials`,`fail`,`${e} is mode ${n}, other users can read your token`,`chmod 600 ${e}`):E(`credentials`,`pass`,`${e} (${n})`)}function N(){for(let e of[`HTTPS_PROXY`,`https_proxy`,`HTTP_PROXY`,`http_proxy`]){let t=process.env[e];if(t)return E(`proxy`,`warn`,`${e} is set to ${t}`)}return null}async function P(e,n){if(!n)return[E(`api`,`warn`,`skipped, no token to authenticate with`,`${x.binName} login`)];let r=Date.now(),i;try{i=await fetch(`${e}${x.verifyPath}`,{headers:{Authorization:`Bearer ${n}`,Accept:`application/json`,"User-Agent":t(x.id)},signal:AbortSignal.timeout(15e3)})}catch(t){return[E(`api`,`fail`,`${e} unreachable: ${t instanceof Error?t.message:String(t)}`,`Check your network, a proxy, or --api-url`)]}let a=Date.now()-r,o=[];i.status===401||i.status===403?o.push(E(`api`,`fail`,`${e} answered ${i.status}, the token was rejected`,`${x.binName} login`)):i.ok?o.push(E(`api`,`pass`,`${e} ${a} ms`)):o.push(E(`api`,`fail`,`${e} answered ${i.status}`));let s=Number(i.headers.get(`ratelimit-limit`)),c=Number(i.headers.get(`ratelimit-remaining`)),l=Number(i.headers.get(`ratelimit-reset`));if(i.headers.has(`ratelimit-limit`)&&Number.isFinite(s)&&Number.isFinite(c)){let e=Number.isFinite(l)?`, resets in ${l}s`:``;o.push(E(`rate limit`,c<=20?`warn`:`pass`,`${c} of ${s} left${e}`))}else o.push(E(`rate limit`,`warn`,`the API sent no RateLimit headers`));let u=i.headers.get(`date`);if(u){let e=Math.round((Date.now()-Date.parse(u))/1e3),t=Math.abs(e);o.push(t>60?E(`clock`,`fail`,`this machine is ${t}s ${e>0?`ahead of`:`behind`} the server`,`Turn on network time sync on this machine`):E(`clock`,`pass`,`${t}s from the server clock`))}else o.push(E(`clock`,`warn`,`the API sent no Date header`));return await i.arrayBuffer().catch(()=>void 0),o}async function F(e){try{let t=await fetch(`${e}/openapi.json`,{headers:{Accept:`application/json`},signal:AbortSignal.timeout(1e4)});return t.ok?E(`openapi`,`pass`,`reachable, version ${(await t.json()).info?.version??`unknown`}`):E(`openapi`,`warn`,`answered ${t.status}`)}catch{return E(`openapi`,`warn`,`not reachable`)}}const I={pass:`✓`,warn:`⚠`,fail:`✗`};function L(e,t){return e===`pass`?a(t):e===`warn`?i(t):r(t)}function R(t){t.command(`doctor`).description(`check this machine, the config files and the API`).action(async()=>{let t=y(),n=[D(),await O(),A(),j(),M()],r,i=p().url,a=`default`;try{let e=f();r=e.token,i=e.apiUrl,a=e.name,n.push(E(`token`,`pass`,`${d(e.token)} from ${_(e.tokenSource)}`))}catch(e){a=t.profile??a,n.push(E(`token`,`fail`,e instanceof Error?e.message:String(e),`${x.binName} login`))}n.push(E(`api url`,`pass`,`${i} (from ${m(p().source)})`)),n.push(...await P(i,r)),n.push(await F(i));let u=N();u&&n.push(u);let h=n.filter(e=>e.status===`fail`);if(l()){c({ok:h.length===0,command:`doctor`,data:{profile:a,checks:n}}),h.length>0&&(process.exitCode=e.GENERIC);return}let g=Math.max(...n.map(e=>e.id.length));for(let e of n)s(` ${L(e.status,I[e.status])} ${e.id.padEnd(g)} ${e.detail}`),e.fix&&s(` ${` `.repeat(g)} ${o(`fix: ${e.fix}`)}`);s(``),s(h.length===0?`No problems found.`:`${h.length} ${h.length===1?`problem`:`problems`} found.`),h.length>0&&(process.exitCode=e.GENERIC)})}export{R as registerDoctorCommand};
@@ -1 +1 @@
1
- import"./exit-codes-IaZq17dv.js";import"./errors-Dkv23Z0t.js";import"./version-CFnbqWhw.js";import"./color-BbAK7_Y7.js";import"./output-uP7GrsdR.js";import"./config-Bg2ls0gu.js";import"./product-CXL7Ga4M.js";import{a as e,c as t,d as n,f as r,i,l as a,n as o,o as s,r as c,s as l,t as u,u as d}from"./http-Bryxg3iu.js";export{u as DEFAULT_TIMEOUT_MS,o as LONG_TIMEOUT_MS,c as MAX_ATTEMPTS,i as MAX_RETRY_AFTER_MS,e as RATE_LIMIT_WARN_THRESHOLD,s as RETRY_BASE_MS,l as buildUrl,t as configureHttp,a as getLastRateLimit,d as parseRetryAfter,n as request,r as timeoutForRequest};
1
+ import"./exit-codes-IaZq17dv.js";import"./errors-Dkv23Z0t.js";import"./version-BPszCYbY.js";import"./color-BbAK7_Y7.js";import"./output-uP7GrsdR.js";import"./config-Bg2ls0gu.js";import"./product-CXL7Ga4M.js";import{a as e,c as t,d as n,f as r,i,l as a,n as o,o as s,r as c,s as l,t as u,u as d}from"./http-ZFrs1UcT.js";export{u as DEFAULT_TIMEOUT_MS,o as LONG_TIMEOUT_MS,c as MAX_ATTEMPTS,i as MAX_RETRY_AFTER_MS,e as RATE_LIMIT_WARN_THRESHOLD,s as RETRY_BASE_MS,l as buildUrl,t as configureHttp,a as getLastRateLimit,d as parseRetryAfter,n as request,r as timeoutForRequest};
@@ -1,2 +1,2 @@
1
- import{t as e}from"./exit-codes-IaZq17dv.js";import{l as t,n,t as r}from"./errors-Dkv23Z0t.js";import{i}from"./version-CFnbqWhw.js";import{r as a}from"./color-BbAK7_Y7.js";import{s as o}from"./output-uP7GrsdR.js";import{I as s,S as c,m as l,p as u,x as d}from"./config-Bg2ls0gu.js";import{t as f}from"./product-CXL7Ga4M.js";const p=3e4,m=12e4,h=3,g=1e3,_=6e4,v=20,y=[/^\/ai\//,/^\/mentions\/[^/]+\/explain$/];let b={},x,S,C,w=!1;function T(e){let t=e;return typeof t.profile==`object`||t.globals!==void 0||t.sleep!==void 0}function E(e=u()){b=T(e)?{...e}:{globals:e},x=b.profile,S=void 0,w=!1}function D(){return x||=c(b.globals??u()),x}function O(){return b.language===void 0?(S===void 0&&(S=d(b.globals?.lang)??``),S===``?void 0:S):String(b.language)}function k(){return l(b.debug??b.globals?.debug)}function A(){return b.quiet??b.globals?.quiet??o()}function j(){return C}function M(e,t,n){let r=e.replace(/\/+$/,``),i=t.startsWith(`/`)?t:`/${t}`,a=new URL(`${r}${i}`);for(let[e,t]of Object.entries(n??{}))if(t!=null){if(Array.isArray(t)){for(let n of t)n!=null&&a.searchParams.append(e,String(n));continue}a.searchParams.append(e,String(t))}return a.toString()}function N(e,t){return e===`POST`&&y.some(e=>e.test(t))?m:p}function P(e,t=Date.now()){if(!e)return;let n=e.trim();if(n===``)return;if(/^\d+$/.test(n))return Number(n)*1e3;let r=Date.parse(n);if(!Number.isNaN(r))return Math.max(0,r-t)}function F(e){let t=g*2**(e-1);return Math.round(t*(.75+Math.random()*.5))}function I(e){if(e===null)return;let t=Number(e.trim());return Number.isFinite(t)?t:void 0}function L(e){let t=I(e.get(`ratelimit-limit`)??e.get(`x-ratelimit-limit`)),n=I(e.get(`ratelimit-remaining`)??e.get(`x-ratelimit-remaining`)),r=I(e.get(`ratelimit-reset`)??e.get(`x-ratelimit-reset`)),i=e.get(`ratelimit-policy`)??void 0;t===void 0&&n===void 0&&r===void 0&&i===void 0||(C={limit:t,remaining:n,reset:r,...i?{policy:i}:{}},R())}function R(){if(w||!C)return;let{limit:e,remaining:t,reset:n}=C;if(t===void 0||t>20||A()||!process.stdout.isTTY)return;w=!0;let r=e===void 0?`the`:String(e),i=n===void 0?``:`, resets in ${Math.max(0,Math.round(n))}s`;process.stderr.write(a(`rate limit: ${t} of ${r} left${i}\n`))}function z(e){let t={};for(let[n,r]of Object.entries(e))t[n]=n.toLowerCase()===`authorization`?`Bearer ${s(r.replace(/^Bearer\s+/i,``))}`:r;return t}function B(e){process.stderr.write(a(e.endsWith(`
1
+ import{t as e}from"./exit-codes-IaZq17dv.js";import{l as t,n,t as r}from"./errors-Dkv23Z0t.js";import{i}from"./version-BPszCYbY.js";import{r as a}from"./color-BbAK7_Y7.js";import{s as o}from"./output-uP7GrsdR.js";import{I as s,S as c,m as l,p as u,x as d}from"./config-Bg2ls0gu.js";import{t as f}from"./product-CXL7Ga4M.js";const p=3e4,m=12e4,h=3,g=1e3,_=6e4,v=20,y=[/^\/ai\//,/^\/mentions\/[^/]+\/explain$/];let b={},x,S,C,w=!1;function T(e){let t=e;return typeof t.profile==`object`||t.globals!==void 0||t.sleep!==void 0}function E(e=u()){b=T(e)?{...e}:{globals:e},x=b.profile,S=void 0,w=!1}function D(){return x||=c(b.globals??u()),x}function O(){return b.language===void 0?(S===void 0&&(S=d(b.globals?.lang)??``),S===``?void 0:S):String(b.language)}function k(){return l(b.debug??b.globals?.debug)}function A(){return b.quiet??b.globals?.quiet??o()}function j(){return C}function M(e,t,n){let r=e.replace(/\/+$/,``),i=t.startsWith(`/`)?t:`/${t}`,a=new URL(`${r}${i}`);for(let[e,t]of Object.entries(n??{}))if(t!=null){if(Array.isArray(t)){for(let n of t)n!=null&&a.searchParams.append(e,String(n));continue}a.searchParams.append(e,String(t))}return a.toString()}function N(e,t){return e===`POST`&&y.some(e=>e.test(t))?m:p}function P(e,t=Date.now()){if(!e)return;let n=e.trim();if(n===``)return;if(/^\d+$/.test(n))return Number(n)*1e3;let r=Date.parse(n);if(!Number.isNaN(r))return Math.max(0,r-t)}function F(e){let t=g*2**(e-1);return Math.round(t*(.75+Math.random()*.5))}function I(e){if(e===null)return;let t=Number(e.trim());return Number.isFinite(t)?t:void 0}function L(e){let t=I(e.get(`ratelimit-limit`)??e.get(`x-ratelimit-limit`)),n=I(e.get(`ratelimit-remaining`)??e.get(`x-ratelimit-remaining`)),r=I(e.get(`ratelimit-reset`)??e.get(`x-ratelimit-reset`)),i=e.get(`ratelimit-policy`)??void 0;t===void 0&&n===void 0&&r===void 0&&i===void 0||(C={limit:t,remaining:n,reset:r,...i?{policy:i}:{}},R())}function R(){if(w||!C)return;let{limit:e,remaining:t,reset:n}=C;if(t===void 0||t>20||A()||!process.stdout.isTTY)return;w=!0;let r=e===void 0?`the`:String(e),i=n===void 0?``:`, resets in ${Math.max(0,Math.round(n))}s`;process.stderr.write(a(`rate limit: ${t} of ${r} left${i}\n`))}function z(e){let t={};for(let[n,r]of Object.entries(e))t[n]=n.toLowerCase()===`authorization`?`Bearer ${s(r.replace(/^Bearer\s+/i,``))}`:r;return t}function B(e){process.stderr.write(a(e.endsWith(`
2
2
  `)?e:`${e}\n`))}function V(e){return e.get(`x-request-id`)??e.get(`x-requestid`)??e.get(`request-id`)??void 0}async function H(e){if(e.status===204)return;let t=await e.text();if(t!==``){if((e.headers.get(`content-type`)??``).includes(`json`))try{return JSON.parse(t)}catch{return t}return t}}function U(e){return new Promise(t=>{setTimeout(t,e).unref?.()})}function W(e,n,r){return e instanceof Error&&(e.name===`TimeoutError`||e.name===`AbortError`)?t(`Request to ${n} timed out after ${Math.round(r/1e3)}s`,e):t(`Could not reach ${n}: ${e.message}`,e,`Check your network connection, a proxy, or --api-url`)}async function G(t){if(/^https?:/i.test(t.path))throw new n(`path must be relative to the API base URL, got "${t.path}"`,{exitCode:e.USAGE});let a=D(),o=k(),s=O(),c=b.sleep??U,l=t.idempotent??t.method===`GET`,u=t.timeoutMs??N(t.method,t.path),d=M(a.apiUrl,t.path,t.query),p={authorization:`Bearer ${a.token}`,accept:`application/json`,"user-agent":i(f.id),...s?{"x-language":s}:{},...t.headers},m=t.body!==void 0&&t.method!==`GET`;m&&(p[`content-type`]=`application/json`);let h;for(let e=1;e<=3;e+=1){let n=Date.now();o&&(B(`→ ${t.method} ${d} (attempt ${e}/3, timeout ${u}ms)`),B(` headers ${JSON.stringify(z(p))}`),m&&B(` body ${JSON.stringify(t.body)}`));let i;try{i=await fetch(d,{method:t.method,headers:p,...m?{body:JSON.stringify(t.body)}:{},signal:AbortSignal.timeout(u)})}catch(t){if(h=W(t,d,u),o&&B(`← network error after ${Date.now()-n}ms: ${t.message}`),e<3){await c(F(e));continue}throw h}L(i.headers);let a=await H(i);if(o&&(B(`← ${i.status} ${i.statusText} in ${Date.now()-n}ms`),B(` rateLimit ${JSON.stringify(C??{})}`)),i.ok)return a;let s=new r({status:i.status,body:a,requestId:V(i.headers),method:t.method,path:t.path});if(!(i.status===429?l:i.status===502||i.status===503||i.status===504)||e===3)throw s;let f=P(i.headers.get(`retry-after`))??F(e);if(f>_)throw s;await c(f),h=s}throw h??new n(`Request failed`,{exitCode:e.GENERIC})}export{v as a,E as c,G as d,N as f,_ as i,j as l,m as n,g as o,h as r,M as s,p as t,P as u};
@@ -0,0 +1 @@
1
+ import"./exit-codes-IaZq17dv.js";import"./errors-Dkv23Z0t.js";import"./version-BPszCYbY.js";import"./color-BbAK7_Y7.js";import"./output-uP7GrsdR.js";import"./config-Bg2ls0gu.js";import"./product-CXL7Ga4M.js";import"./http-ZFrs1UcT.js";import"./types-Bu8scNHe.js";import"./prompt-DR68wwvQ.js";import"./client-CVesEwEU.js";import{a as e,i as t,n,o as r,r as i,t as a}from"./keyword-DrmAAuXc.js";export{a as collectKeyword,n as findKeyword,i as formatMoney,t as normalizeKeyword,e as normalizeKeywords,r as registerKeywordCommands};
@@ -1 +1 @@
1
- import{t as e}from"./exit-codes-IaZq17dv.js";import{f as t,n,u as r}from"./errors-Dkv23Z0t.js";import{c as i,f as a,g as o,h as s,i as c,m as l,o as u,p as d,r as f,s as p,v as m}from"./output-uP7GrsdR.js";import{t as h}from"./product-CXL7Ga4M.js";import{f as g,n as _,u as v}from"./types-Bu8scNHe.js";import{i as y}from"./prompt-DR68wwvQ.js";import{_ as b,b as x,c as S,i as C,l as w,n as T,o as E,p as D,t as O,u as k,y as A}from"./client-jT4mvZ9E.js";const j=`${h.appUrl}/billing`;function M(e){let n=e.trim().toLowerCase();if(n===``)throw t(`A keyword cannot be empty`);if(n.length>_)throw t(`"${n.slice(0,32)}…" is ${n.length} characters, the limit is ${_}`);return n}function N(e){return[...new Set(e.map(M))]}const P=(e,t=[])=>[...t,M(e)];function F(e){return`$${e.toFixed(2)}`}function I(e,t){for(let n of e){let e=n.keywords.find(e=>e.id===t);if(e)return{website:n,keyword:e}}}const L=[{header:`ID`,value:e=>f(e.id)},{header:`KEYWORD`,value:e=>e.value},{header:`STATUS`,value:e=>e.status},{header:`NOTE`,value:e=>e.status===`PENDING`?`no free slot on this plan`:`—`}];async function R(e,t){let n=p()||u()?null:g(e);try{return await t()}finally{n?.stop()}}async function z(e){let{websites:t}=await R(`Loading keywords…`,b),n=I(t,e);if(!n)throw r(`No keyword with id "${e}" in this workspace`,`list them with: ${h.binName} site list`);return n}function B(e){let t=e.keywords.filter(e=>e.status===`PENDING`).length;t!==0&&(i(``),i(`${t} pending. Price an upgrade: ${h.binName} keyword plan --count ${e.keywords.filter(e=>e.status!==`DISABLED`).length}`))}async function V(e,n){let r=N(n);if(r.length===0)throw t(`Pass at least one keyword`);let a=await R(`Adding keywords…`,()=>T(e,{keywords:r}));if(u()){d(`keyword.add`,a);return}let c=a.keywords.filter(e=>r.includes(e.value)),l=a.keywords.filter(e=>e.status===`ACTIVE`).length;o(`${a.domain} now has ${a.keywords.length} keywords (${l} active)`),c.length>0&&(i(``),s(c,L)),B(a)}async function H(e,t){let n=M(t.value),{keyword:r}=await z(e);if(r.value===n){if(u()){d(`keyword.edit`,r);return}i(`No change (case-only edit).`);return}let s=await R(`Renaming keyword…`,()=>w(e,{value:n}));if(u()){d(`keyword.edit`,s);return}o(`${r.value} → ${s.value}`),a([[`status`,s.status],[`slot`,`kept, editing is free and unlimited`]])}async function U(e){let t=await R(`Disabling keyword…`,()=>S(e));if(u()){d(`keyword.disable`,t);return}o(`"${t.value}" is ${t.status}`),i(`Its mentions are kept and it no longer occupies a paid slot. Nothing was charged.`)}async function W(e){let t=await R(`Enabling keyword…`,()=>k(e));if(u()){d(`keyword.enable`,t);return}if(t.status===`PENDING`){o(`"${t.value}" is PENDING`),i(`No free slot on this plan, so it is not collecting yet. Nothing was charged.`),c(`price an upgrade: ${h.binName} keyword plan`);return}o(`"${t.value}" is ${t.status}`),i(`Nothing was charged.`)}async function G(t,r){let{website:i,keyword:a}=await z(t),{total:s}=await C({websiteId:i.id,keywords:[a.value],statuses:[...v],includeLowRelevance:!0});if(r.yes!==!0&&(m(`Deleting "${a.value}" also deletes the ${s} mention${s===1?``:`s`} it produced. There is no undo and no refund.`),c(`To pause instead, keeping the mentions: ${h.binName} keyword disable ${a.id}`),(await y(`Type DELETE to confirm`,{hint:`Pass --yes to delete without typing DELETE`})).trim()!==`DELETE`))throw new n(`That is not DELETE, nothing was deleted.`,{exitCode:e.CANCELLED});let l=await E(a.id);if(u()){d(`keyword.delete`,l);return}o(`Deleted`)}async function K(){let{websites:e}=await R(`Activating pending keywords…`,O);if(u()){d(`keyword.activate-pending`,e,{total:e.length,hasMore:!1});return}let t=e.reduce((e,t)=>e+t.keywords.filter(e=>e.status===`ACTIVE`).length,0),n=e.reduce((e,t)=>e+t.keywords.filter(e=>e.status===`PENDING`).length,0);o(`${t} active keyword${t===1?``:`s`} across ${e.length} site${e.length===1?``:`s`}`),i(n===0?`Nothing left pending. This never charges.`:`${n} still pending, there was no free slot. This never charges.`),n>0&&c(`price an upgrade: ${h.binName} keyword plan --count ${t+n}`)}function q(e){l([`CURRENT`,`TARGET`],[[`${e.currentPlanName??`no plan`} ${F(e.currentMonthlyPrice)}/mo`,`${e.targetPlanName??`no plan`} ${F(e.targetMonthlyPrice)}/mo (${e.targetKeywords} keywords)`]]),i(``),a([[`upgrade`,e.isUpgrade?`yes`:e.isDowngrade?`no, downgrade`:`no change`],[`charged now`,`${F(e.immediateCharge)}${e.isUpgrade?` (prorated)`:``}`],[`payment needed`,e.requiresImmediatePayment?`yes`:`no`]]),i(``),i(`Plans change in the ${h.displayName} app: ${j}`)}async function J(e){let n;if(e.count===void 0)n=await R(`Pricing your pending keywords…`,A);else{let r=Number(e.count);if(!Number.isInteger(r)||r<1)throw t(`--count must be a whole number of 1 or more, got "${e.count}"`,`--count is the account-wide total of active keywords you want, not how many to add`);n=await R(`Pricing that keyword count…`,()=>x({desiredKeywordCount:r}))}if(u()){d(`keyword.plan`,n);return}q(n)}async function Y(){let e=await R(`Reading keyword edit usage…`,D);if(u()){d(`keyword.usage`,e);return}if(e.unlimited){i(`Keyword edits: unlimited (this plan does not meter them).`);return}a([[`used`,String(e.used)],[`limit`,String(e.limit)],[`remaining`,String(e.remaining)]])}function X(e){let t=e.command(`keyword`).alias(`keywords`).alias(`kw`).description(`keywords a site listens for`);t.command(`add <siteId> <keyword...>`).description(`add keywords to a site`).action(async(e,t)=>{await V(e,t)}),t.command(`edit <id>`).description(`rename a keyword, free and unlimited`).requiredOption(`--value <keyword>`,`the new keyword`).action(async(e,t)=>{await H(e,t)}),t.command(`disable <id>`).description(`stop collecting for a keyword, keeping its mentions`).action(async e=>{await U(e)}),t.command(`enable <id>`).description(`start collecting for a disabled keyword`).action(async e=>{await W(e)}),t.command(`delete <id>`).alias(`rm`).description(`delete a keyword and every mention it produced`).action(async(e,t,n)=>{await G(e,n.optsWithGlobals())}),t.command(`activate-pending`).description(`promote pending keywords into any free slots`).action(async()=>{await K()}),t.command(`plan`).description(`price the plan a keyword count needs`).option(`--count <n>`,`account-wide total of active keywords you want, not an increment`).action(async e=>{await J(e)}),t.command(`usage`).description(`how many keyword edits this plan allows`).action(async()=>{await Y()})}export{N as a,M as i,I as n,X as o,F as r,P as t};
1
+ import{t as e}from"./exit-codes-IaZq17dv.js";import{f as t,n,u as r}from"./errors-Dkv23Z0t.js";import{c as i,f as a,g as o,h as s,i as c,m as l,o as u,p as d,r as f,s as p,v as m}from"./output-uP7GrsdR.js";import{t as h}from"./product-CXL7Ga4M.js";import{f as g,n as _,u as v}from"./types-Bu8scNHe.js";import{i as y}from"./prompt-DR68wwvQ.js";import{_ as b,b as x,c as S,i as C,l as w,n as T,o as E,p as D,t as O,u as k,y as A}from"./client-CVesEwEU.js";const j=`${h.appUrl}/billing`;function M(e){let n=e.trim().toLowerCase();if(n===``)throw t(`A keyword cannot be empty`);if(n.length>_)throw t(`"${n.slice(0,32)}…" is ${n.length} characters, the limit is ${_}`);return n}function N(e){return[...new Set(e.map(M))]}const P=(e,t=[])=>[...t,M(e)];function F(e){return`$${e.toFixed(2)}`}function I(e,t){for(let n of e){let e=n.keywords.find(e=>e.id===t);if(e)return{website:n,keyword:e}}}const L=[{header:`ID`,value:e=>f(e.id)},{header:`KEYWORD`,value:e=>e.value},{header:`STATUS`,value:e=>e.status},{header:`NOTE`,value:e=>e.status===`PENDING`?`no free slot on this plan`:`—`}];async function R(e,t){let n=p()||u()?null:g(e);try{return await t()}finally{n?.stop()}}async function z(e){let{websites:t}=await R(`Loading keywords…`,b),n=I(t,e);if(!n)throw r(`No keyword with id "${e}" in this workspace`,`list them with: ${h.binName} site list`);return n}function B(e){let t=e.keywords.filter(e=>e.status===`PENDING`).length;t!==0&&(i(``),i(`${t} pending. Price an upgrade: ${h.binName} keyword plan --count ${e.keywords.filter(e=>e.status!==`DISABLED`).length}`))}async function V(e,n){let r=N(n);if(r.length===0)throw t(`Pass at least one keyword`);let a=await R(`Adding keywords…`,()=>T(e,{keywords:r}));if(u()){d(`keyword.add`,a);return}let c=a.keywords.filter(e=>r.includes(e.value)),l=a.keywords.filter(e=>e.status===`ACTIVE`).length;o(`${a.domain} now has ${a.keywords.length} keywords (${l} active)`),c.length>0&&(i(``),s(c,L)),B(a)}async function H(e,t){let n=M(t.value),{keyword:r}=await z(e);if(r.value===n){if(u()){d(`keyword.edit`,r);return}i(`No change (case-only edit).`);return}let s=await R(`Renaming keyword…`,()=>w(e,{value:n}));if(u()){d(`keyword.edit`,s);return}o(`${r.value} → ${s.value}`),a([[`status`,s.status],[`slot`,`kept, editing is free and unlimited`]])}async function U(e){let t=await R(`Disabling keyword…`,()=>S(e));if(u()){d(`keyword.disable`,t);return}o(`"${t.value}" is ${t.status}`),i(`Its mentions are kept and it no longer occupies a paid slot. Nothing was charged.`)}async function W(e){let t=await R(`Enabling keyword…`,()=>k(e));if(u()){d(`keyword.enable`,t);return}if(t.status===`PENDING`){o(`"${t.value}" is PENDING`),i(`No free slot on this plan, so it is not collecting yet. Nothing was charged.`),c(`price an upgrade: ${h.binName} keyword plan`);return}o(`"${t.value}" is ${t.status}`),i(`Nothing was charged.`)}async function G(t,r){let{website:i,keyword:a}=await z(t),{total:s}=await C({websiteId:i.id,keywords:[a.value],statuses:[...v],includeLowRelevance:!0});if(r.yes!==!0&&(m(`Deleting "${a.value}" also deletes the ${s} mention${s===1?``:`s`} it produced. There is no undo and no refund.`),c(`To pause instead, keeping the mentions: ${h.binName} keyword disable ${a.id}`),(await y(`Type DELETE to confirm`,{hint:`Pass --yes to delete without typing DELETE`})).trim()!==`DELETE`))throw new n(`That is not DELETE, nothing was deleted.`,{exitCode:e.CANCELLED});let l=await E(a.id);if(u()){d(`keyword.delete`,l);return}o(`Deleted`)}async function K(){let{websites:e}=await R(`Activating pending keywords…`,O);if(u()){d(`keyword.activate-pending`,e,{total:e.length,hasMore:!1});return}let t=e.reduce((e,t)=>e+t.keywords.filter(e=>e.status===`ACTIVE`).length,0),n=e.reduce((e,t)=>e+t.keywords.filter(e=>e.status===`PENDING`).length,0);o(`${t} active keyword${t===1?``:`s`} across ${e.length} site${e.length===1?``:`s`}`),i(n===0?`Nothing left pending. This never charges.`:`${n} still pending, there was no free slot. This never charges.`),n>0&&c(`price an upgrade: ${h.binName} keyword plan --count ${t+n}`)}function q(e){l([`CURRENT`,`TARGET`],[[`${e.currentPlanName??`no plan`} ${F(e.currentMonthlyPrice)}/mo`,`${e.targetPlanName??`no plan`} ${F(e.targetMonthlyPrice)}/mo (${e.targetKeywords} keywords)`]]),i(``),a([[`upgrade`,e.isUpgrade?`yes`:e.isDowngrade?`no, downgrade`:`no change`],[`charged now`,`${F(e.immediateCharge)}${e.isUpgrade?` (prorated)`:``}`],[`payment needed`,e.requiresImmediatePayment?`yes`:`no`]]),i(``),i(`Plans change in the ${h.displayName} app: ${j}`)}async function J(e){let n;if(e.count===void 0)n=await R(`Pricing your pending keywords…`,A);else{let r=Number(e.count);if(!Number.isInteger(r)||r<1)throw t(`--count must be a whole number of 1 or more, got "${e.count}"`,`--count is the account-wide total of active keywords you want, not how many to add`);n=await R(`Pricing that keyword count…`,()=>x({desiredKeywordCount:r}))}if(u()){d(`keyword.plan`,n);return}q(n)}async function Y(){let e=await R(`Reading keyword edit usage…`,D);if(u()){d(`keyword.usage`,e);return}if(e.unlimited){i(`Keyword edits: unlimited (this plan does not meter them).`);return}a([[`used`,String(e.used)],[`limit`,String(e.limit)],[`remaining`,String(e.remaining)]])}function X(e){let t=e.command(`keyword`).alias(`keywords`).alias(`kw`).description(`keywords a site listens for`);t.command(`add <siteId> <keyword...>`).description(`add keywords to a site`).action(async(e,t)=>{await V(e,t)}),t.command(`edit <id>`).description(`rename a keyword, free and unlimited`).requiredOption(`--value <keyword>`,`the new keyword`).action(async(e,t)=>{await H(e,t)}),t.command(`disable <id>`).description(`stop collecting for a keyword, keeping its mentions`).action(async e=>{await U(e)}),t.command(`enable <id>`).description(`start collecting for a disabled keyword`).action(async e=>{await W(e)}),t.command(`delete <id>`).alias(`rm`).description(`delete a keyword and every mention it produced`).action(async(e,t,n)=>{await G(e,n.optsWithGlobals())}),t.command(`activate-pending`).description(`promote pending keywords into any free slots`).action(async()=>{await K()}),t.command(`plan`).description(`price the plan a keyword count needs`).option(`--count <n>`,`account-wide total of active keywords you want, not an increment`).action(async e=>{await J(e)}),t.command(`usage`).description(`how many keyword edits this plan allows`).action(async()=>{await Y()})}export{N as a,M as i,I as n,X as o,F as r,P as t};
@@ -1 +1 @@
1
- import{t as e}from"./exit-codes-IaZq17dv.js";import{f as t,u as n}from"./errors-Dkv23Z0t.js";import"./version-CFnbqWhw.js";import{r}from"./color-BbAK7_Y7.js";import{_ as i,c as a,f as o,g as s,h as c,i as l,o as u,p as d,r as f,s as p,u as m,v as h}from"./output-uP7GrsdR.js";import{a as g,i as _,n as v,r as y,t as b}from"./time-B5S7M7Dg.js";import{v as ee}from"./config-Bg2ls0gu.js";import{t as x}from"./product-CXL7Ga4M.js";import"./http-Bryxg3iu.js";import{c as S,d as C,f as te,l as w,o as T,s as E,u as D}from"./types-Bu8scNHe.js";import{d as O,g as k,i as A,w as j}from"./client-jT4mvZ9E.js";import{spawn as ne}from"node:child_process";function re(e,n,r,i=`--limit`){if(e===void 0)return r;let a=typeof e==`number`?e:Number(e);if(!Number.isInteger(a)||a<n||a>r)throw t(`${i} must be an integer between ${n} and ${r}`);return a}function ie(e,n=`--offset`){if(e===void 0)return 0;let r=typeof e==`number`?e:Number(e);if(!Number.isInteger(r)||r<0)throw t(`${n} must be an integer of 0 or more`);return r}async function ae(e){let t=e.maxPages??50,n=e.collect!==!1,r=[],i=e.offset??0,a=0,o=0,s,c=!1;for(;a<t;){let l=await e.fetchPage({limit:e.pageSize,offset:i});if(a+=1,o+=l.items.length,l.total!==void 0&&(s=l.total),n&&r.push(...l.items),await e.onPage?.(l.items,{index:a-1,offset:i,total:l.total}),i+=l.items.length,l.items.length===0||l.hasMore===!1||l.hasMore===void 0&&(l.items.length<e.pageSize||s!==void 0&&i>=s))break;if(a>=t){c=!0;break}}return c&&!e.quiet&&h(`stopped after ${t} requests (${o} items). Continue with --offset ${i}`),{items:r,total:s,pages:a,fetched:o,truncated:c}}const M=5e3;var oe=class{keys=new Map;constructor(e){this.limit=e}has(e){return this.keys.has(e)?(this.keys.delete(e),this.keys.set(e,!0),!0):!1}add(e){for(this.keys.has(e)&&this.keys.delete(e),this.keys.set(e,!0);this.keys.size>this.limit;){let e=this.keys.keys().next();if(e.done)break;this.keys.delete(e.value)}}get size(){return this.keys.size}};function se(e){return new Promise(t=>{setTimeout(t,e).unref?.()})}function ce(e){if(!e||typeof e!=`object`)return;let t=e;if(t.status!==429)return;let n=[t.retryAfterMs,t.retryAfterSeconds,t.retryAfter];for(let[e,t]of n.entries())if(typeof t==`number`&&Number.isFinite(t))return e===0?t:t*1e3;let r=t.body;if(r&&typeof r==`object`){let e=r.retryAfter;if(typeof e==`number`&&Number.isFinite(e))return e*1e3}return M}function le(e){let t=Math.round(e/1e3);if(t<60)return`${t}s`;let n=Math.floor(t/60),r=t%60;return n<60?r===0?`${n}m`:`${n}m${r}s`:`${Math.floor(n/60)}h${n%60}m`}async function ue(t){let n=Math.max(M,t.intervalMs),i=Math.max(n,t.maxIntervalMs??6e4),a=t.sleep??se,o=t.onExit??(e=>process.exit(e)),s=new oe(1e4),c=Date.now(),l=n,u=t.cursor,d=0,f=0,p,m=!1,h,g=()=>{m=!0,h?.()};process.on(`SIGINT`,g);let _=async e=>{m||await new Promise(t=>{let n=!1,r=()=>{n||(n=!0,h=void 0,t())};h=r,a(e).then(r)})},v=e=>({emitted:d,polls:f,reason:e,cursor:u,last:p});try{for(;;){let e;try{e=await t.fetchPage(u)}catch(e){let t=ce(e);if(t===void 0)throw e;if(await _(Math.min(t,i)),m)break;continue}f+=1,u=e.cursor;let r=0,a=!1;for(let n of e.items){let e=t.key(n);if(!s.has(e)&&(s.add(e),r+=1,p=n,await t.onItem(n),d+=1,t.until?.(n))){a=!0;break}}if(a)return v(`until`);if(m)break;if(l=r>0?n:Math.min(i,Math.round(l*1.5)),t.timeoutMs!==void 0&&Date.now()-c>=t.timeoutMs)return v(`timeout`);if(await _(l),m)break;if(t.timeoutMs!==void 0&&Date.now()-c>=t.timeoutMs)return v(`timeout`)}}finally{process.removeListener(`SIGINT`,g)}let y=t.label??`items`;return process.stderr.write(r(`\nstopped. ${d} ${y} in ${le(Date.now()-c)}, ${f} polls\n`)),o(e.CANCELLED),v(`interrupted`)}const de=[[75,`VERY_HIGH`],[50,`HIGH`],[30,`MEDIUM`],[10,`LOW`],[0,`VERY_LOW`]];function N(e){if(e===null||!Number.isFinite(e))return null;for(let[t,n]of de)if(e>=t)return n;return`VERY_LOW`}function P(e){let n=e.trim().toUpperCase();if(!D.includes(n))throw t(`Unknown status "${e}"`,`valid statuses: ${D.join(`, `)}`);return n}function F(e){let n=e.trim().toUpperCase().replace(/-/g,`_`);if(!C.includes(n))throw t(`Unknown bucket "${e}"`,`valid buckets: ${C.join(`, `)}`);return n}function I(e){let n=e.trim().toUpperCase().replace(/-/g,`_`);if(!w.includes(n))throw t(`Unknown source "${e}"`,`valid sources: ${w.join(`, `)}`);return n}function L(e){let n=e.trim().toUpperCase();if(!S.includes(n))throw t(`Unknown sort "${e}"`,`valid sorts: ${S.join(`, `)}`);return n}const fe=(e,t=[])=>[...t,e],R=(e,t=[])=>[...t,P(e)],z=(e,t=[])=>[...t,F(e)],B=(e,t=[])=>[...t,I(e)];function V(e){let t={};return e.site!==void 0&&e.site!==``&&(t.websiteId=e.site),e.status&&e.status.length>0&&(t.statuses=e.status),e.bucket&&e.bucket.length>0&&(t.scoreBuckets=e.bucket),e.includeLow===!0&&(t.includeLowRelevance=!0),e.keyword&&e.keyword.length>0&&(t.keywords=e.keyword),e.source&&e.source.length>0&&(t.sources=e.source),e.from!==void 0&&(t.from=g(y(e.from))),e.to!==void 0&&(t.to=g(y(e.to))),t}function H(e){if(e!==void 0&&e!==``)return e;let t=ee().defaultSite;return typeof t==`string`&&t!==``?t:void 0}function U(e){return e.subreddit?`r/${e.subreddit}`:e.source}function W(e){return e.author?e.source===`REDDIT_POST`||e.source===`REDDIT_COMMENT`?e.author.startsWith(`u/`)?e.author:`u/${e.author}`:e.author:`—`}function G(e){let t=e.publishedAt??e.ingestedAt??e.createdAt;if(t===null)return null;let n=new Date(t);return Number.isNaN(n.getTime())?null:n}const pe=e=>{let t=G(e);return t===null?`—`:v(t)},K=e=>(e??``).replace(/\s+/g,` `).trim()||`—`,me=[{header:`SCORE`,value:e=>e.relevanceScore??`—`,align:`right`},{header:`SOURCE`,value:U},{header:`WHEN`,value:pe},{header:`KEYWORD`,value:e=>e.keyword||`—`},{header:`TITLE`,value:e=>K(e.title??e.contentText)}];async function q(e,t){let n=p()||u()?null:te(e);try{return await t()}finally{n?.stop()}}function he(e,t,n){let r=e.replace(/\s+/g,` `).trim().split(` `),i=[],a=``;for(let e of r){if(a===``){a=e;continue}if(`${a} ${e}`.length+n.length>t){i.push(`${n}${a}`),a=e;continue}a=`${a} ${e}`}return a!==``&&i.push(`${n}${a}`),i}function J(e,t=` `){for(let n of he(e,Math.max(40,i()-2),t))a(n)}async function ge(e,t){try{let{total:n}=await A({...e,includeLowRelevance:!0});return Math.max(0,n-t)}catch{return 0}}async function _e(e){let t=V({...e,site:H(e.site)}),n=e.limit===void 0?50:re(e.limit,E,T),r=ie(e.offset),i=e.sort,o,s,f=!1;if(e.all){let n=await ae({pageSize:T,offset:r,quiet:e.quiet===!0||p(),fetchPage:async e=>{let n=await k({...t,sort:i,limit:e.limit,offset:e.offset});return{items:n.mentions,total:n.total,hasMore:n.offset+n.mentions.length<n.total}}});o=n.items,s=n.total}else{let e=await q(`Loading mentions…`,()=>k({...t,sort:i,limit:n,offset:r}));o=e.mentions,s=e.total,f=e.offset+e.mentions.length<e.total}if(u()){d(`mention.list`,o,{total:s,limit:e.all?void 0:n,offset:e.all?void 0:r,hasMore:f}),m(o);return}if(o.length===0?a(`No mentions match those filters.`):(c(o,me),a(``),a(`${o.length} of ${s??o.length} · open: ${x.binName} mention show <id>`),f&&a(`next: --offset ${r+o.length}`)),t.statuses?.includes(`REJECTED`)||l(`REJECTED mentions are hidden unless you pass --status REJECTED.`),e.includeLow!==!0){let e=await ge(t,s??o.length);e>0&&l(`${e} mention${e===1?``:`s`} below the site’s minimum score ${e===1?`is`:`are`} hidden. Add --include-low.`)}}async function ve(e){let t=V({...e,site:H(e.site)}),n=await q(`Counting mentions…`,()=>A(t));if(u()){d(`mention.count`,n);return}a(`${n.total} mention${n.total===1?``:`s`} match`)}async function ye(e,t){let n={...t,statuses:t.statuses??[...D],includeLowRelevance:!0};for(let t=0;t<20;t+=1){let r=t*T,i=await k({...n,sort:`RECENT`,limit:T,offset:r}),a=i.mentions.find(t=>t.id===e||t.id.startsWith(e));if(a)return a;if(i.mentions.length===0||r+i.mentions.length>=i.total)return}}function Y(e){let t=G(e),n=N(e.relevanceScore);a([U(e),t===null?`unknown time`:v(t),e.relevanceScore===null?`unscored`:`score ${e.relevanceScore}${n===null?``:` (${n})`}`,e.status].join(` · `)),o([[`id`,e.id],[`keyword`,e.keyword||`—`],[`author`,W(e)],[`url`,e.url],...t===null?[]:[[`posted`,b(t,{timezone:_()})]],...e.tags.length>0?[[`tags`,e.tags.join(`, `)]]:[]]),e.title&&(a(``),J(e.title)),e.contentText&&(a(``),J(e.contentText)),e.relevanceReason&&(a(``),a(r(e.relevanceScore===null?`why it was scored`:`why it scored ${e.relevanceScore}`)),J(e.relevanceReason,` `)),e.aiReplySuggestion&&(a(``),a(r(`suggested reply`)),J(e.aiReplySuggestion,` `)),a(``),a(`approve: ${x.binName} mention status ${e.id} APPROVED`)}async function be(e,t){let r=t.explain?await q(`Explaining mention…`,()=>O(e)):await q(`Searching mentions…`,()=>ye(e,V({...t,site:H(t.site)})));if(!r)throw n(`Mention not found in this workspace`,t.explain?`drop --explain to page through /mentions instead`:`${x.binName} mention list --limit 20`);if(u()){d(`mention.show`,r);return}Y(r)}async function xe(e,t){let n=P(t),r=await q(`Updating status…`,()=>j(e,{status:n}));if(u()){d(`mention.status`,r);return}s(`${f(r.id)} is ${r.status}`),a(`Reversible: ${x.binName} mention status ${r.id} NEW`)}async function Se(e){l(`The first call runs generation and can take up to two minutes. Later calls are instant reads.`);let t=await q(`Explaining mention…`,()=>O(e));if(!t)throw n(`Mention not found in this workspace`,`${x.binName} mention list --limit 20`);if(u()){d(`mention.explain`,t);return}Y(t)}function X(e){if(e===void 0)return 60;let n=Number(e);if(!Number.isInteger(n)||n<30)throw t(`--interval must be a whole number of 30 seconds or more, got "${e}"`,`every poll spends from the 600 requests per minute budget`);return n}function Z(e){if(e===void 0)return;let n=Number(e);if(!Number.isInteger(n)||n<0||n>100)throw t(`--min-score must be a whole number between 0 and 100, got "${e}"`);return n}function Ce(e){return{RR_ID:e.id,RR_SCORE:e.relevanceScore===null?``:String(e.relevanceScore),RR_URL:e.url,RR_SOURCE:e.source,RR_KEYWORD:e.keyword??``,RR_TITLE:e.title??``}}async function we(e,t){return new Promise(n=>{let r=ne(e,{shell:!0,stdio:[`pipe`,`pipe`,`pipe`],env:{...process.env,...Ce(t)}});r.stdout?.on(`data`,e=>process.stderr.write(e)),r.stderr?.on(`data`,e=>process.stderr.write(e)),r.on(`error`,e=>{process.stderr.write(`${e.message}\n`),n(1)}),r.on(`close`,e=>n(e??1)),r.stdin?.end(`${JSON.stringify(t)}\n`)})}async function Q(e){let t=Z(e.minScore),n=X(e.interval),r=e.since===void 0?new Date:y(e.since),i=_(),o=V({...e,site:H(e.site),from:void 0}),s={...o,from:g(r),sort:`RECENT`,limit:50};u()||a(`Tailing new mentions ${o.websiteId===void 0?`for every site`:`for site ${f(o.websiteId)}`}${t===void 0?``:`, score ≥ ${t}`}, every ${n}s. Ctrl-C to stop.`),await ue({intervalMs:n*1e3,maxIntervalMs:3e5,label:`mentions`,key:e=>e.id,fetchPage:async e=>({items:[...(await k(s)).mentions].reverse().filter(e=>t===void 0?!0:(e.relevanceScore??-1)>=t),cursor:e}),onItem:async t=>{if(u()?process.stdout.write(`${JSON.stringify(t)}\n`):a([b(G(t)??new Date,{timezone:i,seconds:!0,withZone:!1}).slice(11),String(t.relevanceScore??`—`).padStart(3),U(t).padEnd(12),K(t.title??t.contentText)].join(` `)),e.exec===void 0)return;let n=await we(e.exec,t);if(n!==0){h(`--exec exited ${n} for ${t.id}, the tail continues`);return}if(e.approveOnExecSuccess===!0)try{await j(t.id,{status:`APPROVED`})}catch(e){h(`could not approve ${t.id}: ${e instanceof Error?e.message:String(e)}`)}}})}const $=e=>e.option(`--site <id>`,`only this site`).option(`--status <status>`,`filter by status, repeatable: ${D.join(`, `)}`,R,[]).option(`--bucket <bucket>`,`filter by score bucket, repeatable: ${C.join(`, `)}`,z,[]).option(`--include-low`,`include mentions below the site’s minimum score`).option(`--keyword <keyword>`,`filter by keyword, repeatable`,fe,[]).option(`--source <source>`,`filter by source, repeatable: ${w.join(`, `)}`,B,[]).option(`--from <date>`,`lower bound on ingestion time`).option(`--to <date>`,`upper bound on ingestion time`);function Te(e){let t=e.command(`mention`).alias(`mentions`).description(`lead mentions found across Reddit, Hacker News, X and Bluesky`);$(t.command(`list`)).alias(`ls`).description(`list mentions`).option(`--sort <order>`,`${S.join(` or `)}`,L).option(`--limit <n>`,`mentions per page, ${E} to ${T}`).option(`--offset <n>`,`mentions to skip`).option(`--all`,`page until the server runs out`).action(async(e,t)=>{await _e(t.optsWithGlobals())}),$(t.command(`count`)).description(`count the mentions matching the filters`).action(async e=>{await ve(e)}),$(t.command(`show <id>`)).alias(`get`).description(`show one mention, its score reason and its suggested reply`).option(`--explain`,`fetch it through /mentions/{id}/explain instead of paging /mentions`).action(async(e,t)=>{await be(e,t)}),t.command(`status <id> <status>`).description(`set a mention's status: ${D.join(`, `)}`).action(async(e,t)=>{await xe(e,t)}),t.command(`explain <id>`).description(`generate, then read, why a mention scored as it did`).action(async e=>{await Se(e)}),$(t.command(`tail`)).description(`follow new mentions as they arrive`).option(`--min-score <n>`,`skip mentions scoring below this`).option(`--interval <seconds>`,`poll every N seconds, floor 30`).option(`--since <date>`,`start from this time instead of now`).option(`--exec <command>`,`run this command once per mention, JSON on its stdin`).option(`--approve-on-exec-success`,`approve a mention when --exec exits 0`).action(async(e,t)=>{await Q(t.optsWithGlobals())})}export{W as authorLabel,V as buildFilterQuery,G as mentionDate,F as normalizeBucket,L as normalizeSort,I as normalizeSource,P as normalizeStatus,Z as parseMinScore,X as parseTailInterval,Te as registerMentionCommands,N as relevanceBucketOf,H as resolveSite,U as sourceLabel};
1
+ import{t as e}from"./exit-codes-IaZq17dv.js";import{f as t,u as n}from"./errors-Dkv23Z0t.js";import"./version-BPszCYbY.js";import{r}from"./color-BbAK7_Y7.js";import{_ as i,c as a,f as o,g as s,h as c,i as l,o as u,p as d,r as f,s as p,u as m,v as h}from"./output-uP7GrsdR.js";import{a as g,i as _,n as v,r as y,t as b}from"./time-B5S7M7Dg.js";import{v as ee}from"./config-Bg2ls0gu.js";import{t as x}from"./product-CXL7Ga4M.js";import"./http-ZFrs1UcT.js";import{c as S,d as C,f as te,l as w,o as T,s as E,u as D}from"./types-Bu8scNHe.js";import{d as O,g as k,i as A,w as j}from"./client-CVesEwEU.js";import{spawn as ne}from"node:child_process";function re(e,n,r,i=`--limit`){if(e===void 0)return r;let a=typeof e==`number`?e:Number(e);if(!Number.isInteger(a)||a<n||a>r)throw t(`${i} must be an integer between ${n} and ${r}`);return a}function ie(e,n=`--offset`){if(e===void 0)return 0;let r=typeof e==`number`?e:Number(e);if(!Number.isInteger(r)||r<0)throw t(`${n} must be an integer of 0 or more`);return r}async function ae(e){let t=e.maxPages??50,n=e.collect!==!1,r=[],i=e.offset??0,a=0,o=0,s,c=!1;for(;a<t;){let l=await e.fetchPage({limit:e.pageSize,offset:i});if(a+=1,o+=l.items.length,l.total!==void 0&&(s=l.total),n&&r.push(...l.items),await e.onPage?.(l.items,{index:a-1,offset:i,total:l.total}),i+=l.items.length,l.items.length===0||l.hasMore===!1||l.hasMore===void 0&&(l.items.length<e.pageSize||s!==void 0&&i>=s))break;if(a>=t){c=!0;break}}return c&&!e.quiet&&h(`stopped after ${t} requests (${o} items). Continue with --offset ${i}`),{items:r,total:s,pages:a,fetched:o,truncated:c}}const M=5e3;var oe=class{keys=new Map;constructor(e){this.limit=e}has(e){return this.keys.has(e)?(this.keys.delete(e),this.keys.set(e,!0),!0):!1}add(e){for(this.keys.has(e)&&this.keys.delete(e),this.keys.set(e,!0);this.keys.size>this.limit;){let e=this.keys.keys().next();if(e.done)break;this.keys.delete(e.value)}}get size(){return this.keys.size}};function se(e){return new Promise(t=>{setTimeout(t,e).unref?.()})}function ce(e){if(!e||typeof e!=`object`)return;let t=e;if(t.status!==429)return;let n=[t.retryAfterMs,t.retryAfterSeconds,t.retryAfter];for(let[e,t]of n.entries())if(typeof t==`number`&&Number.isFinite(t))return e===0?t:t*1e3;let r=t.body;if(r&&typeof r==`object`){let e=r.retryAfter;if(typeof e==`number`&&Number.isFinite(e))return e*1e3}return M}function le(e){let t=Math.round(e/1e3);if(t<60)return`${t}s`;let n=Math.floor(t/60),r=t%60;return n<60?r===0?`${n}m`:`${n}m${r}s`:`${Math.floor(n/60)}h${n%60}m`}async function ue(t){let n=Math.max(M,t.intervalMs),i=Math.max(n,t.maxIntervalMs??6e4),a=t.sleep??se,o=t.onExit??(e=>process.exit(e)),s=new oe(1e4),c=Date.now(),l=n,u=t.cursor,d=0,f=0,p,m=!1,h,g=()=>{m=!0,h?.()};process.on(`SIGINT`,g);let _=async e=>{m||await new Promise(t=>{let n=!1,r=()=>{n||(n=!0,h=void 0,t())};h=r,a(e).then(r)})},v=e=>({emitted:d,polls:f,reason:e,cursor:u,last:p});try{for(;;){let e;try{e=await t.fetchPage(u)}catch(e){let t=ce(e);if(t===void 0)throw e;if(await _(Math.min(t,i)),m)break;continue}f+=1,u=e.cursor;let r=0,a=!1;for(let n of e.items){let e=t.key(n);if(!s.has(e)&&(s.add(e),r+=1,p=n,await t.onItem(n),d+=1,t.until?.(n))){a=!0;break}}if(a)return v(`until`);if(m)break;if(l=r>0?n:Math.min(i,Math.round(l*1.5)),t.timeoutMs!==void 0&&Date.now()-c>=t.timeoutMs)return v(`timeout`);if(await _(l),m)break;if(t.timeoutMs!==void 0&&Date.now()-c>=t.timeoutMs)return v(`timeout`)}}finally{process.removeListener(`SIGINT`,g)}let y=t.label??`items`;return process.stderr.write(r(`\nstopped. ${d} ${y} in ${le(Date.now()-c)}, ${f} polls\n`)),o(e.CANCELLED),v(`interrupted`)}const de=[[75,`VERY_HIGH`],[50,`HIGH`],[30,`MEDIUM`],[10,`LOW`],[0,`VERY_LOW`]];function N(e){if(e===null||!Number.isFinite(e))return null;for(let[t,n]of de)if(e>=t)return n;return`VERY_LOW`}function P(e){let n=e.trim().toUpperCase();if(!D.includes(n))throw t(`Unknown status "${e}"`,`valid statuses: ${D.join(`, `)}`);return n}function F(e){let n=e.trim().toUpperCase().replace(/-/g,`_`);if(!C.includes(n))throw t(`Unknown bucket "${e}"`,`valid buckets: ${C.join(`, `)}`);return n}function I(e){let n=e.trim().toUpperCase().replace(/-/g,`_`);if(!w.includes(n))throw t(`Unknown source "${e}"`,`valid sources: ${w.join(`, `)}`);return n}function L(e){let n=e.trim().toUpperCase();if(!S.includes(n))throw t(`Unknown sort "${e}"`,`valid sorts: ${S.join(`, `)}`);return n}const fe=(e,t=[])=>[...t,e],R=(e,t=[])=>[...t,P(e)],z=(e,t=[])=>[...t,F(e)],B=(e,t=[])=>[...t,I(e)];function V(e){let t={};return e.site!==void 0&&e.site!==``&&(t.websiteId=e.site),e.status&&e.status.length>0&&(t.statuses=e.status),e.bucket&&e.bucket.length>0&&(t.scoreBuckets=e.bucket),e.includeLow===!0&&(t.includeLowRelevance=!0),e.keyword&&e.keyword.length>0&&(t.keywords=e.keyword),e.source&&e.source.length>0&&(t.sources=e.source),e.from!==void 0&&(t.from=g(y(e.from))),e.to!==void 0&&(t.to=g(y(e.to))),t}function H(e){if(e!==void 0&&e!==``)return e;let t=ee().defaultSite;return typeof t==`string`&&t!==``?t:void 0}function U(e){return e.subreddit?`r/${e.subreddit}`:e.source}function W(e){return e.author?e.source===`REDDIT_POST`||e.source===`REDDIT_COMMENT`?e.author.startsWith(`u/`)?e.author:`u/${e.author}`:e.author:`—`}function G(e){let t=e.publishedAt??e.ingestedAt??e.createdAt;if(t===null)return null;let n=new Date(t);return Number.isNaN(n.getTime())?null:n}const pe=e=>{let t=G(e);return t===null?`—`:v(t)},K=e=>(e??``).replace(/\s+/g,` `).trim()||`—`,me=[{header:`SCORE`,value:e=>e.relevanceScore??`—`,align:`right`},{header:`SOURCE`,value:U},{header:`WHEN`,value:pe},{header:`KEYWORD`,value:e=>e.keyword||`—`},{header:`TITLE`,value:e=>K(e.title??e.contentText)}];async function q(e,t){let n=p()||u()?null:te(e);try{return await t()}finally{n?.stop()}}function he(e,t,n){let r=e.replace(/\s+/g,` `).trim().split(` `),i=[],a=``;for(let e of r){if(a===``){a=e;continue}if(`${a} ${e}`.length+n.length>t){i.push(`${n}${a}`),a=e;continue}a=`${a} ${e}`}return a!==``&&i.push(`${n}${a}`),i}function J(e,t=` `){for(let n of he(e,Math.max(40,i()-2),t))a(n)}async function ge(e,t){try{let{total:n}=await A({...e,includeLowRelevance:!0});return Math.max(0,n-t)}catch{return 0}}async function _e(e){let t=V({...e,site:H(e.site)}),n=e.limit===void 0?50:re(e.limit,E,T),r=ie(e.offset),i=e.sort,o,s,f=!1;if(e.all){let n=await ae({pageSize:T,offset:r,quiet:e.quiet===!0||p(),fetchPage:async e=>{let n=await k({...t,sort:i,limit:e.limit,offset:e.offset});return{items:n.mentions,total:n.total,hasMore:n.offset+n.mentions.length<n.total}}});o=n.items,s=n.total}else{let e=await q(`Loading mentions…`,()=>k({...t,sort:i,limit:n,offset:r}));o=e.mentions,s=e.total,f=e.offset+e.mentions.length<e.total}if(u()){d(`mention.list`,o,{total:s,limit:e.all?void 0:n,offset:e.all?void 0:r,hasMore:f}),m(o);return}if(o.length===0?a(`No mentions match those filters.`):(c(o,me),a(``),a(`${o.length} of ${s??o.length} · open: ${x.binName} mention show <id>`),f&&a(`next: --offset ${r+o.length}`)),t.statuses?.includes(`REJECTED`)||l(`REJECTED mentions are hidden unless you pass --status REJECTED.`),e.includeLow!==!0){let e=await ge(t,s??o.length);e>0&&l(`${e} mention${e===1?``:`s`} below the site’s minimum score ${e===1?`is`:`are`} hidden. Add --include-low.`)}}async function ve(e){let t=V({...e,site:H(e.site)}),n=await q(`Counting mentions…`,()=>A(t));if(u()){d(`mention.count`,n);return}a(`${n.total} mention${n.total===1?``:`s`} match`)}async function ye(e,t){let n={...t,statuses:t.statuses??[...D],includeLowRelevance:!0};for(let t=0;t<20;t+=1){let r=t*T,i=await k({...n,sort:`RECENT`,limit:T,offset:r}),a=i.mentions.find(t=>t.id===e||t.id.startsWith(e));if(a)return a;if(i.mentions.length===0||r+i.mentions.length>=i.total)return}}function Y(e){let t=G(e),n=N(e.relevanceScore);a([U(e),t===null?`unknown time`:v(t),e.relevanceScore===null?`unscored`:`score ${e.relevanceScore}${n===null?``:` (${n})`}`,e.status].join(` · `)),o([[`id`,e.id],[`keyword`,e.keyword||`—`],[`author`,W(e)],[`url`,e.url],...t===null?[]:[[`posted`,b(t,{timezone:_()})]],...e.tags.length>0?[[`tags`,e.tags.join(`, `)]]:[]]),e.title&&(a(``),J(e.title)),e.contentText&&(a(``),J(e.contentText)),e.relevanceReason&&(a(``),a(r(e.relevanceScore===null?`why it was scored`:`why it scored ${e.relevanceScore}`)),J(e.relevanceReason,` `)),e.aiReplySuggestion&&(a(``),a(r(`suggested reply`)),J(e.aiReplySuggestion,` `)),a(``),a(`approve: ${x.binName} mention status ${e.id} APPROVED`)}async function be(e,t){let r=t.explain?await q(`Explaining mention…`,()=>O(e)):await q(`Searching mentions…`,()=>ye(e,V({...t,site:H(t.site)})));if(!r)throw n(`Mention not found in this workspace`,t.explain?`drop --explain to page through /mentions instead`:`${x.binName} mention list --limit 20`);if(u()){d(`mention.show`,r);return}Y(r)}async function xe(e,t){let n=P(t),r=await q(`Updating status…`,()=>j(e,{status:n}));if(u()){d(`mention.status`,r);return}s(`${f(r.id)} is ${r.status}`),a(`Reversible: ${x.binName} mention status ${r.id} NEW`)}async function Se(e){l(`The first call runs generation and can take up to two minutes. Later calls are instant reads.`);let t=await q(`Explaining mention…`,()=>O(e));if(!t)throw n(`Mention not found in this workspace`,`${x.binName} mention list --limit 20`);if(u()){d(`mention.explain`,t);return}Y(t)}function X(e){if(e===void 0)return 60;let n=Number(e);if(!Number.isInteger(n)||n<30)throw t(`--interval must be a whole number of 30 seconds or more, got "${e}"`,`every poll spends from the 600 requests per minute budget`);return n}function Z(e){if(e===void 0)return;let n=Number(e);if(!Number.isInteger(n)||n<0||n>100)throw t(`--min-score must be a whole number between 0 and 100, got "${e}"`);return n}function Ce(e){return{RR_ID:e.id,RR_SCORE:e.relevanceScore===null?``:String(e.relevanceScore),RR_URL:e.url,RR_SOURCE:e.source,RR_KEYWORD:e.keyword??``,RR_TITLE:e.title??``}}async function we(e,t){return new Promise(n=>{let r=ne(e,{shell:!0,stdio:[`pipe`,`pipe`,`pipe`],env:{...process.env,...Ce(t)}});r.stdout?.on(`data`,e=>process.stderr.write(e)),r.stderr?.on(`data`,e=>process.stderr.write(e)),r.on(`error`,e=>{process.stderr.write(`${e.message}\n`),n(1)}),r.on(`close`,e=>n(e??1)),r.stdin?.end(`${JSON.stringify(t)}\n`)})}async function Q(e){let t=Z(e.minScore),n=X(e.interval),r=e.since===void 0?new Date:y(e.since),i=_(),o=V({...e,site:H(e.site),from:void 0}),s={...o,from:g(r),sort:`RECENT`,limit:50};u()||a(`Tailing new mentions ${o.websiteId===void 0?`for every site`:`for site ${f(o.websiteId)}`}${t===void 0?``:`, score ≥ ${t}`}, every ${n}s. Ctrl-C to stop.`),await ue({intervalMs:n*1e3,maxIntervalMs:3e5,label:`mentions`,key:e=>e.id,fetchPage:async e=>({items:[...(await k(s)).mentions].reverse().filter(e=>t===void 0?!0:(e.relevanceScore??-1)>=t),cursor:e}),onItem:async t=>{if(u()?process.stdout.write(`${JSON.stringify(t)}\n`):a([b(G(t)??new Date,{timezone:i,seconds:!0,withZone:!1}).slice(11),String(t.relevanceScore??`—`).padStart(3),U(t).padEnd(12),K(t.title??t.contentText)].join(` `)),e.exec===void 0)return;let n=await we(e.exec,t);if(n!==0){h(`--exec exited ${n} for ${t.id}, the tail continues`);return}if(e.approveOnExecSuccess===!0)try{await j(t.id,{status:`APPROVED`})}catch(e){h(`could not approve ${t.id}: ${e instanceof Error?e.message:String(e)}`)}}})}const $=e=>e.option(`--site <id>`,`only this site`).option(`--status <status>`,`filter by status, repeatable: ${D.join(`, `)}`,R,[]).option(`--bucket <bucket>`,`filter by score bucket, repeatable: ${C.join(`, `)}`,z,[]).option(`--include-low`,`include mentions below the site’s minimum score`).option(`--keyword <keyword>`,`filter by keyword, repeatable`,fe,[]).option(`--source <source>`,`filter by source, repeatable: ${w.join(`, `)}`,B,[]).option(`--from <date>`,`lower bound on ingestion time`).option(`--to <date>`,`upper bound on ingestion time`);function Te(e){let t=e.command(`mention`).alias(`mentions`).description(`lead mentions found across Reddit, Hacker News, X and Bluesky`);$(t.command(`list`)).alias(`ls`).description(`list mentions`).option(`--sort <order>`,`${S.join(` or `)}`,L).option(`--limit <n>`,`mentions per page, ${E} to ${T}`).option(`--offset <n>`,`mentions to skip`).option(`--all`,`page until the server runs out`).action(async(e,t)=>{await _e(t.optsWithGlobals())}),$(t.command(`count`)).description(`count the mentions matching the filters`).action(async e=>{await ve(e)}),$(t.command(`show <id>`)).alias(`get`).description(`show one mention, its score reason and its suggested reply`).option(`--explain`,`fetch it through /mentions/{id}/explain instead of paging /mentions`).action(async(e,t)=>{await be(e,t)}),t.command(`status <id> <status>`).description(`set a mention's status: ${D.join(`, `)}`).action(async(e,t)=>{await xe(e,t)}),t.command(`explain <id>`).description(`generate, then read, why a mention scored as it did`).action(async e=>{await Se(e)}),$(t.command(`tail`)).description(`follow new mentions as they arrive`).option(`--min-score <n>`,`skip mentions scoring below this`).option(`--interval <seconds>`,`poll every N seconds, floor 30`).option(`--since <date>`,`start from this time instead of now`).option(`--exec <command>`,`run this command once per mention, JSON on its stdin`).option(`--approve-on-exec-success`,`approve a mention when --exec exits 0`).action(async(e,t)=>{await Q(t.optsWithGlobals())})}export{W as authorLabel,V as buildFilterQuery,G as mentionDate,F as normalizeBucket,L as normalizeSort,I as normalizeSource,P as normalizeStatus,Z as parseMinScore,X as parseTailInterval,Te as registerMentionCommands,N as relevanceBucketOf,H as resolveSite,U as sourceLabel};
@@ -1 +1 @@
1
- import{t as e}from"./exit-codes-IaZq17dv.js";import{f as t,n}from"./errors-Dkv23Z0t.js";import"./version-CFnbqWhw.js";import"./color-BbAK7_Y7.js";import{c as r,f as i,g as a,h as o,i as s,n as c,o as l,p as u,r as d,s as f,u as p,v as m}from"./output-uP7GrsdR.js";import{n as h,t as g}from"./time-B5S7M7Dg.js";import{d as _}from"./config-Bg2ls0gu.js";import{t as v}from"./product-CXL7Ga4M.js";import"./http-Bryxg3iu.js";import{f as y,r as b,u as x}from"./types-Bu8scNHe.js";import{i as S,n as C}from"./prompt-DR68wwvQ.js";import{T as w,_ as T,a as E,h as D,i as O,r as k,s as A}from"./client-jT4mvZ9E.js";import{a as j,t as M}from"./keyword-D5EhLCMO.js";import{resolve as N}from"node:path";import{readFile as P}from"node:fs/promises";const F=[`ACTIVE`,`PENDING`,`DISABLED`,`SUSPENDED`];function I(e){let t={ACTIVE:0,PENDING:0,DISABLED:0,SUSPENDED:0};for(let n of e.keywords)t[n.status]+=1;return t}function L(e){let t=I(e),n=F.filter(e=>t[e]>0).map(e=>`${t[e]} ${e.toLowerCase()}`);return n.length===0?`none`:n.join(`, `)}function R(e,n=`--url`){let r=e.trim(),i;try{i=new URL(r)}catch{throw t(`${n} must be a full URL, got "${e}"`,`${v.binName} site create --url https://acme.com`)}if(i.protocol!==`https:`&&i.protocol!==`http:`)throw t(`${n} must be an http or https URL, got "${e}"`);return r}async function z(){let e=[];for await(let t of process.stdin)e.push(t);return Buffer.concat(e).toString(`utf8`)}async function B(e){let n=(e===`-`?await z():e.startsWith(`@`)?await V(e.slice(1)):e).trim();if(n.length>b)throw t(`--description is ${n.length} characters, the limit is ${b}`);return n}async function V(t){try{return await P(N(t),`utf8`)}catch(r){throw new n(`Cannot read ${t}: ${r.message}`,{exitCode:e.USAGE,cause:r})}}const H=[{header:`ID`,value:e=>d(e.id)},{header:`DOMAIN`,value:e=>e.domain},{header:`NAME`,value:e=>e.name||`—`},{header:`KEYWORDS`,value:e=>L(e)},{header:`DESCRIPTION`,value:e=>e.description?`yes`:`missing`}],U=[{header:`ID`,value:e=>d(e.id)},{header:`KEYWORD`,value:e=>e.value},{header:`STATUS`,value:e=>e.status},{header:`ADDED`,value:e=>e.createdAt?h(new Date(e.createdAt)):`—`}];async function W(e,t){let n=f()||l()?null:y(e);try{return await t()}finally{n?.stop()}}async function G(){let{websites:e}=await W(`Loading sites…`,T);if(l()){u(`site.list`,e,{total:e.length,hasMore:!1}),p(e);return}if(e.length===0){r(`No sites yet.`),s(`add one: ${v.binName} site create --url https://acme.com -k "your keyword"`);return}o(e,H),r(``),r(`${e.length} ${e.length===1?`site`:`sites`}`);for(let t of e)t.description||(m(`${t.domain} has no description. Its mentions are not scored.`),s(` fix: ${v.binName} site analyze --url ${t.url}`));let t=e.reduce((e,t)=>e+I(t).PENDING,0);s(`Listing sites activates any PENDING keyword that fits your plan’s free headroom.`),t>0&&s(`${t} keyword${t===1?``:`s`} still PENDING, there was no free slot. Price an upgrade: ${v.binName} keyword plan`)}async function K(e){let t=await W(`Loading site…`,()=>D(e));if(l()){u(`site.get`,t);return}r(t.id),i([[`domain`,t.domain],[`url`,t.url],[`name`,t.name||`—`],[`description`,t.description?`${t.description.length} characters`:`missing, mentions are not scored`],[`keywords`,L(t)],[`created`,t.createdAt?g(new Date(t.createdAt),{timezone:`UTC`}):`—`]]),t.keywords.length>0&&(r(``),o(t.keywords,U)),t.description||(r(``),s(`fix: ${v.binName} site analyze --url ${t.url}`))}async function q(t){let o=R(t.url),f=j(t.keyword),p=t.description===void 0?void 0:await B(t.description),h;if(p!==void 0)h={url:o,keywords:f,description:p,...t.name?{name:t.name}:{}};else if(t.analyze===!1)h={url:o,keywords:f,description:``,...t.name?{name:t.name}:{}},m(`--no-analyze sends an empty description, so nothing this site collects will be scored.`);else{let r=new URL(o).hostname;if(m(`No --description given. The server will scrape ${r} and spend one AI generation from this month’s quota.`),!l()&&!await C(`Continue?`,{assumeYes:t.yes===!0,initialValue:!0}))throw new n(`Cancelled.`,{exitCode:e.CANCELLED});h={url:o,keywords:f,...t.name?{name:t.name}:{}}}let g=await W(`Creating site…`,()=>E(h));if(l()){u(`site.create`,g);return}a(`Created ${d(g.id)} ${g.domain}`),i([[`description`,g.description?`${p===void 0?`generated`:`stored`} (${g.description.length} chars)`:`missing`],[`keywords`,L(g)]]),!g.description&&t.analyze!==!1&&(r(``),c(`Description generation failed. Mentions will be unscored ("Scoring skipped: website description missing").`),s(`retry: ${v.binName} site analyze --url ${g.url}`)),I(g).PENDING>0&&s(`Some keywords are PENDING. Price an upgrade: ${v.binName} keyword plan`)}async function J(e,n){let o={};if(n.name!==void 0&&(o.name=n.name),n.description!==void 0&&(o.description=await B(n.description)),Object.keys(o).length===0)throw t(`Nothing to update.`,`Pass --name, --description, or both`);let s=await W(`Updating site…`,()=>w(e,o));if(l()){u(`site.update`,s);return}a(`Updated ${d(s.id)} ${s.domain}`),i([[`name`,s.name||`—`],[`description`,s.description?`${s.description.length} characters`:`missing`]]),r(`Existing mentions are not rescored.`)}async function Y(t,i){let o=await W(`Loading site…`,()=>D(t)),{total:s}=await O({websiteId:o.id,statuses:[...x],includeLowRelevance:!0});if(i.yes!==!0&&(r(`This deletes ${o.domain}, its ${o.keywords.length} keyword${o.keywords.length===1?``:`s`} and ${s} collected mention${s===1?``:`s`}.`),(await S(`Type the domain to confirm`,{hint:`Pass --yes to delete without typing the domain`})).trim()!==o.domain))throw new n(`That is not "${o.domain}", nothing was deleted.`,{exitCode:e.CANCELLED});let c=await A(o.id);if(l()){u(`site.delete`,c);return}a(`Deleted`)}async function X(t){let r=R(t.url);if(m(`This spends one AI generation from this month’s quota unless a precomputed description exists for the domain. A failed generation is refunded.`),!l()&&!await C(`Continue?`,{assumeYes:t.yes===!0,initialValue:!0}))throw new n(`Cancelled.`,{exitCode:e.CANCELLED});let{description:i}=await W(`Analysing…`,()=>k({url:r}));if(l()){u(`site.analyze`,{description:i});return}process.stdout.write(`${i}\n`),s(`store it: ${_(`FORCE_TTY`)}=1 ${v.binName} site analyze --url ${r} | ${v.binName} site update <id> --description -`)}function Z(e){let t=e.command(`site`).alias(`sites`).description(`monitored websites and their keywords`);t.command(`list`).alias(`ls`).description(`list every monitored site`).action(async()=>{await G()}),t.command(`get <id>`).alias(`view`).description(`show one site with its full keyword table`).action(async e=>{await K(e)}),t.command(`create`).description(`start monitoring a website`).requiredOption(`--url <url>`,`the website to monitor`).option(`--name <name>`,`label for the site`).option(`-k, --keyword <keyword>`,`keyword to watch, repeatable`,M,[]).option(`--description <text>`,`what the site does; @file reads a file, - reads stdin`).option(`--no-analyze`,`send an empty description and skip the paid scrape`).action(async(e,t)=>{await q(t.optsWithGlobals())}),t.command(`update <id>`).description(`rename a site or replace its description`).option(`--name <name>`,`new label for the site`).option(`--description <text>`,`new description; @file reads a file, - reads stdin`).action(async(e,t)=>{await J(e,t)}),t.command(`delete <id>`).alias(`rm`).description(`delete a site, its keywords and every mention they produced`).action(async(e,t,n)=>{await Y(e,n.optsWithGlobals())}),t.command(`analyze`).description(`generate a site description from its URL`).requiredOption(`--url <url>`,`the website to read`).action(async(e,t)=>{await X(t.optsWithGlobals())})}export{R as assertWebsiteUrl,L as describeKeywords,I as keywordCounts,B as readDescription,Z as registerSiteCommands};
1
+ import{t as e}from"./exit-codes-IaZq17dv.js";import{f as t,n}from"./errors-Dkv23Z0t.js";import"./version-BPszCYbY.js";import"./color-BbAK7_Y7.js";import{c as r,f as i,g as a,h as o,i as s,n as c,o as l,p as u,r as d,s as f,u as p,v as m}from"./output-uP7GrsdR.js";import{n as h,t as g}from"./time-B5S7M7Dg.js";import{d as _}from"./config-Bg2ls0gu.js";import{t as v}from"./product-CXL7Ga4M.js";import"./http-ZFrs1UcT.js";import{f as y,r as b,u as x}from"./types-Bu8scNHe.js";import{i as S,n as C}from"./prompt-DR68wwvQ.js";import{T as w,_ as T,a as E,h as D,i as O,r as k,s as A}from"./client-CVesEwEU.js";import{a as j,t as M}from"./keyword-DrmAAuXc.js";import{resolve as N}from"node:path";import{readFile as P}from"node:fs/promises";const F=[`ACTIVE`,`PENDING`,`DISABLED`,`SUSPENDED`];function I(e){let t={ACTIVE:0,PENDING:0,DISABLED:0,SUSPENDED:0};for(let n of e.keywords)t[n.status]+=1;return t}function L(e){let t=I(e),n=F.filter(e=>t[e]>0).map(e=>`${t[e]} ${e.toLowerCase()}`);return n.length===0?`none`:n.join(`, `)}function R(e,n=`--url`){let r=e.trim(),i;try{i=new URL(r)}catch{throw t(`${n} must be a full URL, got "${e}"`,`${v.binName} site create --url https://acme.com`)}if(i.protocol!==`https:`&&i.protocol!==`http:`)throw t(`${n} must be an http or https URL, got "${e}"`);return r}async function z(){let e=[];for await(let t of process.stdin)e.push(t);return Buffer.concat(e).toString(`utf8`)}async function B(e){let n=(e===`-`?await z():e.startsWith(`@`)?await V(e.slice(1)):e).trim();if(n.length>b)throw t(`--description is ${n.length} characters, the limit is ${b}`);return n}async function V(t){try{return await P(N(t),`utf8`)}catch(r){throw new n(`Cannot read ${t}: ${r.message}`,{exitCode:e.USAGE,cause:r})}}const H=[{header:`ID`,value:e=>d(e.id)},{header:`DOMAIN`,value:e=>e.domain},{header:`NAME`,value:e=>e.name||`—`},{header:`KEYWORDS`,value:e=>L(e)},{header:`DESCRIPTION`,value:e=>e.description?`yes`:`missing`}],U=[{header:`ID`,value:e=>d(e.id)},{header:`KEYWORD`,value:e=>e.value},{header:`STATUS`,value:e=>e.status},{header:`ADDED`,value:e=>e.createdAt?h(new Date(e.createdAt)):`—`}];async function W(e,t){let n=f()||l()?null:y(e);try{return await t()}finally{n?.stop()}}async function G(){let{websites:e}=await W(`Loading sites…`,T);if(l()){u(`site.list`,e,{total:e.length,hasMore:!1}),p(e);return}if(e.length===0){r(`No sites yet.`),s(`add one: ${v.binName} site create --url https://acme.com -k "your keyword"`);return}o(e,H),r(``),r(`${e.length} ${e.length===1?`site`:`sites`}`);for(let t of e)t.description||(m(`${t.domain} has no description. Its mentions are not scored.`),s(` fix: ${v.binName} site analyze --url ${t.url}`));let t=e.reduce((e,t)=>e+I(t).PENDING,0);s(`Listing sites activates any PENDING keyword that fits your plan’s free headroom.`),t>0&&s(`${t} keyword${t===1?``:`s`} still PENDING, there was no free slot. Price an upgrade: ${v.binName} keyword plan`)}async function K(e){let t=await W(`Loading site…`,()=>D(e));if(l()){u(`site.get`,t);return}r(t.id),i([[`domain`,t.domain],[`url`,t.url],[`name`,t.name||`—`],[`description`,t.description?`${t.description.length} characters`:`missing, mentions are not scored`],[`keywords`,L(t)],[`created`,t.createdAt?g(new Date(t.createdAt),{timezone:`UTC`}):`—`]]),t.keywords.length>0&&(r(``),o(t.keywords,U)),t.description||(r(``),s(`fix: ${v.binName} site analyze --url ${t.url}`))}async function q(t){let o=R(t.url),f=j(t.keyword),p=t.description===void 0?void 0:await B(t.description),h;if(p!==void 0)h={url:o,keywords:f,description:p,...t.name?{name:t.name}:{}};else if(t.analyze===!1)h={url:o,keywords:f,description:``,...t.name?{name:t.name}:{}},m(`--no-analyze sends an empty description, so nothing this site collects will be scored.`);else{let r=new URL(o).hostname;if(m(`No --description given. The server will scrape ${r} and spend one AI generation from this month’s quota.`),!l()&&!await C(`Continue?`,{assumeYes:t.yes===!0,initialValue:!0}))throw new n(`Cancelled.`,{exitCode:e.CANCELLED});h={url:o,keywords:f,...t.name?{name:t.name}:{}}}let g=await W(`Creating site…`,()=>E(h));if(l()){u(`site.create`,g);return}a(`Created ${d(g.id)} ${g.domain}`),i([[`description`,g.description?`${p===void 0?`generated`:`stored`} (${g.description.length} chars)`:`missing`],[`keywords`,L(g)]]),!g.description&&t.analyze!==!1&&(r(``),c(`Description generation failed. Mentions will be unscored ("Scoring skipped: website description missing").`),s(`retry: ${v.binName} site analyze --url ${g.url}`)),I(g).PENDING>0&&s(`Some keywords are PENDING. Price an upgrade: ${v.binName} keyword plan`)}async function J(e,n){let o={};if(n.name!==void 0&&(o.name=n.name),n.description!==void 0&&(o.description=await B(n.description)),Object.keys(o).length===0)throw t(`Nothing to update.`,`Pass --name, --description, or both`);let s=await W(`Updating site…`,()=>w(e,o));if(l()){u(`site.update`,s);return}a(`Updated ${d(s.id)} ${s.domain}`),i([[`name`,s.name||`—`],[`description`,s.description?`${s.description.length} characters`:`missing`]]),r(`Existing mentions are not rescored.`)}async function Y(t,i){let o=await W(`Loading site…`,()=>D(t)),{total:s}=await O({websiteId:o.id,statuses:[...x],includeLowRelevance:!0});if(i.yes!==!0&&(r(`This deletes ${o.domain}, its ${o.keywords.length} keyword${o.keywords.length===1?``:`s`} and ${s} collected mention${s===1?``:`s`}.`),(await S(`Type the domain to confirm`,{hint:`Pass --yes to delete without typing the domain`})).trim()!==o.domain))throw new n(`That is not "${o.domain}", nothing was deleted.`,{exitCode:e.CANCELLED});let c=await A(o.id);if(l()){u(`site.delete`,c);return}a(`Deleted`)}async function X(t){let r=R(t.url);if(m(`This spends one AI generation from this month’s quota unless a precomputed description exists for the domain. A failed generation is refunded.`),!l()&&!await C(`Continue?`,{assumeYes:t.yes===!0,initialValue:!0}))throw new n(`Cancelled.`,{exitCode:e.CANCELLED});let{description:i}=await W(`Analysing…`,()=>k({url:r}));if(l()){u(`site.analyze`,{description:i});return}process.stdout.write(`${i}\n`),s(`store it: ${_(`FORCE_TTY`)}=1 ${v.binName} site analyze --url ${r} | ${v.binName} site update <id> --description -`)}function Z(e){let t=e.command(`site`).alias(`sites`).description(`monitored websites and their keywords`);t.command(`list`).alias(`ls`).description(`list every monitored site`).action(async()=>{await G()}),t.command(`get <id>`).alias(`view`).description(`show one site with its full keyword table`).action(async e=>{await K(e)}),t.command(`create`).description(`start monitoring a website`).requiredOption(`--url <url>`,`the website to monitor`).option(`--name <name>`,`label for the site`).option(`-k, --keyword <keyword>`,`keyword to watch, repeatable`,M,[]).option(`--description <text>`,`what the site does; @file reads a file, - reads stdin`).option(`--no-analyze`,`send an empty description and skip the paid scrape`).action(async(e,t)=>{await q(t.optsWithGlobals())}),t.command(`update <id>`).description(`rename a site or replace its description`).option(`--name <name>`,`new label for the site`).option(`--description <text>`,`new description; @file reads a file, - reads stdin`).action(async(e,t)=>{await J(e,t)}),t.command(`delete <id>`).alias(`rm`).description(`delete a site, its keywords and every mention they produced`).action(async(e,t,n)=>{await Y(e,n.optsWithGlobals())}),t.command(`analyze`).description(`generate a site description from its URL`).requiredOption(`--url <url>`,`the website to read`).action(async(e,t)=>{await X(t.optsWithGlobals())})}export{R as assertWebsiteUrl,L as describeKeywords,I as keywordCounts,B as readDescription,Z as registerSiteCommands};
@@ -1 +1 @@
1
- import{r as e}from"./version-CFnbqWhw.js";import{c as t,r as n}from"./color-BbAK7_Y7.js";import{D as r,d as i,y as a}from"./config-Bg2ls0gu.js";import{t as o}from"./product-CXL7Ga4M.js";const s=1440*60*1e3,c=2e3,l=`https://registry.npmjs.org`;function u(e,t){let n=e=>{let[t,n]=e.replace(/^v/,``).split(`-`,2);return{parts:t.split(`.`).map(e=>Number.parseInt(e,10)||0),pre:n??``}},r=n(e),i=n(t);for(let e=0;e<3;e+=1){let t=(r.parts[e]??0)-(i.parts[e]??0);if(t!==0)return t<0?-1:1}return r.pre===i.pre?0:r.pre===``?1:i.pre===``||r.pre<i.pre?-1:1}async function d(e=o.npmPackage,t=c){let n=await fetch(`${l}/${e.replace(`/`,`%2f`)}/latest`,{headers:{accept:`application/vnd.npm.install-v1+json, application/json`},signal:AbortSignal.timeout(t)});if(!n.ok)return;let r=await n.json();return typeof r.version==`string`?r.version:void 0}function f(e){return e.quiet||process.env.CI||process.env[i(`NO_UPDATE_CHECK`)]?!0:e.force?!1:!process.stdout.isTTY}async function p(t={}){if(f(t))return;let n=t.now??Date.now(),i;try{i=a()}catch{return}if(i.updateCheck===!1)return;let o=i.lastUpdateCheck,c=o?.checked?Date.parse(o.checked):NaN,l=!t.force&&Number.isFinite(c)&&n-c<s,p=l?o?.latest:void 0;if(!l){let e;try{e=await d()}catch{return}if(!e)return;p=e;let t={checked:new Date(n).toISOString(),latest:e};try{r(e=>{e.lastUpdateCheck=t})}catch{return}}if(p&&!(u(p,e)<=0))return{current:e,latest:p}}function m(e){process.stderr.write(`${t(`A new version of ${o.binName} is available: ${e.latest}`)} ${n(`(you have ${e.current})`)}\n`),process.stderr.write(n(`Update: npm i -g ${o.npmPackage} · disable: ${o.binName} config set updateCheck false\n`))}async function h(e={}){try{let t=await p(e);t&&m(t)}catch{return}}export{u as a,h as c,p as i,s as n,d as o,c as r,m as s,l as t};
1
+ import{r as e}from"./version-BPszCYbY.js";import{c as t,r as n}from"./color-BbAK7_Y7.js";import{D as r,d as i,y as a}from"./config-Bg2ls0gu.js";import{t as o}from"./product-CXL7Ga4M.js";const s=1440*60*1e3,c=2e3,l=`https://registry.npmjs.org`;function u(e,t){let n=e=>{let[t,n]=e.replace(/^v/,``).split(`-`,2);return{parts:t.split(`.`).map(e=>Number.parseInt(e,10)||0),pre:n??``}},r=n(e),i=n(t);for(let e=0;e<3;e+=1){let t=(r.parts[e]??0)-(i.parts[e]??0);if(t!==0)return t<0?-1:1}return r.pre===i.pre?0:r.pre===``?1:i.pre===``||r.pre<i.pre?-1:1}async function d(e=o.npmPackage,t=c){let n=await fetch(`${l}/${e.replace(`/`,`%2f`)}/latest`,{headers:{accept:`application/vnd.npm.install-v1+json, application/json`},signal:AbortSignal.timeout(t)});if(!n.ok)return;let r=await n.json();return typeof r.version==`string`?r.version:void 0}function f(e){return e.quiet||process.env.CI||process.env[i(`NO_UPDATE_CHECK`)]?!0:e.force?!1:!process.stdout.isTTY}async function p(t={}){if(f(t))return;let n=t.now??Date.now(),i;try{i=a()}catch{return}if(i.updateCheck===!1)return;let o=i.lastUpdateCheck,c=o?.checked?Date.parse(o.checked):NaN,l=!t.force&&Number.isFinite(c)&&n-c<s,p=l?o?.latest:void 0;if(!l){let e;try{e=await d()}catch{return}if(!e)return;p=e;let t={checked:new Date(n).toISOString(),latest:e};try{r(e=>{e.lastUpdateCheck=t})}catch{return}}if(p&&!(u(p,e)<=0))return{current:e,latest:p}}function m(e){process.stderr.write(`${t(`A new version of ${o.binName} is available: ${e.latest}`)} ${n(`(you have ${e.current})`)}\n`),process.stderr.write(n(`Update: npm i -g ${o.npmPackage} · disable: ${o.binName} config set updateCheck false\n`))}async function h(e={}){try{let t=await p(e);t&&m(t)}catch{return}}export{u as a,h as c,p as i,s as n,d as o,c as r,m as s,l as t};
@@ -1 +1 @@
1
- import"./exit-codes-IaZq17dv.js";import"./errors-Dkv23Z0t.js";import"./version-CFnbqWhw.js";import"./color-BbAK7_Y7.js";import"./config-Bg2ls0gu.js";import"./product-CXL7Ga4M.js";import{a as e,c as t,i as n,n as r,o as i,r as a,s as o,t as s}from"./update-check-CkjowHze.js";export{s as REGISTRY_URL,r as UPDATE_CHECK_INTERVAL_MS,a as UPDATE_CHECK_TIMEOUT_MS,n as checkForUpdate,e as compareSemver,i as fetchLatestVersion,o as printUpdateNotice,t as runUpdateCheck};
1
+ import"./exit-codes-IaZq17dv.js";import"./errors-Dkv23Z0t.js";import"./version-BPszCYbY.js";import"./color-BbAK7_Y7.js";import"./config-Bg2ls0gu.js";import"./product-CXL7Ga4M.js";import{a as e,c as t,i as n,n as r,o as i,r as a,s as o,t as s}from"./update-check-CALr-1_t.js";export{s as REGISTRY_URL,r as UPDATE_CHECK_INTERVAL_MS,a as UPDATE_CHECK_TIMEOUT_MS,n as checkForUpdate,e as compareSemver,i as fetchLatestVersion,o as printUpdateNotice,t as runUpdateCheck};
@@ -1 +1 @@
1
- const e=`0.1.1`,t=process.versions.node,n=`${process.platform}-${process.arch}`;function r(r){return`${r}/${e} node-v${t} ${n}`}function i(r){return`${r}-cli/${e} node/${t} ${n}`}export{r as a,i,n,e as r,t};
1
+ const e=`0.1.2`,t=process.versions.node,n=`${process.platform}-${process.arch}`;function r(r){return`${r}/${e} node-v${t} ${n}`}function i(r){return`${r}-cli/${e} node/${t} ${n}`}export{r as a,i,n,e as r,t};
@@ -0,0 +1 @@
1
+ import{a as e,i as t,n,r,t as i}from"./version-BPszCYbY.js";export{i as NODE_VERSION,n as PLATFORM,r as VERSION,t as userAgent,e as versionLine};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redreplier/cli",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "RedReplier from your terminal",
5
5
  "keywords": [
6
6
  "cli",
@@ -1 +0,0 @@
1
- import"./exit-codes-IaZq17dv.js";import"./errors-Dkv23Z0t.js";import"./version-CFnbqWhw.js";import"./color-BbAK7_Y7.js";import"./output-uP7GrsdR.js";import"./config-Bg2ls0gu.js";import"./product-CXL7Ga4M.js";import"./http-Bryxg3iu.js";import"./types-Bu8scNHe.js";import"./prompt-DR68wwvQ.js";import"./client-jT4mvZ9E.js";import{a as e,i as t,n,o as r,r as i,t as a}from"./keyword-D5EhLCMO.js";export{a as collectKeyword,n as findKeyword,i as formatMoney,t as normalizeKeyword,e as normalizeKeywords,r as registerKeywordCommands};
@@ -1 +0,0 @@
1
- import{a as e,i as t,n,r,t as i}from"./version-CFnbqWhw.js";export{i as NODE_VERSION,n as PLATFORM,r as VERSION,t as userAgent,e as versionLine};