agent-afk 2.3.0 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.mjs +1 -1
  2. package/package.json +12 -12
package/dist/cli.mjs CHANGED
@@ -1905,7 +1905,7 @@ complete -c afk -l trigger -x -a '${n}' -d 'Trigger type'`}function Tp(e){e.comm
1905
1905
  `);return r.length>0&&r[r.length-1]===""&&r.pop(),r.slice(-t)}catch{return[]}}function Lv(e){try{if(process.platform==="linux"){let t=`/proc/${e}/stat`;if(!$t(t))return{};let r=Mo(t,"utf-8").split(" "),o=Number.parseInt(r[21]??"0",10),l=Rv("/proc/1").mtimeMs/1e3+o/100,c=Math.floor(Date.now()/1e3-l),p=Mo(`/proc/${e}/status`,"utf-8").match(/VmRSS:\s+(\d+)\s+kB/),m=p?Math.round(Number.parseInt(p[1]??"0",10)/1024):void 0;return{uptimeSec:c,memoryMb:m}}if(process.platform==="darwin"){let{execFileSync:t}=Bp("child_process"),n=t("ps",["-p",String(e),"-o","etime=,rss="],{encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim(),[r,o]=n.split(/\s+/);return{uptimeSec:Fv(r??""),memoryMb:o?Math.round(Number.parseInt(o,10)/1024):void 0}}}catch{}return{}}function Fv(e){if(!e)return;let t=e.split("-"),n=0,r=e;t.length===2&&(n=Number.parseInt(t[0]??"0",10),r=t[1]??"");let o=r.split(":").map(l=>Number.parseInt(l,10));if(o.some(l=>!Number.isFinite(l)))return;let s=0,a=0,i=0;if(o.length===3)[s,a,i]=o;else if(o.length===2)[a,i]=o;else if(o.length===1)[i]=o;else return;return n*86400+s*3600+a*60+i}import{createInterface as Nv}from"readline";import te from"chalk";var Cp="https://api.telegram.org";async function Pp(e){try{let t=await fetch(`${Cp}/bot${e}/getMe`);if(!t.ok)return null;let n=await t.json();return!n.ok||!n.result?.id||!n.result?.first_name?null:{id:n.result.id,...n.result.username!==void 0?{username:n.result.username}:{},firstName:n.result.first_name}}catch{return null}}function Uv(e){let t=new Map;for(let n of e){let o=(n.message??n.edited_message)?.chat;!o||typeof o.id!="number"||t.set(o.id,{chatId:o.id,type:o.type??"unknown",...o.username!==void 0?{username:o.username}:{},...o.first_name!==void 0?{firstName:o.first_name}:{}})}return[...t.values()].reverse()}async function jv(e){try{let t=await fetch(`${Cp}/bot${e}/getUpdates`);if(!t.ok)return[];let n=await t.json();return!n.ok||!Array.isArray(n.result)?[]:n.result}catch{return[]}}async function Bv(e,t={}){let n=t.maxAttempts??30,r=t.intervalMs??2e3;for(let o=0;o<n;o++){let s=await jv(e),a=Uv(s);if(a.length>0)return a;o<n-1&&await new Promise(i=>setTimeout(i,r))}return[]}function bi(e){let t=Nv({input:process.stdin,output:process.stdout});return new Promise(n=>{t.question(e,r=>{t.close(),n(r.trim())})})}async function Ip(){let e=Ke();console.log(""),console.log(te.bold("\u{1F916} Telegram bot setup")),console.log(""),console.log(te.gray(`Config will be written to ${e}`)),console.log("");let t=process.env.TELEGRAM_BOT_TOKEN?.trim()??"",n=null;for(t&&(console.log(te.gray("Validating existing TELEGRAM_BOT_TOKEN...")),n=await Pp(t),n?console.log(te.green(`\u2713 Token valid for @${n.username??n.firstName} (id ${n.id})`)):(console.log(te.yellow("\u26A0 Existing TELEGRAM_BOT_TOKEN is invalid; prompting for a new one")),t=""));!n;)t=await bi("Paste your bot token (from @BotFather): "),t||(console.error(te.red("No token provided. Aborting.")),process.exit(1)),n=await Pp(t),n||console.log(te.red("\u2717 Token rejected by getMe. Try again or Ctrl-C to abort."));on(e,"TELEGRAM_BOT_TOKEN",t),console.log(te.green(`\u2713 Saved TELEGRAM_BOT_TOKEN \u2192 ${e}`)),console.log(""),console.log(te.bold("Now DM your bot to authorize your account."));let r=n.username?`@${n.username}`:`"${n.firstName}"`;console.log(` 1. Open Telegram and find ${te.cyan(r)}`),console.log(' 2. Send any message (e.g. "hi")'),console.log(""),console.log(te.gray("Polling for your chat ID (up to 60s)..."));let o=await Bv(t);if(o.length===0){console.error(te.red("\u2717 No chats found after 60s.")),console.error(te.gray(" Send a message to the bot and run `afk telegram setup` again,")),console.error(te.gray(" or paste your chat ID manually:"));let a=await bi("Chat ID: "),i=Number.parseInt(a,10);return Number.isFinite(i)||(console.error(te.red("Invalid chat ID. Aborting.")),process.exit(1)),on(e,"AFK_TELEGRAM_ALLOWED_CHAT_IDS",String(i)),console.log(te.green(`\u2713 Saved AFK_TELEGRAM_ALLOWED_CHAT_IDS=${i}`)),{envPath:e,bot:n,chatId:i}}let s=o[0];if(o.length>1){console.log(te.bold(`
1906
1906
  Multiple chats found:`)),o.forEach((l,c)=>{let u=l.username?`@${l.username}`:l.firstName??l.type;console.log(` [${c+1}] ${u} (id ${l.chatId}, ${l.type})`)});let a=await bi("Which chat should be allowed? [1]: "),i=Number.parseInt(a||"1",10)-1;Number.isFinite(i)&&i>=0&&i<o.length&&(s=o[i])}else{let a=s.username?`@${s.username}`:s.firstName??s.type;console.log(te.green(`\u2713 Found chat with ${a} (id ${s.chatId})`))}return on(e,"AFK_TELEGRAM_ALLOWED_CHAT_IDS",String(s.chatId)),console.log(te.green(`\u2713 Saved AFK_TELEGRAM_ALLOWED_CHAT_IDS=${s.chatId} \u2192 ${e}`)),console.log(""),console.log(te.bold("Setup complete. Start the bot with:")),console.log(te.cyan(" afk telegram start")),console.log(""),{envPath:e,bot:n,chatId:s.chatId}}function _p(e){let t=e.command("telegram").description("Manage the Agent AFK Telegram bot (setup, start, stop, status)");t.command("setup").description("Interactive setup: validate bot token, discover chat ID, persist to ~/.afk/config/afk.env").action(async()=>{try{await Ip()}catch(n){console.error(Q.red(`Setup failed: ${n.message}`)),process.exit(1)}}),t.command("start").description("Start the bot as a background daemon").action(async()=>{let n=await hi();if(n.kind==="started"){console.log(Q.green(`\u2713 Bot started (PID ${n.pid})`)),console.log(Q.gray(` Logs: ${n.logFile}`)),console.log(Q.gray(" Tail with: afk telegram logs --follow"));return}if(n.kind==="already-running"&&(console.log(Q.yellow(`\u26A0 ${n.message}`)),process.exit(1)),n.kind==="exited-immediately"){if(console.error(Q.red(`\u2717 ${n.message}`)),n.logTail&&n.logTail.length>0){console.error(""),console.error(Q.bold("Last log entries:"));for(let r of n.logTail)console.error(Q.gray(` ${r}`))}process.exit(1)}console.error(Q.red(`\u2717 ${n.message}`)),process.exit(1)}),t.command("stop").description("Stop the bot (SIGTERM, then SIGKILL after 5s)").action(async()=>{let n=await yi();if(n.kind==="not-running"){console.log(Q.yellow("\u26A0 Bot is not running"));return}if(n.kind==="stopped"){console.log(Q.green(`\u2713 Bot stopped (PID ${n.pid})`));return}console.log(Q.yellow(`\u26A0 Bot force-killed (PID ${n.pid}); graceful shutdown timed out`))}),t.command("restart").description("Stop and restart the bot").action(async()=>{let n=await yi();(n.kind==="stopped"||n.kind==="force-killed")&&console.log(Q.gray(`Stopped (PID ${n.pid})`));let r=await hi();if(r.kind==="started"){console.log(Q.green(`\u2713 Bot restarted (PID ${r.pid})`));return}console.error(Q.red(`\u2717 Restart failed: ${r.message}`)),process.exit(1)}),t.command("status").description("Show running state, uptime, memory, and recent log entries").action(()=>{let n=ki();Gv(n)}),t.command("logs").description("Show or follow the bot log").option("-f, --follow","Stream new log entries (like tail -f)",!1).option("-n, --lines <count>","Number of trailing lines to show","50").action(n=>{let{logFile:r}=ki();if(!Wv(r)){console.log(Q.yellow(`No log file at ${r}`)),console.log(Q.gray("Start the bot first: afk telegram start"));return}let o=Number.parseInt(n.lines??"50",10);if(n.follow){Hv("tail",["-n",String(o),"-f",r],{stdio:"inherit"}).on("error",i=>{console.error(Q.red(`Failed to spawn tail: ${i.message}`))});return}let s=Kv(r,"utf-8").split(`
1907
1907
  `).slice(-o-1);console.log(s.join(`
1908
- `))})}function Gv(e){if(console.log(Q.bold("\u{1F4CA} Telegram Bot Status")),console.log(""),e.running?(console.log(` ${Q.green("\u25CF")} Running (PID ${e.pid})`),e.uptimeSec!==void 0&&console.log(` Uptime: ${zv(e.uptimeSec)}`),e.memoryMb!==void 0&&console.log(` Memory: ${e.memoryMb} MB`)):console.log(` ${Q.red("\u25CF")} Stopped`),console.log(` PID: ${e.pidFile}`),console.log(` Logs: ${e.logFile}`),e.logTail&&e.logTail.length>0){console.log(""),console.log(Q.bold("Recent log entries:"));for(let t of e.logTail)console.log(Q.gray(` ${t}`))}}function zv(e){if(e<60)return`${e}s`;let t=Math.floor(e/60);if(t<60)return`${t}m ${e%60}s`;let n=Math.floor(t/60);return n<24?`${n}h ${t%60}m`:`${Math.floor(n/24)}d ${n%24}h`}import{readFileSync as qv}from"fs";import{dirname as Vv,join as Yv}from"path";import{fileURLToPath as Jv}from"url";function Wn(){try{return"2.3.0"}catch{}try{let e=Vv(Jv(import.meta.url));for(let t of["../../package.json","../package.json"])try{let n=JSON.parse(qv(Yv(e,t),"utf-8"));if(typeof n.version=="string")return n.version}catch{}}catch{}return"0.0.0-unknown"}import{spawn as Mp}from"child_process";import{existsSync as Xv,mkdirSync as Qv,readFileSync as Rp,unlinkSync as Zv,writeFileSync as ex}from"fs";import{join as $p}from"path";var tx=1440*60*1e3,nx="update-check.json",rx="pending-update.json";function Op(){return $p(Vn(),nx)}function wi(){return $p(Vn(),rx)}function Dp(){let e=Vn();Xv(e)||Qv(e,{recursive:!0})}function ox(e,t){let n=e.split(".").map(Number),r=t.split(".").map(Number),o=Math.max(n.length,r.length);for(let s=0;s<o;s++){let a=n[s]??0,i=r[s]??0;if(i>a)return!0;if(i<a)return!1}return!1}function sx(){try{let e=Rp(Op(),"utf-8"),t=JSON.parse(e);if(typeof t.latestVersion=="string"&&typeof t.checkedAt=="number")return t}catch{}return null}function ix(){try{Dp();let e=`
1908
+ `))})}function Gv(e){if(console.log(Q.bold("\u{1F4CA} Telegram Bot Status")),console.log(""),e.running?(console.log(` ${Q.green("\u25CF")} Running (PID ${e.pid})`),e.uptimeSec!==void 0&&console.log(` Uptime: ${zv(e.uptimeSec)}`),e.memoryMb!==void 0&&console.log(` Memory: ${e.memoryMb} MB`)):console.log(` ${Q.red("\u25CF")} Stopped`),console.log(` PID: ${e.pidFile}`),console.log(` Logs: ${e.logFile}`),e.logTail&&e.logTail.length>0){console.log(""),console.log(Q.bold("Recent log entries:"));for(let t of e.logTail)console.log(Q.gray(` ${t}`))}}function zv(e){if(e<60)return`${e}s`;let t=Math.floor(e/60);if(t<60)return`${t}m ${e%60}s`;let n=Math.floor(t/60);return n<24?`${n}h ${t%60}m`:`${Math.floor(n/24)}d ${n%24}h`}import{readFileSync as qv}from"fs";import{dirname as Vv,join as Yv}from"path";import{fileURLToPath as Jv}from"url";function Wn(){try{return"2.3.1"}catch{}try{let e=Vv(Jv(import.meta.url));for(let t of["../../package.json","../package.json"])try{let n=JSON.parse(qv(Yv(e,t),"utf-8"));if(typeof n.version=="string")return n.version}catch{}}catch{}return"0.0.0-unknown"}import{spawn as Mp}from"child_process";import{existsSync as Xv,mkdirSync as Qv,readFileSync as Rp,unlinkSync as Zv,writeFileSync as ex}from"fs";import{join as $p}from"path";var tx=1440*60*1e3,nx="update-check.json",rx="pending-update.json";function Op(){return $p(Vn(),nx)}function wi(){return $p(Vn(),rx)}function Dp(){let e=Vn();Xv(e)||Qv(e,{recursive:!0})}function ox(e,t){let n=e.split(".").map(Number),r=t.split(".").map(Number),o=Math.max(n.length,r.length);for(let s=0;s<o;s++){let a=n[s]??0,i=r[s]??0;if(i>a)return!0;if(i<a)return!1}return!1}function sx(){try{let e=Rp(Op(),"utf-8"),t=JSON.parse(e);if(typeof t.latestVersion=="string"&&typeof t.checkedAt=="number")return t}catch{}return null}function ix(){try{Dp();let e=`
1909
1909
  const https = require('https');
1910
1910
  const fs = require('fs');
1911
1911
  const url = 'https://registry.npmjs.org/agent-afk/latest';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-afk",
3
- "version": "2.3.0",
3
+ "version": "2.3.1",
4
4
  "description": "CLI tool for interacting with AI agents via multiple interfaces",
5
5
  "main": "dist/index.mjs",
6
6
  "type": "module",
@@ -58,17 +58,17 @@
58
58
  "postinstall": "node dist/postinstall.mjs || true",
59
59
  "build": "tsc && node scripts/copy-prompts.js",
60
60
  "dev": "tsx watch src/cli/index.ts",
61
- "start": "node dist/cli.mjs",
62
- "start:chat": "node dist/cli.mjs chat",
63
- "start:interactive": "node dist/cli.mjs interactive",
64
- "start:status": "node dist/cli.mjs status",
65
- "telegram": "node dist/cli.mjs telegram start",
66
- "telegram:setup": "node dist/cli.mjs telegram setup",
67
- "telegram:start": "node dist/cli.mjs telegram start",
68
- "telegram:stop": "node dist/cli.mjs telegram stop",
69
- "telegram:status": "node dist/cli.mjs telegram status",
70
- "telegram:restart": "node dist/cli.mjs telegram restart",
71
- "telegram:logs": "node dist/cli.mjs telegram logs",
61
+ "start": "node dist/cli/index.js",
62
+ "start:chat": "node dist/cli/index.js chat",
63
+ "start:interactive": "node dist/cli/index.js interactive",
64
+ "start:status": "node dist/cli/index.js status",
65
+ "telegram": "node dist/cli/index.js telegram start",
66
+ "telegram:setup": "node dist/cli/index.js telegram setup",
67
+ "telegram:start": "node dist/cli/index.js telegram start",
68
+ "telegram:stop": "node dist/cli/index.js telegram stop",
69
+ "telegram:status": "node dist/cli/index.js telegram status",
70
+ "telegram:restart": "node dist/cli/index.js telegram restart",
71
+ "telegram:logs": "node dist/cli/index.js telegram logs",
72
72
  "test": "vitest run",
73
73
  "test:integration": "vitest run tests/integration",
74
74
  "test:e2e": "vitest run tests/e2e",