agent-afk 2.22.2 → 2.24.0
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/dist/cli.mjs +60 -60
- package/dist/index.mjs +88 -88
- package/dist/postinstall.mjs +34 -0
- package/dist/telegram.mjs +108 -108
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var vh=Object.defineProperty;var Th=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,n)=>(typeof require<"u"?require:t)[n]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var yl=(e,t)=>()=>(e&&(t=e(e=0)),t);var xh=(e,t)=>{for(var n in t)vh(e,n,{get:t[n],enumerable:!0})};function _o(e,t=()=>{}){let n=new Set;if(!e)return n;for(let r of e.split(",")){let o=r.trim();if(o){if(!/^-?\d+$/.test(o)){t("[allowlist] Ignoring non-numeric chat ID:",o);continue}n.add(Number(o))}}return n}var Wi=yl(()=>{"use strict"});var lu={};xh(lu,{push:()=>Ro,pushIfConfigured:()=>Io});async function Ro(e){if(!e.token)throw new Error("push: token is required");if(e.chatId===""||e.chatId==null||e.chatId===0)throw new Error("push: chatId is required");let t=e.fetchImpl??fetch,r=`${e.apiBase??Gw}/bot${e.token}/sendMessage`,o={chat_id:e.chatId,text:e.text.slice(0,4096)};e.parseMode&&(o.parse_mode=e.parseMode),e.replyMarkup&&(o.reply_markup=e.replyMarkup);let s=new AbortController,a=setTimeout(()=>s.abort(),1e4);try{let i=await t(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(o),signal:s.signal});if(i.ok)return{ok:!0,status:i.status};let l;try{l=(await i.json()).description}catch{l=`HTTP ${i.status}`}return{ok:!1,status:i.status,...l!==void 0?{errorMessage:l}:{}}}catch(i){return{ok:!1,status:0,errorMessage:i instanceof Error?i.message:String(i)}}finally{clearTimeout(a)}}async function Io(e,t={}){let n=process.env.TELEGRAM_BOT_TOKEN;if(!n)return null;let r=_o(process.env.AFK_TELEGRAM_ALLOWED_CHAT_IDS);if(r.size===0)return null;let o=[];for(let s of r)o.push(await Ro({token:n,chatId:s,text:e,...t.parseMode!==void 0?{parseMode:t.parseMode}:{},...t.replyMarkup!==void 0?{replyMarkup:t.replyMarkup}:{},...t.fetchImpl!==void 0?{fetchImpl:t.fetchImpl}:{}}));return o}var Gw,Mo=yl(()=>{"use strict";Wi();Gw="https://api.telegram.org"});import{config as gl}from"dotenv";import{existsSync as bl,mkdirSync as Eh,renameSync as Ch}from"fs";import{join as G,dirname as kl}from"path";import{homedir as Ys}from"os";import{fileURLToPath as Ph}from"url";function ge(){return process.env.AFK_HOME||G(Ys(),".afk")}function lt(){return G(ge(),"agent-framework")}function yn(){return G(lt(),"forge-telemetry.jsonl")}function bt(){return G(lt(),"briefs")}function Ur(){return G(lt(),"ceiling-ledger")}function jr(){return G(ge(),"skills")}function we(){return G(ge(),"plugins")}function wl(){return G(process.cwd(),".afk")}function Sl(){return G(wl(),"skills")}function Vs(){return G(wl(),"plugins")}function Y(){return G(we(),".index.json")}function ct(){return G(we(),"cache")}function Jn(e){return G(ct(),e)}function Js(){let e=Ph(import.meta.url),t=kl(e);return G(t,"bundled-plugins")}function Br(){return G(ge(),"config")}function qe(){return G(ge(),"state")}function Wr(){return G(ge(),"cache")}function Hr(){return G(ge(),"logs")}function kt(){return G(qe(),"sessions")}function Xs(){return G(qe(),"todos")}function Kr(){return G(qe(),"memory")}function Gr(){return G(qe(),"session-grants.jsonl")}function vl(){return G(ge(),"farms")}function Zs(e){return G(vl(),e)}function Tl(e){return G(qe(),"witness",e)}function xl(){return G(qe(),"worktree-sweep.lock")}function Ce(){return G(Br(),"afk.env")}function bn(){return G(Br(),"afk.config.json")}function El(){return G(Ys(),".afk.env")}function zr(){return G(Ys(),".afk.config.json")}function Ah(){return G(ge(),"sessions")}function _h(){return G(ge(),"todos")}function Cl(e,t){if(e!==t&&bl(e)&&!bl(t))try{Eh(kl(t),{recursive:!0}),Ch(e,t)}catch{}}function Pl(){Cl(Ah(),kt())}function Al(){Cl(_h(),Xs())}function Qs(){return G(qe(),"repl-history.jsonl")}import{Command as
|
|
2
|
+
var vh=Object.defineProperty;var Th=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,n)=>(typeof require<"u"?require:t)[n]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var yl=(e,t)=>()=>(e&&(t=e(e=0)),t);var xh=(e,t)=>{for(var n in t)vh(e,n,{get:t[n],enumerable:!0})};function _o(e,t=()=>{}){let n=new Set;if(!e)return n;for(let r of e.split(",")){let o=r.trim();if(o){if(!/^-?\d+$/.test(o)){t("[allowlist] Ignoring non-numeric chat ID:",o);continue}n.add(Number(o))}}return n}var Wi=yl(()=>{"use strict"});var lu={};xh(lu,{push:()=>Ro,pushIfConfigured:()=>Io});async function Ro(e){if(!e.token)throw new Error("push: token is required");if(e.chatId===""||e.chatId==null||e.chatId===0)throw new Error("push: chatId is required");let t=e.fetchImpl??fetch,r=`${e.apiBase??Gw}/bot${e.token}/sendMessage`,o={chat_id:e.chatId,text:e.text.slice(0,4096)};e.parseMode&&(o.parse_mode=e.parseMode),e.replyMarkup&&(o.reply_markup=e.replyMarkup);let s=new AbortController,a=setTimeout(()=>s.abort(),1e4);try{let i=await t(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(o),signal:s.signal});if(i.ok)return{ok:!0,status:i.status};let l;try{l=(await i.json()).description}catch{l=`HTTP ${i.status}`}return{ok:!1,status:i.status,...l!==void 0?{errorMessage:l}:{}}}catch(i){return{ok:!1,status:0,errorMessage:i instanceof Error?i.message:String(i)}}finally{clearTimeout(a)}}async function Io(e,t={}){let n=process.env.TELEGRAM_BOT_TOKEN;if(!n)return null;let r=_o(process.env.AFK_TELEGRAM_ALLOWED_CHAT_IDS);if(r.size===0)return null;let o=[];for(let s of r)o.push(await Ro({token:n,chatId:s,text:e,...t.parseMode!==void 0?{parseMode:t.parseMode}:{},...t.replyMarkup!==void 0?{replyMarkup:t.replyMarkup}:{},...t.fetchImpl!==void 0?{fetchImpl:t.fetchImpl}:{}}));return o}var Gw,Mo=yl(()=>{"use strict";Wi();Gw="https://api.telegram.org"});import{config as gl}from"dotenv";import{existsSync as bl,mkdirSync as Eh,renameSync as Ch}from"fs";import{join as G,dirname as kl}from"path";import{homedir as Ys}from"os";import{fileURLToPath as Ph}from"url";function ge(){return process.env.AFK_HOME||G(Ys(),".afk")}function lt(){return G(ge(),"agent-framework")}function yn(){return G(lt(),"forge-telemetry.jsonl")}function bt(){return G(lt(),"briefs")}function Ur(){return G(lt(),"ceiling-ledger")}function jr(){return G(ge(),"skills")}function we(){return G(ge(),"plugins")}function wl(){return G(process.cwd(),".afk")}function Sl(){return G(wl(),"skills")}function Vs(){return G(wl(),"plugins")}function Y(){return G(we(),".index.json")}function ct(){return G(we(),"cache")}function Jn(e){return G(ct(),e)}function Js(){let e=Ph(import.meta.url),t=kl(e);return G(t,"bundled-plugins")}function Br(){return G(ge(),"config")}function qe(){return G(ge(),"state")}function Wr(){return G(ge(),"cache")}function Hr(){return G(ge(),"logs")}function kt(){return G(qe(),"sessions")}function Xs(){return G(qe(),"todos")}function Kr(){return G(qe(),"memory")}function Gr(){return G(qe(),"session-grants.jsonl")}function vl(){return G(ge(),"farms")}function Zs(e){return G(vl(),e)}function Tl(e){return G(qe(),"witness",e)}function xl(){return G(qe(),"worktree-sweep.lock")}function Ce(){return G(Br(),"afk.env")}function bn(){return G(Br(),"afk.config.json")}function El(){return G(Ys(),".afk.env")}function zr(){return G(Ys(),".afk.config.json")}function Ah(){return G(ge(),"sessions")}function _h(){return G(ge(),"todos")}function Cl(e,t){if(e!==t&&bl(e)&&!bl(t))try{Eh(kl(t),{recursive:!0}),Ch(e,t)}catch{}}function Pl(){Cl(Ah(),kt())}function Al(){Cl(_h(),Xs())}function Qs(){return G(qe(),"repl-history.jsonl")}import{Command as w_}from"commander";import ei from"chalk";function _l(){let e=process.env.FORCE_COLOR;if(e&&e.length>0)return;let t=process.env.NO_COLOR;if(t&&t.length>0){ei.level=0;return}let n=process.env.CI;if(n&&n.length>0){ei.level=0;return}process.stdout.isTTY||(ei.level=0)}import mp from"chalk";import Wv from"ora";var De=class extends Error{constructor(t){super(t),this.name="AbortError"}},Fe=class extends Error{constructor(n,r){super(n);this.timeoutMs=r;this.name="TimeoutError"}timeoutMs},pe=class extends Error{constructor(n,r,o,s){super(n);this.event=r;this.reason=o;this.name="HookBlockedError",s?.cause!==void 0&&(this.cause=s.cause)}event;reason;cause};var wt=class extends Error{constructor(n,r,o){super(o??`Budget ceiling reached: $${n.toFixed(4)} cumulative >= $${r.toFixed(4)} limit`);this.runningCostUsd=n;this.maxBudgetUsd=r;this.name="BudgetExceededError"}runningCostUsd;maxBudgetUsd},qt=class extends Error{constructor(n,r,o){super(o??`${n} provider does not support AgentConfig.${r}.`);this.provider=n;this.field=r;this.name="UnsupportedProviderConfigError"}provider;field};import{execFileSync as Rl}from"child_process";import{existsSync as Rh,readFileSync as Ih,writeFileSync as Mh}from"fs";import{homedir as Il,userInfo as Ml}from"os";import{join as $l}from"path";var $h="9d1c250a-e61b-44d9-88ed-5944d1962f5e",Oh="https://platform.claude.com/v1/oauth/token",Dh=300*1e3;function Yt(){let e=Dl();if(e===void 0)return;let t=Fl(e);if(t!==void 0){if(t.expiresAt!==void 0&&t.expiresAt<=Date.now()){process.stderr.write("agent-afk: Claude Code OAuth token in keychain is expired. Run `claude login` to refresh.\n");return}return t.accessToken}}async function Ol(){let e=Dl();if(e===void 0)return;let t=Fl(e);if(t===void 0)return;if(t.expiresAt!==void 0&&t.expiresAt>Date.now()+Dh)return t.accessToken;if(!t.refreshToken){process.stderr.write("agent-afk: OAuth token expired and no refresh token available. Run `claude login` to refresh.\n");return}let n=await Fh(t.refreshToken);if(!n){process.stderr.write("agent-afk: OAuth token refresh failed. Run `claude login` to refresh.\n");return}try{let r={};try{r=JSON.parse(e)}catch{}let o=r.claudeAiOauth??{};r.claudeAiOauth={...o,accessToken:n.accessToken,expiresAt:n.expiresAt,...n.refreshToken!==void 0?{refreshToken:n.refreshToken}:{}},Lh(JSON.stringify(r))}catch{process.stderr.write(`agent-afk: Refreshed OAuth token but failed to write back to credential store.
|
|
3
3
|
`)}return n.accessToken}function Dl(){if(process.platform==="darwin")try{return Rl("security",["find-generic-password","-s","Claude Code-credentials","-a",Ml().username,"-w"],{stdio:["ignore","pipe","ignore"],encoding:"utf-8"}).trim()}catch{return}if(process.platform==="linux"){let e=$l(Il(),".claude",".credentials.json");if(!Rh(e))return;try{return Ih(e,"utf-8")}catch{return}}}function Fl(e){let t;try{t=JSON.parse(e)}catch{return}if(typeof t!="object"||t===null)return;let n=t.claudeAiOauth;if(typeof n!="object"||n===null)return;let r=n,o=r.accessToken;if(typeof o!="string"||o.length===0)return;let s={accessToken:o},a=r.refreshToken;typeof a=="string"&&a.length>0&&(s.refreshToken=a);let i=r.expiresAt;return typeof i=="number"&&(s.expiresAt=i),s}async function Fh(e){try{let t=await fetch(Oh,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({grant_type:"refresh_token",refresh_token:e,client_id:$h})});if(!t.ok)return;let n=await t.json(),r=n.access_token,o=n.expires_in;if(typeof r!="string"||typeof o!="number")return;let s=n.refresh_token;return{accessToken:r,expiresAt:Date.now()+o*1e3,...typeof s=="string"&&s.length>0?{refreshToken:s}:{}}}catch{return}}function ti(e){if(!e||e.length<3)return"token:(unknown)";try{let n=e.split(".");if(n.length<2)throw new Error("not a JWT");let r=Buffer.from(n[1],"base64url").toString("utf-8"),o=JSON.parse(r),s=typeof o.email=="string"&&o.email||typeof o.sub=="string"&&o.sub||typeof o.account_id=="string"&&o.account_id||typeof o.preferred_username=="string"&&o.preferred_username;if(s)return s}catch{}return`token:${e.length>=8?e.slice(-8):e}`}function Lh(e){if(process.platform==="darwin")Rl("security",["add-generic-password","-U","-s","Claude Code-credentials","-a",Ml().username,"-w",e],{stdio:["ignore","ignore","ignore"]});else if(process.platform==="linux"){let t=$l(Il(),".claude",".credentials.json");Mh(t,e,"utf-8")}}function ni(e){if(!("status"in e))return null;let t=e.status;if(t===429){let n=e.message.split("|");if(n.length>=2){let r=parseInt(n[1].trim(),10);if(!isNaN(r)&&r>0)return{kind:"oauth-limit",resetsAt:new Date(r*1e3)}}return{kind:"oauth-limit-no-ts"}}return t===400&&e.message.includes("invalid_request_error")&&e.message.includes("credit balance")?{kind:"credit-exhausted"}:null}async function Ll(e){let{resetsAt:t,signal:n,readToken:r=Yt}=e,o=r(),s=t.getTime()+3e4;return new Promise(a=>{let i=()=>n.aborted?(a("aborted"),!0):Date.now()>=s?(a("timer"),!0):r()!==o?(a("hot-swap"),!0):!1;if(i())return;let l=setInterval(()=>{i()&&clearInterval(l)},3e4);n.addEventListener("abort",()=>{clearInterval(l),a("aborted")},{once:!0})})}function Nl(e){let t=e instanceof Error?e.message:String(e);return t.toLowerCase().includes("rate limit")||t.toLowerCase().includes("too many requests")}function Ul(e){let t=e instanceof Error?e.message:String(e);return t.toLowerCase().includes("network")||t.toLowerCase().includes("connect")||t.toLowerCase().includes("timeout")}function kn(e){if(e instanceof wt)return{kind:"budget_exceeded",userMessage:`Session stopped: cost ceiling reached ($${e.runningCostUsd.toFixed(4)} of $${e.maxBudgetUsd.toFixed(4)} limit).`,exitCode:1,raw:e};if(e instanceof qt)return{kind:"unsupported_config",userMessage:`The "${e.provider}" provider does not support this configuration option.`,hint:`Option "${e.field}" is not available for provider "${e.provider}". Switch to a compatible provider or remove the option.`,exitCode:1,raw:e};if(e instanceof pe)return{kind:"hook_blocked",userMessage:`A hook blocked the operation (event: ${e.event}).`,...e.reason!==void 0?{hint:e.reason}:{},exitCode:1,raw:e};if(e instanceof Fe){let s=Math.round(e.timeoutMs/1e3);return{kind:"timeout",userMessage:`The operation timed out after ${s} second${s!==1?"s":""}.`,hint:`Timeout: ${e.timeoutMs}ms (${s}s). Increase the timeout or retry.`,exitCode:124,raw:e}}let t=e,n=e instanceof Error?e.message:String(e),r=n.toLowerCase();return t.status===401||e instanceof Error&&e.name==="AuthenticationError"?{kind:"auth",userMessage:"Authentication failed. Check that your API key is valid and has not expired.",hint:"Verify the ANTHROPIC_API_KEY environment variable or run `afk login`.",exitCode:1,raw:e}:t.status===429||Nl(e)?{kind:"rate_limit",userMessage:"Anthropic rate limit reached. The request was rejected (HTTP 429).",hint:"Wait a moment and retry, or reduce the request frequency.",exitCode:1,raw:e}:n==="Not in a git repository."||r.includes("not in a git repository")?{kind:"not_git_repo",userMessage:"This command must be run from inside a git repository.",hint:"Run `git init` to initialise a repository, or change to a directory that is already a git repo.",exitCode:1,raw:e}:Ul(e)||r.includes("econnrefused")||r.includes("etimedout")?{kind:"network",userMessage:"Network error: unable to reach the API endpoint.",hint:"Check your internet connection and try again.",exitCode:1,raw:e}:{kind:"unknown",userMessage:(e instanceof Error?e.message:String(e))||"An unexpected error occurred.",exitCode:1,raw:e}}import Nh from"string-width";var ri=/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g,jl=typeof Intl<"u"&&"Segmenter"in Intl?new Intl.Segmenter(void 0,{granularity:"grapheme"}):null;function St(e){return e.replace(ri,"")}function j(e){return Nh(e)}function qr(e){return e.length===0?[]:jl?Array.from(jl.segment(e),t=>t.segment):Array.from(e)}function Uh(e){let t=[],n=0,r;for(ri.lastIndex=0;(r=ri.exec(e))!==null;){if(r.index>n)for(let o of qr(e.slice(n,r.index)))t.push({type:"text",value:o});t.push({type:"ansi",value:r[0]}),n=r.index+r[0].length}if(n<e.length)for(let o of qr(e.slice(n)))t.push({type:"text",value:o});return t}function he(e,t){let n=Math.max(0,t-j(e));return e+" ".repeat(n)}function jh(e,t){let n=Math.max(0,t-j(e));return" ".repeat(n)+e}function oi(e,t,n="left"){let r=Math.max(0,t-j(e));if(r===0)return e;if(n==="right")return jh(e,t);if(n==="center"){let o=Math.floor(r/2);return" ".repeat(o)+e+" ".repeat(r-o)}return he(e,t)}function se(e,t,n="\u2026"){if(t<=0)return"";if(j(e)<=t)return e;let r=j(n),o=Math.max(0,t-r),s=0,a="",i=!1;for(let l of Uh(e)){if(l.type==="ansi"){a+=l.value,i=!0;continue}let c=s+j(l.value);if(c>o)break;a+=l.value,s=c}return a+n+(i?"\x1B[0m":"")}function Bl(e,t){return Number.isFinite(e)?Math.max(0,Math.min(t,Math.trunc(e))):0}function si(e,t){let n=Bl(t,e.length);if(n===0||e.length===0)return 0;let r=0;for(let o of qr(e)){let s=r+o.length;if(s>=n)return r;r=s}return r}function Xn(e,t){let n=Bl(t,e.length);if(n>=e.length||e.length===0)return e.length;let r=0;for(let o of qr(e)){let s=r+o.length;if(r>=n||n>r&&n<s)return s;r=s}return e.length}import Yr from"chalk";import{Lexer as Gl}from"marked";import Bh from"chalk";import{createEmphasize as Wh,common as Hh}from"emphasize";import ye from"chalk";var p={brand:ye.hex("#E67E4C"),user:ye.cyan,tool:ye.hex("#7FB3D5"),toolArg:ye.dim.white,thinking:ye.italic.hex("#9B8FB5"),success:ye.green,error:ye.red,warning:ye.yellow,plan:ye.hex("#9F7CE0"),meta:ye.blackBright,info:ye.hex("#5BA8FF"),heading:ye.bold.cyan,label:ye.dim,dim:ye.dim,bold:ye.bold,italic:ye.italic};var Wl={keyword:p.brand,built_in:p.brand,literal:p.brand,tag:p.brand,string:p.user,regexp:p.user,attr:p.user,comment:p.meta,meta:p.meta,quote:p.meta,number:p.warning,function:p.tool,title:p.tool,class:p.tool,"selector-tag":p.tool};var Hl=Wh(Hh),Kh=2048,Gh=512,zh=32,dt=new Map;function qh(e){let t=dt.get(e);if(t!==void 0)return dt.delete(e),dt.set(e,t),t}function Yh(e,t){if(dt.has(e)&&dt.delete(e),dt.set(e,t),dt.size>zh){let n=dt.keys().next().value;n!==void 0&&dt.delete(n)}}function Kl(e,t){if(Bh.level===0||e.length>Kh)return e;let n=e.length<Gh,r=n?`${t} ${e}`:"";if(n){let s=qh(r);if(s!==void 0)return s}let o;try{if(!t||!Hl.registered(t))o=e;else{let s=Hl.highlight(t,e,Wl);o=typeof s?.value=="string"?s.value:e}}catch{o=e}return n&&Yh(r,o),o}import Vh from"wrap-ansi";function te(e,t){if(!Number.isFinite(t)||t<=0||t===Number.POSITIVE_INFINITY)return e;let n=Math.floor(t);return Vh(e,n,{hard:!1,trim:!1,wordWrap:!0})}function ii(e){return j(e)}function Jh(e,t,n){return oi(e,t,n??"left")}var zl=/^\/[A-Za-z][\w:-]*$/,Xh=/(?<=\s|^)(\/[A-Za-z][\w:-]*)(?=\s|[,.:;!?]?$|[,.:;!?]\s)/g;function vt(e){return e?e.map(t=>{switch(t.type){case"codespan":{let n=t.text;return zl.test(n)?p.brand(n):p.user(n)}case"strong":{let n=t;return p.bold(n.tokens?vt(n.tokens):n.text)}case"em":{let n=t;return p.italic(n.tokens?vt(n.tokens):n.text)}case"text":return t.text.replace(Xh,n=>p.brand(n));case"link":{let n=t,r=n.tokens?vt(n.tokens):n.text;return r===n.href?r:r+p.dim(` (${n.href})`)}case"escape":return t.text;default:return t.raw}}).join(""):""}var Zh=new Set(["code","table","blockquote","hr","html"]);function Tt(e){let t=Gl.lex(e);return t.some(r=>Zh.has(r.type))?e:t.map(r=>{switch(r.type){case"heading":{let o=r;return p.bold(vt(o.tokens))}case"list":return r.items.map(s=>{let i=s.tokens[0]?.tokens??[];return"\u2022 "+vt(i)}).join(", ");case"paragraph":return vt(r.tokens);case"text":{let o=r;return o.tokens?vt(o.tokens):o.text}case"space":return"";default:return r.raw}}).join("")}function Qe(e,t={}){let n=Gl.lex(e),r=Number.isFinite(t.maxWidth)?Math.floor(t.maxWidth??0):void 0;function o(a){return vt(a)}function s(a){return a.map(i=>{switch(i.type){case"heading":{let l=i,c=l.tokens?o(l.tokens):l.text;return l.depth===1?p.bold(p.info(`
|
|
4
4
|
`+c+`
|
|
5
5
|
`)):l.depth===2?p.heading(`
|
|
@@ -26,7 +26,7 @@ var vh=Object.defineProperty;var Th=(e=>typeof require<"u"?require:typeof Proxy<
|
|
|
26
26
|
`+p.error(n.message)),n&&n.stack&&process.env.DEBUG&&(r+=`
|
|
27
27
|
`+p.dim(n.stack)),r}formatSuccess(t){return p.success("\u2713 ")+t}formatInfo(t){return p.info("\u2139 ")+t}formatWarning(t){return p.warning("\u26A0 ")+t}formatCommand(t){return p.dim(t)}formatPrompt(t){return p.bold(p.plan(`afk (${t})`))+p.dim(" \u203A ")}formatModelInfo(t,n,r){return p.dim(`Model: ${Yr.white(t)} | Max tokens: ${Yr.white(n)} | Temperature: ${Yr.white(r)}`)}separator(t="\u2500",n=50){return p.dim(t.repeat(n))}formatHelp(t){let n=[];for(let r of t){n.push(p.heading(`
|
|
28
28
|
${r.title}`)),n.push(this.separator());for(let o of r.items)n.push(` ${o}`)}return n.join(`
|
|
29
|
-
`)}formatStreaming(t){return this.useColors,t}},
|
|
29
|
+
`)}formatStreaming(t){return this.useColors,t}},cR=new ai;function ee(){let e=process.stdout.columns;return typeof e=="number"&&e>0?e:80}var Jr=new Set,Vr=!1,Vt=null;function Qh(){for(let e of Jr)try{e()}catch{}}function ey(){Vt!==null&&clearTimeout(Vt),Vt=setTimeout(()=>{Vt=null,Qh()},150)}function ql(){ey()}function ty(e){return Jr.add(e),Vr||(process.stdout.on("resize",ql),Vr=!0),()=>{Jr.delete(e),Jr.size===0&&(Vr&&(process.stdout.off("resize",ql),Vr=!1),Vt!==null&&(clearTimeout(Vt),Vt=null))}}var xt={subscribe:ty};function Zn(){return Math.max(22,ee()-6)}function Yl(e,t){return se(e,t)}var ny={ok:p.success("\u25CF"),warn:p.warning("\u25CF"),error:p.error("\u25CF"),info:p.info("\u25C6")};function Vl(e,t){let o=t.reduce((w,C)=>Math.max(w,j(C.label)),0),s=t.reduce((w,C)=>Math.max(w,j(C.value)),0),a=o+4+2+s,i=Math.min(ee()-4,100),l=Math.max(44,j(e),a,i);l=Math.min(l,Zn());let c=l+4,u=p.dim,d=u("\u256D"+"\u2500".repeat(c)+"\u256E"),m=u("\u251C"+"\u2500".repeat(c)+"\u2524"),f=u("\u2570"+"\u2500".repeat(c)+"\u256F"),g=u("\u2502"),S=te(e,l).split(`
|
|
30
30
|
`).map(w=>g+" "+he(w,l)+" "+g),h=Math.max(1,l-o-4-2),b=t.map(w=>{let C=w.kind?ny[w.kind]+" ":" ",T=p.dim(he(Yl(w.label,o),o)),A=" ".repeat(4),x=Yl(w.value,h),v=he(x,h),E=T+A+C+v;return g+" "+E+" "+g});return[d,...S,m,...b,f].join(`
|
|
31
31
|
`)}function Jl(e){let t="Agent AFK",n=" \xB7 ",r=p.bold(t)+p.dim(n)+e.mode,o=t+n+e.mode,s=Math.min(ee()-4,120),a=Math.max(54,j(o)+4,s);a=Math.min(a,Zn());let i=a+4,l=p.dim,c=l("\u256D"+"\u2500".repeat(i)+"\u256E"),d=te(r,a).split(`
|
|
32
32
|
`).map(g=>l("\u2502")+" "+he(g,a)+" "+l("\u2502")),m=l("\u2570"+"\u2500".repeat(i)+"\u256F"),f=[c,...d,m];return e.metaLine!==void 0&&f.push(...te(p.dim(" "+e.metaLine),ee()).split(`
|
|
@@ -974,7 +974,7 @@ Don't refuse the flow; just clarify where the wizard runs.
|
|
|
974
974
|
Be terse and operational. The user is doing one-time setup; they want it done, not narrated. Confirm each step in one line, don't over-explain. Use \`\u2713\` for success, \`\u2717\` for failure, and code fences for any command they should run.
|
|
975
975
|
`}};function ie(e){let t=bc[e];if(!t){let n=Object.keys(bc).sort(),r=n.length>0?"Available: "+n.join(", "):"";throw new Error("Unknown skill: "+e+". "+r)}return t}var to=new Map;function Le(e){to.set(e.name,e)}function Se(e){let t=to.get(e);if(t)return t;let n=Array.from(to.keys()).sort(),r=n.length>0?`
|
|
976
976
|
Available skills: ${n.join(", ")}`:"";throw new Error(`Skill not found: ${e}${r}`)}function Qt(){return Array.from(to.keys()).sort()}var no=class{nodes=new Map;traceWriter;constructor(t){this.traceWriter=t}register(t,n){this.nodes.has(t)||this.nodes.set(t,{controller:n,children:new Set,listeners:new Set,cascading:!1})}has(t){return this.nodes.has(t)}getController(t){return this.nodes.get(t)?.controller}linkChild(t,n){let r=this.nodes.get(t),o=this.nodes.get(n);if(!r)throw new Error(`AbortGraph: parent ${t} not registered`);if(!o)throw new Error(`AbortGraph: child ${n} not registered`);if(o.parentId=t,r.children.add(n),r.controller.signal.aborted){o.controller.signal.aborted||(o.cascading=!0,o.controller.abort(r.controller.signal.reason));return}r.controller.signal.addEventListener("abort",()=>{let s=this.nodes.get(n);!s||s.parentId!==t||s.controller.signal.aborted||(s.cascading=!0,s.controller.abort(r.controller.signal.reason))},{once:!0}),o.controller.signal.addEventListener("abort",()=>{let s=this.nodes.get(n);if(!s||s.parentId!==t||s.cascading)return;let a=this.nodes.get(t);if(!a)return;let i={parentId:t,childId:n,reason:s.controller.signal.reason};for(let l of a.listeners)try{l(i)}catch{}},{once:!0})}onChildAborted(t,n){let r=this.nodes.get(t);if(!r)throw new Error(`AbortGraph: ${t} not registered`);return r.listeners.add(n),()=>{r.listeners.delete(n)}}abort(t,n,r="user_signal"){let o=this.nodes.get(t);if(!o||o.controller.signal.aborted)return;let s=[],a=[...o.children],i=new Set;for(;a.length;){let l=a.shift();if(i.has(l))continue;i.add(l);let c=this.nodes.get(l);if(c){c.cascading=!0,s.push(l);for(let u of c.children)a.push(u)}}Ql(this.traceWriter,{origin:r,cascadedTo:s,...n!==void 0?{reason:xy(n)}:{}}),o.controller.abort(n);for(let l of s){let c=this.nodes.get(l);c&&!c.controller.signal.aborted&&c.controller.abort(n)}}dispose(t){let n=this.nodes.get(t);if(n){n.parentId&&this.nodes.get(n.parentId)?.children.delete(t);for(let r of n.children){let o=this.nodes.get(r);o&&(o.parentId=void 0)}this.nodes.delete(t)}}};function xy(e){if(typeof e=="string")return e;if(e instanceof Error)return e.message;try{return JSON.stringify(e)}catch{return String(e)}}var ro=0,di=5e3;async function oo(e,t,n={}){if(!Number.isFinite(t)||t<=0)return e;let r,o=new Promise((s,a)=>{r=setTimeout(()=>{let i=n.label?` (${n.label})`:"",l=new Fe(`Operation timed out after ${t}ms${i}`,t);n.controller&&!n.controller.signal.aborted&&n.controller.abort(l),a(l)},t)});try{return await Promise.race([e,o])}finally{r!==void 0&&clearTimeout(r)}}async function Ct(e,t,n,r){if(!e)return;if(r.kind==="blocked"){await Sn(e,{hookEvent:t,decision:"block",...r.err.reason!==void 0?{reason:r.err.reason}:{},...t==="PreToolUse"&&n.toolName!==void 0?{blockedTool:n.toolName}:{}});return}let o=r.decision;await Sn(e,{hookEvent:t,decision:o.decision,...o.reason!==void 0?{reason:o.reason}:{},...o.injectContext!==void 0?{injectedContextBytes:Buffer.byteLength(o.injectContext,"utf8")}:{}})}async function kc(e,t,n={}){if(e)try{let r=await e.dispatch(t,n.signal);await Ct(n.traceWriter,"SubagentStart",{},{kind:"decision",decision:r})}catch(r){throw r instanceof pe&&await Ct(n.traceWriter,"SubagentStart",{},{kind:"blocked",err:r}),r}}async function wc(e,t,n={}){if(!e)return{};try{let r=await e.dispatch(t,n.signal);return await Ct(n.traceWriter,"SubagentStop",{},{kind:"decision",decision:r}),r}catch(r){return r instanceof pe&&await Ct(n.traceWriter,"SubagentStop",{},{kind:"blocked",err:r}),r instanceof pe||r instanceof De?(X(`SubagentStop hook swallowed ${r.name}: ${r.message}`),n.onError?.(r),{}):(X(`SubagentStop hook unexpected error: ${String(r)}`),n.onError?.(r instanceof Error?r:new Error(String(r))),{})}}async function ui(e,t,n={}){if(e)try{let r=await e.dispatch(t,n.signal);await Ct(n.traceWriter,"PreToolUse",{toolName:t.toolName},{kind:"decision",decision:r})}catch(r){throw r instanceof pe&&await Ct(n.traceWriter,"PreToolUse",{toolName:t.toolName},{kind:"blocked",err:r}),r}}async function pi(e,t,n={}){if(e)try{let r=await e.dispatch(t,n.signal);await Ct(n.traceWriter,"PostToolUse",{toolName:t.toolName},{kind:"decision",decision:r})}catch(r){if(r instanceof pe&&await Ct(n.traceWriter,"PostToolUse",{toolName:t.toolName},{kind:"blocked",err:r}),r instanceof pe||r instanceof De){X(`PostToolUse hook swallowed ${r.name}: ${r.message}`),n.onError?.(r);return}X(`PostToolUse hook unexpected error: ${String(r)}`),n.onError?.(r instanceof Error?r:new Error(String(r)))}}import{mkdir as Ey,writeFile as Cy}from"fs/promises";import{dirname as Py,join as Ay}from"path";function _y(){return Ay(lt(),"routing-decisions.jsonl")}async function Ne(e){if(!(process.env.VITEST||process.env.NODE_ENV==="test"))try{let t=_y();await Ey(Py(t),{recursive:!0});let r={ts:new Date().toISOString().split(".")[0]+"Z",surface:"afk"};for(let[s,a]of Object.entries(e))a!==void 0&&(r[s]=a);let o=JSON.stringify(r)+`
|
|
977
|
-
`;await Cy(t,o,{flag:"a"})}catch{}}import{AsyncLocalStorage as Ry}from"node:async_hooks";var Sc=new Ry;function vn(e,t){return Sc.run(e,t)}function Ye(){return Sc.getStore()}function vc(e){let t=Iy(e);return t!==void 0?t:My(e)}function Iy(e){let t=/```(?:json)?\s*([\s\S]*?)```/gi,n,r;for(;(r=t.exec(e))!==null;)n=r[1];if(n)return Tc(n.trim())}function My(e){for(let t=e.length-1;t>=0;t--){if(e[t]!=="}")continue;let n=$y(e,t);if(n===-1)continue;let r=e.slice(n,t+1),o=Tc(r);if(o!==void 0)return o}}function $y(e,t){let n=0,r=!1,o=!1;for(let s=t;s>=0;s--){let a=e[s];if(o){o=!1;continue}if(r){if(a==="\\"){o=!0;continue}a==='"'&&(r=!1);continue}if(a==='"'){r=!0;continue}if(a==="}")n++;else if(a==="{"&&(n--,n===0))return s}return-1}function Tc(e){try{return JSON.parse(e)}catch{return}}function mi(){return{toolCalls:[],toolResults:[],thinkingPresent:!1,turnCount:0}}function xc(e,t,n,r,o){if(!r)return{id:e,status:t,message:n,trace:o};let s=vc(n.content),a=r.safeParse(s);return a.success?{id:e,status:t,message:n,output:a.data,trace:o}:{id:e,status:"failed",message:n,error:new Error(`structured output did not match schema: ${a.error.message}`,{cause:a.error}),schemaError:a.error,trace:o}}function Ec(e,t,n,r){let o=n instanceof Error?n:new Error(String(n));return{id:e,status:t,error:o,trace:r}}function de(e){return`${e.status}${e.error?`: ${e.error.message}`:""}`}function Cc(e,t){let n=e;return t.partialOutput!==void 0&&t.partialOutput!==null&&(n.partialOutput=t.partialOutput),t.subagentId!==void 0&&(n.subagentId=t.subagentId),n}var so=class{constructor(t,n,r,o,s,a,i,l,c,u,d,m,f,g){this.id=t;this.session=n;this.controller=r;this.abortGraph=o;this.outputSchema=s;this.timeoutMs=a;this.hookRegistry=i;this.onTerminal=l;this.parentInputStreamRef=c;this.parentAbortSignal=u;this.agentType=d;this.traceWriter=g;this.progressSink=m,this.parentId=f}id;session;controller;abortGraph;outputSchema;timeoutMs;hookRegistry;onTerminal;parentInputStreamRef;parentAbortSignal;agentType;traceWriter;currentStatus="idle";inFlight=null;lastMessage;lastDurationMs;latestTerminalStatus;stopDispatched=!1;progressSink;parentId;currentTrace=mi();lastStreamedContent="";get status(){return this.currentStatus}async run(t){if(this.currentStatus==="running")throw new Error(`Subagent ${this.id} is already running`);if(this.currentStatus==="cancelled")throw new Error(`Subagent ${this.id} is cancelled`);this.currentStatus="running";let n=Date.now(),r=oo(this.streamToFinalMessage(t),this.timeoutMs,{controller:this.controller,label:this.id});this.inFlight=r;try{let o=await r;return this.lastMessage=o.content,this.lastDurationMs=Date.now()-n,this.currentStatus="succeeded",this.latestTerminalStatus="succeeded",Jt(this.traceWriter,{transition:"succeeded",subagentId:this.id,durationMs:this.lastDurationMs,turnCount:this.currentTrace.turnCount,outputBytes:Buffer.byteLength(this.lastMessage,"utf8")}),this.onTerminal(),o}catch(o){throw this.lastDurationMs=Date.now()-n,this.currentStatus!=="cancelled"&&(this.controller.signal.aborted?Jt(this.traceWriter,{transition:"cancelled",subagentId:this.id,source:"cascade"}):Jt(this.traceWriter,{transition:"failed",subagentId:this.id,errorClass:o instanceof Error?o.constructor.name:"Unknown",errorMessage:o instanceof Error?o.message:String(o),partialOutputBytes:Buffer.byteLength(this.lastStreamedContent,"utf8")}),this.currentStatus="failed",this.latestTerminalStatus="failed"),this.onTerminal(),o}finally{this.inFlight=null}}async streamToFinalMessage(t){let n,r;this.lastStreamedContent="",this.currentTrace=mi();let o=this.progressSink??Ye(),s={subagentId:this.id,...this.parentId!==void 0&&{parentId:this.parentId},...this.agentType!==void 0&&{agentType:this.agentType}};for await(let a of this.session.sendMessageStream(t)){if(o&&o(a,s),a.type==="chunk"){let i=a.chunk;i.type==="content"?this.lastStreamedContent+=i.content:i.type==="tool_use_detail"?this.currentTrace.toolCalls.push({id:i.toolUseId,name:i.toolName,inputBytes:Buffer.byteLength(i.toolInput,"utf8")}):i.type==="tool_result"?this.currentTrace.toolResults.push({toolUseId:i.toolUseId,isError:i.isError,truncated:i.truncated,sizeBytes:i.sizeBytes}):i.type==="thinking"&&(this.currentTrace.thinkingPresent=!0)}if(a.type==="message")n=a.message,this.currentTrace.turnCount++;else if(a.type==="error"){r=a.error;break}else if(a.type==="done"){if(typeof a.metadata?.usage=="object"&&a.metadata.usage!==null){let i=a.metadata.usage;this.currentTrace.usage={inputTokens:typeof i.input_tokens=="number"?i.input_tokens:void 0,outputTokens:typeof i.output_tokens=="number"?i.output_tokens:void 0,cacheReadTokens:typeof i.cache_read_input_tokens=="number"?i.cache_read_input_tokens:void 0,cacheCreationTokens:typeof i.cache_creation_input_tokens=="number"?i.cache_creation_input_tokens:void 0}}break}}if(r)throw r;if(n)return n;if(this.lastStreamedContent.length>0)return{role:"assistant",content:this.lastStreamedContent,timestamp:new Date};throw new Error(`Subagent ${this.id} produced no terminal message`)}async runToResult(t){try{let n=await this.run(t);return xc(this.id,this.currentStatus,n,this.outputSchema,this.currentTrace)}catch(n){let r=Ec(this.id,this.currentStatus,n,this.currentTrace);return this.lastStreamedContent.length>0&&(r.partialOutput=this.lastStreamedContent),r}}runInBackground(t,n){this.runToResult(t).then(r=>{n?.(r)})}async cancel(){if(this.currentStatus==="cancelled"||this.stopDispatched)return;let t=this.latestTerminalStatus??"cancelled";this.currentStatus="cancelled",Jt(this.traceWriter,{transition:"cancelled",subagentId:this.id,source:"explicit"});try{this.abortGraph.abort(this.id,"cancelled")}catch{}try{this.inFlight&&await this.session.interrupt()}catch{}try{await this.session.close()}finally{await this.dispatchStopAndRelease(t)}}async teardown(){if(this.stopDispatched)return;let t=this.latestTerminalStatus??"cancelled";try{this.inFlight&&await this.session.interrupt()}catch{}try{await this.session.close()}finally{await this.dispatchStopAndRelease(t)}}async dispatchStopAndRelease(t){if(this.stopDispatched){this.onTerminal();return}this.stopDispatched=!0;let n=await wc(this.hookRegistry,{event:"SubagentStop",subagentId:this.id,status:t,lastMessage:this.lastMessage,agentType:this.agentType,durationMs:this.lastDurationMs,trace:this.currentTrace},this.traceWriter?{traceWriter:this.traceWriter}:{});if(n.injectContext&&this.parentInputStreamRef)if(this.parentAbortSignal?.aborted)X(`Skipping SubagentStop injectContext for ${this.id}: parent is aborted`);else try{this.parentInputStreamRef.pushUserMessage(n.injectContext)}catch(r){X(`Failed to inject context from SubagentStop handler: ${String(r)}`)}this.onTerminal()}};var U=class{active=new Map;parentCanUseTool;hookRegistry;progressSink;parentApiKey;parentCwd;abortGraph;rootId;rootController;counter=0;constructor(t={}){if(this.parentCanUseTool=t.canUseTool,this.hookRegistry=t.hookRegistry,this.progressSink=t.progressSink,this.parentApiKey=t.apiKey,this.parentCwd=t.cwd,this.abortGraph=new no(t.traceWriter),this.rootId=`manager-root-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,this.rootController=new AbortController,this.abortGraph.register(this.rootId,this.rootController),t.parentAbortSignal){let n=t.parentAbortSignal;n.aborted?this.rootController.abort(n.reason):n.addEventListener("abort",()=>{this.rootController.signal.aborted||this.rootController.abort(n.reason)},{once:!0})}}list(){return[...this.active.values()].map(t=>({id:t.id,status:t.status}))}get(t){return this.active.get(t)}onChildAborted(t){return this.abortGraph.onChildAborted(this.rootId,t)}abortAll(t,n="user_signal"){this.abortGraph.abort(this.rootId,t,n)}async forkSubagent(t){let n=`${t.idPrefix??"subagent"}-${Date.now()}-${++this.counter}`,r=t.parent.sessionId,o=t.config.hookRegistry??this.hookRegistry;o&&await kc(o,{event:"SubagentStart",subagentId:n,parentSessionId:t.parent.sessionId},{signal:this.rootController.signal,...t.config.traceWriter?{traceWriter:t.config.traceWriter}:{}});let s=new AbortController;this.abortGraph.register(n,s),this.abortGraph.linkChild(this.rootId,n);let a={...t.config,resume:r,forkSession:r?!0:t.config.forkSession,abortSignal:s.signal,apiKey:t.config.apiKey||this.parentApiKey,...t.config.cwd===void 0&&this.parentCwd!==void 0?{cwd:this.parentCwd}:{},hookRegistry:t.config.hookRegistry??this.hookRegistry,permissionBubbler:t.config.permissionBubbler??(this.parentCanUseTool!==void 0&&t.config.canUseTool===void 0?{canUseTool:this.parentCanUseTool}:void 0)},i=new Ae(a),l=t.parent.getInputStreamRef?.(),c=t.parent.abortSignal,u=this.progressSink??Ye(),d=t.agentType?.trim()||void 0,m=t.parentId?.trim()||void 0,f=new so(n,i,s,this.abortGraph,t.outputSchema,t.config.timeoutMs??ro,o,()=>{this.active.delete(n),this.abortGraph.dispose(n)},l,c,d??t.idPrefix,u,m??t.parent.sessionId,t.config.traceWriter);this.active.set(n,f);let g=typeof t.config.model=="string"?t.config.model:JSON.stringify(t.config.model);return Jt(t.config.traceWriter,{transition:"started",subagentId:n,parentId:t.parent.sessionId??this.rootId,model:g,...a.tools?.allowedTools?{allowedTools:[...a.tools.allowedTools]}:{}}),await Ne({event:"subagent.dispatched",subagent_id:n,id_prefix:t.idPrefix,parent_session_id:t.parent.sessionId}),f}async kill(t){let n=this.active.get(t);return n?(await n.cancel(),!0):!1}async killAll(){await Promise.allSettled([...this.active.values()].map(t=>t.cancel()))}async teardownAll(){await Promise.allSettled([...this.active.values()].map(t=>t.teardown()))}};async function io(e,t={}){let{failFast:n=!0,teardown:r=!0}=t;if(e.length===0)return[];let o=new Array(e.length),s=new Set(e.map((i,l)=>l)),a=e.map((i,l)=>i.handle.runToResult(i.prompt).then(c=>{if(o[l]=c,s.delete(l),n&&c.status!=="succeeded")for(let u of s){let d=e[u];d&&d.handle.status==="running"&&d.handle.cancel().catch(()=>{})}}));return await Promise.all(a),r&&await Promise.allSettled(e.map(i=>i.handle.teardown())),o}import{fileURLToPath as Oy}from"node:url";import{dirname as Dy}from"node:path";var Fy=Oy(import.meta.url),EI=Dy(Fy),_e={name:"research-agent",systemPrompt:`---
|
|
977
|
+
`;await Cy(t,o,{flag:"a"})}catch{}}import{AsyncLocalStorage as Ry}from"node:async_hooks";var Sc=new Ry;function vn(e,t){return Sc.run(e,t)}function Ye(){return Sc.getStore()}function vc(e){let t=Iy(e);return t!==void 0?t:My(e)}function Iy(e){let t=/```(?:json)?\s*([\s\S]*?)```/gi,n,r;for(;(r=t.exec(e))!==null;)n=r[1];if(n)return Tc(n.trim())}function My(e){for(let t=e.length-1;t>=0;t--){if(e[t]!=="}")continue;let n=$y(e,t);if(n===-1)continue;let r=e.slice(n,t+1),o=Tc(r);if(o!==void 0)return o}}function $y(e,t){let n=0,r=!1,o=!1;for(let s=t;s>=0;s--){let a=e[s];if(o){o=!1;continue}if(r){if(a==="\\"){o=!0;continue}a==='"'&&(r=!1);continue}if(a==='"'){r=!0;continue}if(a==="}")n++;else if(a==="{"&&(n--,n===0))return s}return-1}function Tc(e){try{return JSON.parse(e)}catch{return}}function mi(){return{toolCalls:[],toolResults:[],thinkingPresent:!1,turnCount:0}}function xc(e,t,n,r,o){if(!r)return{id:e,status:t,message:n,trace:o};let s=vc(n.content),a=r.safeParse(s);return a.success?{id:e,status:t,message:n,output:a.data,trace:o}:{id:e,status:"failed",message:n,error:new Error(`structured output did not match schema: ${a.error.message}`,{cause:a.error}),schemaError:a.error,trace:o}}function Ec(e,t,n,r){let o=n instanceof Error?n:new Error(String(n));return{id:e,status:t,error:o,trace:r}}function de(e){return`${e.status}${e.error?`: ${e.error.message}`:""}`}function Cc(e,t){let n=e;return t.partialOutput!==void 0&&t.partialOutput!==null&&(n.partialOutput=t.partialOutput),t.subagentId!==void 0&&(n.subagentId=t.subagentId),n}var so=class{constructor(t,n,r,o,s,a,i,l,c,u,d,m,f,g){this.id=t;this.session=n;this.controller=r;this.abortGraph=o;this.outputSchema=s;this.timeoutMs=a;this.hookRegistry=i;this.onTerminal=l;this.parentInputStreamRef=c;this.parentAbortSignal=u;this.agentType=d;this.traceWriter=g;this.progressSink=m,this.parentId=f}id;session;controller;abortGraph;outputSchema;timeoutMs;hookRegistry;onTerminal;parentInputStreamRef;parentAbortSignal;agentType;traceWriter;currentStatus="idle";inFlight=null;lastMessage;lastDurationMs;latestTerminalStatus;stopDispatched=!1;progressSink;parentId;currentTrace=mi();lastStreamedContent="";get status(){return this.currentStatus}async run(t){if(this.currentStatus==="running")throw new Error(`Subagent ${this.id} is already running`);if(this.currentStatus==="cancelled")throw new Error(`Subagent ${this.id} is cancelled`);this.currentStatus="running";let n=Date.now(),r=oo(this.streamToFinalMessage(t),this.timeoutMs,{controller:this.controller,label:this.id});this.inFlight=r;try{let o=await r;return this.lastMessage=o.content,this.lastDurationMs=Date.now()-n,this.currentStatus="succeeded",this.latestTerminalStatus="succeeded",Jt(this.traceWriter,{transition:"succeeded",subagentId:this.id,durationMs:this.lastDurationMs,turnCount:this.currentTrace.turnCount,outputBytes:Buffer.byteLength(this.lastMessage,"utf8")}),this.onTerminal(),o}catch(o){throw this.lastDurationMs=Date.now()-n,this.currentStatus!=="cancelled"&&(this.controller.signal.aborted?Jt(this.traceWriter,{transition:"cancelled",subagentId:this.id,source:"cascade"}):Jt(this.traceWriter,{transition:"failed",subagentId:this.id,errorClass:o instanceof Error?o.constructor.name:"Unknown",errorMessage:o instanceof Error?o.message:String(o),partialOutputBytes:Buffer.byteLength(this.lastStreamedContent,"utf8")}),this.currentStatus="failed",this.latestTerminalStatus="failed"),this.onTerminal(),o}finally{this.inFlight=null}}async streamToFinalMessage(t){let n,r;this.lastStreamedContent="",this.currentTrace=mi();let o=this.progressSink??Ye(),s={subagentId:this.id,...this.parentId!==void 0&&{parentId:this.parentId},...this.agentType!==void 0&&{agentType:this.agentType}};for await(let a of this.session.sendMessageStream(t)){if(o&&o(a,s),a.type==="chunk"){let i=a.chunk;i.type==="content"?this.lastStreamedContent+=i.content:i.type==="tool_use_detail"?this.currentTrace.toolCalls.push({id:i.toolUseId,name:i.toolName,inputBytes:Buffer.byteLength(i.toolInput,"utf8")}):i.type==="tool_result"?this.currentTrace.toolResults.push({toolUseId:i.toolUseId,isError:i.isError,truncated:i.truncated,sizeBytes:i.sizeBytes}):i.type==="thinking"&&(this.currentTrace.thinkingPresent=!0)}if(a.type==="message")n=a.message,this.currentTrace.turnCount++;else if(a.type==="error"){r=a.error;break}else if(a.type==="done"){if(typeof a.metadata?.usage=="object"&&a.metadata.usage!==null){let i=a.metadata.usage;this.currentTrace.usage={inputTokens:typeof i.input_tokens=="number"?i.input_tokens:void 0,outputTokens:typeof i.output_tokens=="number"?i.output_tokens:void 0,cacheReadTokens:typeof i.cache_read_input_tokens=="number"?i.cache_read_input_tokens:void 0,cacheCreationTokens:typeof i.cache_creation_input_tokens=="number"?i.cache_creation_input_tokens:void 0}}break}}if(r)throw r;if(n)return n;if(this.lastStreamedContent.length>0)return{role:"assistant",content:this.lastStreamedContent,timestamp:new Date};throw new Error(`Subagent ${this.id} produced no terminal message`)}async runToResult(t){try{let n=await this.run(t);return xc(this.id,this.currentStatus,n,this.outputSchema,this.currentTrace)}catch(n){let r=Ec(this.id,this.currentStatus,n,this.currentTrace);return this.lastStreamedContent.length>0&&(r.partialOutput=this.lastStreamedContent),r}}runInBackground(t,n){this.runToResult(t).then(r=>{n?.(r)})}async cancel(){if(this.currentStatus==="cancelled"||this.stopDispatched)return;let t=this.latestTerminalStatus??"cancelled";this.currentStatus="cancelled",Jt(this.traceWriter,{transition:"cancelled",subagentId:this.id,source:"explicit"});try{this.abortGraph.abort(this.id,"cancelled")}catch{}try{this.inFlight&&await this.session.interrupt()}catch{}try{await this.session.close()}finally{await this.dispatchStopAndRelease(t)}}async teardown(){if(this.stopDispatched)return;let t=this.latestTerminalStatus??"cancelled";try{this.inFlight&&await this.session.interrupt()}catch{}try{await this.session.close()}finally{await this.dispatchStopAndRelease(t)}}async dispatchStopAndRelease(t){if(this.stopDispatched){this.onTerminal();return}this.stopDispatched=!0;let n=await wc(this.hookRegistry,{event:"SubagentStop",subagentId:this.id,status:t,lastMessage:this.lastMessage,agentType:this.agentType,durationMs:this.lastDurationMs,trace:this.currentTrace},this.traceWriter?{traceWriter:this.traceWriter}:{});if(n.injectContext&&this.parentInputStreamRef)if(this.parentAbortSignal?.aborted)X(`Skipping SubagentStop injectContext for ${this.id}: parent is aborted`);else try{this.parentInputStreamRef.pushUserMessage(n.injectContext)}catch(r){X(`Failed to inject context from SubagentStop handler: ${String(r)}`)}this.onTerminal()}};var U=class{active=new Map;parentCanUseTool;hookRegistry;progressSink;parentApiKey;parentCwd;abortGraph;rootId;rootController;counter=0;constructor(t={}){if(this.parentCanUseTool=t.canUseTool,this.hookRegistry=t.hookRegistry,this.progressSink=t.progressSink,this.parentApiKey=t.apiKey,this.parentCwd=t.cwd,this.abortGraph=new no(t.traceWriter),this.rootId=`manager-root-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,this.rootController=new AbortController,this.abortGraph.register(this.rootId,this.rootController),t.parentAbortSignal){let n=t.parentAbortSignal;n.aborted?this.rootController.abort(n.reason):n.addEventListener("abort",()=>{this.rootController.signal.aborted||this.rootController.abort(n.reason)},{once:!0})}}list(){return[...this.active.values()].map(t=>({id:t.id,status:t.status}))}get(t){return this.active.get(t)}onChildAborted(t){return this.abortGraph.onChildAborted(this.rootId,t)}abortAll(t,n="user_signal"){this.abortGraph.abort(this.rootId,t,n)}async forkSubagent(t){let n=`${t.idPrefix??"subagent"}-${Date.now()}-${++this.counter}`,r=t.parent.sessionId,o=t.config.hookRegistry??this.hookRegistry;o&&await kc(o,{event:"SubagentStart",subagentId:n,parentSessionId:t.parent.sessionId},{signal:this.rootController.signal,...t.config.traceWriter?{traceWriter:t.config.traceWriter}:{}});let s=new AbortController;this.abortGraph.register(n,s),this.abortGraph.linkChild(this.rootId,n);let a={...t.config,resume:r,forkSession:r?!0:t.config.forkSession,abortSignal:s.signal,apiKey:t.config.apiKey||this.parentApiKey,...t.config.cwd===void 0&&this.parentCwd!==void 0?{cwd:this.parentCwd}:{},hookRegistry:t.config.hookRegistry??this.hookRegistry,permissionBubbler:t.config.permissionBubbler??(this.parentCanUseTool!==void 0&&t.config.canUseTool===void 0?{canUseTool:this.parentCanUseTool}:void 0)},i=new Ae(a),l=t.parent.getInputStreamRef?.(),c=t.parent.abortSignal,u=this.progressSink??Ye(),d=t.agentType?.trim()||void 0,m=t.parentId?.trim()||void 0,f=new so(n,i,s,this.abortGraph,t.outputSchema,t.config.timeoutMs??ro,o,()=>{this.active.delete(n),this.abortGraph.dispose(n)},l,c,d??t.idPrefix,u,m??t.parent.sessionId,t.config.traceWriter);this.active.set(n,f);let g=typeof t.config.model=="string"?t.config.model:JSON.stringify(t.config.model);return Jt(t.config.traceWriter,{transition:"started",subagentId:n,parentId:t.parent.sessionId??this.rootId,model:g,...a.tools?.allowedTools?{allowedTools:[...a.tools.allowedTools]}:{}}),await Ne({event:"subagent.dispatched",subagent_id:n,id_prefix:t.idPrefix,parent_session_id:t.parent.sessionId}),f}async kill(t){let n=this.active.get(t);return n?(await n.cancel(),!0):!1}async killAll(){await Promise.allSettled([...this.active.values()].map(t=>t.cancel()))}async teardownAll(){await Promise.allSettled([...this.active.values()].map(t=>t.teardown()))}};async function io(e,t={}){let{failFast:n=!0,teardown:r=!0}=t;if(e.length===0)return[];let o=new Array(e.length),s=new Set(e.map((i,l)=>l)),a=e.map((i,l)=>i.handle.runToResult(i.prompt).then(c=>{if(o[l]=c,s.delete(l),n&&c.status!=="succeeded")for(let u of s){let d=e[u];d&&d.handle.status==="running"&&d.handle.cancel().catch(()=>{})}}));return await Promise.all(a),r&&await Promise.allSettled(e.map(i=>i.handle.teardown())),o}import{fileURLToPath as Oy}from"node:url";import{dirname as Dy}from"node:path";var Fy=Oy(import.meta.url),CI=Dy(Fy),_e={name:"research-agent",systemPrompt:`---
|
|
978
978
|
name: research-agent
|
|
979
979
|
description: Read-only sub-agent for research, validation, verification, and codebase inspection. Mechanically locked to Read, Grep, Glob, WebFetch, WebSearch \u2014 cannot Edit, Write, Bash, commit, or push. Delegates git queries to \`git-investigator\`. Use when the dispatched task is findings-only.
|
|
980
980
|
model: sonnet
|
|
@@ -1027,7 +1027,7 @@ Unless the dispatcher specifies a different schema, return:
|
|
|
1027
1027
|
**\`boundary_flag\` is required.** If nothing applies, emit \`"none"\` \u2014 do not omit the field. Treat missing as \`"none"\` is acceptable on the orchestrator side, but emit the field explicitly so downstream synthesizers and validators do not see \`null\`.
|
|
1028
1028
|
|
|
1029
1029
|
If \`scope_check\` flags implementation (non-git), the orchestrator should dispatch a different sub-agent type for follow-up. Do not re-dispatch the same task through \`research-agent\`.
|
|
1030
|
-
`,sourcePath:"agent-framework-private/agents/research-agent.md",allowedTools:["Read","Grep","Glob","WebFetch","WebSearch"],description:"Read-only sub-agent for research, validation, verification, and codebase inspection. Mechanically locked to Read, Grep, Glob, WebFetch, WebSearch \u2014 cannot Edit, Write, Bash, commit, or push. Delegates git queries to `git-investigator`. Use when the dispatched task is findings-only."};import{existsSync as At,readdirSync as Vy,readFileSync as Jy}from"fs";import{join as pt}from"path";import{existsSync as gi,readFileSync as Ky,readdirSync as Gy,statSync as zy}from"fs";import{join as nr,resolve as Ic}from"path";import{existsSync as Ac,mkdirSync as Ly,readFileSync as Ny,renameSync as Uy,writeFileSync as jy,unlinkSync as By}from"fs";import{dirname as Pc,join as Wy}from"path";import{randomBytes as Hy}from"crypto";function ne(e=Y()){if(!Ac(e))return ao();try{let t=Ny(e,"utf8"),n=JSON.parse(t);if(!n||typeof n!="object")return ao();let r=n,o=r.plugins&&typeof r.plugins=="object"?r.plugins:{};if(r.version===1)return{version:2,plugins:o,marketplaces:{}};if(r.version===2){let s=r.marketplaces&&typeof r.marketplaces=="object"?r.marketplaces:{};return{version:2,plugins:o,marketplaces:s}}return ao()}catch{return ao()}}function er(e,t=Y()){Ly(Pc(t),{recursive:!0});let n=Wy(Pc(t),`.index.json.${process.pid}.${Hy(4).toString("hex")}.tmp`),r=JSON.stringify(e,null,2);try{jy(n,r,"utf8"),Uy(n,t)}catch(o){try{Ac(n)&&By(n)}catch{}throw o}}function Pt(e,t,n=Y()){let r=ne(n);return r.plugins[e]=t,er(r,n),r}function _c(e,t=Y()){let n=ne(t);return e in n.plugins&&(delete n.plugins[e],er(n,t)),n}function fi(e,t,n=Y()){let r=ne(n),o=r.plugins[e];if(!o)throw new Error(`plugin "${e}" is not in the index`);return o.enabled=t,o.updatedAt=new Date().toISOString(),er(r,n),r}function tr(e,t,n=Y()){let r=ne(n);return r.marketplaces[e]=t,er(r,n),r}function Rc(e,t=Y()){let n=ne(t),r=!1;e in n.marketplaces&&(delete n.marketplaces[e],r=!0);for(let[o,s]of Object.entries(n.plugins))s.marketplace===e&&(delete n.plugins[o],r=!0);return r&&er(n,t),n}function ao(){return{version:2,plugins:{},marketplaces:{}}}var qy=5,Mc="cache";function ut(e=we()){if(!gi(e))return[];let t=e===we()?Y():nr(e,".index.json"),n=ne(t),r=[];return $c(e,e,0,r,new Set,n.plugins),r}function $c(e,t,n,r,o,s){if(n>qy||o.has(t))return;if(o.add(t),gi(nr(t,".claude-plugin","plugin.json"))){let i=hi(e,t);if(i===null){r.push({type:"local",path:t});return}if(i.layout==="cache"){let c=s[i.key];if(!c||c.enabled===!1)return;r.push({type:"local",path:t});return}let l=s[i.key];if(l&&l.enabled===!1)return;r.push({type:"local",path:t});return}let a;try{a=Gy(t)}catch{return}for(let i of a){if(i.startsWith("."))continue;let l=nr(t,i),c;try{c=zy(l)}catch{continue}c.isDirectory()&&$c(e,l,n+1,r,o,s)}}function hi(e,t){if(!t.startsWith(e))return null;let n=t.slice(e.length).replace(/^\/+/,"");if(!n)return null;let r=n.split("/").filter(s=>s.length>0);if(r.length===0)return null;if(r[0]===Mc&&r.length>=3){let s=r[1];if(s){let a=nr(e,Mc,s),l=Yy(a,t)??r[2];if(l)return{layout:"cache",key:`${s}:${l}`}}}let o=r[0];return o?{layout:"flat",key:o}:null}function Yy(e,t){let n=nr(e,".claude-plugin","marketplace.json");if(!gi(n))return null;let r;try{r=JSON.parse(Ky(n,"utf8"))}catch{return null}if(!r||typeof r!="object")return null;let o=r.plugins;if(!Array.isArray(o))return null;let s=Ic(t);for(let a of o){if(!a||typeof a!="object")continue;let i=a;if(!(typeof i.name!="string"||typeof i.source!="string")&&!(!i.source.startsWith("./")&&!i.source.startsWith("../"))&&Ic(e,i.source)===s)return i.name}return null}var Oc=["command","agent"];function Dc(e=ge()){let t=[],n=pt(e,"skills");if(At(n))for(let r of lo(n)){let o=pt(n,r,"SKILL.md");At(o)&&t.push({path:o,type:"skill",source:"user"})}for(let r of Oc){let o=pt(e,`${r}s`);if(At(o))for(let s of lo(o))s.endsWith(".md")&&t.push({path:pt(o,s),type:r,source:"user"})}return t}function Fc(e=we()){if(!At(e))return[];let t=[],n=ut(e);for(let r of n){let s=hi(e,r.path)?.key,a=pt(r.path,"skills");if(At(a))for(let i of lo(a)){let l=pt(a,i,"SKILL.md");if(!At(l))continue;let c={path:l,type:"skill",source:"plugin"};s&&(c.plugin_key=s),t.push(c)}for(let i of Oc){let l=pt(r.path,`${i}s`);if(At(l))for(let c of lo(l)){if(!c.endsWith(".md"))continue;let u={path:pt(l,c),type:i,source:"plugin"};s&&(u.plugin_key=s),t.push(u)}}}return t}function Lc(e=pt(ge(),"settings.json")){if(!At(e))return[];try{let t=Jy(e,"utf8"),r=JSON.parse(t).hooks;if(!r||typeof r!="object")return[];let o=[];for(let[s,a]of Object.entries(r))if(Array.isArray(a))for(let i=0;i<a.length;i++)o.push({event:s,index:i,raw:a[i]});return o}catch{return[]}}function lo(e){try{return Vy(e).filter(t=>!t.startsWith("."))}catch{return[]}}var Bc=ae.object({path:ae.string(),type:ae.enum(["skill","command","agent","hook"]),source:ae.enum(["user","plugin"]),plugin_key:ae.string().optional(),verdict:ae.enum(["correct","misfit","outlier"]),recommended_type:ae.string(),rationale:ae.string(),confidence:ae.enum(["high","med","low"])}),jc=ae.record(ae.string(),ae.record(ae.string(),ae.number())),
|
|
1030
|
+
`,sourcePath:"agent-framework-private/agents/research-agent.md",allowedTools:["Read","Grep","Glob","WebFetch","WebSearch"],description:"Read-only sub-agent for research, validation, verification, and codebase inspection. Mechanically locked to Read, Grep, Glob, WebFetch, WebSearch \u2014 cannot Edit, Write, Bash, commit, or push. Delegates git queries to `git-investigator`. Use when the dispatched task is findings-only."};import{existsSync as At,readdirSync as Vy,readFileSync as Jy}from"fs";import{join as pt}from"path";import{existsSync as gi,readFileSync as Ky,readdirSync as Gy,statSync as zy}from"fs";import{join as nr,resolve as Ic}from"path";import{existsSync as Ac,mkdirSync as Ly,readFileSync as Ny,renameSync as Uy,writeFileSync as jy,unlinkSync as By}from"fs";import{dirname as Pc,join as Wy}from"path";import{randomBytes as Hy}from"crypto";function ne(e=Y()){if(!Ac(e))return ao();try{let t=Ny(e,"utf8"),n=JSON.parse(t);if(!n||typeof n!="object")return ao();let r=n,o=r.plugins&&typeof r.plugins=="object"?r.plugins:{};if(r.version===1)return{version:2,plugins:o,marketplaces:{}};if(r.version===2){let s=r.marketplaces&&typeof r.marketplaces=="object"?r.marketplaces:{};return{version:2,plugins:o,marketplaces:s}}return ao()}catch{return ao()}}function er(e,t=Y()){Ly(Pc(t),{recursive:!0});let n=Wy(Pc(t),`.index.json.${process.pid}.${Hy(4).toString("hex")}.tmp`),r=JSON.stringify(e,null,2);try{jy(n,r,"utf8"),Uy(n,t)}catch(o){try{Ac(n)&&By(n)}catch{}throw o}}function Pt(e,t,n=Y()){let r=ne(n);return r.plugins[e]=t,er(r,n),r}function _c(e,t=Y()){let n=ne(t);return e in n.plugins&&(delete n.plugins[e],er(n,t)),n}function fi(e,t,n=Y()){let r=ne(n),o=r.plugins[e];if(!o)throw new Error(`plugin "${e}" is not in the index`);return o.enabled=t,o.updatedAt=new Date().toISOString(),er(r,n),r}function tr(e,t,n=Y()){let r=ne(n);return r.marketplaces[e]=t,er(r,n),r}function Rc(e,t=Y()){let n=ne(t),r=!1;e in n.marketplaces&&(delete n.marketplaces[e],r=!0);for(let[o,s]of Object.entries(n.plugins))s.marketplace===e&&(delete n.plugins[o],r=!0);return r&&er(n,t),n}function ao(){return{version:2,plugins:{},marketplaces:{}}}var qy=5,Mc="cache";function ut(e=we()){if(!gi(e))return[];let t=e===we()?Y():nr(e,".index.json"),n=ne(t),r=[];return $c(e,e,0,r,new Set,n.plugins),r}function $c(e,t,n,r,o,s){if(n>qy||o.has(t))return;if(o.add(t),gi(nr(t,".claude-plugin","plugin.json"))){let i=hi(e,t);if(i===null){r.push({type:"local",path:t});return}if(i.layout==="cache"){let c=s[i.key];if(!c||c.enabled===!1)return;r.push({type:"local",path:t});return}let l=s[i.key];if(l&&l.enabled===!1)return;r.push({type:"local",path:t});return}let a;try{a=Gy(t)}catch{return}for(let i of a){if(i.startsWith("."))continue;let l=nr(t,i),c;try{c=zy(l)}catch{continue}c.isDirectory()&&$c(e,l,n+1,r,o,s)}}function hi(e,t){if(!t.startsWith(e))return null;let n=t.slice(e.length).replace(/^\/+/,"");if(!n)return null;let r=n.split("/").filter(s=>s.length>0);if(r.length===0)return null;if(r[0]===Mc&&r.length>=3){let s=r[1];if(s){let a=nr(e,Mc,s),l=Yy(a,t)??r[2];if(l)return{layout:"cache",key:`${s}:${l}`}}}let o=r[0];return o?{layout:"flat",key:o}:null}function Yy(e,t){let n=nr(e,".claude-plugin","marketplace.json");if(!gi(n))return null;let r;try{r=JSON.parse(Ky(n,"utf8"))}catch{return null}if(!r||typeof r!="object")return null;let o=r.plugins;if(!Array.isArray(o))return null;let s=Ic(t);for(let a of o){if(!a||typeof a!="object")continue;let i=a;if(!(typeof i.name!="string"||typeof i.source!="string")&&!(!i.source.startsWith("./")&&!i.source.startsWith("../"))&&Ic(e,i.source)===s)return i.name}return null}var Oc=["command","agent"];function Dc(e=ge()){let t=[],n=pt(e,"skills");if(At(n))for(let r of lo(n)){let o=pt(n,r,"SKILL.md");At(o)&&t.push({path:o,type:"skill",source:"user"})}for(let r of Oc){let o=pt(e,`${r}s`);if(At(o))for(let s of lo(o))s.endsWith(".md")&&t.push({path:pt(o,s),type:r,source:"user"})}return t}function Fc(e=we()){if(!At(e))return[];let t=[],n=ut(e);for(let r of n){let s=hi(e,r.path)?.key,a=pt(r.path,"skills");if(At(a))for(let i of lo(a)){let l=pt(a,i,"SKILL.md");if(!At(l))continue;let c={path:l,type:"skill",source:"plugin"};s&&(c.plugin_key=s),t.push(c)}for(let i of Oc){let l=pt(r.path,`${i}s`);if(At(l))for(let c of lo(l)){if(!c.endsWith(".md"))continue;let u={path:pt(l,c),type:i,source:"plugin"};s&&(u.plugin_key=s),t.push(u)}}}return t}function Lc(e=pt(ge(),"settings.json")){if(!At(e))return[];try{let t=Jy(e,"utf8"),r=JSON.parse(t).hooks;if(!r||typeof r!="object")return[];let o=[];for(let[s,a]of Object.entries(r))if(Array.isArray(a))for(let i=0;i<a.length;i++)o.push({event:s,index:i,raw:a[i]});return o}catch{return[]}}function lo(e){try{return Vy(e).filter(t=>!t.startsWith("."))}catch{return[]}}var Bc=ae.object({path:ae.string(),type:ae.enum(["skill","command","agent","hook"]),source:ae.enum(["user","plugin"]),plugin_key:ae.string().optional(),verdict:ae.enum(["correct","misfit","outlier"]),recommended_type:ae.string(),rationale:ae.string(),confidence:ae.enum(["high","med","low"])}),jc=ae.record(ae.string(),ae.record(ae.string(),ae.number())),QI=ae.object({inventory:ae.object({user:jc,plugin:jc}),misfits:ae.array(Bc),briefs_written:ae.number(),total_artifacts:ae.number()}),Xy=ae.object({writeBriefs:ae.boolean().optional(),scope:ae.enum(["user","plugin","all"]).optional()}),Zy=["skill","command","agent"],Wc=["skill","command","agent","hook"];function Qy(e){return{runUserDiscovery:e!=="plugin",runPluginDiscovery:e!=="user",runHookInspector:e!=="plugin"}}function eb(e){let t=()=>{let s={};for(let a of Wc)s[a]={correct:0,misfit:0,outlier:0};return s},n={user:t(),plugin:t()};for(let s of e)n[s.source][s.type][s.verdict]+=1;let r={high:0,med:1,low:2},o=e.filter(s=>s.verdict==="misfit").slice().sort((s,a)=>r[s.confidence]-r[a.confidence]);return{inventory:n,misfits:o}}function tb(e){return e.verdict==="misfit"&&e.confidence==="high"&&e.source==="user"}function nb(e){let t=e.filter(o=>o.source==="user"),n=e.filter(o=>o.source==="plugin"),r=["","## Discovered artifacts (audit only these)",""];if(r.push('### User-scope artifacts (set `"source": "user"`, omit `plugin_key`)'),t.length===0)r.push("(none discovered)");else for(let o of t)r.push(`- ${o.path}`);if(r.push(""),r.push('### Plugin-scope artifacts (set `"source": "plugin"`, copy `plugin_key` from each entry)'),n.length===0)r.push("(none discovered)");else for(let o of n){let s=o.plugin_key??"<unknown>";r.push(`- ${o.path} (plugin_key: ${s})`)}return r.join(`
|
|
1031
1031
|
`)}function rb(e,t){let n=["","## Discovered hooks (audit only these)",""];if(n.push(`Settings file (use this absolute path verbatim in each verdict's \`path\` field): \`${e}\``),n.push(""),t.length===0)return n.push("(no hooks discovered)"),n.join(`
|
|
1032
1032
|
`);for(let r of t){let o=`${r.event}-${r.index}`;n.push(`### Hook \`${o}\``),n.push(""),n.push("```json"),n.push(JSON.stringify(r.raw,null,2)),n.push("```"),n.push("")}return n.join(`
|
|
1033
1033
|
`)}function ob(e,t){if(!t)return{kind:"failure",message:`${e}: no result`};if(t.schemaError)return{kind:"failure",message:`${e}: schema mismatch \u2014 ${t.schemaError.message}`};if(t.status!=="succeeded"){let n=t.error?` \u2014 ${t.error.message}`:"";return{kind:"failure",message:`${e}: ${t.status}${n}`}}return t.output?{kind:"success",output:t.output}:{kind:"failure",message:`${e}: no output`}}async function sb(e,t,n){let r=n?.apiKey,o=typeof e=="object"&&e!==null?e:{},s=Xy.parse(o),a=s.writeBriefs??!0,i=s.scope??"all",l=Qy(i);if(!t?.sessionId)throw new Error("audit-fit requires a parent session with sessionId");let c=t.sessionId,u=ie("audit-fit"),d={skill:u["01-skill-inspector.md"],command:u["02-command-inspector.md"],agent:u["03-agent-inspector.md"],hook:u["04-hook-inspector.md"]};for(let I of Wc)if(!d[I])throw new Error(`audit-fit skill missing inspector prompt for ${I}`);let m=l.runUserDiscovery?Dc():[],f=l.runPluginDiscovery?Fc():[],g={skill:[],command:[],agent:[]};for(let I of[...m,...f])g[I.type].push(I);let y=new U({apiKey:r}),S=()=>async I=>_e.allowedTools.includes(I)?{behavior:"allow"}:{behavior:"deny",message:`Tool ${I} not allowed for audit-fit inspectors. Allowed tools: ${_e.allowedTools.join(", ")}`},h=[];for(let I of Zy){let D=g[I];if(D.length===0)continue;let F=d[I];F&&h.push({type:I,prompt:`${F}
|
|
@@ -1059,7 +1059,7 @@ ${D.rationale}
|
|
|
1059
1059
|
---
|
|
1060
1060
|
Generated by audit-fit on ${new Date().toISOString().split(".")[0]}Z
|
|
1061
1061
|
`;await Uc(_,M),T++}}let A=lt();await Nc(A,{recursive:!0});let x=I=>{let D=0;for(let F of Object.values(I))for(let _ of Object.values(F))D+=_;return D},v=I=>{let D=w.user[I]??{},F=w.plugin[I]??{},_=M=>Object.values(M).reduce((N,V)=>N+V,0);return _(D)+_(F)},E={timestamp:new Date().toISOString(),surface:"afk",scope:i,total_artifacts:b.length,misfits_count:C.length,briefs_written:T,by_source:{user:x(w.user),plugin:x(w.plugin)},by_type:{skill:v("skill"),command:v("command"),agent:v("agent"),hook:v("hook")}},R=yi(A,"audit-fit-telemetry.jsonl");return await Uc(R,JSON.stringify(E)+`
|
|
1062
|
-
`),{inventory:w,misfits:C,briefs_written:T,total_artifacts:b.length}}var ib={name:"audit-fit",description:"Audit ~/.afk artifacts (skills, commands, agents, hooks) for correct type categorization. Walks user-scope dirs (~/.afk/{skills,commands,agents}/) and every plugin installed under ~/.afk/plugins/ (flat and marketplace-cache layouts), plus ~/.afk/settings.json for hooks. Dispatches per-type inspectors in parallel, applies decision heuristics (progressive-disclosure value, isolation need, deterministic vs. reasoning), flags misfits. Generates migration briefs only for user-scope misfits (plugin misfits are inventory-only \u2014 refactoring vendored plugin code is the maintainer's job). Optional `scope` input filters to `user`, `plugin`, or `all` (default). Use for inventory audits after bulk authoring, imports, or periodic hygiene.",handler:sb,argumentHint:"[--write-briefs]",whenToUse:"When the user wants ~/.afk artifacts (skills, commands, agents, hooks) audited for correct type categorization.",flags:["--write-briefs"]};Le(ib);import{z as B}from"zod";import{execFile as db}from"node:child_process";import{promisify as ub}from"node:util";import{tmpdir as pb}from"node:os";import{join as Kc}from"node:path";function Hc(e){return e.confidence<.5?{verify:!0,reason:`low confidence (${e.confidence.toFixed(2)} < ${.5})`}:e.boundary_flag&&e.boundary_flag.length>0?{verify:!0,reason:`boundary flag set: ${e.boundary_flag}`}:e.coverage_gaps&&e.coverage_gaps.length>0?{verify:!0,reason:`coverage gap${e.coverage_gaps.length===1?"":"s"}: ${e.coverage_gaps.length} unresolved`}:{verify:!1,reason:`confidence ${e.confidence.toFixed(2)} with no gaps or boundary`}}import{fileURLToPath as ab}from"node:url";import{dirname as lb}from"node:path";var cb=ab(import.meta.url),
|
|
1062
|
+
`),{inventory:w,misfits:C,briefs_written:T,total_artifacts:b.length}}var ib={name:"audit-fit",description:"Audit ~/.afk artifacts (skills, commands, agents, hooks) for correct type categorization. Walks user-scope dirs (~/.afk/{skills,commands,agents}/) and every plugin installed under ~/.afk/plugins/ (flat and marketplace-cache layouts), plus ~/.afk/settings.json for hooks. Dispatches per-type inspectors in parallel, applies decision heuristics (progressive-disclosure value, isolation need, deterministic vs. reasoning), flags misfits. Generates migration briefs only for user-scope misfits (plugin misfits are inventory-only \u2014 refactoring vendored plugin code is the maintainer's job). Optional `scope` input filters to `user`, `plugin`, or `all` (default). Use for inventory audits after bulk authoring, imports, or periodic hygiene.",handler:sb,argumentHint:"[--write-briefs]",whenToUse:"When the user wants ~/.afk artifacts (skills, commands, agents, hooks) audited for correct type categorization.",flags:["--write-briefs"]};Le(ib);import{z as B}from"zod";import{execFile as db}from"node:child_process";import{promisify as ub}from"node:util";import{tmpdir as pb}from"node:os";import{join as Kc}from"node:path";function Hc(e){return e.confidence<.5?{verify:!0,reason:`low confidence (${e.confidence.toFixed(2)} < ${.5})`}:e.boundary_flag&&e.boundary_flag.length>0?{verify:!0,reason:`boundary flag set: ${e.boundary_flag}`}:e.coverage_gaps&&e.coverage_gaps.length>0?{verify:!0,reason:`coverage gap${e.coverage_gaps.length===1?"":"s"}: ${e.coverage_gaps.length} unresolved`}:{verify:!1,reason:`confidence ${e.confidence.toFixed(2)} with no gaps or boundary`}}import{fileURLToPath as ab}from"node:url";import{dirname as lb}from"node:path";var cb=ab(import.meta.url),sM=lb(cb),bi={name:"git-investigator",systemPrompt:'---\nname: git-investigator\ndescription: Read-only git specialist. Dispatched by research-agent (or any research-shaped caller) when a finding requires git history, reflog, diff, blame, branch/remote state, or merge-base analysis. Runs git commands only \u2014 no mutations, no shell escapes.\nmodel: sonnet\ntools: Bash, Read, Grep, Glob\n---\n\nYou are `git-investigator`, a leaf sub-agent specialized for read-only git queries.\n\nYou have Bash, Read, Grep, and Glob. You do not dispatch other sub-agents. You do not Edit or Write. Your Bash surface is restricted **by this prompt** to `git ...` invocations and benign output-shaping pipes.\n\n## Allowed commands\n\nRead-only git only:\n\n- `git status`, `git log`, `git diff`, `git show`\n- `git rev-parse`, `git rev-list`, `git reflog`\n- `git branch -v / -vv / -a` (list only)\n- `git remote -v`, `git ls-remote`\n- `git ls-files`, `git blame`\n- `git merge-base`, `git for-each-ref`, `git describe`\n- `git cat-file`, `git shortlog`\n- `git tag` (list/show only)\n- `git stash list`, `git stash show`\n- `git config --get`, `git config --get-all`, `git config --list`\n- `git worktree list` (read only)\n\nOutput-shaping pipes are fine: `| head`, `| tail`, `| wc`, `| grep`, `| jq`, `| awk \'NR==...\'` (for formatting only \u2014 no mutations).\n\n## Forbidden\n\nAnything that mutates repo or working tree state:\n\n- `commit`, `push`, `pull`, `fetch --prune`\n- `reset`, `revert`, `rebase`, `merge`, `cherry-pick`\n- `checkout` (except `checkout -- <path>` file-restore, and even that is mutation \u2014 avoid it, just report the need)\n- `restore`, `switch`\n- `branch -d / -D / -m / -M`, `branch <new>`\n- `stash push / pop / drop / apply / clear`\n- `tag -d`, creating a new tag\n- `remote add / remove / set-url`\n- `config --set`, `config --unset`\n- `gc`, `fsck`, `prune`, `reflog delete`, `reflog expire`\n- `filter-branch`, `filter-repo`\n- `worktree add / remove / move`\n- `hooks install`, `submodule add / update`\n- Any non-`git` command that mutates: `rm`, `mv`, `cp` (writes), `sed -i`, `> file`, `>> file`, `tee`, `curl`, `wget`, `pip install`, shell builtins that change state.\n\nIf the caller asks for any of the above, do not run it. Return `scope_check: "requires mutation: <reason>"` and stop.\n\n## Behavior\n\n- Run the minimum set of commands needed. Prefer `git log -n 5 --oneline -- <path>` over `git log -- <path>` when a count is fine.\n- Cite concrete evidence: commit SHAs (short form OK), ref names, `path:line` references from blame, diff hunks trimmed to the relevant range.\n- Use `Read`/`Grep`/`Glob` for follow-up inspection of files the git output identifies (e.g., `git show SHA:path | head` then `Read` the current file to diff mentally).\n- Do not speculate beyond what the commands show. If a question needs history the commands don\'t surface (deleted-file recovery, ancient reflog that has expired), say so in `caveats`.\n- Keep output compact \u2014 dispatchers merge your findings into a larger response. No preamble, no ceremony.\n\n## Return shape\n\n```\n{\n "findings": "<summary of what the git data shows>",\n "evidence": ["<SHA>", "<ref>", "<path:line>", ...],\n "git_commands_run": ["git log ...", "git diff ...", ...],\n "caveats": "<gaps, ambiguity, or \'none\'>",\n "scope_check": "pure git research" | "requires mutation: <reason>"\n}\n```\n\nBegin your response with the first schema field. No preamble.\n',sourcePath:"agent-framework-private/agents/git-investigator.md",allowedTools:["Bash","Read","Grep","Glob"],description:"Read-only git specialist. Dispatched by research-agent (or any research-shaped caller) when a finding requires git history, reflog, diff, blame, branch/remote state, or merge-base analysis. Runs git commands only \u2014 no mutations, no shell escapes.",model:"sonnet"};function ki(e){let t={description:e.description,prompt:e.systemPrompt};return e.allowedTools&&(t.tools=[...e.allowedTools]),e.model&&(t.model=e.model),t}var co=ub(db),qc=B.object({id:B.string(),claim:B.string(),confidence:B.number().min(0).max(1),evidence_sources:B.array(B.string()),location:B.string().optional(),proposed_fix:B.string().optional(),coverage_gaps:B.array(B.string()).optional(),boundary_flag:B.string().optional()}),mb=B.object({hypothesis_id:B.string(),claim:B.string(),verdict:B.enum(["VERIFIED","REFUTED","INCONCLUSIVE"]),evidence:B.string(),gate_reason:B.string()}),Yc=B.object({hypothesis_id:B.string(),reproducer_passed:B.boolean(),regressions:B.array(B.string()),confidence:B.number().min(0).max(1),verification_log:B.string()}),fb=B.enum(["crash","regression","logic-error","flaky","environment","unknown"]),gb=B.object({failure_type:fb,error_signature:B.string(),affected_area:B.string()}),hb=B.enum(["clear_winner","multiple_plausible","dissent","all_inconclusive","no_hypotheses"]),vM=B.object({reproducer:B.string().optional(),triage:gb.optional(),hypotheses:B.array(qc),premise_verifications:B.array(mb).optional(),winner:B.object({hypothesis_id:B.string(),verification_log:B.string(),proposed_fix:B.string()}).optional(),verification_results:B.array(Yc).optional(),outcome:hb.optional(),recommended_next_skill:B.enum(["spec"]).optional()});async function yb(e,t){let n=e.map(l=>({hypothesis:l,decision:Hc(l)})).filter(l=>l.decision.verify);if(n.length===0)return{premise_verifications:[],hypotheses_to_test:e};let r=[],o;try{r=await t(n.map(l=>l.hypothesis.claim))}catch(l){o=l instanceof Error?l.message:String(l)}let s=n.map((l,c)=>{let u=r[c];return o!==void 0?{hypothesis_id:l.hypothesis.id,claim:l.hypothesis.claim,verdict:"INCONCLUSIVE",evidence:`shadow-verify dispatch failed: ${o}`,gate_reason:l.decision.reason}:u?{hypothesis_id:l.hypothesis.id,claim:l.hypothesis.claim,verdict:u.verdict,evidence:u.evidence,gate_reason:l.decision.reason}:{hypothesis_id:l.hypothesis.id,claim:l.hypothesis.claim,verdict:"INCONCLUSIVE",evidence:"no verifier result for this claim",gate_reason:l.decision.reason}}),a=new Set(s.filter(l=>l.verdict==="REFUTED").map(l=>l.hypothesis_id)),i=a.size===0?e:e.filter(l=>!a.has(l.id));return{premise_verifications:s,hypotheses_to_test:i}}async function bb(e,t,n){let r=n?.apiKey,o=(()=>{if(typeof e=="string")return{failure:e,repoPath:process.cwd(),context:"",maxHypotheses:4};if(typeof e=="object"&&e!==null){let L=e;if(typeof L.failure=="string")return{failure:L.failure,repoPath:L.repoPath||process.cwd(),context:L.context||"",maxHypotheses:Math.min(L.maxHypotheses||4,4)}}throw new Error("diagnose handler requires input.failure (string) or a string argument")})();if(!t?.sessionId)throw new Error("diagnose requires a parent session with sessionId");let s=t.sessionId,a=ie("diagnose"),i=a["system.md"],l=a["research.md"],c=a["hypothesis.md"],u=a["verify.md"];if(!i||!l||!c||!u)throw new Error("diagnose skill missing required prompts (system.md, research.md, hypothesis.md, verify.md)");let d=new U({apiKey:r}),m=vb(o.context),f=kb(o.failure,o.context),g=`Triage:
|
|
1063
1063
|
failure_type: ${f.failure_type}
|
|
1064
1064
|
error_signature: ${f.error_signature}
|
|
1065
1065
|
affected_area: ${f.affected_area}`,y=`${_e.systemPrompt}
|
|
@@ -1102,7 +1102,7 @@ Location: ${e.location||"unknown"}
|
|
|
1102
1102
|
Proposed fix: ${e.proposed_fix||"unknown"}
|
|
1103
1103
|
Reproducer: ${t}
|
|
1104
1104
|
|
|
1105
|
-
Working directory (isolated): ${a}`,c=await i.runToResult(l);return c.status!=="succeeded"||!c.output?{hypothesis_id:e.id,reproducer_passed:!1,regressions:[],confidence:0,verification_log:`Verification failed: ${de(c)}`}:c.output}catch(l){return{hypothesis_id:e.id,reproducer_passed:!1,regressions:[],confidence:0,verification_log:`Error during verification: ${l instanceof Error?l.message:String(l)}`}}finally{if(i)try{await i.teardown()}catch{}try{await co("git",["worktree","remove","--force",a],{cwd:n})}catch{}}}function Eb(){let e=["Edit","Write","Bash","Agent","Task"];return async t=>e.includes(t)?{behavior:"deny",message:`Tool ${t} not allowed in worktree verification. Verification is read-only.`}:_e.allowedTools.includes(t)?{behavior:"allow"}:{behavior:"deny",message:`Tool ${t} not allowed. Allowed tools: ${_e.allowedTools.join(", ")}`}}var Cb={name:"diagnose",description:"Parallel root-cause analysis for bugs and failing tests \u2014 forks research subagents, synthesizes hypotheses, and validates each in isolated worktrees",handler:bb,argumentHint:"<bug-or-failing-test>",whenToUse:"When a test is failing, a bug is reported, or behavior is unexplained \u2014 runs parallel root-cause analysis with hypothesis sub-agents."};Le(Cb);import{z as Ve}from"zod";import{execFile as jb}from"child_process";import{promisify as Bb}from"util";import{mkdir as nd,writeFile as rd}from"fs/promises";import{existsSync as vi}from"fs";import{dirname as od,join as _t}from"path";import{fileURLToPath as Wb}from"url";import{fileURLToPath as Pb}from"node:url";import{dirname as Ab}from"node:path";var _b=Pb(import.meta.url),
|
|
1105
|
+
Working directory (isolated): ${a}`,c=await i.runToResult(l);return c.status!=="succeeded"||!c.output?{hypothesis_id:e.id,reproducer_passed:!1,regressions:[],confidence:0,verification_log:`Verification failed: ${de(c)}`}:c.output}catch(l){return{hypothesis_id:e.id,reproducer_passed:!1,regressions:[],confidence:0,verification_log:`Error during verification: ${l instanceof Error?l.message:String(l)}`}}finally{if(i)try{await i.teardown()}catch{}try{await co("git",["worktree","remove","--force",a],{cwd:n})}catch{}}}function Eb(){let e=["Edit","Write","Bash","Agent","Task"];return async t=>e.includes(t)?{behavior:"deny",message:`Tool ${t} not allowed in worktree verification. Verification is read-only.`}:_e.allowedTools.includes(t)?{behavior:"allow"}:{behavior:"deny",message:`Tool ${t} not allowed. Allowed tools: ${_e.allowedTools.join(", ")}`}}var Cb={name:"diagnose",description:"Parallel root-cause analysis for bugs and failing tests \u2014 forks research subagents, synthesizes hypotheses, and validates each in isolated worktrees",handler:bb,argumentHint:"<bug-or-failing-test>",whenToUse:"When a test is failing, a bug is reported, or behavior is unexplained \u2014 runs parallel root-cause analysis with hypothesis sub-agents."};Le(Cb);import{z as Ve}from"zod";import{execFile as jb}from"child_process";import{promisify as Bb}from"util";import{mkdir as nd,writeFile as rd}from"fs/promises";import{existsSync as vi}from"fs";import{dirname as od,join as _t}from"path";import{fileURLToPath as Wb}from"url";import{fileURLToPath as Pb}from"node:url";import{dirname as Ab}from"node:path";var _b=Pb(import.meta.url),PM=Ab(_b),wi={name:"qualify",systemPrompt:`---
|
|
1106
1106
|
name: qualify
|
|
1107
1107
|
description: Gate proposed plugin skills. Approve only real force multipliers. Reject reminders, checklists, best-practice nudges, and generic execution advice. Invoke when evaluating whether a proposed skill deserves top-level status in this plugin.
|
|
1108
1108
|
model: sonnet
|
|
@@ -1335,7 +1335,7 @@ If the append fails (permissions, disk full, unwritable path), do not retry and
|
|
|
1335
1335
|
- Stage 1 alone would land at SALVAGE (rule 8). Rule 6 fires because Stage 2 \u22648 \u2192 downgrade one tier \u2192 **REJECT**. Rewrite target: raise Bounded Damage (dry-run/draft-PR instead of push), Default Reversibility (require confirmation), Assumption Exposure (surface what tests assume before acting).
|
|
1336
1336
|
|
|
1337
1337
|
Be skeptical. Protect the plugin from fluff. Stage 2 catches patterns that are strong when they work and catastrophic when they don't.
|
|
1338
|
-
`,sourcePath:"agent-framework-local/agents/qualify.md"};import{fileURLToPath as Rb}from"node:url";import{dirname as Ib}from"node:path";var Mb=Rb(import.meta.url),
|
|
1338
|
+
`,sourcePath:"agent-framework-local/agents/qualify.md"};import{fileURLToPath as Rb}from"node:url";import{dirname as Ib}from"node:path";var Mb=Rb(import.meta.url),MM=Ib(Mb);import{mkdir as Vc,writeFile as Jc}from"fs/promises";import{dirname as $b,join as Ob}from"path";async function mt(e){let t=yn();await Vc($b(t),{recursive:!0});let n=new Date().toISOString().split(".")[0]+"Z",r={timestamp:n,surface:"afk",...e},o=JSON.stringify(r)+`
|
|
1339
1339
|
`;return await Jc(t,o,{flag:"a"}),n}async function Xc(){let e=Ur(),t=Ob(e,"forge-thaw-history.jsonl");await Vc(e,{recursive:!0});let r={timestamp:new Date().toISOString().split(".")[0]+"Z",surface:"afk",event:"forge.thaw_override",thaw_triggered:!0},o=JSON.stringify(r)+`
|
|
1340
1340
|
`;await Jc(t,o,{flag:"a"})}import{readFile as Zc,readdir as Db,writeFile as Fb,mkdir as Lb,unlink as Nb}from"fs/promises";import{join as uo}from"path";import{existsSync as Ub}from"fs";async function Qc(e){let t=uo(bt(),e+".md"),n=await Zc(t,"utf-8");return{id:e,content:n}}async function ed(){let e=bt();return Ub(e)?(await Db(e,{withFileTypes:!0})).filter(r=>r.isFile()&&r.name.endsWith(".md")).map(r=>r.name.slice(0,-3)):[]}async function Si(e,t){let n=bt(),r=uo(n,e+".md"),o=uo(n,t),s=uo(o,e+".md");await Lb(o,{recursive:!0});let a=await Zc(r,"utf-8");await Fb(s,a,"utf-8"),await Nb(r)}function td(e){let t=/^\*{0,2}(APPROVE|SALVAGE|REJECT)\*{0,2}/,n=e.split(`
|
|
1341
1341
|
`).map(c=>c.trim()).filter(c=>c),r=n.find(c=>t.test(c));if(!r)return{verdict:"REJECT",feedback:e};let o=r.match(t)?.[1];if(!o)return{verdict:"REJECT",feedback:e};let s=e.match(/score:\s*(\d+)/i),a=s&&s[1]?parseInt(s[1],10):void 0,i=n.indexOf(r),l=n.slice(i+1).join(`
|
|
@@ -1343,7 +1343,7 @@ Be skeptical. Protect the plugin from fluff. Stage 2 catches patterns that are s
|
|
|
1343
1343
|
- ${t.join(`
|
|
1344
1344
|
- `)}`)}function Gb(){let e=od(Wb(import.meta.url));return Kb(e)}function zb(e){return _t(e,"..","..","..","plugins","awa-private")}function qb(){return Ur()}function Yb(e){let t=e.split(`
|
|
1345
1345
|
`),n=[],r=/^\s+✗\s+(\S+):/;for(let o of t){let s=o.match(r);s&&s[1]&&n.push(s[1])}return n}async function Vb(e){let t=qb(),n=_t(t,"qualifications.jsonl");await nd(t,{recursive:!0});let o=new Date().toISOString().split(".")[0]+"Z",a=JSON.stringify({timestamp:o,surface:"afk",refers_to_run_id:e,source:"forge-gate-check-ts"})+`
|
|
1346
|
-
`;return await rd(n,a,{flag:"a"}),o}async function Jb(){let e;try{e=Gb()}catch(l){throw new Error(`Failed to resolve eval-harness runner.py: ${l instanceof Error?l.message:String(l)}`)}let t=zb(e),n="",r="",o=0;try{let l=await Hb("python3",[e,"--plugin-root",t],{timeout:6e4});n=l.stdout||"",r=l.stderr||"",o=0}catch(l){let c=l;if(n=c.stdout||"",r=c.stderr||"",o=typeof c.code=="number"?c.code:1,c.code==="ENOENT"||r&&r.includes("No such file"))throw new Error(`eval-harness runner.py not found at ${e}.`)}let s=o===0?"OPEN":"CLOSED",a=s==="CLOSED"?Yb(n):void 0,i;if(s==="OPEN"){let l=new Date().toISOString().split(".")[0]+"Z";i=await Vb(l)}return{gate_status:s,exit_code:o,stdout:n,stderr:r||void 0,tasks_failed:a,ledger_entry_ref:i}}var Xb=Ve.object({iteration:Ve.number().int().positive(),verdict:Ve.enum(["APPROVE","SALVAGE","REJECT"]),score:Ve.number().optional(),feedback:Ve.string()}),
|
|
1346
|
+
`;return await rd(n,a,{flag:"a"}),o}async function Jb(){let e;try{e=Gb()}catch(l){throw new Error(`Failed to resolve eval-harness runner.py: ${l instanceof Error?l.message:String(l)}`)}let t=zb(e),n="",r="",o=0;try{let l=await Hb("python3",[e,"--plugin-root",t],{timeout:6e4});n=l.stdout||"",r=l.stderr||"",o=0}catch(l){let c=l;if(n=c.stdout||"",r=c.stderr||"",o=typeof c.code=="number"?c.code:1,c.code==="ENOENT"||r&&r.includes("No such file"))throw new Error(`eval-harness runner.py not found at ${e}.`)}let s=o===0?"OPEN":"CLOSED",a=s==="CLOSED"?Yb(n):void 0,i;if(s==="OPEN"){let l=new Date().toISOString().split(".")[0]+"Z";i=await Vb(l)}return{gate_status:s,exit_code:o,stdout:n,stderr:r||void 0,tasks_failed:a,ledger_entry_ref:i}}var Xb=Ve.object({iteration:Ve.number().int().positive(),verdict:Ve.enum(["APPROVE","SALVAGE","REJECT"]),score:Ve.number().optional(),feedback:Ve.string()}),m0=Ve.object({status:Ve.enum(["APPROVED","REJECTED","GATE_CLOSED","MAX_ITERATIONS"]),skill_path:Ve.string().optional(),qualify_verdicts:Ve.array(Xb),brief_id:Ve.string().optional(),telemetry_ref:Ve.string()});async function Zb(e,t,n){let r=n?.apiKey,o=typeof e=="string"?{brief:e}:typeof e=="object"&&e!==null?e:{},s=o.brief,a=o.forceThaw??!1,i=o.maxIterations??3,l="",c=[],u="REJECTED",d,m;try{let f=await Jb();if(f.gate_status==="CLOSED"&&!a)return l=await mt({event:"forge.gate_check",gate_status:"CLOSED"}),{status:"GATE_CLOSED",qualify_verdicts:[],telemetry_ref:l};a&&f.gate_status==="CLOSED"&&(await Xc(),l=await mt({event:"forge.thaw_override",gate_status:"CLOSED"})),l=await mt({event:"forge.gate_check",gate_status:"OPEN"});let g="",y=!1;if(s)g=s,y=!0;else{let x=await ed();if(x.length>0){let v=x[0],E=await Qc(v);g=E.content,m=E.id,y=!0}else{if(!t?.sessionId)throw new Error("forge requires parent session for gap discovery");let E=ie("forge")["gap-discovery.md"];if(!E)throw new Error("forge skill missing gap-discovery.md prompt");let D=await(await new U({apiKey:r}).forkSubagent({parent:{sessionId:t.sessionId},config:{model:"sonnet",systemPrompt:E},idPrefix:"forge-gap-discovery"})).runToResult("Identify the most impactful skill gap.");if(D.status!=="succeeded")throw new Error(`gap discovery failed: ${de(D)}`);if(g=D.message?.content||"",!g)throw new Error("gap discovery returned no concept")}}if(l=await mt({event:"forge.brief_loaded",used_brief:y,brief_id:m||null}),!t?.sessionId)throw new Error("forge requires parent session for skill generation");let S=ie("forge"),h=S["generate.md"],b=S["system.md"];if(!h)throw new Error("forge skill missing generate.md prompt");if(!b)throw new Error("forge skill missing system.md prompt");let T=await(await new U({apiKey:r}).forkSubagent({parent:{sessionId:t.sessionId},config:{model:"sonnet",systemPrompt:b},idPrefix:"forge-generate"})).runToResult(`Generate a new amplifier skill based on this concept:
|
|
1347
1347
|
|
|
1348
1348
|
${g}`);if(T.status!=="succeeded")throw new Error(`skill generation failed: ${de(T)}`);let A=T.message?.content||"";if(!A)throw new Error("skill generation returned no output");for(let x=1;x<=i;x++){let v=wi.systemPrompt;if(!v)throw new Error("qualify agent missing system prompt");let I=await(await new U({apiKey:r}).forkSubagent({parent:{sessionId:t.sessionId},config:{model:"sonnet",systemPrompt:v},idPrefix:`forge-qualify-${x}`})).runToResult(`Evaluate this amplifier skill against the force-multiplier criteria:
|
|
1349
1349
|
|
|
@@ -1702,7 +1702,7 @@ ${JSON.stringify(e.buildResults,null,2)}
|
|
|
1702
1702
|
Verification results:
|
|
1703
1703
|
${JSON.stringify(e.verifyResults,null,2)}
|
|
1704
1704
|
|
|
1705
|
-
Create a ship-ready summary with next steps.`,l=await a.runToResult(i);if(l.status!=="succeeded"||!l.message)throw new Error(`ship phase failed: ${de(l)}`);let c=e.buildResults?.filesChanged.length??0,u=e.healIterations;return _n({kind:"checkpoint",title:"ship \u2014 done",body:[`Files changed: ${c}`,`Heal iterations: ${u}`,`Idea: ${e.idea}`]}),l.message.content}import{existsSync as Ud,mkdirSync as $k,readFileSync as Ok,unlinkSync as Dk,writeFileSync as Fk}from"fs";import{dirname as Lk,join as Nk}from"path";function Ri(e){return Nk(kt(),e,"mint-state.json")}function jd(e,t){let n=Ri(e);$k(Lk(n),{recursive:!0}),Fk(n,JSON.stringify(t,null,2),"utf-8")}function Uk(e){if(typeof e!="object"||e===null)return!1;let t=e;return typeof t.currentPhase=="string"&&typeof t.idea=="string"&&typeof t.spec=="string"&&typeof t.healIterations=="number"&&Array.isArray(t.history)}function Bd(e){let t=Ri(e);if(!Ud(t))return null;try{let n=JSON.parse(Ok(t,"utf-8"));return Uk(n)?n:null}catch{return null}}function Ii(e){let t=Ri(e);if(Ud(t))try{Dk(t)}catch{}}var jk=2,Wd=/^\s*(?:--continue(?:\s+(?:approved|yes|y))?|approved?|yes|y|lgtm)\s*$/i,Bk='To approve and run the rest of the pipeline, say "approve", "yes", or "lgtm" \u2014 or invoke /mint --continue approved. The handler will reload the spec state from disk.';function et(e,t,n){e.history.push({phase:t,output:n,timestamp:Date.now()})}function zd(e){if("completed"in e&&"paused"in e)throw new Error("mint: invariant violation \u2014 MintResult carries both completed and paused keys simultaneously")}var Hd=240;function Wk(e){return e.length<=Hd?e:e.slice(0,Hd)+"\u2026"}function qd(e){if(typeof e=="string"){if(Wd.test(e))return{userApproved:!0};if(e.length>1&&e.trimStart().startsWith("{"))try{let t=JSON.parse(e);if(typeof t=="object"&&t!==null)return qd(t)}catch{}return{idea:e}}if(typeof e=="object"&&e!==null){let t=e,n=typeof t.idea=="string"?t.idea:void 0;if(n!==void 0&&Wd.test(n))return{userApproved:!0};if("idea"in t||"resumeFrom"in t||t.userApproved===!0)return t}throw new Error("mint handler requires input.idea (string), input as string, or {userApproved: true} to resume")}async function Kd(e,t){if(!t.sessionId)throw new Error("runPhasesAfterSpec requires parentSession.sessionId");let n=t.sessionId,r=t.cwd;try{e.currentPhase="research",e.research=await $d(e.spec,n,r),et(e,"research",e.research),e.currentPhase="plan",e.plan=await Od(e.spec,e.research,n,r),et(e,"plan",e.plan),e.currentPhase="parallelize";let o=await Dd(e.plan,t);if(o.kind==="plan")e.waveOrchestrationPlan=o.plan,et(e,"parallelize",JSON.stringify(o.plan));else if(o.kind==="skipped")e.waveOrchestrationPlan=void 0,et(e,"parallelize",`skipped: ${o.reason}`);else if(o.kind==="failed"){e.waveOrchestrationPlan=void 0;let i=Wk(o.error);et(e,"parallelize",`failed: ${i}`),Ne({event:"fallback.inline",parent_session_id:n,reason:"parallelize-dispatch-failed",error_message:i}),console.warn(`[mint] parallelize dispatch failed (single-lane fallback): ${i}`)}else{let i=o}e.currentPhase="build",e.buildResults=await Fd(e.plan,e.waveOrchestrationPlan,n,r),et(e,"build",JSON.stringify(e.buildResults)),e.currentPhase="verify",e.verifyResults=await So(e.plan,e.buildResults,n,r),et(e,"verify",JSON.stringify(e.verifyResults)),e.currentPhase="heal";let s=e.verifyResults.testsPassed&&e.verifyResults.lintPassed&&e.verifyResults.designReviewPassed;for(;!s&&e.healIterations<jk;){let i=await Ld(e.plan,e.buildResults,e.verifyResults,e.healIterations,t);e.healIterations=i.newHealIterations,e.verifyResults=i.newVerifyResults,s=i.healed,et(e,"heal",`Iterations: ${e.healIterations}, Success: ${s}`)}if(!s)return{paused:!0,phase:"heal-failed",reason:`Heal capped at ${e.healIterations} iterations; still have failures`,state:e,nextStep:"Heal loop exhausted. Inspect verifyResults, fix manually, then re-invoke /mint with a fresh idea \u2014 resume is not supported from heal-failed."};e.currentPhase="ship";let a=await Nd(e,n,r);return et(e,"ship",a),{completed:!0,artifact:a,state:e}}catch(o){throw new Error(`mint failed at ${e.currentPhase}: ${o}`)}}function Gd(e,t){return zd(t),("completed"in t||t.phase==="heal-failed")&&Ii(e),t}async function Hk(e,t){let n=qd(e);if(!t?.sessionId)throw new Error("mint handler requires a parent session to fork subagents");let r=t.sessionId;if(n.userApproved){let a=n.resumeFrom??Bd(r);if(!a)throw new Error("mint: no paused spec found for this session to continue. Run /mint <idea> first, then /mint --continue approved.");let i=await Kd(a,t);return Gd(r,i)}if(!n.idea)throw new Error("mint: no idea provided. Run /mint <idea> to start, or /mint --continue approved to resume a paused spec.");Ii(r);let o={currentPhase:"spec",idea:n.idea,healIterations:0,history:[]};try{o.spec=await Md(n.idea,r,t.cwd),et(o,"spec",o.spec)}catch(a){throw new Error(`mint failed at spec: ${a}`)}if(!n.autoApprove){jd(r,o);let a={paused:!0,phase:"spec",spec:o.spec,state:o,nextStep:Bk};return zd(a),a}let s=await Kd(o,t);return Gd(r,s)}var Kk={name:"mint",description:"Takes a feature idea or refactor scope and delivers a ship-ready, verified implementation end-to-end",handler:Hk,argumentHint:"<idea> | --continue [approved]",whenToUse:'When the user wants a feature or refactor delivered end-to-end (spec \u2192 research \u2192 build \u2192 verify) in one ship-ready pass. After the spec phase pauses for approval, resume by invoking mint again with the literal string `"approved"` (or `"yes"`, `"lgtm"`, `"--continue approved"`) as the arguments. Equivalent JSON forms `{"userApproved": true}` and `{"idea": "approved"}` are also accepted. The handler reloads the spec state from disk and runs phases 2\u20138.',flags:["--continue"]};Le(Kk);async function Gk(){throw new Error("telegram-setup is a fork skill; its handler should never be called directly. Invoke via the `skill` tool or `/telegram-setup` slash command.")}var zk={name:"telegram-setup",description:"Guide the user through first-time Telegram bot onboarding without leaking the bearer token. Walks the user to run `afk telegram setup` in a terminal for token entry, then uses the sanctioned `afk telegram check-token`/`discover-chat`/`set-allowed-chat` subcommands to validate and finish allowlist setup \u2014 the token never enters the model context. Works in REPL or Telegram. Use when the user wants to set up Telegram push notifications for the first time, or to debug a partially-configured install.",handler:Gk,context:"fork",whenToUse:`When the user wants to set up Telegram bot notifications for the first time, or when they say something like "set up telegram", "connect telegram", "enable push", or you detect that TELEGRAM_BOT_TOKEN is unset and they're asking for notifications.`};Le(zk);import{readdirSync as Yk,readFileSync as Vk}from"fs";import{join as Jk}from"path";var qk=/(?<![a-zA-Z0-9_/-])--([a-z][a-z0-9-]*)(?![a-zA-Z0-9_-])/g;function Yd(e){return e.startsWith("--")?e:`--${e}`}function Mi(e){let t=new Set;for(let n of e.matchAll(qk))n[1]&&t.add(`--${n[1]}`);return Array.from(t).sort()}function dr(e){if(!e.startsWith(`---
|
|
1705
|
+
Create a ship-ready summary with next steps.`,l=await a.runToResult(i);if(l.status!=="succeeded"||!l.message)throw new Error(`ship phase failed: ${de(l)}`);let c=e.buildResults?.filesChanged.length??0,u=e.healIterations;return _n({kind:"checkpoint",title:"ship \u2014 done",body:[`Files changed: ${c}`,`Heal iterations: ${u}`,`Idea: ${e.idea}`]}),l.message.content}import{existsSync as Ud,mkdirSync as $k,readFileSync as Ok,unlinkSync as Dk,writeFileSync as Fk}from"fs";import{dirname as Lk,join as Nk}from"path";function Ri(e){return Nk(kt(),e,"mint-state.json")}function jd(e,t){let n=Ri(e);$k(Lk(n),{recursive:!0}),Fk(n,JSON.stringify(t,null,2),"utf-8")}function Uk(e){if(typeof e!="object"||e===null)return!1;let t=e;return typeof t.currentPhase=="string"&&typeof t.idea=="string"&&typeof t.spec=="string"&&typeof t.healIterations=="number"&&Array.isArray(t.history)}function Bd(e){let t=Ri(e);if(!Ud(t))return null;try{let n=JSON.parse(Ok(t,"utf-8"));return Uk(n)?n:null}catch{return null}}function Ii(e){let t=Ri(e);if(Ud(t))try{Dk(t)}catch{}}var jk=2,Wd=/^\s*(?:--continue(?:\s+(?:approved|yes|y))?|approved?|yes|y|lgtm|sure)\s*$/i,Bk='To approve and run the rest of the pipeline, say "approve", "yes", "sure", or "lgtm" \u2014 or invoke /mint --continue approved. The handler will reload the spec state from disk.';function et(e,t,n){e.history.push({phase:t,output:n,timestamp:Date.now()})}function zd(e){if("completed"in e&&"paused"in e)throw new Error("mint: invariant violation \u2014 MintResult carries both completed and paused keys simultaneously")}var Hd=240;function Wk(e){return e.length<=Hd?e:e.slice(0,Hd)+"\u2026"}function qd(e){if(typeof e=="string"){if(Wd.test(e))return{userApproved:!0};if(e.length>1&&e.trimStart().startsWith("{"))try{let t=JSON.parse(e);if(typeof t=="object"&&t!==null)return qd(t)}catch{}return{idea:e}}if(typeof e=="object"&&e!==null){let t=e,n=typeof t.idea=="string"?t.idea:void 0;if(n!==void 0&&Wd.test(n))return{userApproved:!0};if("idea"in t||"resumeFrom"in t||t.userApproved===!0)return t}throw new Error("mint handler requires input.idea (string), input as string, or {userApproved: true} to resume")}async function Kd(e,t){if(!t.sessionId)throw new Error("runPhasesAfterSpec requires parentSession.sessionId");let n=t.sessionId,r=t.cwd;try{e.currentPhase="research",e.research=await $d(e.spec,n,r),et(e,"research",e.research),e.currentPhase="plan",e.plan=await Od(e.spec,e.research,n,r),et(e,"plan",e.plan),e.currentPhase="parallelize";let o=await Dd(e.plan,t);if(o.kind==="plan")e.waveOrchestrationPlan=o.plan,et(e,"parallelize",JSON.stringify(o.plan));else if(o.kind==="skipped")e.waveOrchestrationPlan=void 0,et(e,"parallelize",`skipped: ${o.reason}`);else if(o.kind==="failed"){e.waveOrchestrationPlan=void 0;let i=Wk(o.error);et(e,"parallelize",`failed: ${i}`),Ne({event:"fallback.inline",parent_session_id:n,reason:"parallelize-dispatch-failed",error_message:i}),console.warn(`[mint] parallelize dispatch failed (single-lane fallback): ${i}`)}else{let i=o}e.currentPhase="build",e.buildResults=await Fd(e.plan,e.waveOrchestrationPlan,n,r),et(e,"build",JSON.stringify(e.buildResults)),e.currentPhase="verify",e.verifyResults=await So(e.plan,e.buildResults,n,r),et(e,"verify",JSON.stringify(e.verifyResults)),e.currentPhase="heal";let s=e.verifyResults.testsPassed&&e.verifyResults.lintPassed&&e.verifyResults.designReviewPassed;for(;!s&&e.healIterations<jk;){let i=await Ld(e.plan,e.buildResults,e.verifyResults,e.healIterations,t);e.healIterations=i.newHealIterations,e.verifyResults=i.newVerifyResults,s=i.healed,et(e,"heal",`Iterations: ${e.healIterations}, Success: ${s}`)}if(!s)return{paused:!0,phase:"heal-failed",reason:`Heal capped at ${e.healIterations} iterations; still have failures`,state:e,nextStep:"Heal loop exhausted. Inspect verifyResults, fix manually, then re-invoke /mint with a fresh idea \u2014 resume is not supported from heal-failed."};e.currentPhase="ship";let a=await Nd(e,n,r);return et(e,"ship",a),{completed:!0,artifact:a,state:e}}catch(o){throw new Error(`mint failed at ${e.currentPhase}: ${o}`)}}function Gd(e,t){return zd(t),("completed"in t||t.phase==="heal-failed")&&Ii(e),t}async function Hk(e,t){let n=qd(e);if(!t?.sessionId)throw new Error("mint handler requires a parent session to fork subagents");let r=t.sessionId;if(n.userApproved){let a=n.resumeFrom??Bd(r);if(!a)throw new Error("mint: no paused spec found for this session to continue. Run /mint <idea> first, then /mint --continue approved.");let i=await Kd(a,t);return Gd(r,i)}if(!n.idea)throw new Error("mint: no idea provided. Run /mint <idea> to start, or /mint --continue approved to resume a paused spec.");Ii(r);let o={currentPhase:"spec",idea:n.idea,healIterations:0,history:[]};try{o.spec=await Md(n.idea,r,t.cwd),et(o,"spec",o.spec)}catch(a){throw new Error(`mint failed at spec: ${a}`)}if(!n.autoApprove){jd(r,o);let a={paused:!0,phase:"spec",spec:o.spec,state:o,nextStep:Bk};return zd(a),a}let s=await Kd(o,t);return Gd(r,s)}var Kk={name:"mint",description:"Takes a feature idea or refactor scope and delivers a ship-ready, verified implementation end-to-end",handler:Hk,argumentHint:"<idea> | --continue [approved]",whenToUse:'When the user wants a feature or refactor delivered end-to-end (spec \u2192 research \u2192 build \u2192 verify) in one ship-ready pass. After the spec phase pauses for approval, resume by invoking mint again with the literal string `"approved"` (or `"yes"`, `"lgtm"`, `"--continue approved"`) as the arguments. Equivalent JSON forms `{"userApproved": true}` and `{"idea": "approved"}` are also accepted. The handler reloads the spec state from disk and runs phases 2\u20138.',flags:["--continue"]};Le(Kk);async function Gk(){throw new Error("telegram-setup is a fork skill; its handler should never be called directly. Invoke via the `skill` tool or `/telegram-setup` slash command.")}var zk={name:"telegram-setup",description:"Guide the user through first-time Telegram bot onboarding without leaking the bearer token. Walks the user to run `afk telegram setup` in a terminal for token entry, then uses the sanctioned `afk telegram check-token`/`discover-chat`/`set-allowed-chat` subcommands to validate and finish allowlist setup \u2014 the token never enters the model context. Works in REPL or Telegram. Use when the user wants to set up Telegram push notifications for the first time, or to debug a partially-configured install.",handler:Gk,context:"fork",whenToUse:`When the user wants to set up Telegram bot notifications for the first time, or when they say something like "set up telegram", "connect telegram", "enable push", or you detect that TELEGRAM_BOT_TOKEN is unset and they're asking for notifications.`};Le(zk);import{readdirSync as Yk,readFileSync as Vk}from"fs";import{join as Jk}from"path";var qk=/(?<![a-zA-Z0-9_/-])--([a-z][a-z0-9-]*)(?![a-zA-Z0-9_-])/g;function Yd(e){return e.startsWith("--")?e:`--${e}`}function Mi(e){let t=new Set;for(let n of e.matchAll(qk))n[1]&&t.add(`--${n[1]}`);return Array.from(t).sort()}function dr(e){if(!e.startsWith(`---
|
|
1706
1706
|
`))return{frontmatter:null,frontmatterFlags:null,body:e};let t=e.indexOf(`
|
|
1707
1707
|
---
|
|
1708
1708
|
`,4);if(t===-1)return{frontmatter:null,frontmatterFlags:null,body:e};let n=e.slice(4,t),r=e.slice(t+5),o={},s=null,a=n.split(`
|
|
@@ -1811,14 +1811,14 @@ ${w.map(x=>`> - ${x}`).join(`
|
|
|
1811
1811
|
|
|
1812
1812
|
`:"")+S,A=g.failed.length>0;return{content:T,isError:A}}catch(d){let m=d instanceof Error?d.message:String(d);return Ne({event:"compose.failed",parent_session_id:this.ctx.parentSession.sessionId,error_message:m.slice(0,240),duration_ms:Date.now()-u}).catch(()=>{}),{content:`Compose execution error: ${m}`,isError:!0}}finally{await l.teardownAll()}}};function Mn(e,t,n,r){let o=Cu();o.register("SubagentStop",Pu);let s=n??new Re;return r!==void 0&&o.register("PreToolUse",Au(r)),o.register("SessionEnd",Ti(s,t)),o.register("SessionEnd",a=>a.event!=="SessionEnd"?{}:(a.sessionId&&Fu(a.sessionId),{})),e&&o.register("SubagentStop",a=>a.event!=="SubagentStop"?{}:a.status==="idle"||a.status==="running"?{}:(e({subagentId:a.subagentId,status:a.status,durationMs:a.durationMs,agentType:a.agentType}),{})),{registry:o,memoryStore:s}}function me(e){let t=Math.round(e/1e3);if(t<=0)return"0s";let n=Math.floor(t/86400),r=Math.floor(t%86400/3600),o=Math.floor(t%3600/60),s=t%60;return n>0?`${n}d ${r}h`:r>0?`${r}h ${o}m`:o>0?`${o}m ${s}s`:`${s}s`}function Ie(e){return e===0?"$0.00":e<.01?`$${e.toFixed(4)}`:`$${e.toFixed(2)}`}function H(e){if(e<1e3)return String(e);if(e<1e6){let n=e/1e3;return n%1===0?`${n}k`:`${n.toFixed(1).replace(/\.0$/,"")}k`}let t=e/1e6;return t%1===0?`${t}m`:`${t.toFixed(1).replace(/\.0$/,"")}m`}var XS="[skill-routing: active]\n\nRoute recurring work through registered skills instead of rolling ad-hoc solutions:\n\n- Multi-file implementation or new features \u2192 `/mint`\n- Bugs, failing tests, or regressions \u2192 `/diagnose`\n- High-stakes sub-agent output that will drive edits or commits \u2192 `/shadow-verify` before acting\n- Refactor needing parallel waves \u2192 `/parallelize`\n- Parallel or dependent multi-task work \u2192 `compose` tool (DAG of subagent nodes)\n\nCommon composed sequences \u2014 reach for these when the task shape matches:\n\n- Bug with failing test and non-trivial fix \u2192 `/diagnose` \u2192 `/shadow-verify` on the proposed fix\n- Refactor needing parallel waves \u2192 plan \u2192 `/parallelize` \u2192 build waves\n- Diagnose + fix in parallel \u2192 `compose` with two independent nodes\n- Research \u2192 implement \u2192 verify pipeline \u2192 `compose` with edges: research\u2192implement\u2192verify\n- Multiple independent investigations \u2192 `compose` with N nodes, no edges\n\nReach for context-isolated investigators when the task is exploratory:\n\n- Map an unfamiliar module before editing \u2192 `/gather` or `/research`\n- Re-derive a load-bearing claim independently \u2192 `/shadow-verify`\n- Audit a diff before merge \u2192 `/review`\n- Survey git + infra + memory before non-trivial work \u2192 `/ground-state`\n- Generate alternatives before committing to a plan \u2192 `/devils-advocate`\n\nOr dispatch a raw `agent` call when no skill matches but the work is parallelizable, verification-heavy, or would otherwise consume substantial inline context.\n\nSkip orchestration for: single-line edits, trivial Q&A, and direct tool calls the user explicitly requested. The goal is leverage, not ceremony. If a skill would add overhead without adding value, don't invoke it.";function jo(e,t){return!e||!t?e:`${e}
|
|
1813
1813
|
|
|
1814
|
-
${XS}`}import nn from"chalk";var ZS=new Set(["Read","Glob","Grep","NotebookRead","LS","read_file","glob","grep","list_directory","memory_search"]),QS=new Set(["Write","Edit","NotebookEdit","MultiEdit","write_file","edit_file","memory_update","procedure_write"]),ev=new Set(["Bash","BashOutput","KillBash","bash"]),hr=new Set(["Agent","Task","agent"]),Lu=new Set(["Skill","skill"]),Nu=new Set(["Compose","compose"]),gt=new Set([...hr,...Nu,...Lu]),tv=new Set(["WebFetch","WebSearch","send_telegram"]),nv=new Set(["TaskCreate","TaskUpdate","TaskList","TaskGet","TaskOutput","TaskStop","EnterPlanMode","ExitPlanMode","ToolSearch"]);function Ot(e,t){if(e.has(t))return!0;let n=t.charAt(0).toUpperCase()+t.slice(1);return n!==t&&e.has(n)}function Bo(e){return e.startsWith("mcp__")||e.startsWith("MCP__")?"mcp":Ot(ZS,e)?"read":Ot(QS,e)?"write":Ot(ev,e)?"shell":Ot(hr,e)?"subagent":Ot(Lu,e)?"skill":Ot(Nu,e)?"dag":Ot(tv,e)?"web":Ot(nv,e)?"planning":"other"}var rv={read:nn.hex("#9CC4D6"),write:nn.hex("#E8A33D"),shell:nn.hex("#A8E060"),subagent:p.plan,skill:nn.hex("#F08AC4"),dag:nn.hex("#4EC9B0"),mcp:nn.hex("#5FE0C0"),web:nn.hex("#7FCDC0"),planning:p.meta,other:p.info},ov={read:"\u25CF",write:"\u270E",shell:"$",subagent:"\u2192",skill:"\u25C6",dag:"\u2B21",mcp:"\u22A1",web:"\u2316",planning:"\u25B1",other:"\u25CF"},sv={subagent:"subagent",skill:"skill",dag:"dag"};function Uu(e){return sv[e]}function Zi(e){return{color:rv[e],glyph:ov[e]}}function $n(e){return Zi(Bo(e))}function ju(e){let{description:t,summary:n,lastToolName:r,totalTokens:o,toolUses:s,durationMs:a}=e,i=[];if(r){let{color:c,glyph:u}=$n(r);i.push(`via ${c(`${u} ${r}`)}`)}s&&i.push(`${s} tool${s===1?"":"s"}`),o&&i.push(`${H(o)} tok`),a&&i.push(me(a));let l=i.length>0?` (${i.join(" \xB7 ")})`:"";return n?[p.dim(` \u25E6 ${t}`),p.dim(` ${n}${l}`)]:[p.dim(` \u25E6 ${t}${l}`)]}function Wo(e){let t=e.status==="succeeded"?"\u2713":e.status==="failed"?"\u2717":"\u2298",n=e.agentType??e.subagentId,r=[t,n];return e.durationMs!==void 0&&r.push(`\xB7 ${me(e.durationMs)}`),p.dim(` ${r.join(" ")}`)}var Bu=new Set;function Wu(e){Bu.add(e)}function Hu(e){return Bu.has(e)}var Qi=new Set,ea=new Set;function Ku(e){Qi.add(e)}function Gu(e){Qi.delete(e)}function zu(e){ea.add(e)}function qu(e){ea.delete(e)}function Yu(e){for(let t of Qi)t(e)}function Vu(e){for(let t of ea)t(e)}function iv(e){if(typeof e!="object"||e===null)return;let t=e.name;if(typeof t!="string")return;let n=t.trim();return n.length>0?n:void 0}function av(e){if(typeof e!="object"||e===null)throw new Error("Skill tool input must be an object");let t=e,n=t.name;if(typeof n!="string"||n.trim().length===0)throw new Error('Skill tool input must have a non-empty "name" field');let r,o=t.arguments;if(o!==void 0){if(typeof o!="string")throw new Error('Skill tool "arguments" must be a string');r=o}return{name:n.trim(),arguments:r}}var Dt=class{constructor(t){this.ctx=t}ctx;pluginBodies=null;async execute(t){if(t.signal.aborted)return{content:"Skill tool call aborted",isError:!0};let n=this.ctx.depth??0,r=this.ctx.maxDepth??On;if(n>=r){let l=iv(t.input);return Ne({event:"delegation.skipped",parent_session_id:this.ctx.parentSession.sessionId,reason:"max_depth",depth:n,requested_name:l}).catch(()=>{}),{content:`Skill tool not available at nesting depth ${n} (max ${r})`,isError:!0}}let o;try{o=av(t.input)}catch(l){return{content:`Skill tool input validation failed: ${l instanceof Error?l.message:String(l)}`,isError:!0}}try{let l=Se(o.name);return await this.executeRegistrySkill(l,o.arguments,t)}catch{}let s=this.getPluginSkillBody(o.name);if(s)return await this.executePluginSkill(o.name,s,o.arguments,t);let i=ur(this.ctx.pluginConfigs).map(l=>l.name).join(", ");return{content:`Skill "${o.name}" not found. Available skills: ${i||"(none)"}`,isError:!0}}async executeRegistrySkill(t,n,r){if(r.signal.aborted)return{content:"Skill call aborted",isError:!0};if(t.context==="fork")return this.executeForkedRegistrySkill(t,n,r);let o=Hu(t.name);o&&Vu(t.name);let s=Date.now(),a,i;try{i=await t.handler(n&&n.length>0?n:void 0,this.ctx.parentSession,{apiKey:this.ctx.apiKey,defaultModel:this.ctx.defaultModel,defaultSubagentModel:this.ctx.defaultSubagentModel,dispatchSkill:this.createDispatchSkillCallback(r)})}catch(c){a=c}finally{if(o){let c=Date.now()-s;Yu({skillName:t.name,durationMs:c,...a!==void 0?{isError:!0}:{}})}}return a!==void 0?{content:`Skill execution error: ${a instanceof Error?a.message:String(a)}`,isError:!0}:{content:typeof i=="string"?i:i!=null?JSON.stringify(i):"Skill completed successfully."}}buildForkedChildConfig(t,n){let r=this.ctx.depth??0,o=this.ctx.maxDepth??On,s={...t};if(!this.ctx.childProviderFactory||r>=o)return{childConfig:s,childManager:void 0};let a=new U({parentAbortSignal:n}),i=new Ft({subagentManager:a,parentSession:yr(n),defaultConfig:{model:s.model,apiKey:this.ctx.apiKey},defaultSubagentModel:this.ctx.defaultSubagentModel,childProviderFactory:this.ctx.childProviderFactory,childSkillExecutorFactory:this.ctx.childSkillExecutorFactory,depth:r+1,maxDepth:o}),l=this.ctx.childSkillExecutorFactory?this.ctx.childSkillExecutorFactory(r+1,o,n):void 0;return s.provider=this.ctx.childProviderFactory({childExecutor:i,childSkillExecutor:l}),{childConfig:s,childManager:a}}async executeForkedRegistrySkill(t,n,r){if(r.signal.aborted)return{content:"Skill call aborted",isError:!0};let o;try{if(o=ie(t.name)["system.md"],!o)return{content:`Skill "${t.name}" has context: "fork" but no prompts/system.md found`,isError:!0}}catch(l){return{content:`Failed to load skill prompts: ${l instanceof Error?l.message:String(l)}`,isError:!0}}let s=new U({parentAbortSignal:r.signal,apiKey:this.ctx.apiKey,progressSink:Ye()}),{childConfig:a,childManager:i}=this.buildForkedChildConfig({model:t.model??this.ctx.defaultSubagentModel??this.ctx.defaultModel??"sonnet",systemPrompt:o},r.signal);try{let l=await s.forkSubagent({parent:this.ctx.parentSession,config:a,idPrefix:`skill-fork-${t.name}`,parentId:r.id,agentType:t.name}),c=n&&n.length>0?n:"Run the skill.",u=await l.runToResult(c);return u.status==="succeeded"&&u.message?{content:u.message.content}:{content:u.error?.message??"Forked skill failed with no output",isError:!0}}catch(l){return{content:`Forked skill execution error: ${l instanceof Error?l.message:String(l)}`,isError:!0}}finally{await i?.teardownAll(),await s.teardownAll()}}async executePluginSkill(t,n,r,o){if(o.signal.aborted)return{content:"Skill call aborted",isError:!0};let s=new U({parentAbortSignal:o.signal,apiKey:this.ctx.apiKey,progressSink:Ye()}),{childConfig:a,childManager:i}=this.buildForkedChildConfig({model:this.ctx.defaultSubagentModel??this.ctx.defaultModel??"sonnet",systemPrompt:n},o.signal);try{let l=await s.forkSubagent({parent:this.ctx.parentSession,config:a,idPrefix:`skill-${t}`,parentId:o.id,agentType:t}),c=r&&r.length>0?r:"Run the skill.",u=await l.runToResult(c);return u.status==="succeeded"&&u.message?{content:u.message.content}:{content:u.error?.message??"Plugin skill failed with no output",isError:!0}}catch(l){return{content:`Plugin skill execution error: ${l instanceof Error?l.message:String(l)}`,isError:!0}}finally{await i?.teardownAll(),await s.teardownAll()}}getPluginSkillBody(t){return this.pluginBodies||(this.pluginBodies=wo(this.ctx.pluginConfigs)),this.pluginBodies.get(t)}createDispatchSkillCallback(t){return async(n,r)=>{let o={id:`${t.id}-dispatch-${n}`,name:"skill",input:{name:n,...r!==void 0?{arguments:r}:{}},signal:t.signal},s=await this.execute(o);if(s.isError)throw new Error(s.content);return s.content}}};var On=3;function yr(e){return{sessionId:void 0,getInputStreamRef:()=>({pushUserMessage:()=>{}}),abortSignal:e}}var lv=[...Rt,"agent","skill"];function Ho(){return({childExecutor:e,childSkillExecutor:t})=>new Te({permissions:{allowedTools:lv},subagentExecutor:e,skillExecutor:t})}function Ko(e,t,n){let r=(o,s,a)=>new Dt({parentSession:yr(a),defaultModel:e,apiKey:t,depth:o,maxDepth:s,childProviderFactory:n,childSkillExecutorFactory:r});return r}function Ju(e){return e.replace(/\x1b\[[0-9;]*[a-zA-Z]/g,"")}function cv(e){if(typeof e!="object"||e===null)throw new Error("Agent tool input must be an object");let t=e,n=t.prompt;if(typeof n!="string")throw new Error('Agent tool input must have a "prompt" field of type string');if(n.trim().length===0)throw new Error("Agent tool prompt cannot be empty");let r,o=t.model;if(o!==void 0){if(typeof o!="string")throw new Error("Agent tool model must be a string");r=o}let s=10,a=t.max_turns;if(a!==void 0){if(typeof a!="number")throw new Error("Agent tool max_turns must be a number");s=Math.max(1,Math.min(50,Math.floor(a)))}let i="agent-tool",l=t.id_prefix;if(l!==void 0){if(typeof l!="string")throw new Error("Agent tool id_prefix must be a string");i=l}return{prompt:n,model:r,max_turns:s,id_prefix:i}}function ta(e){try{return Ne(e).catch(()=>{})}catch{return Promise.resolve()}}function br(e,t=240){return e.length<=t?e:e.slice(0,t)+"\u2026"}function Zu(e){if(e!=null){if(typeof e=="string")return e.length;try{return JSON.stringify(e).length}catch{return}}}var dv=4096,Xu=1024;function uv(e){if(e==null)return;let t=Zu(e);return t!==void 0&&t>dv?{truncated:!0,chars:t}:e}function pv(e){let t={status:e.status,error:br(e.errorMessage,Xu),subagent_id:e.subagentId};e.schemaErrorMessage&&(t.schemaError=br(e.schemaErrorMessage,Xu));let n=uv(e.partialOutput);return n!==void 0&&(t.partialOutput=n),t}var Ft=class e{constructor(t){this.ctx=t}ctx;async execute(t){if(t.signal.aborted)return{content:"Agent tool call aborted",isError:!0};let n;try{n=cv(t.input)}catch(m){return{content:`Agent tool input validation failed: ${m instanceof Error?m.message:String(m)}`,isError:!0}}let r=this.ctx.depth??0,o=this.ctx.maxDepth??On,s,a={model:n.model??this.ctx.defaultSubagentModel??"sonnet",apiKey:this.ctx.defaultConfig.apiKey,systemPrompt:this.ctx.defaultConfig.systemPrompt,maxTurns:n.max_turns},i;if(this.ctx.childProviderFactory&&r<o){s=new U({parentAbortSignal:t.signal}),i=yr(t.signal);let m=new e({subagentManager:s,parentSession:i,defaultConfig:this.ctx.defaultConfig,defaultSubagentModel:this.ctx.defaultSubagentModel,childProviderFactory:this.ctx.childProviderFactory,childSkillExecutorFactory:this.ctx.childSkillExecutorFactory,depth:r+1,maxDepth:o}),f=this.ctx.childSkillExecutorFactory?this.ctx.childSkillExecutorFactory(r+1,o,t.signal):void 0;a.provider=this.ctx.childProviderFactory({childExecutor:m,childSkillExecutor:f})}let l;try{l=await this.ctx.subagentManager.forkSubagent({parent:this.ctx.parentSession,parentId:t.id,config:a,idPrefix:n.id_prefix,agentType:n.id_prefix&&n.id_prefix!=="agent-tool"?Ju(n.id_prefix).replace(/[\r\n]+/g," ").trim()||"agent":Ju(n.prompt).replace(/[\r\n]+/g," ").slice(0,40).trim()||"agent"}),i!==void 0&&(i.sessionId=l.id)}catch(m){return{content:`Failed to fork subagent: ${m instanceof Error?m.message:String(m)}`,isError:!0}}let c=()=>{l.cancel()};t.signal.addEventListener("abort",c,{once:!0});let u=Date.now(),d=this.ctx.parentSession.sessionId;try{let m=await l.runToResult(n.prompt);if(m.status==="succeeded"&&m.message){let S=m.message.content,h=typeof S=="string"?S:JSON.stringify(S),b=m.trace;return ta({event:"subagent.completed",subagent_id:l.id,parent_session_id:d,status:m.status,duration_ms:Date.now()-u,content_chars:h.length,depth:r,tool_call_count:b?.toolCalls.length,thinking_present:b?.thinkingPresent,tool_names:b?.toolCalls.length?JSON.stringify([...new Set(b.toolCalls.map(w=>w.name))]):void 0}),{content:h}}let f=m.error?.message??"Subagent failed with no output",g=m.trace;ta({event:"subagent.failed",subagent_id:l.id,parent_session_id:d,status:m.status,duration_ms:Date.now()-u,error_message:br(f),schema_error:m.schemaError?br(m.schemaError.message):void 0,partial_output_chars:Zu(m.partialOutput),depth:r,tool_call_count:g?.toolCalls.length,thinking_present:g?.thinkingPresent,tool_names:g?.toolCalls.length?JSON.stringify([...new Set(g.toolCalls.map(S=>S.name))]):void 0});let y=pv({status:m.status,errorMessage:f,schemaErrorMessage:m.schemaError?.message,partialOutput:m.partialOutput,subagentId:l.id});return{content:JSON.stringify(y),isError:!0}}catch(m){let f=m instanceof Error?m.message:String(m);throw ta({event:"subagent.failed",subagent_id:l.id,parent_session_id:d,status:"failed",duration_ms:Date.now()-u,error_message:br(f),depth:r}),m}finally{t.signal.removeEventListener("abort",c),await s?.teardownAll(),await l.teardown()}}};import{randomUUID as Rv}from"node:crypto";import{createHash as Cv}from"crypto";import{mkdir as Pv,open as Av,writeFile as _v}from"fs/promises";import{join as lp}from"path";import{z as k}from"zod";var mv=k.object({phase:k.literal("started"),toolUseId:k.string(),name:k.string(),inputBytes:k.number().int().nonnegative(),subagentId:k.string().optional()}),fv=k.object({phase:k.literal("completed"),toolUseId:k.string(),name:k.string(),resultBytes:k.number().int().nonnegative(),isError:k.boolean(),truncated:k.boolean(),durationMs:k.number().nonnegative(),subagentId:k.string().optional()}),Qu=k.discriminatedUnion("phase",[mv,fv]),gv=k.enum(["PreToolUse","PostToolUse","SessionStart","SessionEnd","SubagentStart","SubagentStop"]),ep=k.object({hookEvent:gv,decision:k.union([k.literal("block"),k.literal("approve"),k.undefined()]),reason:k.string().optional(),blockedTool:k.string().optional(),injectedContextBytes:k.number().int().nonnegative().optional()}),hv=k.object({transition:k.literal("started"),subagentId:k.string(),parentId:k.string(),model:k.string(),allowedTools:k.array(k.string()).readonly().optional(),systemPromptHash:k.string().optional()}),yv=k.object({transition:k.literal("succeeded"),subagentId:k.string(),durationMs:k.number().nonnegative(),turnCount:k.number().int().nonnegative(),totalCostUsd:k.number().nonnegative().optional(),outputBytes:k.number().int().nonnegative()}),bv=k.object({transition:k.literal("failed"),subagentId:k.string(),errorClass:k.string(),errorMessage:k.string(),partialOutputBytes:k.number().int().nonnegative()}),kv=k.object({transition:k.literal("cancelled"),subagentId:k.string(),source:k.enum(["cascade","explicit"])}),tp=k.discriminatedUnion("transition",[hv,yv,bv,kv]),np=k.object({kind:k.literal("monetary"),runningCostUsd:k.number().nonnegative(),maxBudgetUsd:k.number().nonnegative(),lastTurnCostUsd:k.number().nonnegative()}),wv=k.enum(["user_signal","cascade","timeout","budget","hook_block"]),rp=k.object({origin:wv,cascadedTo:k.array(k.string()).readonly(),reason:k.string().optional()}),op=k.enum(["manual","token_threshold","turn_count"]),Sv=k.object({path:k.string(),sizeBytes:k.number().int().nonnegative(),sha256:k.string().regex(/^[0-9a-f]{64}$/)}),vv=k.object({trigger:op,preCompactionMessages:k.array(k.unknown()),summary:k.string(),keptTailCount:k.number().int().nonnegative(),keepLastNConfig:k.number().int().nonnegative(),messagesBefore:k.number().int().nonnegative(),messagesAfter:k.number().int().nonnegative(),tokensSavedEstimate:k.number().nonnegative().optional(),summarizationTokens:k.object({input:k.number().int().nonnegative(),output:k.number().int().nonnegative()}).optional()}),Tv=k.object({trigger:op,preCompactionMessagesRef:Sv,summary:k.string(),keptTailCount:k.number().int().nonnegative(),keepLastNConfig:k.number().int().nonnegative(),messagesBefore:k.number().int().nonnegative(),messagesAfter:k.number().int().nonnegative(),tokensSavedEstimate:k.number().nonnegative().optional(),summarizationTokens:k.object({input:k.number().int().nonnegative(),output:k.number().int().nonnegative()}).optional()}),xv=k.enum(["model_end_turn","iteration_cap","abort","timeout","budget_exceeded","hook_blocked","max_turns_exceeded"]),sp=k.object({reason:xv,finalTurnCount:k.number().int().nonnegative(),finalCostUsd:k.number().nonnegative(),finalTokens:k.object({input:k.number().int().nonnegative().optional(),output:k.number().int().nonnegative().optional(),cacheRead:k.number().int().nonnegative().optional(),cacheCreation:k.number().int().nonnegative().optional()}),lastStopReason:k.string().optional()}),ip=k.object({source:k.string(),assertion:k.string(),evidence:k.array(k.string()).readonly(),confidence:k.number().min(0).max(1),dissent:k.string().optional()}),Ev=k.object({status:k.enum(["succeeded","failed","cancelled"]),finalCostUsd:k.number().nonnegative(),finalTurnCount:k.number().int().nonnegative(),closedAt:k.string().datetime()}),ap=k.discriminatedUnion("kind",[k.object({kind:k.literal("tool_call"),payload:Qu}),k.object({kind:k.literal("hook_decision"),payload:ep}),k.object({kind:k.literal("subagent_lifecycle"),payload:tp}),k.object({kind:k.literal("budget"),payload:np}),k.object({kind:k.literal("abort"),payload:rp}),k.object({kind:k.literal("compaction"),payload:vv}),k.object({kind:k.literal("closure"),payload:sp}),k.object({kind:k.literal("claim"),payload:ip})]),nN=k.discriminatedUnion("kind",[k.object({ts:k.string().datetime(),seq:k.number().int().nonnegative(),kind:k.literal("tool_call"),payload:Qu}),k.object({ts:k.string().datetime(),seq:k.number().int().nonnegative(),kind:k.literal("hook_decision"),payload:ep}),k.object({ts:k.string().datetime(),seq:k.number().int().nonnegative(),kind:k.literal("subagent_lifecycle"),payload:tp}),k.object({ts:k.string().datetime(),seq:k.number().int().nonnegative(),kind:k.literal("budget"),payload:np}),k.object({ts:k.string().datetime(),seq:k.number().int().nonnegative(),kind:k.literal("abort"),payload:rp}),k.object({ts:k.string().datetime(),seq:k.number().int().nonnegative(),kind:k.literal("compaction"),payload:Tv}),k.object({ts:k.string().datetime(),seq:k.number().int().nonnegative(),kind:k.literal("closure"),payload:sp}),k.object({ts:k.string().datetime(),seq:k.number().int().nonnegative(),kind:k.literal("claim"),payload:ip}),k.object({ts:k.string().datetime(),seq:k.number().int().nonnegative(),kind:k.literal("session_sealed"),payload:Ev})]);var Go=class{traceDir;tracePath;seq=0;sealed=!1;fh=null;writeQueue=Promise.resolve();constructor(t){this.traceDir=t.traceDir,this.tracePath=lp(this.traceDir,"trace.jsonl")}getTracePath(){return this.tracePath}async write(t){if(this.sealed)throw new Error("NdjsonTraceWriter: trace is sealed; write() rejected");return ap.parse(t),this.enqueue(async()=>{await this.ensureOpen();let n=await this.materializePersistedEvent(t);await this.appendLine(n)})}async seal(t){this.sealed||(this.sealed=!0,await this.enqueue(async()=>{await this.ensureOpen();let n={ts:new Date().toISOString(),seq:this.seq++,kind:"session_sealed",payload:t};await this.appendLine(n),this.fh&&await this.fh.sync()}),await this.closeHandle())}async close(){await this.enqueue(async()=>{}),await this.closeHandle()}enqueue(t){let n=this.writeQueue.then(t,t);return this.writeQueue=n.then(()=>{},()=>{}),n}async ensureOpen(){this.fh||(await Pv(this.traceDir,{recursive:!0}),this.fh=await Av(this.tracePath,"a"))}async closeHandle(){if(!this.fh)return;let t=this.fh;this.fh=null,await t.close()}async appendLine(t){if(!this.fh)throw new Error("NdjsonTraceWriter: file handle missing");await this.fh.appendFile(`${JSON.stringify(t)}
|
|
1814
|
+
${XS}`}import nn from"chalk";var ZS=new Set(["Read","Glob","Grep","NotebookRead","LS","read_file","glob","grep","list_directory","memory_search"]),QS=new Set(["Write","Edit","NotebookEdit","MultiEdit","write_file","edit_file","memory_update","procedure_write"]),ev=new Set(["Bash","BashOutput","KillBash","bash"]),hr=new Set(["Agent","Task","agent"]),Lu=new Set(["Skill","skill"]),Nu=new Set(["Compose","compose"]),gt=new Set([...hr,...Nu,...Lu]),tv=new Set(["WebFetch","WebSearch","send_telegram"]),nv=new Set(["TaskCreate","TaskUpdate","TaskList","TaskGet","TaskOutput","TaskStop","EnterPlanMode","ExitPlanMode","ToolSearch"]);function Ot(e,t){if(e.has(t))return!0;let n=t.charAt(0).toUpperCase()+t.slice(1);return n!==t&&e.has(n)}function Bo(e){return e.startsWith("mcp__")||e.startsWith("MCP__")?"mcp":Ot(ZS,e)?"read":Ot(QS,e)?"write":Ot(ev,e)?"shell":Ot(hr,e)?"subagent":Ot(Lu,e)?"skill":Ot(Nu,e)?"dag":Ot(tv,e)?"web":Ot(nv,e)?"planning":"other"}var rv={read:nn.hex("#9CC4D6"),write:nn.hex("#E8A33D"),shell:nn.hex("#A8E060"),subagent:p.plan,skill:nn.hex("#F08AC4"),dag:nn.hex("#4EC9B0"),mcp:nn.hex("#5FE0C0"),web:nn.hex("#7FCDC0"),planning:p.meta,other:p.info},ov={read:"\u25CF",write:"\u270E",shell:"$",subagent:"\u2192",skill:"\u25C6",dag:"\u2B21",mcp:"\u22A1",web:"\u2316",planning:"\u25B1",other:"\u25CF"},sv={subagent:"subagent",skill:"skill",dag:"dag"};function Uu(e){return sv[e]}function Zi(e){return{color:rv[e],glyph:ov[e]}}function $n(e){return Zi(Bo(e))}function ju(e){let{description:t,summary:n,lastToolName:r,totalTokens:o,toolUses:s,durationMs:a}=e,i=[];if(r){let{color:c,glyph:u}=$n(r);i.push(`via ${c(`${u} ${r}`)}`)}s&&i.push(`${s} tool${s===1?"":"s"}`),o&&i.push(`${H(o)} tok`),a&&i.push(me(a));let l=i.length>0?` (${i.join(" \xB7 ")})`:"";return n?[p.dim(` \u25E6 ${t}`),p.dim(` ${n}${l}`)]:[p.dim(` \u25E6 ${t}${l}`)]}function Wo(e){let t=e.status==="succeeded"?"\u2713":e.status==="failed"?"\u2717":"\u2298",n=e.agentType??e.subagentId,r=[t,n];return e.durationMs!==void 0&&r.push(`\xB7 ${me(e.durationMs)}`),p.dim(` ${r.join(" ")}`)}var Bu=new Set;function Wu(e){Bu.add(e)}function Hu(e){return Bu.has(e)}var Qi=new Set,ea=new Set;function Ku(e){Qi.add(e)}function Gu(e){Qi.delete(e)}function zu(e){ea.add(e)}function qu(e){ea.delete(e)}function Yu(e){for(let t of Qi)t(e)}function Vu(e){for(let t of ea)t(e)}function iv(e){if(typeof e!="object"||e===null)return;let t=e.name;if(typeof t!="string")return;let n=t.trim();return n.length>0?n:void 0}function av(e){if(typeof e!="object"||e===null)throw new Error("Skill tool input must be an object");let t=e,n=t.name;if(typeof n!="string"||n.trim().length===0)throw new Error('Skill tool input must have a non-empty "name" field');let r,o=t.arguments;if(o!==void 0){if(typeof o!="string")throw new Error('Skill tool "arguments" must be a string');r=o}return{name:n.trim(),arguments:r}}var Dt=class{constructor(t){this.ctx=t}ctx;pluginBodies=null;async execute(t){if(t.signal.aborted)return{content:"Skill tool call aborted",isError:!0};let n=this.ctx.depth??0,r=this.ctx.maxDepth??On;if(n>=r){let l=iv(t.input);return Ne({event:"delegation.skipped",parent_session_id:this.ctx.parentSession.sessionId,reason:"max_depth",depth:n,requested_name:l}).catch(()=>{}),{content:`Skill tool not available at nesting depth ${n} (max ${r})`,isError:!0}}let o;try{o=av(t.input)}catch(l){return{content:`Skill tool input validation failed: ${l instanceof Error?l.message:String(l)}`,isError:!0}}try{let l=Se(o.name);return await this.executeRegistrySkill(l,o.arguments,t)}catch{}let s=this.getPluginSkillBody(o.name);if(s)return await this.executePluginSkill(o.name,s,o.arguments,t);let i=ur(this.ctx.pluginConfigs).map(l=>l.name).join(", ");return{content:`Skill "${o.name}" not found. Available skills: ${i||"(none)"}`,isError:!0}}async executeRegistrySkill(t,n,r){if(r.signal.aborted)return{content:"Skill call aborted",isError:!0};if(t.context==="fork")return this.executeForkedRegistrySkill(t,n,r);let o=Hu(t.name);o&&Vu(t.name);let s=Date.now(),a,i;try{i=await t.handler(n&&n.length>0?n:void 0,this.ctx.parentSession,{apiKey:this.ctx.apiKey,defaultModel:this.ctx.defaultModel,defaultSubagentModel:this.ctx.defaultSubagentModel,dispatchSkill:this.createDispatchSkillCallback(r)})}catch(c){a=c}finally{if(o){let c=Date.now()-s;Yu({skillName:t.name,durationMs:c,...a!==void 0?{isError:!0}:{}})}}return a!==void 0?{content:`Skill execution error: ${a instanceof Error?a.message:String(a)}`,isError:!0}:{content:typeof i=="string"?i:i!=null?JSON.stringify(i):"Skill completed successfully."}}buildForkedChildConfig(t,n){let r=this.ctx.depth??0,o=this.ctx.maxDepth??On,s={...t};if(!this.ctx.childProviderFactory||r>=o)return{childConfig:s,childManager:void 0};let a=new U({parentAbortSignal:n}),i=new Ft({subagentManager:a,parentSession:yr(n),defaultConfig:{model:s.model,apiKey:this.ctx.apiKey},defaultSubagentModel:this.ctx.defaultSubagentModel,childProviderFactory:this.ctx.childProviderFactory,childSkillExecutorFactory:this.ctx.childSkillExecutorFactory,depth:r+1,maxDepth:o}),l=this.ctx.childSkillExecutorFactory?this.ctx.childSkillExecutorFactory(r+1,o,n):void 0;return s.provider=this.ctx.childProviderFactory({childExecutor:i,childSkillExecutor:l}),{childConfig:s,childManager:a}}async executeForkedRegistrySkill(t,n,r){if(r.signal.aborted)return{content:"Skill call aborted",isError:!0};let o;try{if(o=ie(t.name)["system.md"],!o)return{content:`Skill "${t.name}" has context: "fork" but no prompts/system.md found`,isError:!0}}catch(l){return{content:`Failed to load skill prompts: ${l instanceof Error?l.message:String(l)}`,isError:!0}}let s=new U({parentAbortSignal:r.signal,apiKey:this.ctx.apiKey,progressSink:Ye()}),{childConfig:a,childManager:i}=this.buildForkedChildConfig({model:t.model??this.ctx.defaultSubagentModel??this.ctx.defaultModel??"sonnet",systemPrompt:o},r.signal);try{let l=await s.forkSubagent({parent:this.ctx.parentSession,config:a,idPrefix:`skill-fork-${t.name}`,parentId:r.id,agentType:t.name}),c=n&&n.length>0?n:"Run the skill.",u=await l.runToResult(c);return u.status==="succeeded"&&u.message?{content:u.message.content}:{content:u.error?.message??"Forked skill failed with no output",isError:!0}}catch(l){return{content:`Forked skill execution error: ${l instanceof Error?l.message:String(l)}`,isError:!0}}finally{await i?.teardownAll(),await s.teardownAll()}}async executePluginSkill(t,n,r,o){if(o.signal.aborted)return{content:"Skill call aborted",isError:!0};let s=new U({parentAbortSignal:o.signal,apiKey:this.ctx.apiKey,progressSink:Ye()}),{childConfig:a,childManager:i}=this.buildForkedChildConfig({model:this.ctx.defaultSubagentModel??this.ctx.defaultModel??"sonnet",systemPrompt:n},o.signal);try{let l=await s.forkSubagent({parent:this.ctx.parentSession,config:a,idPrefix:`skill-${t}`,parentId:o.id,agentType:t}),c=r&&r.length>0?r:"Run the skill.",u=await l.runToResult(c);return u.status==="succeeded"&&u.message?{content:u.message.content}:{content:u.error?.message??"Plugin skill failed with no output",isError:!0}}catch(l){return{content:`Plugin skill execution error: ${l instanceof Error?l.message:String(l)}`,isError:!0}}finally{await i?.teardownAll(),await s.teardownAll()}}getPluginSkillBody(t){return this.pluginBodies||(this.pluginBodies=wo(this.ctx.pluginConfigs)),this.pluginBodies.get(t)}createDispatchSkillCallback(t){return async(n,r)=>{let o={id:`${t.id}-dispatch-${n}`,name:"skill",input:{name:n,...r!==void 0?{arguments:r}:{}},signal:t.signal},s=await this.execute(o);if(s.isError)throw new Error(s.content);return s.content}}};var On=3;function yr(e){return{sessionId:void 0,getInputStreamRef:()=>({pushUserMessage:()=>{}}),abortSignal:e}}var lv=[...Rt,"agent","skill"];function Ho(){return({childExecutor:e,childSkillExecutor:t})=>new Te({permissions:{allowedTools:lv},subagentExecutor:e,skillExecutor:t})}function Ko(e,t,n){let r=(o,s,a)=>new Dt({parentSession:yr(a),defaultModel:e,apiKey:t,depth:o,maxDepth:s,childProviderFactory:n,childSkillExecutorFactory:r});return r}function Ju(e){return e.replace(/\x1b\[[0-9;]*[a-zA-Z]/g,"")}function cv(e){if(typeof e!="object"||e===null)throw new Error("Agent tool input must be an object");let t=e,n=t.prompt;if(typeof n!="string")throw new Error('Agent tool input must have a "prompt" field of type string');if(n.trim().length===0)throw new Error("Agent tool prompt cannot be empty");let r,o=t.model;if(o!==void 0){if(typeof o!="string")throw new Error("Agent tool model must be a string");r=o}let s=10,a=t.max_turns;if(a!==void 0){if(typeof a!="number")throw new Error("Agent tool max_turns must be a number");s=Math.max(1,Math.min(50,Math.floor(a)))}let i="agent-tool",l=t.id_prefix;if(l!==void 0){if(typeof l!="string")throw new Error("Agent tool id_prefix must be a string");i=l}return{prompt:n,model:r,max_turns:s,id_prefix:i}}function ta(e){try{return Ne(e).catch(()=>{})}catch{return Promise.resolve()}}function br(e,t=240){return e.length<=t?e:e.slice(0,t)+"\u2026"}function Zu(e){if(e!=null){if(typeof e=="string")return e.length;try{return JSON.stringify(e).length}catch{return}}}var dv=4096,Xu=1024;function uv(e){if(e==null)return;let t=Zu(e);return t!==void 0&&t>dv?{truncated:!0,chars:t}:e}function pv(e){let t={status:e.status,error:br(e.errorMessage,Xu),subagent_id:e.subagentId};e.schemaErrorMessage&&(t.schemaError=br(e.schemaErrorMessage,Xu));let n=uv(e.partialOutput);return n!==void 0&&(t.partialOutput=n),t}var Ft=class e{constructor(t){this.ctx=t}ctx;async execute(t){if(t.signal.aborted)return{content:"Agent tool call aborted",isError:!0};let n;try{n=cv(t.input)}catch(m){return{content:`Agent tool input validation failed: ${m instanceof Error?m.message:String(m)}`,isError:!0}}let r=this.ctx.depth??0,o=this.ctx.maxDepth??On,s,a={model:n.model??this.ctx.defaultSubagentModel??"sonnet",apiKey:this.ctx.defaultConfig.apiKey,systemPrompt:this.ctx.defaultConfig.systemPrompt,maxTurns:n.max_turns},i;if(this.ctx.childProviderFactory&&r<o){s=new U({parentAbortSignal:t.signal}),i=yr(t.signal);let m=new e({subagentManager:s,parentSession:i,defaultConfig:this.ctx.defaultConfig,defaultSubagentModel:this.ctx.defaultSubagentModel,childProviderFactory:this.ctx.childProviderFactory,childSkillExecutorFactory:this.ctx.childSkillExecutorFactory,depth:r+1,maxDepth:o}),f=this.ctx.childSkillExecutorFactory?this.ctx.childSkillExecutorFactory(r+1,o,t.signal):void 0;a.provider=this.ctx.childProviderFactory({childExecutor:m,childSkillExecutor:f})}let l;try{l=await this.ctx.subagentManager.forkSubagent({parent:this.ctx.parentSession,parentId:t.id,config:a,idPrefix:n.id_prefix,agentType:n.id_prefix&&n.id_prefix!=="agent-tool"?Ju(n.id_prefix).replace(/[\r\n]+/g," ").trim()||"agent":Ju(n.prompt).replace(/[\r\n]+/g," ").slice(0,40).trim()||"agent"}),i!==void 0&&(i.sessionId=l.id)}catch(m){return{content:`Failed to fork subagent: ${m instanceof Error?m.message:String(m)}`,isError:!0}}let c=()=>{l.cancel()};t.signal.addEventListener("abort",c,{once:!0});let u=Date.now(),d=this.ctx.parentSession.sessionId;try{let m=await l.runToResult(n.prompt);if(m.status==="succeeded"&&m.message){let S=m.message.content,h=typeof S=="string"?S:JSON.stringify(S),b=m.trace;return ta({event:"subagent.completed",subagent_id:l.id,parent_session_id:d,status:m.status,duration_ms:Date.now()-u,content_chars:h.length,depth:r,tool_call_count:b?.toolCalls.length,thinking_present:b?.thinkingPresent,tool_names:b?.toolCalls.length?JSON.stringify([...new Set(b.toolCalls.map(w=>w.name))]):void 0}),{content:h}}let f=m.error?.message??"Subagent failed with no output",g=m.trace;ta({event:"subagent.failed",subagent_id:l.id,parent_session_id:d,status:m.status,duration_ms:Date.now()-u,error_message:br(f),schema_error:m.schemaError?br(m.schemaError.message):void 0,partial_output_chars:Zu(m.partialOutput),depth:r,tool_call_count:g?.toolCalls.length,thinking_present:g?.thinkingPresent,tool_names:g?.toolCalls.length?JSON.stringify([...new Set(g.toolCalls.map(S=>S.name))]):void 0});let y=pv({status:m.status,errorMessage:f,schemaErrorMessage:m.schemaError?.message,partialOutput:m.partialOutput,subagentId:l.id});return{content:JSON.stringify(y),isError:!0}}catch(m){let f=m instanceof Error?m.message:String(m);throw ta({event:"subagent.failed",subagent_id:l.id,parent_session_id:d,status:"failed",duration_ms:Date.now()-u,error_message:br(f),depth:r}),m}finally{t.signal.removeEventListener("abort",c),await s?.teardownAll(),await l.teardown()}}};import{randomUUID as Rv}from"node:crypto";import{createHash as Cv}from"crypto";import{mkdir as Pv,open as Av,writeFile as _v}from"fs/promises";import{join as lp}from"path";import{z as k}from"zod";var mv=k.object({phase:k.literal("started"),toolUseId:k.string(),name:k.string(),inputBytes:k.number().int().nonnegative(),subagentId:k.string().optional()}),fv=k.object({phase:k.literal("completed"),toolUseId:k.string(),name:k.string(),resultBytes:k.number().int().nonnegative(),isError:k.boolean(),truncated:k.boolean(),durationMs:k.number().nonnegative(),subagentId:k.string().optional()}),Qu=k.discriminatedUnion("phase",[mv,fv]),gv=k.enum(["PreToolUse","PostToolUse","SessionStart","SessionEnd","SubagentStart","SubagentStop"]),ep=k.object({hookEvent:gv,decision:k.union([k.literal("block"),k.literal("approve"),k.undefined()]),reason:k.string().optional(),blockedTool:k.string().optional(),injectedContextBytes:k.number().int().nonnegative().optional()}),hv=k.object({transition:k.literal("started"),subagentId:k.string(),parentId:k.string(),model:k.string(),allowedTools:k.array(k.string()).readonly().optional(),systemPromptHash:k.string().optional()}),yv=k.object({transition:k.literal("succeeded"),subagentId:k.string(),durationMs:k.number().nonnegative(),turnCount:k.number().int().nonnegative(),totalCostUsd:k.number().nonnegative().optional(),outputBytes:k.number().int().nonnegative()}),bv=k.object({transition:k.literal("failed"),subagentId:k.string(),errorClass:k.string(),errorMessage:k.string(),partialOutputBytes:k.number().int().nonnegative()}),kv=k.object({transition:k.literal("cancelled"),subagentId:k.string(),source:k.enum(["cascade","explicit"])}),tp=k.discriminatedUnion("transition",[hv,yv,bv,kv]),np=k.object({kind:k.literal("monetary"),runningCostUsd:k.number().nonnegative(),maxBudgetUsd:k.number().nonnegative(),lastTurnCostUsd:k.number().nonnegative()}),wv=k.enum(["user_signal","cascade","timeout","budget","hook_block"]),rp=k.object({origin:wv,cascadedTo:k.array(k.string()).readonly(),reason:k.string().optional()}),op=k.enum(["manual","token_threshold","turn_count"]),Sv=k.object({path:k.string(),sizeBytes:k.number().int().nonnegative(),sha256:k.string().regex(/^[0-9a-f]{64}$/)}),vv=k.object({trigger:op,preCompactionMessages:k.array(k.unknown()),summary:k.string(),keptTailCount:k.number().int().nonnegative(),keepLastNConfig:k.number().int().nonnegative(),messagesBefore:k.number().int().nonnegative(),messagesAfter:k.number().int().nonnegative(),tokensSavedEstimate:k.number().nonnegative().optional(),summarizationTokens:k.object({input:k.number().int().nonnegative(),output:k.number().int().nonnegative()}).optional()}),Tv=k.object({trigger:op,preCompactionMessagesRef:Sv,summary:k.string(),keptTailCount:k.number().int().nonnegative(),keepLastNConfig:k.number().int().nonnegative(),messagesBefore:k.number().int().nonnegative(),messagesAfter:k.number().int().nonnegative(),tokensSavedEstimate:k.number().nonnegative().optional(),summarizationTokens:k.object({input:k.number().int().nonnegative(),output:k.number().int().nonnegative()}).optional()}),xv=k.enum(["model_end_turn","iteration_cap","abort","timeout","budget_exceeded","hook_blocked","max_turns_exceeded"]),sp=k.object({reason:xv,finalTurnCount:k.number().int().nonnegative(),finalCostUsd:k.number().nonnegative(),finalTokens:k.object({input:k.number().int().nonnegative().optional(),output:k.number().int().nonnegative().optional(),cacheRead:k.number().int().nonnegative().optional(),cacheCreation:k.number().int().nonnegative().optional()}),lastStopReason:k.string().optional()}),ip=k.object({source:k.string(),assertion:k.string(),evidence:k.array(k.string()).readonly(),confidence:k.number().min(0).max(1),dissent:k.string().optional()}),Ev=k.object({status:k.enum(["succeeded","failed","cancelled"]),finalCostUsd:k.number().nonnegative(),finalTurnCount:k.number().int().nonnegative(),closedAt:k.string().datetime()}),ap=k.discriminatedUnion("kind",[k.object({kind:k.literal("tool_call"),payload:Qu}),k.object({kind:k.literal("hook_decision"),payload:ep}),k.object({kind:k.literal("subagent_lifecycle"),payload:tp}),k.object({kind:k.literal("budget"),payload:np}),k.object({kind:k.literal("abort"),payload:rp}),k.object({kind:k.literal("compaction"),payload:vv}),k.object({kind:k.literal("closure"),payload:sp}),k.object({kind:k.literal("claim"),payload:ip})]),rN=k.discriminatedUnion("kind",[k.object({ts:k.string().datetime(),seq:k.number().int().nonnegative(),kind:k.literal("tool_call"),payload:Qu}),k.object({ts:k.string().datetime(),seq:k.number().int().nonnegative(),kind:k.literal("hook_decision"),payload:ep}),k.object({ts:k.string().datetime(),seq:k.number().int().nonnegative(),kind:k.literal("subagent_lifecycle"),payload:tp}),k.object({ts:k.string().datetime(),seq:k.number().int().nonnegative(),kind:k.literal("budget"),payload:np}),k.object({ts:k.string().datetime(),seq:k.number().int().nonnegative(),kind:k.literal("abort"),payload:rp}),k.object({ts:k.string().datetime(),seq:k.number().int().nonnegative(),kind:k.literal("compaction"),payload:Tv}),k.object({ts:k.string().datetime(),seq:k.number().int().nonnegative(),kind:k.literal("closure"),payload:sp}),k.object({ts:k.string().datetime(),seq:k.number().int().nonnegative(),kind:k.literal("claim"),payload:ip}),k.object({ts:k.string().datetime(),seq:k.number().int().nonnegative(),kind:k.literal("session_sealed"),payload:Ev})]);var Go=class{traceDir;tracePath;seq=0;sealed=!1;fh=null;writeQueue=Promise.resolve();constructor(t){this.traceDir=t.traceDir,this.tracePath=lp(this.traceDir,"trace.jsonl")}getTracePath(){return this.tracePath}async write(t){if(this.sealed)throw new Error("NdjsonTraceWriter: trace is sealed; write() rejected");return ap.parse(t),this.enqueue(async()=>{await this.ensureOpen();let n=await this.materializePersistedEvent(t);await this.appendLine(n)})}async seal(t){this.sealed||(this.sealed=!0,await this.enqueue(async()=>{await this.ensureOpen();let n={ts:new Date().toISOString(),seq:this.seq++,kind:"session_sealed",payload:t};await this.appendLine(n),this.fh&&await this.fh.sync()}),await this.closeHandle())}async close(){await this.enqueue(async()=>{}),await this.closeHandle()}enqueue(t){let n=this.writeQueue.then(t,t);return this.writeQueue=n.then(()=>{},()=>{}),n}async ensureOpen(){this.fh||(await Pv(this.traceDir,{recursive:!0}),this.fh=await Av(this.tracePath,"a"))}async closeHandle(){if(!this.fh)return;let t=this.fh;this.fh=null,await t.close()}async appendLine(t){if(!this.fh)throw new Error("NdjsonTraceWriter: file handle missing");await this.fh.appendFile(`${JSON.stringify(t)}
|
|
1815
1815
|
`)}async materializePersistedEvent(t){let n=new Date().toISOString(),r=this.seq++;if(t.kind==="compaction"){let o=await this.persistCompactionSidecar(t.payload,r,n);return{ts:n,seq:r,kind:"compaction",payload:o}}return{ts:n,seq:r,kind:t.kind,payload:t.payload}}async persistCompactionSidecar(t,n,r){let o=r.replace(/[:.]/g,"-"),s=lp(this.traceDir,`${String(n).padStart(6,"0")}-${o}-pre-compaction.json`),a=JSON.stringify(t.preCompactionMessages),i=Buffer.byteLength(a,"utf8"),l=Cv("sha256").update(a).digest("hex");await _v(s,a,{encoding:"utf8",flag:"w"});let c={path:s,sizeBytes:i,sha256:l};return{trigger:t.trigger,preCompactionMessagesRef:c,summary:t.summary,keptTailCount:t.keptTailCount,keepLastNConfig:t.keepLastNConfig,messagesBefore:t.messagesBefore,messagesAfter:t.messagesAfter,...t.tokensSavedEstimate!==void 0?{tokensSavedEstimate:t.tokensSavedEstimate}:{},...t.summarizationTokens!==void 0?{summarizationTokens:t.summarizationTokens}:{}}}};function zo(e={}){if(process.env.AFK_TRACE_DISABLED==="1")return null;let t=e.sessionLabel??Rv(),n=Tl(t),r=new Go({traceDir:n});return{writer:r,tracePath:r.getTracePath(),sessionLabel:t}}import{execFile as Iv}from"node:child_process";import{promisify as Mv}from"node:util";import{promises as kr}from"node:fs";import{dirname as na,isAbsolute as $v,join as wr,resolve as Ov}from"node:path";import{randomBytes as Dv}from"node:crypto";var cp=Mv(Iv),Fv="afk/";function dp(e){if(e!==void 0)return e;let t=process.env.AFK_WORKTREE_BRANCH_PREFIX;return t!==void 0?t:Fv}function Dn(e){return e instanceof Error}function Lv(e){let t=l=>String(l).padStart(2,"0"),n=String(e.getFullYear()),r=t(e.getMonth()+1),o=t(e.getDate()),s=t(e.getHours()),a=t(e.getMinutes()),i=t(e.getSeconds());return`${n}${r}${o}-${s}${a}${i}`}function Nv(e){let t=Lv(new Date),n=Dv(3).toString("hex");return`${e}${t}-${n}`}function up(e){if(e.trim().length===0)throw new Error("Invalid branch name: '' \u2014 branch name cannot be empty.");if(e.startsWith("-"))throw new Error(`Invalid branch name: '${e}' \u2014 must not start with '-' (would be parsed by git as a flag).`);if(e==="HEAD")throw new Error("Invalid branch name: 'HEAD' \u2014 reserved by git.");if(e.includes(".."))throw new Error(`Invalid branch name: '${e}' \u2014 must not contain '..'.`);let n=[{char:"~",label:"'~'"},{char:"^",label:"'^'"},{char:":",label:"':'"},{char:"?",label:"'?'"},{char:"*",label:"'*'"},{char:"[",label:"'['"},{char:"\\",label:"'\\'"},{char:"\0",label:"NUL byte"}];for(let{char:r,label:o}of n)if(e.includes(r))throw new Error(`Invalid branch name: '${e}' \u2014 must not contain ${o}.`);if(/\s/.test(e))throw new Error(`Invalid branch name: '${e}' \u2014 must not contain whitespace.`)}async function Uv(e){let t;try{t=(await e("git",["rev-parse","--git-common-dir"])).stdout.trim()}catch{throw new Error("Not in a git repository (run from inside a git checkout).")}if(!t)throw new Error("Not in a git repository (run from inside a git checkout).");let n=$v(t)?t:Ov(process.cwd(),t);return na(n)}async function jv(e){let t=wr(e,".gitignore"),n=".afk-worktrees/",r="";try{r=await kr.readFile(t,"utf8")}catch(a){if(a.code!=="ENOENT")throw a;r=""}if(r.split(`
|
|
1816
1816
|
`).some(a=>a.trim()===n))return;let s=r;s.length>0&&!s.endsWith(`
|
|
1817
1817
|
`)&&(s+=`
|
|
1818
1818
|
`),s+=`${n}
|
|
1819
1819
|
`,await kr.writeFile(t,s,"utf8")}function Bv(e,t,n){if(!Dn(e))return new Error(`git worktree add failed: ${String(e)}`);let r=e.stderr??"",o=e.message??"",s=`${r}
|
|
1820
1820
|
${o}`;return s.includes("already checked out")||s.includes("is already used by worktree")?new Error(`Branch '${t}' is already checked out in another worktree. Pick a different name.`):s.includes("already exists")?new Error(`Worktree path '${n}' already exists. Remove it or pick a different branch name.`):new Error(o||r||"git worktree add failed")}async function qo(e,t){let n=t?.execFile??cp,r=dp(t?.branchPrefix),o=await Uv(n),s=e===!0?Nv(r):e;up(s);let a=s.replaceAll("/","-"),i=wr(o,".afk-worktrees",a);await jv(o);try{await n("git",["-C",o,"worktree","add","-b",s,i])}catch(c){throw Bv(c,s,i)}let l={path:i,branch:s,cleanup:async()=>{let c=l.path,u=l.branch,d;try{d=await n("git",["-C",c,"status","--porcelain"])}catch(m){let f=Dn(m)?m.message||m.stderr||"":String(m);console.warn(`Worktree cleanup: could not check status at ${c} (${f}). Skipping removal \u2014 manual cleanup may be needed.`);return}if(d.stdout.trim().length>0){console.log(`Worktree preserved at ${c} (branch: ${u}) \u2014 uncommitted changes.`);return}try{await n("git",["-C",o,"worktree","remove","--force",c])}catch(m){let f=Dn(m)?m.message||m.stderr||"":String(m);console.warn(`Worktree cleanup: 'git worktree remove --force ${c}' failed (${f}). Manual removal may be needed.`);return}try{await n("git",["-C",o,"branch","-d",u])}catch(m){let f=Dn(m)?m.message||m.stderr||"":String(m);console.warn(`Could not delete branch '${u}': ${f}`)}}};try{let c="",u="";try{c=(await n("git",["-C",o,"rev-parse","HEAD"])).stdout.trim()}catch{}try{u=(await n("git",["-C",o,"symbolic-ref","--short","HEAD"])).stdout.trim()}catch{}let d={owner:"interactive",createdAt:new Date().toISOString(),baseSha:c,baseBranch:u};await kr.writeFile(wr(i,".afk-worktree-meta.json"),JSON.stringify(d,null,2),"utf-8")}catch{}return l}async function pp(e,t,n){let r=n?.execFile??cp,o=dp(n?.branchPrefix),s=e.path,a=e.branch,i=`${o}${t}`;try{up(i)}catch(d){return{ok:!1,reason:d instanceof Error?d.message:String(d)}}let l=na(s),c=na(l),u=wr(l,t);if(s===u&&a===i)return{ok:!1,reason:"rename would be a no-op (slug matches current state)"};try{await r("git",["-C",c,"worktree","move",s,u])}catch(d){return{ok:!1,reason:`worktree move failed: ${Dn(d)?d.message||d.stderr||"":String(d)}`}}try{await r("git",["-C",u,"branch","-m",a,i])}catch(d){let m=Dn(d)?d.message||d.stderr||"":String(d);return e.path=u,{ok:!1,reason:`branch rename failed (worktree moved successfully): ${m}`,partial:"branch",newPath:u}}e.path=u,e.branch=i;try{let d=wr(u,".afk-worktree-meta.json"),m={};try{let g=await kr.readFile(d,"utf-8");m=JSON.parse(g)}catch{}let f={...m,worktreePath:u,branch:i};await kr.writeFile(d,JSON.stringify(f,null,2),"utf-8")}catch{}return{ok:!0,oldPath:s,newPath:u,oldBranch:a,newBranch:i}}function hp(e){e.command("chat").description("Send a message to the agent").argument("<message>","Message to send").option("-m, --model <model>","Model to use. Short aliases: opus|opus_1m|sonnet|sonnet_1m|haiku. Any other value (e.g. `auto` for cursor-api-proxy, or a full `claude-*` ID) passes through to the SDK/proxy untouched.",ve()).option("-s, --stream","[no-op] reserved; chat currently waits for the full response",!1).option("-f, --format <format>","Output format (text|json)","text").option("--max-turns <number>","Maximum conversation turns","10").option("--thinking <mode>","Thinking mode: 'adaptive' | 'disabled' | 'enabled:<N>'","enabled:max").option("--effort <level>","Effort level: low|medium|high|xhigh|max").option("--max-budget-usd <usd>","Hard session cost ceiling in USD. Env: AFK_MAX_BUDGET_USD").option("--task-budget <tokens>","Soft per-task token budget. Env: AFK_TASK_BUDGET").option("--max-output-tokens <n|max>","Per-response output cap ('max' = model ceiling). Env: AFK_MAX_OUTPUT_TOKENS").option("--provider <name>","Provider to use: anthropic|anthropic-direct|openai-codex. Default: auto-selected by model").option("--dump-prompt [path]",'Dump resolved SDK prompt+options+provenance to file (default: ~/.afk/logs/prompt-dump-<ISO>.json) or "stderr"').option("-w, --worktree [branch]","Create a git worktree for an isolated one-shot. Optional value sets the branch name; otherwise auto-named. On clean exit (no uncommitted changes) the worktree and branch are auto-removed; on dirty exit the worktree is preserved. Mirrors `afk interactive -w`.").action(async(t,n)=>{let r=Wv("Initializing agent...").start(),o=null,s,a,i;try{if(n.worktree!==void 0)try{a=await qo(n.worktree),i=a.path,r.text=`Worktree ready at ${a.path} (branch: ${a.branch})`}catch(_){r.fail("Failed to create worktree"),z(_)}let l,c,u,d,m,f;try{l=Mt(n.thinking)??En(),c=$t(n.effort)??Cn(),u=Pn(n.maxBudgetUsd)??Pi(),d=Pn(n.taskBudget)??Ai(),m=An(n.maxOutputTokens)??cr(),f=void 0}catch(_){r.fail("Invalid options"),z(_)}if(n.dumpPrompt!==void 0){let _=n.dumpPrompt===!0?gp.join(fp.homedir(),".afk","logs",`prompt-dump-${new Date().toISOString().replace(/[:.]/g,"-")}.json`):String(n.dumpPrompt);process.env.AFK_DUMP_PROMPT=_,n.provider!==void 0&&n.provider!=="anthropic"&&n.provider!=="anthropic-direct"&&console.error(`[--dump-prompt] WARNING: active provider (${n.provider}) does not support prompt dumping. No file will be written.`)}let g=J(),y=xn()??Tn(),S=je(),h=S.systemPromptSource,b=S.autoRouting?.chat??!1,w=jo(y,b),C,T=new U({apiKey:g,...i!==void 0?{cwd:i}:{}}),A=Ho(),x={get sessionId(){return C?.sessionId},getInputStreamRef(){return C?.getInputStreamRef?.()??{pushUserMessage:()=>{}}},get abortSignal(){return C?.abortSignal??new AbortController().signal}},v=Ko(n.model,g,A),E=new Ft({subagentManager:T,parentSession:x,defaultConfig:{apiKey:g,systemPrompt:y},defaultSubagentModel:It(),childProviderFactory:A,childSkillExecutorFactory:v}),R=new Dt({parentSession:x,defaultModel:n.model,defaultSubagentModel:It(),apiKey:g,childProviderFactory:A,childSkillExecutorFactory:v}),I=new In({parentSession:x,defaultModel:n.model,defaultSubagentModel:It(),apiKey:g,systemPrompt:y??""});s=new Re,f=ko(n.provider,{subagentExecutor:E,skillExecutor:R,composeExecutor:I,memoryStore:s})??new Te({permissions:{allowedTools:[...Rt,...tn,"agent","skill","compose"]},subagentExecutor:E,skillExecutor:R,composeExecutor:I,memoryStore:s,surface:"cli"});let D=zo();o=new Ae(en({model:n.model,apiKey:g,maxTurns:parseInt(n.maxTurns,10),hookRegistry:Mn(_=>{console.log(Wo(_))},"cli",s).registry,...w!==void 0?{systemPrompt:w}:{},...h!==void 0?{systemPromptSource:h}:{},...l!==void 0?{thinking:l}:{},...c!==void 0?{effort:c}:{},...u!==void 0?{maxBudgetUsd:u}:{},...d!==void 0?{taskBudget:d}:{},...m!==void 0?{maxOutputTokens:m}:{},...D?{traceWriter:D.writer}:{},...S.autoResumeOnUsageLimit!==void 0?{autoResumeOnUsageLimit:S.autoResumeOnUsageLimit}:{},...i!==void 0?{cwd:i}:{},provider:f})),C=o,r.text="Sending message...";let F=await o.sendMessage(t,{stream:n.stream});if(r.succeed("Response received"),n.format==="json"){let _=o.getLastResponseMetadata(),M=_?Number(_.usage?.input_tokens??0):0,N=_?Number(_.usage?.output_tokens??0):0;console.log(JSON.stringify({success:!0,model:n.model,message:F.content,timestamp:F.timestamp,..._?.totalCostUsd!==void 0?{costUsd:_.totalCostUsd}:{},..._?.durationMs!==void 0?{durationMs:_.durationMs}:{},...M>0?{inputTokens:M}:{},...N>0?{outputTokens:N}:{}},null,2))}else{console.log(mp.cyan(`
|
|
1821
|
-
\u{1F916} Claude:`)),console.log(Qe(F.content));let _=o.getLastResponseMetadata();if(_){let M=[];_.durationMs&&M.push(me(_.durationMs)),_.totalCostUsd!==void 0&&M.push(Ie(_.totalCostUsd));let N=Number(_.usage?.input_tokens??0),V=Number(_.usage?.output_tokens??0);N+V>0&&M.push(H(N+V)+" tokens"),M.length>0&&console.log(mp.dim(" \xB7 "+M.join(" \xB7 ")))}console.log("")}}catch(l){r.fail("Failed to send message"),z(l)}finally{o&&await o.close(),s?.close(),a!==void 0&&await a.cleanup()}})}import eP from"ora";import*as gg from"node:os";import*as zn from"node:path";var Yo=new Set;function Fn(e){return Yo.add(e),()=>{Yo.delete(e)}}async function ra(){await Promise.all([...Yo].map(e=>e())),Yo.clear()}import{readFileSync as Hv,writeFileSync as Kv,existsSync as oa,mkdirSync as Gv,readdirSync as zv,statSync as qv}from"fs";import{join as yp,basename as bp}from"path";function sa(){return Pl(),kt()}function ia(e){return yp(sa(),`${e}.json`)}function Vo(e,t){let n=sa();oa(n)||Gv(n,{recursive:!0});let r=t??e.sessionId??`session-${Date.now()}`,o={sessionId:e.sessionId,model:e.model,startedAt:e.sessionStartTime,savedAt:Date.now(),totalTurns:e.totalTurns,totalCostUsd:e.totalCostUsd,totalTokens:e.totalTokens,totalDurationMs:e.totalDurationMs,turns:e.turns},s=ia(r);return Kv(s,JSON.stringify(o,null,2)),s}function Sr(e){let t=e.includes("/")?e:ia(e);if(oa(t))try{let n=Hv(t,"utf-8");return JSON.parse(n)}catch{return}}function Jo(e){let t=e.includes("/")?e:ia(e),n=Sr(t);if(n)return{path:t,id:bp(t,".json"),data:n};for(let r of vr()){if(r.id!==e&&r.sessionId!==e)continue;let o=Sr(r.path);if(o)return{path:r.path,id:r.id,data:o}}}function vr(){let e=sa();if(!oa(e))return[];let t=[];for(let n of zv(e)){if(!n.endsWith(".json"))continue;let r=yp(e,n);try{if(!qv(r).isFile())continue;let s=Sr(r);if(!s||typeof s.savedAt!="number"||typeof s.model!="string")continue;t.push({path:r,id:bp(n,".json"),sessionId:s.sessionId,model:s.model,startedAt:s.startedAt,savedAt:s.savedAt,totalTurns:s.totalTurns,totalCostUsd:s.totalCostUsd})}catch{}}return t.sort((n,r)=>r.savedAt-n.savedAt),t}var Yv=/^[A-Za-z0-9_@%+=:,./-]+$/;function kp(e){return Yv.test(e)?e:`'${e.replace(/'/g,"'\\''")}'`}function Ln(e,t){let n=["afk","interactive"];return typeof t=="string"&&t.length>0&&n.push("--model",kp(t)),n.push("--resume",kp(e)),n.join(" ")}import*as xf from"node:readline";function wp(e){let t=Math.max(0,Math.min(1,e.ratio)),n=t>.8?p.error:t>.5?p.warning:p.meta,r=20,o=Math.round(t*r),s=r-o,a="["+"\u2588".repeat(o)+"\u2591".repeat(s)+"]",i=Math.round(t*100)+"%",l="";e.used!==void 0&&e.limit!==void 0&&(l=H(e.used)+"/"+H(e.limit));let c=l?`${a} ${i} ${l}`:`${a} ${i}`,u=`${a} ${i}`,d=`ctx ${i}`,m=e.sparkline?p.meta(e.sparkline)+" ":"",f=e.sparkline?j(e.sparkline)+1:0,g=Math.max(0,e.width-f);if(j(c)<=g&&g>90)return m+n(c);if(j(u)<=g&&g>32)return m+n(u);if(j(d)<=g)return m+n(d);if(e.width>0){let y=m+n(d);return se(y,e.width)}return n(i)}import Vv from"chalk";var la=new Map;function Sp(e,t){let n=la.get(e);if(n){if(n.glyph===t.glyph&&n.color===t.color&&n.inFlightVerb===t.inFlightVerb)return;throw new Error(`Trusted skill "${e}" already registered with different config`)}la.set(e,t),Wu(e)}function Xo(e){return la.get(e)}function Jv(e){return(e/1e3).toFixed(1)+"s"}function vp(e,t){let n=Xo(e.skillName),r=Jv(e.durationMs);if(!n){let s=`[${e.skillName} \xB7 ${r}]`;return aa(s,t?.columns)}if(t?.isTTY!==!1){let s;if(e.claimsTotal!==void 0){let i=e.claimsTotal===e.claimsConfirmed&&e.claimsRefuted===void 0&&e.claimsInconclusive===void 0,l;if(i)l=`${e.claimsTotal} claims \xB7 all confirmed`;else{let c=`${e.claimsTotal} claims`;e.claimsConfirmed!==void 0&&(c+=` \xB7 ${e.claimsConfirmed} confirmed`),e.claimsRefuted!==void 0&&(c+=` \xB7 ${e.claimsRefuted} refuted`),e.claimsInconclusive!==void 0&&(c+=` \xB7 ${e.claimsInconclusive} inconclusive`),l=c}s=`${n.glyph} ${e.skillName} \xB7 ${l} \xB7 ${r}`}else s=`${n.glyph} ${e.skillName} \xB7 ${r}`;let a=Vv.hex(n.color)(s);return aa(a,t?.columns)}else{let s;if(e.claimsTotal!==void 0){let a=e.claimsConfirmed??0;s=`[${e.skillName} \xB7 ${a}/${e.claimsTotal} confirmed \xB7 ${r}]`}else s=`[${e.skillName} \xB7 ${r}]`;return aa(s,t?.columns)}}function aa(e,t){return t!==void 0&&j(e)>t?se(e,t):e}function Tp(e){let t=Xo(e);return t?`${t.glyph} ${t.inFlightVerb}`:e}import{homedir as Xv}from"node:os";import{sep as nt}from"node:path";function xp(e,t={}){if(!e)return"";let n=t.homedir??Xv(),r=Zv(e,n),o=t.maxWidth;if(o===void 0||o<=0||j(r)<=o)return r;let s=r.split(nt).filter(d=>d.length>0);if(s.length<=1)return se(r,o);let i=r.startsWith("~")?"~":s[0],l=1,c=s[s.length-1],u=[];for(let d=s.length-2;d>=l;d--){let m=s.slice(l,d+1),f=m.length>0?m.join(nt)+nt:"";u.push(`${i}${nt}${f}\u2026${nt}${c}`)}u.push(`${i}${nt}\u2026${nt}${c}`);for(let d of u)if(j(d)<=o)return d;return se(u[u.length-1],o)}function Zv(e,t){if(!t)return e;if(e===t)return"~";let n=t.endsWith(nt)?t:t+nt;return e.startsWith(n)?"~"+nt+e.slice(n.length):e}var Zo=class{stream;force;throttleMs;started=!1;lastRepaint=0;lastFields=null;resizeUnsub=null;lastPaintedRow=null;extraRows=0;constructor(t={}){this.stream=t.stream??process.stdout,this.force=t.force??!1,this.throttleMs=t.throttleMs??100}get enabled(){return this.force||!!this.stream.isTTY}start(){if(this.started||!this.enabled)return;this.started=!0,this.lastRepaint=0;let t=this.currentRows();this.stream.write("\x1B[s"),this.writeScrollRegion(t),this.stream.write("\x1B[u"),this.resizeUnsub===null&&(this.resizeUnsub=xt.subscribe(()=>{this.onResize()}))}onResize(){if(!this.started||!this.enabled)return;let t=this.currentRows();this.stream.write("\x1B[s"),this.lastPaintedRow!==null&&this.lastPaintedRow!==this.paintRow(t)&&(this.stream.write(`\x1B[${this.lastPaintedRow};1H`),this.stream.write("\x1B[2K")),this.writeScrollRegion(t),this.stream.write("\x1B[u"),this.flush()}repaint(t){if(!this.enabled||!this.started){this.lastFields=t;return}let n=Date.now();if(n-this.lastRepaint<this.throttleMs){this.lastFields=t;return}this.lastRepaint=n,this.lastFields=t;let r=this.currentRows();this.stream.write("\x1B[s"),this.stream.write(`\x1B[${this.paintRow(r)};1H`),this.stream.write("\x1B[2K"),this.stream.write(this.formatLine(t)),this.stream.write("\x1B[u"),this.lastPaintedRow=this.paintRow(r)}flush(){this.lastRepaint=0,this.lastFields&&this.repaint(this.lastFields)}setExtraRows(t){if(this.extraRows=t,this.started&&this.enabled){let n=this.currentRows();this.stream.write("\x1B[s"),this.writeScrollRegion(n),this.stream.write("\x1B[u"),this.flush()}}getExtraRows(){return this.extraRows}rearm(){if(!this.started||!this.enabled)return;let t=this.currentRows();this.stream.write("\x1B[s"),this.writeScrollRegion(t),this.stream.write("\x1B[u"),this.flush()}stop(){if(this.resizeUnsub!==null&&(this.resizeUnsub(),this.resizeUnsub=null),!this.started||!this.enabled){this.started=!1;return}let t=this.currentRows();this.stream.write("\x1B[s"),this.stream.write(`\x1B[${this.lastPaintedRow??this.paintRow(t)};1H`),this.stream.write("\x1B[2K"),this.stream.write("\x1B[r"),this.stream.write("\x1B[u"),this.started=!1,this.lastRepaint=0,this.lastPaintedRow=null}formatLine(t){let n=[],r=Math.max(4,(this.stream.columns??80)-2);if(t.cwd){let s=Math.max(8,Math.floor(r*.4)),a=xp(t.cwd,{maxWidth:s});a&&n.push(p.dim(a))}if(t.trustedSkillVerifying&&n.push(Tp(t.trustedSkillVerifying)),n.push(p.brand(t.model)),t.planMode&&n.push(p.warning("\u25CF plan")),t.contextPct!==void 0){let s=wp({ratio:t.contextPct,used:t.contextUsedTokens,limit:t.contextLimit,sparkline:t.contextSparkline,width:r});n.push(s)}t.cost!==void 0&&n.push(p.meta(`$${t.cost.toFixed(2)}`)),t.tokens!==void 0&&n.push(p.meta(`${Qv(t.tokens)} tok`));let o=n.join(p.dim(" \xB7 "));return se(o,r)}currentRows(){let t=this.stream.rows;return typeof t=="number"&&t>0?t:24}paintRow(t){return t>1?t:1}writeScrollRegion(t){let n=1+this.extraRows;if(t>n){this.stream.write(`\x1B[1;${t-n}r`);return}this.stream.write("\x1B[r")}};function Qv(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}k`:`${e}`}var Me=new Map,rn=new Map;function re(e){if(Me.has(e.name))throw new Error(`Slash command already registered: ${e.name}`);Me.set(e.name,e);for(let t of e.aliases??[]){if(rn.has(t)||Me.has(t))throw new Error(`Slash alias collides: ${t}`);rn.set(t,e.name)}}function Lt(e){if(Me.has(e.name)){for(let[t,n]of rn.entries())n===e.name&&rn.delete(t);Me.delete(e.name)}re(e)}function Ep(e){Me.has(e.name)||re(e)}function Cp(){Me.clear(),rn.clear()}function rt(){return[...Me.values()].sort((e,t)=>e.name.localeCompare(t.name))}function Pp(){let e=[];for(let[t,n]of rn.entries()){let r=Me.get(n);r&&e.push({alias:t,canonical:n,summary:r.summary})}return e.sort((t,n)=>t.alias.localeCompare(n.alias))}function eT(e){if(Me.has(e))return Me.get(e);let t=rn.get(e);return t?Me.get(t):void 0}function tT(e,t){let n=Array.from({length:e.length+1},()=>new Array(t.length+1).fill(0));for(let r=0;r<=e.length;r++)n[r][0]=r;for(let r=0;r<=t.length;r++)n[0][r]=r;for(let r=1;r<=e.length;r++)for(let o=1;o<=t.length;o++){let s=e[r-1]===t[o-1]?0:1;n[r][o]=Math.min(n[r-1][o]+1,n[r][o-1]+1,n[r-1][o-1]+s)}return n[e.length][t.length]}function nT(e,t=3){let n;for(let r of Me.keys()){let o=tT(e,r);o<=t&&(n===void 0||o<n.dist)&&(n={name:r,dist:o})}return n?.name}function rT(e){let t=e.trim();if(!t.startsWith("/"))return null;let n=t.indexOf(" ");return n===-1?{name:t,args:""}:{name:t.slice(0,n),args:t.slice(n+1).trim()}}async function Ap(e,t){let n=rT(e);if(n===null)return{handled:!1};let r=eT(n.name);if(!r){let s=nT(n.name);return s?t.out.warn(`Unknown command: ${n.name} (did you mean ${s}?)`):t.out.warn(`Unknown command: ${n.name} (type /help for commands)`),{handled:!0,result:"continue"}}let o=await r.handler(t,n.args);return o==="forward"?{handled:!1}:{handled:!0,result:o}}import sT from"ora";function _p(e){return{totalTurns:0,totalCostUsd:0,totalTokens:0,totalDurationMs:0,sessionStartTime:Date.now(),turnCosts:[],turnTokens:[],turns:[],model:e,planMode:!1}}function Rp(e){e.totalTurns=0,e.totalCostUsd=0,e.totalTokens=0,e.totalDurationMs=0,e.sessionStartTime=Date.now(),e.turnCosts.length=0,e.turnTokens.length=0,e.turns.length=0,delete e.sessionId,delete e.pendingPlanExit}function Qo(e,t,n,r,o){let s=r?.totalCostUsd??0,a=r?.durationMs??0,i=Number(r?.usage?.input_tokens??0),l=Number(r?.usage?.output_tokens??0),c=i,u=l,d=Number(r?.usage?.cache_read_input_tokens??0)+Number(r?.usage?.cache_creation_input_tokens??0),m=r?.usage?.iterations;if(Array.isArray(m)&&m.length>0){let g=m[m.length-1];if(g&&typeof g=="object"){let y=g;c=Number(y.input_tokens??0),u=Number(y.output_tokens??0),d=Number(y.cache_read_input_tokens??0)+Number(y.cache_creation_input_tokens??0)}}e.totalTurns+=1,e.totalCostUsd+=s,e.totalDurationMs+=a,e.totalTokens+=i+l,e.turnCosts.push(s),e.turnTokens.push({input:c,output:u,cache:d}),r?.sessionId&&!e.sessionId&&(e.sessionId=String(r.sessionId));let f={user:t,assistant:n,timestamp:Date.now(),costUsd:s,durationMs:a,inputTokens:i,outputTokens:l,...o&&o.length>0?{toolEvents:o}:{}};return e.turns.push(f),f}function Ip(e,t=5){if(e.length===0)return"";let n=e.slice(-t),r=["\u2581","\u2582","\u2583","\u2584","\u2585","\u2586","\u2587","\u2588"];return n.map(o=>{let s=Math.max(0,Math.min(1,o)),a=Math.min(7,Math.floor(s*8));return r[a]}).join("")}var es={stream:process.stdout,hideCursor:!1,discardStdin:!1};function ca(e,t){if(t?.getRatio()!==void 0)return t.getRatio();let n=e.turnTokens[e.turnTokens.length-1];if(!n)return 0;let r=n.input+n.output+n.cache;return Math.min(1,r/tt(e.model))}function Tr(e,t){let n=ca(e,t),r=tt(e.model),o,s=t?.getDetail();if(s!==void 0)o=s.used;else{let i=e.turnTokens[e.turnTokens.length-1];i&&(o=i.input+i.output+i.cache)}let a;if(e.turnTokens.length>=2){let i=e.turnTokens.map(c=>(c.input+c.output+c.cache)/r),l=Ip(i,5);l.length>0&&(a=l)}return{model:e.model,cost:e.totalCostUsd,tokens:e.totalTokens,contextPct:n,contextLimit:r,contextUsedTokens:o,contextSparkline:a,planMode:e.planMode,...e.cwd!==void 0?{cwd:e.cwd}:{}}}var iT={name:"/exit",aliases:["/quit"],summary:"Exit the session",async handler(){return"exit"}},aT={name:"/clear",summary:"Clear conversation history",async handler(e){try{await e.session.reset(),e.ui.clearScreen(),Rp(e.stats),e.ledger?.clear(),e.out.success("Conversation history cleared.")}catch(t){e.out.error(t instanceof Error?t.message:"Unknown error")}return"continue"}},lT={name:"/compact",summary:"Compact history (summarize older messages)",async handler(e){let t=sT({text:p.meta("Summarizing earlier turns..."),...es}).start();try{let n=await e.session.compact();if(t.stop(),n.compacted){let r=n.tokensSavedEstimate?` (~${n.tokensSavedEstimate} input tokens saved)`:"";e.out.success(`Compacted ${n.messagesBefore} \u2192 ${n.messagesAfter} messages${r}.`)}else{let r=n.reason??"unknown";r==="aborted"?e.out.info("Compaction cancelled."):r.startsWith("summarization-failed")?e.out.error(`Compaction failed: ${r}. History unchanged.`):e.out.info(`Nothing to compact (${r}).`)}}catch(n){t.stop(),e.out.error(n instanceof Error?n.message:"Unknown error")}return"continue"}},cT={name:"/help",summary:"Show this help",async handler(e){let t=rt(),n=t.reduce((r,o)=>Math.max(r,o.name.length),0)+2;e.out.line(),e.out.line(p.bold(p.brand("Commands"))),e.out.line(ce());for(let r of t){let o=r.usage??r.name,s=" ".repeat(Math.max(0,n-o.length));e.out.line(` ${p.warning(o)}${s} ${p.dim(r.summary)}`)}return e.out.line(),e.out.line(p.dim(" Tip: Ctrl+C interrupts a running turn; a second press exits.")),e.out.line(),"continue"}},Mp=[iT,aT,lT,cT];function da(e,t=30){return!e||e.length===0?p.dim("(none)"):e.length<=t?e.join(", "):`${e.slice(0,t).join(", ")}, ${p.dim(`+${e.length-t} more`)}`}function He(e,t){return` ${p.label(e.padEnd(16))} ${t}`}function ts(e){let t=[];t.push(" "+ce("Session Debug")),e.sessionId&&t.push(He("session",e.sessionId)),e.model&&t.push(He("model",e.model)),e.permissionMode&&t.push(He("permission",e.permissionMode)),e.cwd&&t.push(He("cwd",e.cwd)),e.claudeCodeVersion&&t.push(He("sdk",`v${e.claudeCodeVersion}`)),e.apiKeySource&&t.push(He("api key",e.apiKeySource)),e.outputStyle&&t.push(He("output style",e.outputStyle));let n=e.tools?.length??0;t.push(He(`tools (${n})`,da(e.tools)));let r=e.mcpServers??[],o=r.length?r.map(c=>`${c.name}[${c.status}]`).join(", "):p.dim("(none)");t.push(He(`mcp (${r.length})`,o));let s=e.skills?.length??0;t.push(He(`skills (${s})`,da(e.skills)));let a=e.plugins?.length??0,i=a?(e.plugins??[]).map(c=>c.name).join(", "):p.dim("(none)");t.push(He(`plugins (${a})`,i));let l=e.slashCommands?.length??0;return t.push(He(`slash (${l})`,da(e.slashCommands))),t.push(" "+ce()),t.join(`
|
|
1821
|
+
\u{1F916} Claude:`)),console.log(Qe(F.content));let _=o.getLastResponseMetadata();if(_){let M=[];_.durationMs&&M.push(me(_.durationMs)),_.totalCostUsd!==void 0&&M.push(Ie(_.totalCostUsd));let N=Number(_.usage?.input_tokens??0),V=Number(_.usage?.output_tokens??0);N+V>0&&M.push(H(N+V)+" tokens"),M.length>0&&console.log(mp.dim(" \xB7 "+M.join(" \xB7 ")))}console.log("")}}catch(l){r.fail("Failed to send message"),z(l)}finally{o&&await o.close(),s?.close(),a!==void 0&&await a.cleanup()}})}import tP from"ora";import*as gg from"node:os";import*as zn from"node:path";var Yo=new Set;function Fn(e){return Yo.add(e),()=>{Yo.delete(e)}}async function ra(){await Promise.all([...Yo].map(e=>e())),Yo.clear()}import{readFileSync as Hv,writeFileSync as Kv,existsSync as oa,mkdirSync as Gv,readdirSync as zv,statSync as qv}from"fs";import{join as yp,basename as bp}from"path";function sa(){return Pl(),kt()}function ia(e){return yp(sa(),`${e}.json`)}function Vo(e,t){let n=sa();oa(n)||Gv(n,{recursive:!0});let r=t??e.sessionId??`session-${Date.now()}`,o={sessionId:e.sessionId,model:e.model,startedAt:e.sessionStartTime,savedAt:Date.now(),totalTurns:e.totalTurns,totalCostUsd:e.totalCostUsd,totalTokens:e.totalTokens,totalDurationMs:e.totalDurationMs,turns:e.turns},s=ia(r);return Kv(s,JSON.stringify(o,null,2)),s}function Sr(e){let t=e.includes("/")?e:ia(e);if(oa(t))try{let n=Hv(t,"utf-8");return JSON.parse(n)}catch{return}}function Jo(e){let t=e.includes("/")?e:ia(e),n=Sr(t);if(n)return{path:t,id:bp(t,".json"),data:n};for(let r of vr()){if(r.id!==e&&r.sessionId!==e)continue;let o=Sr(r.path);if(o)return{path:r.path,id:r.id,data:o}}}function vr(){let e=sa();if(!oa(e))return[];let t=[];for(let n of zv(e)){if(!n.endsWith(".json"))continue;let r=yp(e,n);try{if(!qv(r).isFile())continue;let s=Sr(r);if(!s||typeof s.savedAt!="number"||typeof s.model!="string")continue;t.push({path:r,id:bp(n,".json"),sessionId:s.sessionId,model:s.model,startedAt:s.startedAt,savedAt:s.savedAt,totalTurns:s.totalTurns,totalCostUsd:s.totalCostUsd})}catch{}}return t.sort((n,r)=>r.savedAt-n.savedAt),t}var Yv=/^[A-Za-z0-9_@%+=:,./-]+$/;function kp(e){return Yv.test(e)?e:`'${e.replace(/'/g,"'\\''")}'`}function Ln(e,t){let n=["afk","interactive"];return typeof t=="string"&&t.length>0&&n.push("--model",kp(t)),n.push("--resume",kp(e)),n.join(" ")}import*as xf from"node:readline";function wp(e){let t=Math.max(0,Math.min(1,e.ratio)),n=t>.8?p.error:t>.5?p.warning:p.meta,r=20,o=Math.round(t*r),s=r-o,a="["+"\u2588".repeat(o)+"\u2591".repeat(s)+"]",i=Math.round(t*100)+"%",l="";e.used!==void 0&&e.limit!==void 0&&(l=H(e.used)+"/"+H(e.limit));let c=l?`${a} ${i} ${l}`:`${a} ${i}`,u=`${a} ${i}`,d=`ctx ${i}`,m=e.sparkline?p.meta(e.sparkline)+" ":"",f=e.sparkline?j(e.sparkline)+1:0,g=Math.max(0,e.width-f);if(j(c)<=g&&g>90)return m+n(c);if(j(u)<=g&&g>32)return m+n(u);if(j(d)<=g)return m+n(d);if(e.width>0){let y=m+n(d);return se(y,e.width)}return n(i)}import Vv from"chalk";var la=new Map;function Sp(e,t){let n=la.get(e);if(n){if(n.glyph===t.glyph&&n.color===t.color&&n.inFlightVerb===t.inFlightVerb)return;throw new Error(`Trusted skill "${e}" already registered with different config`)}la.set(e,t),Wu(e)}function Xo(e){return la.get(e)}function Jv(e){return(e/1e3).toFixed(1)+"s"}function vp(e,t){let n=Xo(e.skillName),r=Jv(e.durationMs);if(!n){let s=`[${e.skillName} \xB7 ${r}]`;return aa(s,t?.columns)}if(t?.isTTY!==!1){let s;if(e.claimsTotal!==void 0){let i=e.claimsTotal===e.claimsConfirmed&&e.claimsRefuted===void 0&&e.claimsInconclusive===void 0,l;if(i)l=`${e.claimsTotal} claims \xB7 all confirmed`;else{let c=`${e.claimsTotal} claims`;e.claimsConfirmed!==void 0&&(c+=` \xB7 ${e.claimsConfirmed} confirmed`),e.claimsRefuted!==void 0&&(c+=` \xB7 ${e.claimsRefuted} refuted`),e.claimsInconclusive!==void 0&&(c+=` \xB7 ${e.claimsInconclusive} inconclusive`),l=c}s=`${n.glyph} ${e.skillName} \xB7 ${l} \xB7 ${r}`}else s=`${n.glyph} ${e.skillName} \xB7 ${r}`;let a=Vv.hex(n.color)(s);return aa(a,t?.columns)}else{let s;if(e.claimsTotal!==void 0){let a=e.claimsConfirmed??0;s=`[${e.skillName} \xB7 ${a}/${e.claimsTotal} confirmed \xB7 ${r}]`}else s=`[${e.skillName} \xB7 ${r}]`;return aa(s,t?.columns)}}function aa(e,t){return t!==void 0&&j(e)>t?se(e,t):e}function Tp(e){let t=Xo(e);return t?`${t.glyph} ${t.inFlightVerb}`:e}import{homedir as Xv}from"node:os";import{sep as nt}from"node:path";function xp(e,t={}){if(!e)return"";let n=t.homedir??Xv(),r=Zv(e,n),o=t.maxWidth;if(o===void 0||o<=0||j(r)<=o)return r;let s=r.split(nt).filter(d=>d.length>0);if(s.length<=1)return se(r,o);let i=r.startsWith("~")?"~":s[0],l=1,c=s[s.length-1],u=[];for(let d=s.length-2;d>=l;d--){let m=s.slice(l,d+1),f=m.length>0?m.join(nt)+nt:"";u.push(`${i}${nt}${f}\u2026${nt}${c}`)}u.push(`${i}${nt}\u2026${nt}${c}`);for(let d of u)if(j(d)<=o)return d;return se(u[u.length-1],o)}function Zv(e,t){if(!t)return e;if(e===t)return"~";let n=t.endsWith(nt)?t:t+nt;return e.startsWith(n)?"~"+nt+e.slice(n.length):e}var Zo=class{stream;force;throttleMs;started=!1;lastRepaint=0;lastFields=null;resizeUnsub=null;lastPaintedRow=null;extraRows=0;constructor(t={}){this.stream=t.stream??process.stdout,this.force=t.force??!1,this.throttleMs=t.throttleMs??100}get enabled(){return this.force||!!this.stream.isTTY}start(){if(this.started||!this.enabled)return;this.started=!0,this.lastRepaint=0;let t=this.currentRows();this.stream.write("\x1B[s"),this.writeScrollRegion(t),this.stream.write("\x1B[u"),this.resizeUnsub===null&&(this.resizeUnsub=xt.subscribe(()=>{this.onResize()}))}onResize(){if(!this.started||!this.enabled)return;let t=this.currentRows();this.stream.write("\x1B[s"),this.lastPaintedRow!==null&&this.lastPaintedRow!==this.paintRow(t)&&(this.stream.write(`\x1B[${this.lastPaintedRow};1H`),this.stream.write("\x1B[2K")),this.writeScrollRegion(t),this.stream.write("\x1B[u"),this.flush()}repaint(t){if(!this.enabled||!this.started){this.lastFields=t;return}let n=Date.now();if(n-this.lastRepaint<this.throttleMs){this.lastFields=t;return}this.lastRepaint=n,this.lastFields=t;let r=this.currentRows();this.stream.write("\x1B[s"),this.stream.write(`\x1B[${this.paintRow(r)};1H`),this.stream.write("\x1B[2K"),this.stream.write(this.formatLine(t)),this.stream.write("\x1B[u"),this.lastPaintedRow=this.paintRow(r)}flush(){this.lastRepaint=0,this.lastFields&&this.repaint(this.lastFields)}setExtraRows(t){if(this.extraRows=t,this.started&&this.enabled){let n=this.currentRows();this.stream.write("\x1B[s"),this.writeScrollRegion(n),this.stream.write("\x1B[u"),this.flush()}}getExtraRows(){return this.extraRows}rearm(){if(!this.started||!this.enabled)return;let t=this.currentRows();this.stream.write("\x1B[s"),this.writeScrollRegion(t),this.stream.write("\x1B[u"),this.flush()}stop(){if(this.resizeUnsub!==null&&(this.resizeUnsub(),this.resizeUnsub=null),!this.started||!this.enabled){this.started=!1;return}let t=this.currentRows();this.stream.write("\x1B[s"),this.stream.write(`\x1B[${this.lastPaintedRow??this.paintRow(t)};1H`),this.stream.write("\x1B[2K"),this.stream.write("\x1B[r"),this.stream.write("\x1B[u"),this.started=!1,this.lastRepaint=0,this.lastPaintedRow=null}formatLine(t){let n=[],r=Math.max(4,(this.stream.columns??80)-2);if(t.cwd){let s=Math.max(8,Math.floor(r*.4)),a=xp(t.cwd,{maxWidth:s});a&&n.push(p.dim(a))}if(t.trustedSkillVerifying&&n.push(Tp(t.trustedSkillVerifying)),n.push(p.brand(t.model)),t.planMode&&n.push(p.warning("\u25CF plan")),t.contextPct!==void 0){let s=wp({ratio:t.contextPct,used:t.contextUsedTokens,limit:t.contextLimit,sparkline:t.contextSparkline,width:r});n.push(s)}t.cost!==void 0&&n.push(p.meta(`$${t.cost.toFixed(2)}`)),t.tokens!==void 0&&n.push(p.meta(`${Qv(t.tokens)} tok`));let o=n.join(p.dim(" \xB7 "));return se(o,r)}currentRows(){let t=this.stream.rows;return typeof t=="number"&&t>0?t:24}paintRow(t){return t>1?t:1}writeScrollRegion(t){let n=1+this.extraRows;if(t>n){this.stream.write(`\x1B[1;${t-n}r`);return}this.stream.write("\x1B[r")}};function Qv(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}k`:`${e}`}var Me=new Map,rn=new Map;function re(e){if(Me.has(e.name))throw new Error(`Slash command already registered: ${e.name}`);Me.set(e.name,e);for(let t of e.aliases??[]){if(rn.has(t)||Me.has(t))throw new Error(`Slash alias collides: ${t}`);rn.set(t,e.name)}}function Lt(e){if(Me.has(e.name)){for(let[t,n]of rn.entries())n===e.name&&rn.delete(t);Me.delete(e.name)}re(e)}function Ep(e){Me.has(e.name)||re(e)}function Cp(){Me.clear(),rn.clear()}function rt(){return[...Me.values()].sort((e,t)=>e.name.localeCompare(t.name))}function Pp(){let e=[];for(let[t,n]of rn.entries()){let r=Me.get(n);r&&e.push({alias:t,canonical:n,summary:r.summary})}return e.sort((t,n)=>t.alias.localeCompare(n.alias))}function eT(e){if(Me.has(e))return Me.get(e);let t=rn.get(e);return t?Me.get(t):void 0}function tT(e,t){let n=Array.from({length:e.length+1},()=>new Array(t.length+1).fill(0));for(let r=0;r<=e.length;r++)n[r][0]=r;for(let r=0;r<=t.length;r++)n[0][r]=r;for(let r=1;r<=e.length;r++)for(let o=1;o<=t.length;o++){let s=e[r-1]===t[o-1]?0:1;n[r][o]=Math.min(n[r-1][o]+1,n[r][o-1]+1,n[r-1][o-1]+s)}return n[e.length][t.length]}function nT(e,t=3){let n;for(let r of Me.keys()){let o=tT(e,r);o<=t&&(n===void 0||o<n.dist)&&(n={name:r,dist:o})}return n?.name}function rT(e){let t=e.trim();if(!t.startsWith("/"))return null;let n=t.indexOf(" ");return n===-1?{name:t,args:""}:{name:t.slice(0,n),args:t.slice(n+1).trim()}}async function Ap(e,t){let n=rT(e);if(n===null)return{handled:!1};let r=eT(n.name);if(!r){let s=nT(n.name);return s?t.out.warn(`Unknown command: ${n.name} (did you mean ${s}?)`):t.out.warn(`Unknown command: ${n.name} (type /help for commands)`),{handled:!0,result:"continue"}}let o=await r.handler(t,n.args);return o==="forward"?{handled:!1}:{handled:!0,result:o}}import sT from"ora";function _p(e){return{totalTurns:0,totalCostUsd:0,totalTokens:0,totalDurationMs:0,sessionStartTime:Date.now(),turnCosts:[],turnTokens:[],turns:[],model:e,planMode:!1}}function Rp(e){e.totalTurns=0,e.totalCostUsd=0,e.totalTokens=0,e.totalDurationMs=0,e.sessionStartTime=Date.now(),e.turnCosts.length=0,e.turnTokens.length=0,e.turns.length=0,delete e.sessionId,delete e.pendingPlanExit}function Qo(e,t,n,r,o){let s=r?.totalCostUsd??0,a=r?.durationMs??0,i=Number(r?.usage?.input_tokens??0),l=Number(r?.usage?.output_tokens??0),c=i,u=l,d=Number(r?.usage?.cache_read_input_tokens??0)+Number(r?.usage?.cache_creation_input_tokens??0),m=r?.usage?.iterations;if(Array.isArray(m)&&m.length>0){let g=m[m.length-1];if(g&&typeof g=="object"){let y=g;c=Number(y.input_tokens??0),u=Number(y.output_tokens??0),d=Number(y.cache_read_input_tokens??0)+Number(y.cache_creation_input_tokens??0)}}e.totalTurns+=1,e.totalCostUsd+=s,e.totalDurationMs+=a,e.totalTokens+=i+l,e.turnCosts.push(s),e.turnTokens.push({input:c,output:u,cache:d}),r?.sessionId&&!e.sessionId&&(e.sessionId=String(r.sessionId));let f={user:t,assistant:n,timestamp:Date.now(),costUsd:s,durationMs:a,inputTokens:i,outputTokens:l,...o&&o.length>0?{toolEvents:o}:{}};return e.turns.push(f),f}function Ip(e,t=5){if(e.length===0)return"";let n=e.slice(-t),r=["\u2581","\u2582","\u2583","\u2584","\u2585","\u2586","\u2587","\u2588"];return n.map(o=>{let s=Math.max(0,Math.min(1,o)),a=Math.min(7,Math.floor(s*8));return r[a]}).join("")}var es={stream:process.stdout,hideCursor:!1,discardStdin:!1};function ca(e,t){if(t?.getRatio()!==void 0)return t.getRatio();let n=e.turnTokens[e.turnTokens.length-1];if(!n)return 0;let r=n.input+n.output+n.cache;return Math.min(1,r/tt(e.model))}function Tr(e,t){let n=ca(e,t),r=tt(e.model),o,s=t?.getDetail();if(s!==void 0)o=s.used;else{let i=e.turnTokens[e.turnTokens.length-1];i&&(o=i.input+i.output+i.cache)}let a;if(e.turnTokens.length>=2){let i=e.turnTokens.map(c=>(c.input+c.output+c.cache)/r),l=Ip(i,5);l.length>0&&(a=l)}return{model:e.model,cost:e.totalCostUsd,tokens:e.totalTokens,contextPct:n,contextLimit:r,contextUsedTokens:o,contextSparkline:a,planMode:e.planMode,...e.cwd!==void 0?{cwd:e.cwd}:{}}}var iT={name:"/exit",aliases:["/quit"],summary:"Exit the session",async handler(){return"exit"}},aT={name:"/clear",summary:"Clear conversation history",async handler(e){try{await e.session.reset(),e.ui.clearScreen(),Rp(e.stats),e.ledger?.clear(),e.out.success("Conversation history cleared.")}catch(t){e.out.error(t instanceof Error?t.message:"Unknown error")}return"continue"}},lT={name:"/compact",summary:"Compact history (summarize older messages)",async handler(e){let t=sT({text:p.meta("Summarizing earlier turns..."),...es}).start();try{let n=await e.session.compact();if(t.stop(),n.compacted){let r=n.tokensSavedEstimate?` (~${n.tokensSavedEstimate} input tokens saved)`:"";e.out.success(`Compacted ${n.messagesBefore} \u2192 ${n.messagesAfter} messages${r}.`)}else{let r=n.reason??"unknown";r==="aborted"?e.out.info("Compaction cancelled."):r.startsWith("summarization-failed")?e.out.error(`Compaction failed: ${r}. History unchanged.`):e.out.info(`Nothing to compact (${r}).`)}}catch(n){t.stop(),e.out.error(n instanceof Error?n.message:"Unknown error")}return"continue"}},cT={name:"/help",summary:"Show this help",async handler(e){let t=rt(),n=t.reduce((r,o)=>Math.max(r,o.name.length),0)+2;e.out.line(),e.out.line(p.bold(p.brand("Commands"))),e.out.line(ce());for(let r of t){let o=r.usage??r.name,s=" ".repeat(Math.max(0,n-o.length));e.out.line(` ${p.warning(o)}${s} ${p.dim(r.summary)}`)}return e.out.line(),e.out.line(p.dim(" Tip: Ctrl+C interrupts a running turn; a second press exits.")),e.out.line(),"continue"}},Mp=[iT,aT,lT,cT];function da(e,t=30){return!e||e.length===0?p.dim("(none)"):e.length<=t?e.join(", "):`${e.slice(0,t).join(", ")}, ${p.dim(`+${e.length-t} more`)}`}function He(e,t){return` ${p.label(e.padEnd(16))} ${t}`}function ts(e){let t=[];t.push(" "+ce("Session Debug")),e.sessionId&&t.push(He("session",e.sessionId)),e.model&&t.push(He("model",e.model)),e.permissionMode&&t.push(He("permission",e.permissionMode)),e.cwd&&t.push(He("cwd",e.cwd)),e.claudeCodeVersion&&t.push(He("sdk",`v${e.claudeCodeVersion}`)),e.apiKeySource&&t.push(He("api key",e.apiKeySource)),e.outputStyle&&t.push(He("output style",e.outputStyle));let n=e.tools?.length??0;t.push(He(`tools (${n})`,da(e.tools)));let r=e.mcpServers??[],o=r.length?r.map(c=>`${c.name}[${c.status}]`).join(", "):p.dim("(none)");t.push(He(`mcp (${r.length})`,o));let s=e.skills?.length??0;t.push(He(`skills (${s})`,da(e.skills)));let a=e.plugins?.length??0,i=a?(e.plugins??[]).map(c=>c.name).join(", "):p.dim("(none)");t.push(He(`plugins (${a})`,i));let l=e.slashCommands?.length??0;return t.push(He(`slash (${l})`,da(e.slashCommands))),t.push(" "+ce()),t.join(`
|
|
1822
1822
|
`)}var ua=["opus","opus_1m","sonnet","sonnet_1m","haiku"],dT={name:"/cost",summary:"Show total and per-turn cost",async handler(e){let{stats:t,out:n}=e;if(n.line(),n.line(p.bold("Session cost")),n.line(ce()),n.line(` total ${p.success(Ie(t.totalCostUsd))}`),n.line(` turns ${p.meta(String(t.totalTurns))}`),t.totalTurns>0){let r=t.totalCostUsd/t.totalTurns;n.line(` avg/turn ${p.meta(Ie(r))}`)}if(t.turnCosts.length>0){let r=t.turnCosts.slice(-5).map(Ie).join(p.dim(" \xB7 "));n.line(` last 5 ${r}`)}return n.line(),"continue"}};function uT(e,t){let n=t.apiUsage,r=n?.input_tokens??0,o=n?.output_tokens??0,s=n?.cache_read_input_tokens??0,a=n?.cache_creation_input_tokens??0,i=r+o+s+a;e.line(),e.line(p.bold("Token usage")+p.dim(" (SDK breakdown)")),e.line(ce()),e.line(` total ${p.success(H(t.totalTokens))} of ${p.meta(H(t.maxTokens))} (${p.meta(`${Math.round(t.percentage*100)/100}%`)})`),t.autoCompactThreshold&&t.isAutoCompactEnabled&&e.line(` compact at ${p.meta(H(t.autoCompactThreshold))}`),e.line(),e.line(p.dim(" Last turn (API):")),e.line(` input ${p.meta(H(r))}`),e.line(` output ${p.meta(H(o))}`),e.line(` cache read ${p.meta(H(s))}`),e.line(` cache creat ${p.meta(H(a))}`),e.line(` total ${p.meta(H(i))}`);let l=t.categories??[];if(l.length>0){let m=[...l].sort((f,g)=>g.tokens-f.tokens).slice(0,5);e.line(),e.line(p.dim(" Top categories:"));for(let f of m)e.line(` ${p.warning(f.name.padEnd(18))} ${p.meta(H(f.tokens))}`)}let c=t.systemTools??[],u=t.mcpTools??[];if(c.length>0||u.length>0){e.line();let m=c.reduce((g,y)=>g+y.tokens,0),f=u.reduce((g,y)=>g+y.tokens,0);c.length>0&&e.line(p.dim(` system tools ${c.length} tools, ${H(m)} tokens`)),u.length>0&&e.line(p.dim(` MCP tools ${u.length} tools, ${H(f)} tokens`))}let d=t.agents??[];if(d.length>0){let m=d.reduce((f,g)=>f+g.tokens,0);e.line(p.dim(` agents ${d.length} loaded, ${H(m)} tokens`))}if(t.skills){let m=t.skills;e.line(p.dim(` skills ${m.includedSkills}/${m.totalSkills} included, ${H(m.tokens)} tokens`))}if(t.slashCommands){let m=t.slashCommands;e.line(p.dim(` slash cmds ${m.includedCommands}/${m.totalCommands} included, ${H(m.tokens)} tokens`))}e.line()}function pT(e,t){let n=t.turnTokens.reduce((c,u)=>c+u.input,0),r=t.turnTokens.reduce((c,u)=>c+u.output,0),o=t.turnTokens.reduce((c,u)=>c+u.cache,0),s=n+r,a=tt(t.model),i=n+r+o,l=Math.round(i/a*100);e.line(),e.line(p.bold("Token usage")+p.dim(" (local stats \u2014 SDK breakdown unavailable)")),e.line(ce()),e.line(` input ${p.meta(H(n))}`),e.line(` output ${p.meta(H(r))}`),e.line(` cache read ${p.meta(H(o))}`),e.line(` total ${p.success(H(s))}`),e.line(` context ${p.meta(`${l}% of ${H(a)} (${t.model})`)}`),e.line()}var mT={name:"/tokens",aliases:["/ctx"],summary:"Show token usage (SDK breakdown with local-stats fallback)",async handler(e){try{let t=await e.session.getContextUsage();uT(e.out,t)}catch{pT(e.out,e.stats)}return"continue"}},fT={name:"/history",summary:"Show conversation history",async handler(e){let{stats:t,out:n}=e;return t.turns.length===0?(n.info("No turns yet in this session."),"continue"):(n.line(),n.line(p.bold(`Session history (${t.turns.length} turn${t.turns.length===1?"":"s"})`)),n.line(ce()),t.turns.forEach((r,o)=>{let s=p.meta(`#${o+1}`),a=r.user.length>100?r.user.slice(0,97)+"...":r.user,i=r.assistant.length>100?r.assistant.slice(0,97)+"...":r.assistant;n.line(` ${s} ${p.user("\u25B6")} ${a}`),n.line(` ${p.brand("\u25C6")} ${p.dim(i)}`)}),n.line(),"continue")}},gT={name:"/reset",summary:"Clear screen, history, and session stats",async handler(e){let{stats:t,session:n,ui:r,out:o}=e;try{await n.sendMessage("/clear")}catch{}return t.totalTurns=0,t.totalCostUsd=0,t.totalTokens=0,t.totalDurationMs=0,t.turnCosts.length=0,t.turnTokens.length=0,t.turns.length=0,t.sessionStartTime=Date.now(),r.clearScreen(),o.success("Session reset."),"continue"}},hT={name:"/model",usage:"/model <opus|opus_1m|sonnet|sonnet_1m|haiku>",summary:"Switch the active model mid-session",async handler(e,t){let n=t.trim().toLowerCase();if(!n)return e.out.info(`Current model: ${p.brand(e.stats.model)}`),e.out.line(p.dim(` Valid: ${ua.join(", ")}`)),"continue";if(!ua.includes(n))return e.out.warn(`Unknown model: ${n}. Valid: ${ua.join(", ")}`),"continue";try{await e.session.setModel(n),e.stats.model=n,e.ui.repaintStatusLine(),e.out.success(`Model switched to ${p.brand(n)}`)}catch(r){e.out.error(`Failed to switch model: ${r instanceof Error?r.message:String(r)}`)}return"continue"}},yT={name:"/tools",summary:"List tools available to the session",async handler(e){try{let n=(await e.session.waitForInitialization()).tools??[];if(n.length===0)return e.out.info("No tools reported by the session."),"continue";e.out.line(),e.out.line(p.bold(`Tools (${n.length})`)),e.out.line(ce());let r=3,o=Math.ceil(n.length/r),s=Math.max(...n.map(a=>a.length))+2;for(let a=0;a<o;a++){let i=[];for(let l=0;l<r;l++){let c=l*o+a;c<n.length&&i.push(n[c].padEnd(s))}e.out.line(" "+i.join(""))}e.out.line()}catch(t){e.out.error(`Could not read session tools: ${t instanceof Error?t.message:String(t)}`)}return"continue"}},bT={name:"/mcp",summary:"List MCP servers connected to the session",async handler(e){try{let n=(await e.session.waitForInitialization()).mcpServers??[];if(n.length===0)return e.out.info("No MCP servers connected."),"continue";e.out.line(),e.out.line(p.bold(`MCP servers (${n.length})`)),e.out.line(ce());for(let r of n){let o=typeof r=="string"?r:r.name??JSON.stringify(r),s=typeof r=="object"&&r!==null&&"status"in r?String(r.status):"",a=s==="connected"?p.success("\u25CF"):p.warning("\u25CF");e.out.line(` ${a} ${o}${s?p.dim(` (${s})`):""}`)}e.out.line()}catch(t){e.out.error(`Could not read MCP servers: ${t instanceof Error?t.message:String(t)}`)}return"continue"}},kT={name:"/limits",summary:"Show known per-model context-window limits",async handler(e){e.out.line(),e.out.line(p.bold("Context-window limits")),e.out.line(ce());for(let[t,n]of Object.entries(To)){let r=t===e.stats.model?p.brand(" \u2190 active"):"";e.out.line(` ${p.warning(t.padEnd(12))} ${p.meta(H(n))}${r}`)}return e.out.line(),"continue"}},wT={name:"/debug",summary:"Show SDK session metadata (tools, MCP, skills, plugins, etc.)",async handler(e){try{let t=await e.session.waitForInitialization();e.out.line(),e.out.line(ts(t)),e.out.line()}catch(t){e.out.error(`Could not read session metadata: ${t instanceof Error?t.message:String(t)}`)}return"continue"}},$p=[dT,mT,fT,gT,hT,yT,bT,kT,wT];var pa=!1;async function ht(e,t,n={}){let r=e.stats.planMode,o=t!==void 0?t:!r;try{if(await e.session.setPermissionMode(o?"plan":"default"),e.stats.planMode=o,e.ui.repaintStatusLine(),o){let s=pa?"":p.dim(" Shift+Tab or /plan to exit.");pa||(pa=!0),e.out.success(p.warning("\u25CF plan mode ON")+p.dim(" \u2014 write_file, edit_file, and write-intent bash are refused.")+s)}else n.closureSummarySkipped?e.out.success(p.success("\u25CB plan mode OFF")+p.dim(" \u2014 force-exit (closure summary skipped). Default permissions restored.")):e.out.success(p.success("\u25CB plan mode OFF")+p.dim(" \u2014 default permissions restored"))}catch(s){e.out.error(`Could not toggle plan mode: ${s instanceof Error?s.message:String(s)}`)}}async function Op(e){e.stats.pendingPlanExit&&(await ht(e,!1),e.stats.planMode||(e.stats.pendingPlanExit=!1))}var ST=["You are about to exit plan mode. Before I flip permissions back to default on the next turn, emit your final plan in three sections:",""," - **Chosen approach** \u2014 the plan you recommend, in one to three sentences."," - **Risks named** \u2014 the concrete failure modes, constraints, or unknowns this plan does not eliminate."," - **Alternatives considered** \u2014 the options you weighed and why you rejected them.","","This is the record. Be specific. Do not propose write actions in this turn \u2014 writes are still refused until the mode flips."].join(`
|
|
1823
1823
|
`);async function vT(e){return e.stats.pendingPlanExit=!0,e.ui.repaintStatusLine(),e.out.success(p.warning("\u25CF plan exit queued")+p.dim(" \u2014 plan mode still ON; writes still refused. Submitting closure summary (chosen approach, risks, alternatives); mode flips after the model responds. Force-exit now: /plan off again or Shift+Tab.")),{kind:"submit",message:ST}}async function TT(e){return e.stats.pendingPlanExit=!1,await ht(e,!1,{closureSummarySkipped:!0}),"continue"}async function xT(e){return e.stats.pendingPlanExit=!1,e.ui.repaintStatusLine(),e.out.success(p.warning("\u25CF plan mode ON")+p.dim(" \u2014 plan exit cancelled, staying in plan mode.")),"continue"}function ET(e){e.out.info(p.dim("(plan exit cancelled \u2014 submitting your prompt instead.)"))}var Dp={name:"/plan",usage:"/plan [on|off|<prompt>]",summary:"Toggle plan mode (write_file, edit_file, and write-intent bash refused)",async handler(e,t){let n=t.trim(),r=n.toLowerCase();if(n!==""&&r!=="on"&&r!=="off"){let s=!!e.stats.pendingPlanExit;return e.stats.planMode||await ht(e,!0),s&&(e.stats.pendingPlanExit=!1,ET(e)),{kind:"submit",message:n}}return(r==="on"?!0:r==="off"?!1:!e.stats.planMode)===!0?e.stats.pendingPlanExit?xT(e):(e.stats.planMode||await ht(e,!0),"continue"):e.stats.planMode?e.stats.pendingPlanExit?TT(e):vT(e):(await ht(e,!1),"continue")}};import{readFileSync as CT,writeFileSync as PT,existsSync as Fp,mkdirSync as AT}from"fs";import{join as _T}from"path";function Lp(){return Al(),Xs()}function Np(e){return _T(Lp(),`${e}.json`)}function ns(e){let t=Np(e);if(!Fp(t))return{sessionId:e,items:[]};try{let n=CT(t,"utf-8"),r=JSON.parse(n);return Array.isArray(r.items)?r:{sessionId:e,items:[]}}catch{return{sessionId:e,items:[]}}}function xr(e){let t=Lp();Fp(t)||AT(t,{recursive:!0}),PT(Np(e.sessionId),JSON.stringify(e,null,2))}function Up(e,t){let r={id:e.items.reduce((o,s)=>Math.max(o,s.id),0)+1,text:t,done:!1,createdAt:Date.now()};return e.items.push(r),r}function jp(e,t){let n=e.items.find(r=>r.id===t);return n&&(n.done=!0),n}function Bp(e,t){let n=e.items.findIndex(r=>r.id===t);return n===-1?!1:(e.items.splice(n,1),!0)}function Wp(e){e.items.length=0}function rs(e){if(e.items.length===0)return[];let t=[],n=Math.max(20,ee());{let r=p.dim("\u250C\u2500 todos "),o=Math.max(0,Math.min(n-10,120));t.push(r+p.dim("\u2500".repeat(o)))}for(let r of e.items){let o=r.done?p.success("[x]"):p.dim("[ ]"),s=r.done?p.dim(r.text):Tt(r.text),i=` ${p.meta(`#${r.id}`)} ${o} `,l=Math.max(8,n-j(i)),c=te(s,l).split(`
|
|
1824
1824
|
`);t.push(i+(c[0]??""));let u=" ".repeat(j(i));for(let d of c.slice(1))t.push(u+d)}{let r=Math.max(0,Math.min(n-1,120));t.push(p.dim("\u2514"+"\u2500".repeat(r)))}return t}function Hp(e){return e.items.length===0?"":e.items.map(t=>`${t.id}:${t.done?1:0}:${t.text}`).join(`
|
|
@@ -1914,11 +1914,11 @@ _cleared_
|
|
|
1914
1914
|
`).catch(()=>{}),n=await Cf(t,e(),!0)},async appendEnded(){await Ir.appendFile(n,`
|
|
1915
1915
|
_ended: ${new Date().toISOString()}_
|
|
1916
1916
|
`).catch(()=>{})}}}import{readdirSync as GE,statSync as zE}from"fs";import{join as _f}from"path";function Rf(e,t=process.cwd()){try{let n=e.lastIndexOf("/"),r=n===-1?"":e.slice(0,n),o=n===-1?e:e.slice(n+1),s=r?_f(t,r):t,a=GE(s),i=[];for(let l of a){if(!l.startsWith(o)||l.startsWith(".")&&!o.startsWith("."))continue;let c=r?`${r}/${l}`:l;try{zE(_f(s,l)).isDirectory()&&(c+="/")}catch{}if(i.push(c),i.length>=30)break}return i.sort()}catch{return[]}}async function If(e){let t="",n=e.promptFn(),r=e.continuationPrompt??" \u203A ";for(;;){e.rl.setPrompt(n),e.rl.prompt();let o=await new Promise(s=>{e.rl.once("line",a=>s(a))});if(o.endsWith("\\")){t+=o.slice(0,-1)+`
|
|
1917
|
-
`,n=r;continue}return t+=o,t}}async function Mf(e){if(e.initialBuffer!==void 0&&e.initialBuffer.length>0)return{text:e.initialBuffer,attachments:[]};let t=null;if(e.onSigint){let n=e.onSigint;t=()=>n(),process.on("SIGINT",t)}try{return{text:await If({rl:e.rl,promptFn:e.promptFn}),attachments:[]}}finally{t&&process.removeListener("SIGINT",t)}}import{emitKeypressEvents as
|
|
1918
|
-
`)}async function Ms(){if(process.platform!=="darwin")return null;un&&pn("probing clipboard for image data");for(let e of["PNGf","TIFF"]){let t=Nf(Lf(),`afk-clipboard-${Da()}.bin`);try{let{ok:n,exitCode:r,stderr:o}=await
|
|
1917
|
+
`,n=r;continue}return t+=o,t}}async function Mf(e){if(e.initialBuffer!==void 0&&e.initialBuffer.length>0)return{text:e.initialBuffer,attachments:[]};let t=null;if(e.onSigint){let n=e.onSigint;t=()=>n(),process.on("SIGINT",t)}try{return{text:await If({rl:e.rl,promptFn:e.promptFn}),attachments:[]}}finally{t&&process.removeListener("SIGINT",t)}}import{emitKeypressEvents as lC}from"readline";import*as Oe from"ansi-escapes";import Hf from"string-width";import qE from"chalk";var YE=/(?<=\s|^)(\/[A-Za-z][\w:-]*)(?=\s|$)/g,VE=/(?<=\s|^)(@[\w./-]*)(?=\s|$)/g;function Oa(e,t){return qE.level===0?e:e.replace(YE,r=>{let o=r.slice(1);return t.has(o)?p.brand(r):p.meta(r)}).replace(VE,r=>p.info(r))}var JE={"image/png":"PNG","image/jpeg":"JPEG","image/gif":"GIF","image/webp":"WEBP"};function XE(e){if(e<1024)return`${e} B`;let t=e/1024;return t<1024?`${t.toFixed(1)} KiB`:`${(t/1024).toFixed(1)} MiB`}function $f(e){if(e.length===0)return"";let t=e.reduce((i,l)=>i+l.sizeBytes,0),n=XE(t),r=e.length===1?"image":"images",o=new Set,s=[];for(let i of e){let l=JE[i.mediaType];o.has(l)||(o.add(l),s.push(l))}let a=s.join(", ");return`[${e.length} ${r} attached \xB7 ${n} \xB7 ${a} \xB7 Ctrl+X to discard]`}function Of(e,t){if(t.length===0)return e;if(e){let n=t.length===1?"image":"images";return`${e} [+ ${t.length} ${n}]`}return t.length===1?"[image attached]":`[${t.length} images attached]`}import{spawn as Df}from"child_process";import{randomUUID as Da}from"crypto";import{readFile as Ff,unlink as Fa}from"fs/promises";import{tmpdir as Lf}from"os";import{join as Nf}from"path";var un=!!process.env.AFK_DEBUG_CLIPBOARD;function pn(e){process.stderr.write(`[afk-clipboard] ${e}
|
|
1918
|
+
`)}async function Ms(){if(process.platform!=="darwin")return null;un&&pn("probing clipboard for image data");for(let e of["PNGf","TIFF"]){let t=Nf(Lf(),`afk-clipboard-${Da()}.bin`);try{let{ok:n,exitCode:r,stderr:o}=await eC(e,t);if(un&&pn(`class=${e} osascript exitCode=${r} stderr=${JSON.stringify(o)} ok=${n}`),!n)continue;let s=await Ff(t);if(s.length===0)continue;if(ZE(s)){un&&pn(`class=${e} magic=TIFF detected, transcoding via sips`);let i=await QE(t);if(!i){un&&pn(`class=${e} sips transcode failed, skipping`);continue}s=i}let a=nC(s);if(un&&pn(`class=${e} magic-byte detection result: ${a??"unrecognized"}`),!a)continue;return un&&pn(`probe success: mediaType=${a} size=${s.byteLength}`),{id:Da(),mediaType:a,bytes:s,sizeBytes:s.byteLength}}catch{}finally{Fa(t).catch(()=>{})}}return un&&pn("probe result: null (no image found on clipboard)"),null}function ZE(e){return e.length<4?!1:e[0]===73&&e[1]===73&&e[2]===42&&e[3]===0||e[0]===77&&e[1]===77&&e[2]===0&&e[3]===42}async function QE(e){let t=Nf(Lf(),`afk-clipboard-${Da()}.png`);if(!await new Promise(r=>{let o=Df("sips",["-s","format","png",e,"--out",t],{stdio:["ignore","ignore","ignore"]});o.on("error",()=>r(!1)),o.on("close",s=>r(s===0))}))return Fa(t).catch(()=>{}),null;try{let r=await Ff(t);return r.length>0?r:null}catch{return null}finally{Fa(t).catch(()=>{})}}async function eC(e,t){let n=`
|
|
1919
1919
|
try
|
|
1920
1920
|
set imgData to the clipboard as \xABclass ${e}\xBB
|
|
1921
|
-
set fileRef to open for access POSIX file ${
|
|
1921
|
+
set fileRef to open for access POSIX file ${tC(t)} with write permission
|
|
1922
1922
|
set eof of fileRef to 0
|
|
1923
1923
|
write imgData to fileRef
|
|
1924
1924
|
close access fileRef
|
|
@@ -1929,7 +1929,7 @@ _ended: ${new Date().toISOString()}_
|
|
|
1929
1929
|
end try
|
|
1930
1930
|
return "no"
|
|
1931
1931
|
end try
|
|
1932
|
-
`;return new Promise(r=>{let o=Df("osascript",["-e",n],{stdio:["ignore","pipe","pipe"]}),s="",a="";o.stdout?.on("data",i=>{s+=i.toString("utf8")}),o.stderr?.on("data",i=>{a+=i.toString("utf8")}),o.on("error",()=>r({ok:!1,exitCode:null,stderr:a})),o.on("close",i=>{r({ok:i===0&&s.trim()==="ok",exitCode:i,stderr:a})})})}function
|
|
1932
|
+
`;return new Promise(r=>{let o=Df("osascript",["-e",n],{stdio:["ignore","pipe","pipe"]}),s="",a="";o.stdout?.on("data",i=>{s+=i.toString("utf8")}),o.stderr?.on("data",i=>{a+=i.toString("utf8")}),o.on("error",()=>r({ok:!1,exitCode:null,stderr:a})),o.on("close",i=>{r({ok:i===0&&s.trim()==="ok",exitCode:i,stderr:a})})})}function tC(e){return'"'+e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')+'"'}function nC(e){return e.length>=8&&e[0]===137&&e[1]===80&&e[2]===78&&e[3]===71?"image/png":e.length>=3&&e[0]===255&&e[1]===216&&e[2]===255?"image/jpeg":e.length>=4&&e[0]===71&&e[1]===73&&e[2]===70&&e[3]===56?"image/gif":e.length>=12&&e[0]===82&&e[1]===73&&e[2]===70&&e[3]===70&&e[8]===87&&e[9]===69&&e[10]===66&&e[11]===80?"image/webp":null}import rC from"chalk";import oC from"string-width";function sC(e,t){if(t<=0)return"";let n=0;for(let r=0;r<e.length;r++)if(n+=oC(e[r]),n>t)return e.slice(0,r)+p.dim("\u2026");return e}function Uf(e,t,n,r){let o=t?">":" ",s=e.value,a=e.summary?` ${e.summary}`:"",i=`${s}${a}`,l=sC(i,n-4),c=` ${o} ${l}`;return t?rC.inverse(p.user(c)):p.meta(c)}var iC="\x1B[?2004h",aC="\x1B[?2004l";function jf(e,t){let n=e.isRaw;e.setRawMode(!0),e.resume(),t.write(iC);let r=!1;return{restore(){if(!r){r=!0;try{t.write(aC)}catch{}try{e.setRawMode(n)}catch{}}}}}function La(e,t){let n=e.slice(0,t);if(/^\/[A-Za-z_-]*$/.test(n))return{kind:"slash",query:n.slice(1)};let r=n.split(/\s+/),o=r[r.length-1]??"";if(o.startsWith("@")&&/^@[^\s]*$/.test(o))return{kind:"file",query:o.slice(1)};let s=/^\/([A-Za-z][A-Za-z0-9_:-]*)\s+(?:.*\s)?--([a-z0-9-]*)$/.exec(n);if(s){let i=s[1],l=s[2],c=rt().find(u=>u.name===`/${i}`);if(c?.flags&&c.flags.length>0)return{kind:"flag",command:i,query:l}}let a=/^\/([A-Za-z][A-Za-z0-9_:-]*)\s+(?:.*\s)?$/.exec(n);if(a){let i=a[1],l=rt().find(c=>c.name===`/${i}`);if(l?.flags&&l.flags.length>0)return{kind:"flag",command:i,query:""}}return null}function Bf(e){let n=rt().filter(s=>s.name.slice(1).startsWith(e)).map(s=>({value:s.name,summary:s.summary})),r=Pp().filter(s=>s.alias.slice(1).startsWith(e)).map(s=>({value:s.alias,summary:s.summary}));return[...n,...r].sort((s,a)=>s.value.localeCompare(a.value)).slice(0,20)}function Wf(e,t=process.cwd()){return Rf(e,t).slice(0,20).map(n=>({value:"@"+n}))}function Na(e,t){let n=rt().find(s=>s.name===`/${e}`);if(!n?.flags||n.flags.length===0)return[];let r=t.startsWith("--")?t.slice(2):t;return n.flags.filter(s=>(s.startsWith("--")?s.slice(2):s).startsWith(r)).map(s=>({value:s})).sort((s,a)=>s.value.localeCompare(a.value)).slice(0,20)}async function Kf(e){let t=process.stdin,n=process.stdout,r=e.compositor?.isArmed()?{restore:()=>{}}:jf(t,n),o=e.statusLine?.getExtraRows()??0;lC(t);let s=e.promptFn(),a=Hf(St(s)),i=null,l=null;try{return e.statusLine?.setExtraRows(o+1),await new Promise((c,u)=>{let d=W.seed(e.initialBuffer??""),m=!1,f=[],g=0,y=null,S=null,h=0,b=0,w=!1,C=!1,T=0,A=0,x=0,v=null,E=[],R=6,I=0,D=!1,F=8,_={has:q=>rt().some(P=>P.name===`/${q}`)},M=()=>{if((x>0||A>0)&&n.write(Oe.cursorUp(x+A)),n.write("\r"),n.write(Oe.eraseDown),E.length>0)n.write($f(E)+`
|
|
1933
1933
|
`),x=1;else if(v!==null){let O=v;v=null,n.write(O+`
|
|
1934
1934
|
`),x=1}else x=0;n.write(s+Oa(d.buffer,_)),y=La(d.buffer,d.cursor);let q=`${d.cursor}:${d.buffer}`;S!==null&&S!==q&&(S=null),y&&S===null?(y.kind==="slash"?f=Bf(y.query):y.kind==="file"?f=Wf(y.query):f=Na(y.command,y.query),m=f.length>0):(m=!1,f=[]),g>=f.length&&(g=Math.max(0,f.length-1)),b>g&&(b=g),g>=b+R&&(b=g-R+1);let P=n.columns||80;if(h=0,m&&P>40){let O=Math.min(P-4,60),ke=Math.min(f.length-b,R);for(let ze=0;ze<ke;ze++){let Nr=b+ze,hl=Uf(f[Nr],Nr===g,O,y?.kind);n.write(`
|
|
1935
1935
|
`+hl);let Sh=Hf(St(hl));h+=Math.max(1,Math.ceil(Sh/P))}}let Ke=ya(d.buffer,a,P),{row:at,col:Ge}=Nt(d.buffer,d.cursor,a,P),Ee=Math.max(0,Ke-at+h);Ee>0&&n.write(Oe.cursorUp(Ee)),n.write("\r"),Ge>0&&n.write(Oe.cursorForward(Ge)),A=Ke},N=!1,V=()=>{D||(D=!0,setImmediate(()=>{D&&!N&&(D=!1,M())}))};M();let be=()=>{let q=f[g];if(!q)return!1;let P=d.buffer.slice(0,d.cursor),Ke=d.buffer.slice(d.cursor),at,Ge;if(y?.kind==="slash"){let Ee=/\/[A-Za-z_-]*$/.exec(P);at=Ee?P.length-Ee[0].length:d.cursor,Ge=q.value+(Ke.startsWith(" ")?"":" ")}else if(y?.kind==="flag"){let Ee=/--[a-z0-9-]*$/.exec(P);at=Ee?P.length-Ee[0].length:d.cursor,Ge=q.value+(Ke.startsWith(" ")?"":" ")}else{let Ee=P.search(/[^\s]*$/);at=Ee>=0?Ee:d.cursor,Ge=q.value}return d=W.replaceRange(d,{start:at,end:d.cursor},Ge),m=!1,b=0,g=0,M(),!0},$=()=>{(x>0||A>0)&&n.write(Oe.cursorUp(x+A)),n.write("\r"),n.write(Oe.eraseDown),h=0;let q=Cr({buffer:Oa(d.buffer,_),promptText:s,isTTY:!!n.isTTY});n.write(q+`
|
|
@@ -1939,24 +1939,24 @@ _ended: ${new Date().toISOString()}_
|
|
|
1939
1939
|
`),e.history?.resetRecall(),M();return}if(w){d=W.insert(d,`
|
|
1940
1940
|
`);return}if(at){d=W.insert(d,`
|
|
1941
1941
|
`),V();return}if(m){let ze=y?.kind,Nr=be();ze==="slash"&&Nr&&$()}else d.buffer.endsWith("\\")?(d=W.replaceRange(d,{start:d.buffer.length-1,end:d.buffer.length},`
|
|
1942
|
-
`),M()):$();return}if(P?.shift&&P?.name==="tab"||P?.sequence==="\x1B[Z"){e.onShiftTab?.();return}if(P?.name==="tab"){m&&be();return}let Ee=typeof q=="string"&&q.length===1&&q>=" "&&!P?.ctrl&&!P?.meta?q:typeof P?.sequence=="string"&&P.sequence.length===1&&P.sequence>=" "&&!P?.ctrl&&!P?.meta?P.sequence:null;Ee!==null&&(d=W.insert(d,Ee),e.history?.resetRecall(),w||(at?V():M()))},l=()=>M(),t.on("keypress",i),n.on("resize",l)})}finally{e.statusLine?.setExtraRows(o),r.restore()}}async function Gf(e){return!process.stdout.isTTY||!process.stdin.isTTY?Mf(e):Kf(e)}import{readFile as Yf,mkdir as
|
|
1942
|
+
`),M()):$();return}if(P?.shift&&P?.name==="tab"||P?.sequence==="\x1B[Z"){e.onShiftTab?.();return}if(P?.name==="tab"){m&&be();return}let Ee=typeof q=="string"&&q.length===1&&q>=" "&&!P?.ctrl&&!P?.meta?q:typeof P?.sequence=="string"&&P.sequence.length===1&&P.sequence>=" "&&!P?.ctrl&&!P?.meta?P.sequence:null;Ee!==null&&(d=W.insert(d,Ee),e.history?.resetRecall(),w||(at?V():M()))},l=()=>M(),t.on("keypress",i),n.on("resize",l)})}finally{e.statusLine?.setExtraRows(o),r.restore()}}async function Gf(e){return!process.stdout.isTTY||!process.stdin.isTTY?Mf(e):Kf(e)}import{readFile as Yf,mkdir as cC,stat as dC,open as Ua}from"fs/promises";import{dirname as uC}from"path";import{O_WRONLY as ja,O_CREAT as Ba,O_APPEND as zf,O_NOFOLLOW as Wa,O_TRUNC as pC}from"node:constants";var $s=1e3,mC=/(?:^sk-[A-Za-z0-9]|^ghp_[A-Za-z0-9]|bearer\s+\S|password\s*=\s*\S|token\s*=\s*\S|key\s*=\s*\S)/i;function fC(e){return e.replace(/\x1b\[[^@-~]*[@-~]|\x1b[^[]/g,"")}var qf=Promise.resolve();function gC(e){let t=qf.then(e,e);return qf=t.then(()=>{},()=>{}),t}var mn=null,Os=class{_entries;_index;_draft;constructor(t){this._entries=t,this._index=-1,this._draft=""}get length(){return this._entries.length}push(t){if(t.startsWith(" "))return;let n=t.trim();!n||mC.test(n)||this._entries[this._entries.length-1]===n||(this._entries.push(n),this._index=-1,this._draft="",hC(n).catch(o=>{process.stderr.write(`[afk] history write failed: ${o.message}
|
|
1943
1943
|
`)}))}back(t){return this._entries.length===0?null:(this._index===-1?(this._draft=t,this._index=this._entries.length-1):this._index>0&&this._index--,this._entries[this._index]??null)}forward(){if(this._index===-1)return null;if(this._index<this._entries.length-1)return this._index++,this._entries[this._index]??null;this._index=-1;let t=this._draft;return this._draft="",t}resetRecall(){this._index=-1,this._draft=""}get inRecall(){return this._index!==-1}};async function Vf(){let e=Qs();try{let t=await Yf(e,"utf8"),n=[];for(let r of t.split(`
|
|
1944
|
-
`)){let o=r.trim();if(o)try{let s=JSON.parse(o);if(s!==null&&typeof s=="object"&&"text"in s&&typeof s.text=="string"){let i=
|
|
1945
|
-
`),new Os([])}}function
|
|
1946
|
-
`;if(mn!==null&&mn<$s-1){let a=await Ua(t,ja|Ba|zf|Wa,384);try{await a.writeFile(r)}finally{await a.close()}mn++;return}let o=await
|
|
1944
|
+
`)){let o=r.trim();if(o)try{let s=JSON.parse(o);if(s!==null&&typeof s=="object"&&"text"in s&&typeof s.text=="string"){let i=fC(s.text);i.trim()&&i!==n[n.length-1]&&n.push(i)}}catch{}}return mn=n.length,new Os(n)}catch(t){return t&&t.code!=="ENOENT"&&process.stderr.write(`[afk] history load failed: ${t.message}
|
|
1945
|
+
`),new Os([])}}function hC(e){return gC(async()=>{let t=Qs();await cC(uC(t),{recursive:!0});let n={text:e,ts:Date.now()},r=JSON.stringify(n)+`
|
|
1946
|
+
`;if(mn!==null&&mn<$s-1){let a=await Ua(t,ja|Ba|zf|Wa,384);try{await a.writeFile(r)}finally{await a.close()}mn++;return}let o=await dC(t).catch(()=>null);if(o&&o.size>5*1024*1024){process.stderr.write(`[afk] history file exceeds 5MB cap (${o.size} bytes); skipping write
|
|
1947
1947
|
`);return}let s=[];try{let a=await Yf(t,"utf8");for(let i of a.split(`
|
|
1948
1948
|
`)){let l=i.trim();if(l)try{let c=JSON.parse(l);c!==null&&typeof c=="object"&&"text"in c&&typeof c.text=="string"&&s.push(c)}catch{}}}catch{}if(mn=s.length,s.length<$s-1){let a=await Ua(t,ja|Ba|zf|Wa,384);try{await a.writeFile(r)}finally{await a.close()}mn++}else{let a=s.slice(-($s-1));a.push(n);let i=a.map(c=>JSON.stringify(c)).join(`
|
|
1949
1949
|
`)+`
|
|
1950
|
-
`,l=await Ua(t,ja|Ba|
|
|
1951
|
-
`),n=t.slice(Math.max(0,t.length-40)),r=-1,o=null;for(let l=n.length-1;l>=0;l--){let c=n[l]??"",u=
|
|
1952
|
-
`).trim();return{kind:o,rawBody:i,...
|
|
1950
|
+
`,l=await Ua(t,ja|Ba|pC|Wa,384);try{await l.writeFile(i)}finally{await l.close()}mn=$s}})}function Jf(e){if(!e)return null;let t=e.split(`
|
|
1951
|
+
`),n=t.slice(Math.max(0,t.length-40)),r=-1,o=null;for(let l=n.length-1;l>=0;l--){let c=n[l]??"",u=yC(c);if(u){r=l,o=u;break}}if(o===null||r<0)return null;let s=n.slice(r+1).map(l=>l.trim());for(;s.length>0&&s[0]==="";)s.shift();for(;s.length>0&&s[s.length-1]==="";)s.pop();let a=bC(s),i=s.join(`
|
|
1952
|
+
`).trim();return{kind:o,rawBody:i,...kC(o,a)}}function yC(e){let t=e.trim().replace(/^#{1,6}\s+/,"").replace(/^[-•▶▸]\s+/,"").replace(/^\*\s+/,"").replace(/^\*\*(.+?)\*\*$/,"$1").replace(/^__(.+?)__$/,"$1").replace(/^\*(.+?)\*$/,"$1").replace(/^_(.+?)_$/,"$1").replace(/[.:!?\s]+$/,"").trim();if(t.length===0||t.length>24)return null;let n=t.toLowerCase();return n==="done"?"done":n==="blocked"?"blocked":n==="asking"?"asking":n==="interrupted"?"interrupted":null}function bC(e){let t=[];for(let n of e){let r=n.trim();if(r==="")continue;let o=/^(?:[-*•▶▸]|\d+[.)])\s+(.*)$/.exec(r),s=o?(o[1]??"").trim():r;if(!o&&t.length>0&&r.length>0){let i=t[t.length-1];i.value=`${i.value} ${r}`.trim();continue}let a=s.indexOf(":");if(a>0&&a<60){let i=s.slice(0,a).trim().replace(/^\*\*(.+?)\*\*$/,"$1").replace(/^__(.+?)__$/,"$1").toLowerCase(),l=s.slice(a+1).trim();t.push({label:i,value:l})}else t.push({label:"",value:s})}return t}function kC(e,t){let n=(...r)=>{for(let o of t)if(o.label!==""){for(let s of r)if(o.label.includes(s))return o.value}};switch(e){case"done":{let r={},o=n("what was done","what i did","completed","done");o!==void 0&&(r.whatWasDone=o);let s=n("evidence","what changed","change","artifact","output");s!==void 0&&(r.evidence=s);let a=n("pending","deferred","follow-up","followup","next");return a!==void 0&&(r.deferred=a),r}case"blocked":{let r={},o=n("what blocks","blocker","blocked by");o!==void 0&&(r.whatBlocks=o);let s=n("unblock","must change","to unblock","condition");s!==void 0&&(r.unblockCondition=s);let a=n("already done","what has been done","progress");return a!==void 0&&(r.alreadyDone=a),r}case"asking":{let r={},o=n("question","asking");o!==void 0&&(r.question=o);let s=n("assumption","resolves");s!==void 0&&(r.assumption=s);let a=n("once answered","follow-up","next","will do","after");return a!==void 0&&(r.followup=a),r}case"interrupted":{let r={},o=n("what you were doing","in progress","doing","task");o!==void 0&&(r.whatWasInProgress=o);let s=n("state was saved","state","saved","where");s!==void 0&&(r.stateLocation=s);let a=n("resumption","resume","requires");return a!==void 0&&(r.resumeRequires=a),r}}}var wC={done:{color:p.success,chip:"\u2713 Done",affordance:"Objective satisfied \u2014 review evidence and close."},blocked:{color:p.error,chip:"\u2298 Blocked",affordance:"External dependency \u2014 unblock above to resume."},asking:{color:p.warning,chip:"? Asking",affordance:"Waiting on you \u2014 answer above to continue."},interrupted:{color:p.info,chip:"\u23F8 Interrupted",affordance:"Halted with state preserved \u2014 resume when ready."}};function Xf(e){let t=wC[e.kind],n=Math.max(40,Math.min(ee()-4,100)),r=n+4,o=t.color("\u256D\u2500")+t.color.call(null,` ${t.chip} `)+t.color("\u2500".repeat(Math.max(0,r-1-j(` ${t.chip} `)))+"\u256E"),s=t.color("\u2570"+"\u2500".repeat(r)+"\u256F"),a=t.color("\u2502"),i=a+" ".repeat(n+4)+a,l=SC(e),c=l.reduce((f,g)=>Math.max(f,j(g.label)),0),u=Math.max(8,n-c-2),d=[o,i];if(l.length===0){let f=e.rawBody.split(`
|
|
1953
1953
|
`);for(let g of f){let y=g.trim();if(y.length===0){d.push(a+" ".repeat(n+4)+a);continue}let S=te(Tt(y),n).split(`
|
|
1954
1954
|
`);for(let h of S)d.push(a+" "+he(h,n)+" "+a)}}else for(let f of l){let g=p.dim(he(f.label,c)),y=te(Tt(f.value),u).split(`
|
|
1955
1955
|
`),S=y[0]??"";d.push(a+" "+g+" "+he(S,u)+" "+a);for(let h of y.slice(1))d.push(a+" "+" ".repeat(c)+" "+he(h,u)+" "+a)}d.push(i);let m=p.dim(se(t.affordance,n));return d.push(a+" "+he(m,n)+" "+a),d.push(s),d.join(`
|
|
1956
|
-
`)}function
|
|
1957
|
-
`);let v=Jf(l);if(v&&(console.log(Xf(v)),console.log(),r.onTerminalState))try{r.onTerminalState(v)}catch{}if(
|
|
1958
|
-
`)[0]?.slice(0,80)??"";x&&T.push(x)}w.error&&T.push(w.error.message);let A=[w.stats.toolUses>0?`${w.stats.toolUses} tools`:"",w.stats.tokens>0?`${Math.round(w.stats.tokens/1e3)}k tok`:"",w.stats.durationMs>0?`${Math.round(w.stats.durationMs/1e3)}s`:""].filter(Boolean).join(" \xB7 ");A&&T.push(A),e.replRenderer.writeLine(Et({kind:w.status==="succeeded"?"checkpoint":"diagnosis",title:`${C} ${w.id} ${w.label}`,body:T})),e.replRenderer.writeLine("")}let g=l.renderIfChanged(e.stats.sessionId);if(g.length>0){for(let w of g)e.replRenderer.writeLine(w);e.replRenderer.writeLine("")}let y=c.render();y&&e.replRenderer.writeLine(y);let S,h;if(i!==void 0){let w=i;i=void 0;let C=ng(e.stats.model,e.stats.planMode),T=Cr({buffer:w,promptText:C,isTTY:!!process.stdout.isTTY});e.replRenderer.writeLine(T),S=w.trim(),h=[]}else{let w=await Gf({rl:e.rl,promptFn:()=>ng(e.stats.model,e.stats.planMode),onSigint:r,statusLine:e.statusLine,compositor:n.activeCompositor??void 0,history:a,onShiftTab:()=>{let C=e.slashCtx;C.stats.planMode&&C.stats.pendingPlanExit?(C.stats.pendingPlanExit=!1,ht(C,!1,{closureSummarySkipped:!0}).catch(()=>{})):ht(C).catch(()=>{}),e.statusLine.rearm()}});S=w.text.trim(),h=w.attachments}if(!S&&h.length===0)continue;if(S.startsWith("/")){let w=await Ap(S,e.slashCtx);if(w.handled){if(w.result==="exit"){e.rl.close();return}if((S==="/clear"||S.startsWith("/clear "))&&(await t.rotateOnClear(),e.replRenderer.writeLine(p.dim(` transcript: ${t.path()}`)),c.reset()),w.result!==null&&typeof w.result=="object"&&"kind"in w.result&&w.result.kind==="submit"){i=w.result.message,e.statusLine.rearm();continue}e.statusLine.rearm();continue}}a.push(S);let b;if(e.firstTurnHook&&e.stats.totalTurns===0){let w=e.firstTurnHook;e.firstTurnHook=void 0,b=Promise.resolve().then(()=>w(S)).catch(C=>{console.warn(p.warning("\u26A0 ")+"first-turn hook failed: "+(C instanceof Error?C.message:String(C)))})}i=await Zf({text:S,attachments:h},e.session,e.stats,{setInFlight(w){n.turnInFlight=w},async onTurnComplete(w,C){await t.appendTurn(w,C)},async onAfterTurn(){await e.contextSampler.onTurn(e.stats.totalTurns),await Op(e.slashCtx),e.statusLine.rearm()},rearmStatus:()=>e.statusLine.rearm(),onTerminalState:w=>c.push(w),setActiveCompositor:w=>{n.activeCompositor=w,e.replRenderer.setCompositor(w)}},e.options.thinkingUi,e.completionWriter,u),b!==void 0&&await b}}finally{d.stop(),l.dispose()}}import{promises as
|
|
1959
|
-
`),ig=/^[a-z0-9]+(-[a-z0-9]+){1,3}$/,Ka=30,
|
|
1956
|
+
`)}function SC(e){let t=[],n=(r,o)=>{o&&o.trim().length>0&&t.push({label:r,value:o.trim()})};switch(e.kind){case"done":n("done",e.whatWasDone),n("evidence",e.evidence),n("deferred",e.deferred);break;case"blocked":n("blocks",e.whatBlocks),n("unblock",e.unblockCondition),n("progress",e.alreadyDone);break;case"asking":n("question",e.question),n("resolves",e.assumption),n("after",e.followup);break;case"interrupted":n("was doing",e.whatWasInProgress),n("saved at",e.stateLocation),n("resume",e.resumeRequires);break}return t}function vC(e,t){let n=[];e&&n.push({type:"text",text:e});for(let r of t)n.push({type:"image",source:{type:"base64",media_type:r.mediaType,data:r.bytes.toString("base64")}});return n}async function Zf(e,t,n,r,o="summary",s,a){let i=Of(e.text,e.attachments);r.setInFlight(!0);let l="",c=!1,u,d=!1,m=!1,f=!1,g,y=!1,S=[],h=new Map,b=e.text.startsWith("/")?e.text.split(/[\s:]/)[0]?.slice(1):void 0,w=new Bt({out:jn(),thinkingMode:o,...b?{activeSkillName:b}:{},onCancel:()=>{t.interrupt().catch(T=>{Pe()&&console.error(" "+p.error("session.interrupt() failed:"),T)})},...a?{onBackground:()=>{y=!0}}:{}}),C=async()=>{if(!m){m=!0;try{await w.dispose()}catch{}}};try{console.log(),await w.arm();let T=w.getCompositor();if(s&&T){let v=T;s.fn=E=>v.commitAbove(E)}r.setActiveCompositor?.(T),r.rearmStatus?.();let A=e.attachments.length===0?e.text:vC(e.text,e.attachments),x=t.sendMessageStream(A);if(await vn(w.sink,async()=>{for await(let v of x){if(y&&a){let E=b??e.text.slice(0,40),R=a.register(E),I=ss(R,a);is(x,l,i,R,a,I,n,r.onTurnComplete,t.abortSignal),await C(),console.log(p.dim(` \u2192 backgrounded as ${R.id}: ${R.label}`)),r.setInFlight(!1),r.rearmStatus?.();return}if(v.type==="chunk"&&v.chunk.type==="content"?(l+=v.chunk.content,c=!0):v.type==="message"&&!c&&(l=v.message.content),v.type==="chunk"&&v.chunk.type==="tool_use_detail"){let E=v.chunk,R={toolName:E.toolName,toolUseId:E.toolUseId,input:E.toolInput};h.set(E.toolUseId,R),S.push(R)}else if(v.type==="chunk"&&v.chunk.type==="tool_result"){let E=v.chunk,R=h.get(E.toolUseId);R&&(R.result=E.content,R.isError=E.isError,h.delete(E.toolUseId))}if(v.type==="paused"){await C(),console.log(Xl({reason:v.reason,...v.resetsAt!==void 0?{resetsAt:v.resetsAt}:{},...v.accountId!==void 0?{accountId:v.accountId}:{}}));continue}if(v.type==="resumed"){let E=v.hotSwapped&&v.accountId?`\u25B6 Resumed on ${v.accountId}`:"\u25B6 Resumed";console.log(p.success(E));continue}if(v.type==="error"){await C(),wn(kn(v.error)),d=!0;continue}w.process(v),v.type==="done"&&(f=!0,g=v.metadata)}}),!m){let v=w.getCompositor();if(v)try{let{text:E,queued:R}=v.getBuffer();R&&E.length>0&&(u=E)}catch{}}if(await C(),f){Qo(n,i,l,g,S),r.onTurnComplete&&await r.onTurnComplete(i,l).catch(()=>{}),c&&console.log(`
|
|
1957
|
+
`);let v=Jf(l);if(v&&(console.log(Xf(v)),console.log(),r.onTerminalState))try{r.onTerminalState(v)}catch{}if(TC(g,n),r.onAfterTurn){let E=r.onAfterTurn();E instanceof Promise&&await E.catch(()=>{})}}}catch(T){await C(),d||wn(kn(T))}finally{await C(),s&&(s.fn=T=>console.log(T)),r.setActiveCompositor?.(null),r.setInFlight(!1),r.rearmStatus?.()}return u}function TC(e,t){if(!e)return;let n=[];e.durationMs&&n.push(me(e.durationMs)),e.totalCostUsd!==void 0&&n.push(Ie(e.totalCostUsd));let r=Number(e.usage?.input_tokens??0),o=Number(e.usage?.output_tokens??0);r+o>0&&n.push(H(r+o)+" tok"),n.length>0&&console.log(p.dim(" \u25E6 "+n.join(" \xB7 ")));let s=ca(t);if(s>.5){let a=s>.8?p.error:p.warning;console.log(a(` context ${Math.round(s*100)}% used of ${H(tt(t.model))}`))}console.log()}function Qf(e={}){let t=e.load??ns,n=e.onResize??(a=>xt.subscribe(a)),r="",o,s=n(()=>{r=""});return{renderIfChanged(a){let i=a??"unbound",l=t(i),c=Hp(l);return i===o&&c===r?[]:(o=i,r=c,c===""?[]:rs(l))},invalidate(){r=""},dispose(){try{s()}catch{}}}}var Ha={done:{glyph:"\u2713",color:p.success,label:"done"},blocked:{glyph:"\u2298",color:p.error,label:"blocked"},asking:{glyph:"?",color:p.warning,label:"asking"},interrupted:{glyph:"\u23F8",color:p.info,label:"interrupted"}};function eg(e={}){let t=Math.max(2,e.capacity??8),n=[];return{push(r){n.push(r.kind),n.length>t&&(n=n.slice(n.length-t))},reset(){n=[]},entries(){return n},render(){if(n.length===0)return null;let r=p.dim(" ledger "),o=p.dim(" \xB7 "),s=n.map(u=>{let d=Ha[u];return d.color(`${d.glyph} ${d.label}`)}),a=p.dim(` (${n.length} turn${n.length===1?"":"s"})`),i=r+s.join(o)+a,l=Math.max(20,ee()-2);if(j(i)<=l)return i;let c=r+n.map(u=>Ha[u].color(Ha[u].glyph)).join(p.dim(" "))+a;return se(c,l)}}}var tg=["\u25D0","\u25D1","\u25D2","\u25D3"],Ds=class{stream;manager;throttleMs;started=!1;lastRepaint=0;spinnerIndex=0;spinnerInterval=null;resizeUnsub=null;updateHandler=null;rowCount=0;onRowCountChange;constructor(t,n={}){this.manager=t,this.stream=n.stream??process.stdout,this.throttleMs=n.throttleMs??200}setRowCountChangeHandler(t){this.onRowCountChange=t}start(){this.started||(this.started=!0,this.updateHandler=()=>this.scheduleRepaint(),this.manager.on("update",this.updateHandler),this.manager.on("complete",this.updateHandler),this.resizeUnsub=xt.subscribe(()=>this.repaint()),this.spinnerInterval=setInterval(()=>{this.spinnerIndex=(this.spinnerIndex+1)%tg.length,this.rowCount>0&&this.repaint()},Math.max(this.throttleMs,50)))}stop(){this.started&&(this.started=!1,this.updateHandler&&(this.manager.removeListener("update",this.updateHandler),this.manager.removeListener("complete",this.updateHandler),this.updateHandler=null),this.resizeUnsub&&(this.resizeUnsub(),this.resizeUnsub=null),this.spinnerInterval&&(clearInterval(this.spinnerInterval),this.spinnerInterval=null),this.rowCount>0&&(this.clearRows(),this.rowCount=0,this.onRowCountChange?.(0)))}scheduleRepaint(){Date.now()-this.lastRepaint<this.throttleMs||this.repaint()}repaint(){if(!this.started||!this.stream.isTTY)return;this.lastRepaint=Date.now();let t=this.manager.running(),n=t.length;if(n!==this.rowCount&&(this.rowCount>0&&this.clearRows(),this.rowCount=n,this.onRowCountChange?.(n)),n===0)return;let o=(this.stream.rows??24)-n;this.stream.write("\x1B[s");for(let s=0;s<t.length;s++){let a=t[s],i=o+s;this.stream.write(`\x1B[${i};1H`),this.stream.write("\x1B[2K"),this.stream.write(this.formatTaskLine(a))}this.stream.write("\x1B[u")}clearRows(){if(!this.stream.isTTY)return;let n=(this.stream.rows??24)-this.rowCount;this.stream.write("\x1B[s");for(let r=0;r<this.rowCount;r++)this.stream.write(`\x1B[${n+r};1H`),this.stream.write("\x1B[2K");this.stream.write("\x1B[u")}formatTaskLine(t){let n=Math.max(4,(this.stream.columns??80)-2),r=p.brand(tg[this.spinnerIndex]),o=p.dim(t.id),s=p.bold(t.label),a=[r,o,s];t.progressDescription&&a.push(p.dim(t.progressDescription));let i=[];t.stats.toolUses>0&&i.push(`${t.stats.toolUses} tool${t.stats.toolUses===1?"":"s"}`),t.stats.tokens>0&&i.push(`${H(t.stats.tokens)} tok`);let l=Date.now()-t.startedAt;return i.push(me(l)),i.length>0&&a.push(p.dim(i.join(" \xB7 "))),se(" "+a.join(" "),n)}};function ng(e,t){let n=p.brand("afk")+p.dim(` (${e})`),r=t?p.warning(" \u25CF plan"):"";return n+r+p.dim(" \u203A ")}async function rg(e,t,n,r){let o=null,s=[];e.session.waitForInitialization().then(async g=>{Pe()&&(o=ts(g)),await Qm(e.session),Pe()&&(s=Zm())}).catch(()=>{});let a=await Vf(),i,l=Qf(),c=eg(),u=new os;em(u),rm(u),sm(u);let d=new Ds(u);d.setRowCountChangeHandler(g=>{e.statusLine.setExtraRows(g)}),d.start();let m=50,f=[];u.on("complete",g=>{f.length>=m&&f.shift(),f.push(g)});try{for(;;){if(o&&(e.replRenderer.writeLine(o),e.replRenderer.writeLine(""),o=null),s.length>0){for(let w of s)e.replRenderer.writeLine(w);e.replRenderer.writeLine(""),s=[]}for(;f.length>0;){let w=f.shift(),C=w.status==="succeeded"?"\u2713":"\u2717",T=[];if(w.resultText){let x=w.resultText.trim().split(`
|
|
1958
|
+
`)[0]?.slice(0,80)??"";x&&T.push(x)}w.error&&T.push(w.error.message);let A=[w.stats.toolUses>0?`${w.stats.toolUses} tools`:"",w.stats.tokens>0?`${Math.round(w.stats.tokens/1e3)}k tok`:"",w.stats.durationMs>0?`${Math.round(w.stats.durationMs/1e3)}s`:""].filter(Boolean).join(" \xB7 ");A&&T.push(A),e.replRenderer.writeLine(Et({kind:w.status==="succeeded"?"checkpoint":"diagnosis",title:`${C} ${w.id} ${w.label}`,body:T})),e.replRenderer.writeLine("")}let g=l.renderIfChanged(e.stats.sessionId);if(g.length>0){for(let w of g)e.replRenderer.writeLine(w);e.replRenderer.writeLine("")}let y=c.render();y&&e.replRenderer.writeLine(y);let S,h;if(i!==void 0){let w=i;i=void 0;let C=ng(e.stats.model,e.stats.planMode),T=Cr({buffer:w,promptText:C,isTTY:!!process.stdout.isTTY});e.replRenderer.writeLine(T),S=w.trim(),h=[]}else{let w=await Gf({rl:e.rl,promptFn:()=>ng(e.stats.model,e.stats.planMode),onSigint:r,statusLine:e.statusLine,compositor:n.activeCompositor??void 0,history:a,onShiftTab:()=>{let C=e.slashCtx;C.stats.planMode&&C.stats.pendingPlanExit?(C.stats.pendingPlanExit=!1,ht(C,!1,{closureSummarySkipped:!0}).catch(()=>{})):ht(C).catch(()=>{}),e.statusLine.rearm()}});S=w.text.trim(),h=w.attachments}if(!S&&h.length===0)continue;if(S.startsWith("/")){let w=await Ap(S,e.slashCtx);if(w.handled){if(w.result==="exit"){e.rl.close();return}if((S==="/clear"||S.startsWith("/clear "))&&(await t.rotateOnClear(),e.replRenderer.writeLine(p.dim(` transcript: ${t.path()}`)),c.reset()),w.result!==null&&typeof w.result=="object"&&"kind"in w.result&&w.result.kind==="submit"){i=w.result.message,e.statusLine.rearm();continue}e.statusLine.rearm();continue}}a.push(S);let b;if(e.firstTurnHook&&e.stats.totalTurns===0){let w=e.firstTurnHook;e.firstTurnHook=void 0,b=Promise.resolve().then(()=>w(S)).catch(C=>{console.warn(p.warning("\u26A0 ")+"first-turn hook failed: "+(C instanceof Error?C.message:String(C)))})}i=await Zf({text:S,attachments:h},e.session,e.stats,{setInFlight(w){n.turnInFlight=w},async onTurnComplete(w,C){await t.appendTurn(w,C)},async onAfterTurn(){await e.contextSampler.onTurn(e.stats.totalTurns),await Op(e.slashCtx),e.statusLine.rearm()},rearmStatus:()=>e.statusLine.rearm(),onTerminalState:w=>c.push(w),setActiveCompositor:w=>{n.activeCompositor=w,e.replRenderer.setCompositor(w)}},e.options.thinkingUi,e.completionWriter,u),b!==void 0&&await b}}finally{d.stop(),l.dispose()}}import{promises as EC}from"node:fs";import{dirname as CC,join as PC}from"node:path";import{randomBytes as AC}from"node:crypto";import xC from"@anthropic-ai/sdk";import{randomUUID as og}from"node:crypto";async function sg(e){let{token:t,model:n,system:r,user:o,maxTokens:s=64,signal:a,clientFactory:i}=e;if(!t)throw new Error("oneShotCompletion: token required");let l=Zr(t),c=Qn(t,l),u=i?i(c):new xC(c),d=og(),m=og(),f=Zt(l,d,m),g={};Object.keys(f).length>0&&(g.headers=f),a&&(g.signal=a);let y=await u.messages.create({model:n,max_tokens:s,system:r,messages:[{role:"user",content:o}]},Object.keys(g).length>0?g:void 0),S=[];for(let b of y.content)b.type==="text"&&S.push(b.text);let h=S.join("").trim();return h.length===0&&console.warn("oneShotCompletion: response contained no text blocks \u2014 returning empty string"),h}var _C=["Generate a 2-4 word kebab-case slug describing this work request.","Rules:","- ASCII lowercase letters and digits only, separated by single hyphens","- 2 to 4 hyphen-separated words","- Maximum 30 characters total","- No prefix, no quotes, no punctuation other than hyphens","- Output ONLY the slug \u2014 no explanation, no preamble","Examples: fix-cleanup-race, add-telegram-allowlist, refactor-prompt-loader, debug-flaky-test"].join(`
|
|
1959
|
+
`),ig=/^[a-z0-9]+(-[a-z0-9]+){1,3}$/,Ka=30,RC=1024,IC=8e3,MC="haiku";async function $C(e,t){let n=e.trim();if(n.length===0||n.startsWith("/"))return null;let r=LC(n,RC),o=new AbortController,s=setTimeout(()=>o.abort(),t.timeoutMs??IC),a=t.signal?NC([t.signal,o.signal]):o.signal,i;try{t.slugGenerator?i=await t.slugGenerator(r,a):i=await sg({token:t.token,model:t.model??MC,system:_C,user:r,maxTokens:32,signal:a})}catch{return null}finally{clearTimeout(s)}let l=OC(i);if(l===null)return null;let c=CC(t.worktreePath);return await DC(l,c)}function OC(e){let t=e.trim().toLowerCase();if(t.length===0)return null;if(ig.test(t)&&t.length<=Ka)return t;let n=t.replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");if(n.length===0)return null;let r=n.split("-").filter(s=>s.length>0).slice(0,4);if(r.length<2)return null;let o=r[0];for(let s=1;s<r.length;s++){let a=`${o}-${r[s]}`;if(a.length>Ka)break;o=a}return ig.test(o)?o:null}async function DC(e,t){if(!await FC(PC(t,e)))return e;let n=AC(2).toString("hex");return`${e.split("-").slice(0,3).join("-").slice(0,Ka-5)}-${n}`}async function FC(e){try{return await EC.access(e),!0}catch{return!1}}function LC(e,t){let n=Buffer.from(e,"utf8");if(n.length<=t)return e;let r=t;for(;r>0&&n[r]!==void 0&&(n[r]&192)===128;)r--;return n.slice(0,r).toString("utf8")}function NC(e){let t=AbortSignal.any;if(typeof t=="function")return t.call(AbortSignal,e);let n=new AbortController;for(let r of e){if(r.aborted)return n.abort(r.reason),n.signal;r.addEventListener("abort",()=>n.abort(r.reason),{once:!0})}return n.signal}async function ag(e){let t=await $C(e.message,{token:e.token,...e.model!==void 0?{model:e.model}:{},...e.timeoutMs!==void 0?{timeoutMs:e.timeoutMs}:{},worktreePath:e.handle.path,...e.signal!==void 0?{signal:e.signal}:{},...e.slugGenerator!==void 0?{slugGenerator:e.slugGenerator}:{}});if(t===null)return{status:"skipped",reason:"slug generation returned null"};let r=await(e.renameFn??pp)(e.handle,t,e.branchPrefix!==void 0?{branchPrefix:e.branchPrefix}:void 0);return r.ok?(e.session&&e.session.setCwd(r.newPath),{status:"renamed",oldPath:r.oldPath,newPath:r.newPath,oldBranch:r.oldBranch,newBranch:r.newBranch}):(r.partial==="branch"&&e.session&&e.session.setCwd(e.handle.path),{status:"failed",reason:r.reason,...r.partial!==void 0?{partial:r.partial}:{}})}import{spawn as lg}from"child_process";import{existsSync as HC,mkdirSync as KC,readFileSync as cg,unlinkSync as GC,writeFileSync as zC}from"fs";import{get as qC}from"https";import{join as dg}from"path";import{readFileSync as UC}from"fs";import{dirname as jC,join as BC}from"path";import{fileURLToPath as WC}from"url";function fn(){try{return"2.24.0"}catch{}try{let e=jC(WC(import.meta.url));for(let t of["../../package.json","../package.json"])try{let n=JSON.parse(UC(BC(e,t),"utf-8"));if(typeof n.version=="string")return n.version}catch{}}catch{}return"0.0.0-unknown"}var YC=64*1024,VC=1440*60*1e3,JC="update-check.json",XC="pending-update.json";function ug(){return dg(Wr(),JC)}function Ga(){return dg(Wr(),XC)}function pg(){let e=Wr();HC(e)||KC(e,{recursive:!0})}function ZC(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 QC(){try{let e=cg(ug(),"utf-8"),t=JSON.parse(e);if(typeof t.latestVersion=="string"&&typeof t.checkedAt=="number")return t}catch{}return null}function eP(){try{pg();let e=`
|
|
1960
1960
|
const https = require('https');
|
|
1961
1961
|
const fs = require('fs');
|
|
1962
1962
|
const url = 'https://registry.npmjs.org/agent-afk/latest';
|
|
@@ -1975,34 +1975,34 @@ _ended: ${new Date().toISOString()}_
|
|
|
1975
1975
|
} catch {}
|
|
1976
1976
|
});
|
|
1977
1977
|
}).on('error', () => {});
|
|
1978
|
-
`;lg(process.execPath,["-e",e],{detached:!0,stdio:"ignore"}).unref()}catch{}}function mg(e){if(e==="off"||process.env.NO_UPDATE_NOTIFIER||process.env.CI)return null;let t=
|
|
1978
|
+
`;lg(process.execPath,["-e",e],{detached:!0,stdio:"ignore"}).unref()}catch{}}function mg(e){if(e==="off"||process.env.NO_UPDATE_NOTIFIER||process.env.CI)return null;let t=QC(),n=Date.now();if((!t||n-t.checkedAt>VC)&&eP(),!t)return null;let r=fn();return ZC(r,t.latestVersion)?{currentVersion:r,latestVersion:t.latestVersion}:null}function Fs(e){let t="\x1B[33m",n="\x1B[1m",r="\x1B[2m",o="\x1B[0m";process.stderr.write(`
|
|
1979
1979
|
${t}${n}Update available:${o} ${r}${e.currentVersion}${o} \u2192 ${n}${e.latestVersion}${o}
|
|
1980
1980
|
${r}Run \`npm install -g agent-afk\` to update${o}
|
|
1981
|
-
`)}var za=/^\d+\.\d+\.\d+(-[\da-z.]+)?$/i;function qa(e){if(za.test(e))try{pg(),
|
|
1982
|
-
`)}}catch{}}var Ls=null;function hg(e,t){Ls={updateInfo:e,pendingMessage:t}}function
|
|
1981
|
+
`)}var za=/^\d+\.\d+\.\d+(-[\da-z.]+)?$/i;function qa(e){if(za.test(e))try{pg(),zC(Ga(),JSON.stringify({targetVersion:e,triggeredAt:Date.now()}))}catch{}}function Ya(e=5e3,t="https://registry.npmjs.org/agent-afk/latest"){return new Promise(n=>{let r=!1,o=a=>{r||(r=!0,n(a))},s=(a,i)=>{try{let l=qC(a,{headers:{Accept:"application/json"}},c=>{if((c.statusCode===301||c.statusCode===302)&&typeof c.headers.location=="string"&&i>0){c.resume(),s(c.headers.location,i-1);return}if(c.statusCode!==200){c.resume(),o(void 0);return}let u="",d=0,m=!1;c.on("data",f=>{if(!m){if(d+=f.byteLength,d>YC){m=!0,l.destroy(),o(void 0);return}u+=f.toString("utf-8")}}),c.on("end",()=>{if(!m){try{let f=JSON.parse(u);if(typeof f.version=="string"&&za.test(f.version)){o(f.version);return}}catch{}o(void 0)}})});l.on("error",()=>o(void 0)),l.setTimeout(e,()=>{l.destroy(),o(void 0)})}catch{o(void 0)}};s(t,3)})}function Va(e){if(za.test(e))try{qa(e),lg("npm",["install","-g",`agent-afk@${e}`],{detached:!0,stdio:"ignore"}).unref()}catch{}}function fg(){try{let e=cg(Ga(),"utf-8"),t=JSON.parse(e);if(typeof t.targetVersion=="string"){let n=fn();GC(Ga()),n===t.targetVersion&&process.stderr.write(`\x1B[32m\x1B[1mUpdated to agent-afk v${n}\x1B[0m
|
|
1982
|
+
`)}}catch{}}var Ls=null;function hg(e,t){Ls={updateInfo:e,pendingMessage:t}}function nP(e){if(e==="summary"||e==="live"||e==="off")return e;throw new Error(`Invalid --thinking-ui value: ${e}. Expected summary|live|off`)}function rP(e,t){if(e.worktreeAutoname===!1)return!1;let n=process.env.AFK_WORKTREE_AUTONAME;if(n!==void 0){let r=n.toLowerCase();return!(r==="0"||r==="false"||r==="off"||r==="no")}return typeof t.interactive?.worktreeAutoname=="boolean"?t.interactive.worktreeAutoname:!0}function yg(e){e.command("interactive",{isDefault:!0}).description("Start interactive chat session").option("-m, --model <model>","Model to use. Short aliases: opus|opus_1m|sonnet|sonnet_1m|haiku. Any other value (e.g. `auto` for cursor-api-proxy, or a full `claude-*` ID) passes through to the SDK/proxy untouched.",ve()).option("--max-turns <number>","Maximum conversation turns","100").option("--thinking <mode>","Thinking mode: 'adaptive' | 'disabled' | 'enabled:<N>'","enabled:max").option("--thinking-ui <mode>","Thinking display mode: summary|live|off",nP,"live").option("--effort <level>","Effort level: low|medium|high|xhigh|max").option("--max-output-tokens <n|max>","Per-response output cap ('max' = model ceiling). Env: AFK_MAX_OUTPUT_TOKENS").option("--resume <id>","Resume a persisted SDK session by id").option("--continue","Continue the most recent persisted session in cwd").option("--debug","Show SDK init metadata on startup; enables /debug command",!1).option("-w, --worktree [branch]","Create a git worktree for an isolated session. Optional value sets the branch name; otherwise auto-named. On clean exit (no uncommitted changes) the worktree and branch are auto-removed; on dirty exit the worktree is preserved.").option("--no-worktree-autoname","Disable mid-session rename of auto-named worktrees from the first user message via haiku. Default on. Also: AFK_WORKTREE_AUTONAME=0, or interactive.worktreeAutoname:false in afk.config.json.").option("--provider <name>","Provider to use: anthropic|anthropic-direct|openai-codex. Default: auto-selected by model").option("--dump-prompt [path]",'Dump resolved SDK prompt+options+provenance to file (default: ~/.afk/logs/prompt-dump-<ISO>.json) or "stderr"').action(async t=>{if(t.debug&&(process.env.AFK_DEBUG="1"),t.dumpPrompt!==void 0){let b=t.dumpPrompt===!0?zn.join(gg.homedir(),".afk","logs",`prompt-dump-${new Date().toISOString().replace(/[:.]/g,"-")}.json`):String(t.dumpPrompt);process.env.AFK_DUMP_PROMPT=b,t.provider!==void 0&&t.provider!=="anthropic"&&t.provider!=="anthropic-direct"&&console.error(`[--dump-prompt] WARNING: active provider (${t.provider}) does not support prompt dumping. No file will be written.`)}let n=tP({text:"Initializing interactive session...",...es}).start(),r=je(),o=process.env.AFK_WORKTREE_BRANCH_PREFIX??r.interactive?.worktreeBranchPrefix,s,a;if(t.worktree!==void 0)try{a=await qo(t.worktree,o!==void 0?{branchPrefix:o}:void 0),s=a.path,n.text=`Worktree ready at ${a.path} (branch: ${a.branch})`}catch(b){n.fail("Worktree setup failed"),z(b)}let i;try{i=await Ef(t,s!==void 0?{cwd:s}:void 0)}catch(b){n.fail("Invalid options"),z(b)}let l=rP(t,r),c=J();if(a!==void 0&&t.worktree===!0&&l&&c!==void 0){let b=a,w=i.session;i.firstTurnHook=async C=>{let T=await ag({handle:b,message:C,token:c,session:w,...o!==void 0?{branchPrefix:o}:{}});if(T.status==="renamed")console.log(p.dim("\u21AA ")+`Renamed \u2192 ${zn.relative(process.cwd(),T.newPath)||T.newPath} `+p.dim(`(branch: ${T.newBranch})`));else if(T.status==="failed"){let A=T.partial==="branch"?" (worktree dir moved, branch rename failed)":"";console.warn(p.warning("\u26A0 ")+`Worktree auto-rename failed${A}: ${T.reason}. `+p.dim("Continuing with the original name."))}}}Fn(async()=>{i.teardownTrustedSkillEvents?.(),await i.session.close(),i.memoryStore.close(),a!==void 0&&await a.cleanup()}),n.succeed("Session ready");let u=await Af(()=>i.stats.model);console.log(p.dim(` transcript: ${u.path()}`)),Fn(async()=>{await u.appendEnded()});let d=!1,m=()=>{if(i.stats.totalTurns===0)return;let b=Vo(i.stats);return d=!0,b};Fn(async()=>{if(!d)try{m()}catch{}});let f={turnInFlight:!1,lastSigintAt:0},g=1500,y=()=>{let b=Date.now();if(f.turnInFlight){i.session.interrupt().catch(()=>{}),f.lastSigintAt=b;let w=`
|
|
1983
1983
|
`+p.warning("\u26A0 Interrupted. Press Ctrl+C again to exit."),C=f.activeCompositor;if(C&&C.isArmed())try{C.commitAbove(w)}catch{console.log(w)}else console.log(w);return}if(b-f.lastSigintAt<g){i.rl.close();return}f.lastSigintAt=b,console.log(`
|
|
1984
1984
|
`+p.info("\u2139 ")+"Press Ctrl+C again (or /exit) to quit.")};process.on("SIGINT",y),Fn(async()=>{process.removeListener("SIGINT",y)});let S=!1,h=()=>{if(S)return;S=!0;try{i.rl.close()}catch{}setTimeout(()=>{ra().finally(()=>process.exit(0))},2e3).unref()};if(process.on("SIGTERM",h),Fn(async()=>{process.removeListener("SIGTERM",h)}),process.stdout.write("\x1B[3J\x1B[2J\x1B[H"),Ls!==null){let{updateInfo:b,pendingMessage:w}=Ls;Ls=null,w!==null&&process.stderr.write(w),b!==null&&Fs(b)}console.log(`
|
|
1985
|
-
`+Jl({mode:`Interactive Mode (${i.stats.model})`,hintLine:"Type /help for commands \xB7 Ctrl+C to interrupt \xB7 /exit to quit"})),console.log(),i.statusLine.start(),i.slashCtx.ui.repaintStatusLine(),i.rl.on("close",async()=>{i.statusLine.stop(),
|
|
1986
|
-
`+ce("Session Summary"));let t=[`${e.stats.totalTurns} turn${e.stats.totalTurns===1?"":"s"}`,me(Date.now()-e.stats.sessionStartTime)];e.stats.totalCostUsd>0&&t.push(Ie(e.stats.totalCostUsd)),e.stats.totalTokens>0&&t.push(H(e.stats.totalTokens)+" tokens"),console.log(p.dim(" "+t.join(" \xB7 "))),console.log()}function
|
|
1985
|
+
`+Jl({mode:`Interactive Mode (${i.stats.model})`,hintLine:"Type /help for commands \xB7 Ctrl+C to interrupt \xB7 /exit to quit"})),console.log(),i.statusLine.start(),i.slashCtx.ui.repaintStatusLine(),i.rl.on("close",async()=>{i.statusLine.stop(),oP(i),sP(i,m),console.log(p.info("\u2139 ")+"Goodbye!"),await ra(),process.exit(0)}),await rg(i,u,f,y)})}function oP(e){if(e.stats.totalTurns===0)return;console.log(`
|
|
1986
|
+
`+ce("Session Summary"));let t=[`${e.stats.totalTurns} turn${e.stats.totalTurns===1?"":"s"}`,me(Date.now()-e.stats.sessionStartTime)];e.stats.totalCostUsd>0&&t.push(Ie(e.stats.totalCostUsd)),e.stats.totalTokens>0&&t.push(H(e.stats.totalTokens)+" tokens"),console.log(p.dim(" "+t.join(" \xB7 "))),console.log()}function sP(e,t){if(e.stats.totalTurns===0)return;let n=e.stats.sessionId;try{let r=t();!n&&r&&(n=zn.basename(r,".json"))}catch{}n&&(console.log(p.dim(" Continue with: ")+p.brand(Ln(n,e.stats.model))),console.log())}import iP from"ora";function bg(e){e.command("status").description("Check agent connection status").option("-f, --format <format>","Output format (text|json)","text").action(async t=>{let n=iP("Checking status...").start();try{let r=ve(),o=Be(r),s=Id(r);if(await new Ae({model:o==="openai-codex"?"gpt-5.4-mini":"haiku",...s!==void 0?{apiKey:s}:{},maxTurns:1}).close(),n.succeed(`${o} provider reachable`),t.format==="json"){let i=J(),l=lr(),c=i?process.env.ANTHROPIC_API_KEY?"ANTHROPIC_API_KEY":"CLAUDE_CODE_OAUTH_TOKEN":null,u=l?process.env.OPENAI_API_KEY?"OPENAI_API_KEY":"CODEX_API_KEY":null;console.log(JSON.stringify({providers:{anthropic:{ok:!!i,source:c},codex:{ok:!!l,source:u}},model:String(r),bypass:!0},null,2))}else console.log(`
|
|
1987
1987
|
`+Vl("Agent AFK \xB7 Status",[{label:"Provider",value:o,kind:"info"},{label:"Auth",value:o==="openai-codex"?s?"Found (OPENAI_API_KEY / CODEX_API_KEY)":"Using `codex login` state on disk":s?"Found (ANTHROPIC_API_KEY)":"Falling back to Claude OAuth",kind:s?"ok":"warn"},{label:"Model",value:String(r),kind:"info"},{label:"Bypass",value:"Permissions disabled",kind:"warn"}])+`
|
|
1988
1988
|
`)}catch(r){n.fail("Connection failed"),z(r)}})}function kg(e){e.command("config").description("View current configuration").option("-f, --format <format>","Output format (text|json)","text").action(t=>{let n=process.env.AFK_MODEL??process.env.CLAUDE_MODEL,r=n??"sonnet",o=Be(n),s=process.env.ANTHROPIC_API_KEY||process.env.CLAUDE_CODE_OAUTH_TOKEN,a=process.env.OPENAI_API_KEY||process.env.CODEX_API_KEY,i=o==="anthropic"?s:a,l=s?process.env.ANTHROPIC_API_KEY?"ANTHROPIC_API_KEY":"CLAUDE_CODE_OAUTH_TOKEN":null,c=a?process.env.OPENAI_API_KEY?"OPENAI_API_KEY":"CODEX_API_KEY":null;if(t.format==="json")console.log(JSON.stringify({model:r,provider:o,apiKey:{present:!!i,source:o==="anthropic"?l:c},thinking:process.env.AFK_THINKING||null,effort:process.env.AFK_EFFORT||null,bypass:!0,raw_env:{AFK_MODEL:process.env.AFK_MODEL??null,AFK_THINKING:process.env.AFK_THINKING??null,AFK_EFFORT:process.env.AFK_EFFORT??null,ANTHROPIC_API_KEY:process.env.ANTHROPIC_API_KEY?"set":"unset",CLAUDE_CODE_OAUTH_TOKEN:process.env.CLAUDE_CODE_OAUTH_TOKEN?"set":"unset",OPENAI_API_KEY:process.env.OPENAI_API_KEY?"set":"unset",CODEX_API_KEY:process.env.CODEX_API_KEY?"set":"unset"}},null,2));else{console.log(p.info(`\u{1F4CB} Current Configuration:
|
|
1989
1989
|
`)),console.log(` Model: ${p.info(n?r:r+" (default)")}`),console.log(` Provider: ${p.plan(o)}`),console.log(o==="anthropic"?` API Key: ${i?p.success("\u2713 Set (ANTHROPIC_API_KEY / CLAUDE_CODE_OAUTH_TOKEN)"):p.warning("\u26A0 Not set \u2014 subprocess will fall back to OAuth / keychain")}`:` API Key: ${i?p.success("\u2713 Set (OPENAI_API_KEY / CODEX_API_KEY)"):p.warning("\u26A0 Not set \u2014 falling back to `codex login` state")}`);let u=process.env.AFK_THINKING||"(unset \u2014 SDK default)";console.log(` Thinking: ${p.info(u)}`);let d=process.env.AFK_EFFORT||"(unset \u2014 SDK default)";console.log(` Effort: ${p.info(d)}`),console.log(` Bypass Permissions: ${p.warning("true (enabled)")}`),console.log(p.meta(`
|
|
1990
|
-
Environment variables:`)),console.log(p.meta(" AFK_MODEL - Default model id (canonical; accepts short aliases or full ids)")),console.log(p.meta(" CLAUDE_MODEL - Legacy alias for AFK_MODEL (Claude-only deployments)")),console.log(p.meta(" ANTHROPIC_API_KEY - Anthropic API key (Claude models)")),console.log(p.meta(" CLAUDE_CODE_OAUTH_TOKEN - Anthropic OAuth token (Claude models)")),console.log(p.meta(" OPENAI_API_KEY / CODEX_API_KEY - OpenAI API key (Codex models)")),console.log(p.meta(" AFK_THINKING - Thinking mode (Claude only: adaptive|disabled|enabled:<N>)")),console.log(p.meta(" AFK_EFFORT - Effort level (low|medium|high|xhigh|max)")),console.log(p.meta(" AFK_TIMEOUT_MS - Per-tick daemon session timeout in ms")),console.log(p.meta(" AFK_SESSIONSTART_COOLDOWN_MS - Phase 6 cooldown between sessionstart fires (default 6h)")),console.log("")}})}import
|
|
1991
|
-
`),s="",a="",i="",l=!1,c=!1,u=!1;for(let d of o)d.startsWith("worktree ")?s=d.slice(9).trim():d.startsWith("HEAD ")?a=d.slice(5).trim():d.startsWith("branch ")?i=d.slice(7).trim():d.trim()==="locked"?l=!0:d.trim()==="prunable"?c=!0:d.trim()==="bare"&&(u=!0);s&&n.push({path:s,head:a,branch:i,locked:l,prunable:c,isBare:u})}return n}function
|
|
1992
|
-
`);for(let o=r.length-1;o>=0;o-=1){let s=r[o];if(s)try{let a=JSON.parse(s);if(a.taskId!==e||typeof a.triggeredAt!="string")continue;let i=Date.parse(a.triggeredAt);if(Number.isNaN(i))continue;return i}catch{continue}}return null}function
|
|
1993
|
-
`,"utf-8"),this.fireOnTaskComplete(t)}catch(n){let r=n instanceof Error?n.message:String(n);console.error(`[daemon] telemetry write failed: ${r}`)}}fireOnTaskComplete(t){let n=this.options.onTaskComplete;if(n)try{let r=n(t);r instanceof Promise&&r.catch(o=>{let s=o instanceof Error?o.message:String(o);console.error(`[daemon] onTaskComplete callback failed: ${s}`)})}catch(r){let o=r instanceof Error?r.message:String(r);console.error(`[daemon] onTaskComplete callback failed: ${o}`)}}};var
|
|
1994
|
-
`)}function $g(e){e.command("daemon").description("Run agent-afk as a daemon that fires scheduled tasks (e.g. /forge-friction --auto)").option("-p, --port <number>","Control HTTP port","7777").option("-t, --task <command>",`Command to fire on each tick (default: ${Ja})`).option("-c, --cron <expression>",'Cron expression (e.g. "0 */6 * * *"). Required when --trigger includes cron.').option("-i, --task-id <id>",`Task identifier (default: ${Xa})`).option("--once","Fire one tick and exit (for testing)",!1).option("--timeout-ms <ms>","Per-tick session timeout in ms. Overrides AFK_TIMEOUT_MS. Defaults to the session default (120000).").option("--thinking <mode>","Thinking mode: 'adaptive' | 'disabled' | 'enabled:<N>'").option("--effort <level>","Effort level: low|medium|high|xhigh|max").option("--trigger <mode>","Trigger mode: cron | sessionstart | both. Defaults to cron.").option("--sessionstart-cooldown-ms <ms>","Cooldown between Phase 6 sessionstart fires. Overrides AFK_SESSIONSTART_COOLDOWN_MS. Defaults to 6h.").option("--briefs-dir <path>","Override directory scanned for pending briefs (defaults to ~/.afk/agent-framework/briefs).").option("--dump-prompt [path]",'Dump resolved SDK prompt+options+provenance to file (default: ~/.afk/logs/prompt-dump-<ISO>.json) or "stderr"').action(async t=>{let n=parseInt(t.port,10);(Number.isNaN(n)||n<=0)&&z(new Error(`Invalid port: ${t.port}`));let r=je(),o=Ig(t.task,process.env.AFK_DAEMON_TASK,r.daemon?.task),s=Mg(t.taskId,process.env.AFK_DAEMON_TASK_ID,r.daemon?.taskId),a,i,l;try{a=Ag(t.timeoutMs,process.env.AFK_TIMEOUT_MS),i=_g(t.sessionstartCooldownMs,process.env.AFK_SESSIONSTART_COOLDOWN_MS),l=Rg(t.trigger)}catch(T){z(T)}(l==="cron"||l==="both")&&!t.cron&&z(new Error(`--cron is required when --trigger is '${l}'.`));let c,u;try{c=Mt(t.thinking)??En(),u=$t(t.effort)??Cn()}catch(T){z(T)}let d={taskId:s,command:o,trigger:l,...t.cron!==void 0?{cronExpression:t.cron}:{}},m=r.daemon?.worktreePrune,f=process.env.AFK_WORKTREE_PRUNE_DISABLE==="1",g=m?.cron??"0 4 * * *",y={taskId:"worktree-prune",command:"__BUILTIN_WORKTREE_PRUNE__",trigger:"cron",cronExpression:g},S=[d];if(!f&&m?.enabled!==!1&&S.push(y),t.dumpPrompt!==void 0&&t.dumpPrompt!==!1){let T=t.dumpPrompt===!0?
|
|
1995
|
-
${v.slice(0,500)}`).catch(E=>{console.error("[daemon] crash notification push failed:",E instanceof Error?E.message:String(E))})};process.on("uncaughtException",T=>{w("uncaughtException",T),process.exit(1)}),process.on("unhandledRejection",T=>{w("unhandledRejection",T),process.exit(1)});let C=process.env.AFK_DAEMON_CWD;try{let T=await Pg({port:n,sessionConfig:{model:ve(),...J()!==void 0?{apiKey:J()}:{},...a!==void 0?{timeoutMs:a}:{},...c!==void 0?{thinking:c}:{},...u!==void 0?{effort:u}:{},...C!==void 0&&C.length>0?{cwd:C}:{}},...i!==void 0?{cooldownMs:i}:{},...t.briefsDir!==void 0?{briefsDir:t.briefsDir}:{},tasks:S,onTaskComplete:x=>{Io(
|
|
1996
|
-
\xB7 Shutting down daemon...`)),await T.stop(),process.exit(0)};process.on("SIGINT",A),process.on("SIGTERM",A)}catch(T){z(T)}})}import Yn from"chalk";import{existsSync as
|
|
1990
|
+
Environment variables:`)),console.log(p.meta(" AFK_MODEL - Default model id (canonical; accepts short aliases or full ids)")),console.log(p.meta(" CLAUDE_MODEL - Legacy alias for AFK_MODEL (Claude-only deployments)")),console.log(p.meta(" ANTHROPIC_API_KEY - Anthropic API key (Claude models)")),console.log(p.meta(" CLAUDE_CODE_OAUTH_TOKEN - Anthropic OAuth token (Claude models)")),console.log(p.meta(" OPENAI_API_KEY / CODEX_API_KEY - OpenAI API key (Codex models)")),console.log(p.meta(" AFK_THINKING - Thinking mode (Claude only: adaptive|disabled|enabled:<N>)")),console.log(p.meta(" AFK_EFFORT - Effort level (low|medium|high|xhigh|max)")),console.log(p.meta(" AFK_TIMEOUT_MS - Per-tick daemon session timeout in ms")),console.log(p.meta(" AFK_SESSIONSTART_COOLDOWN_MS - Phase 6 cooldown between sessionstart fires (default 6h)")),console.log("")}})}import _P from"path";import RP from"os";import{createServer as xP}from"node:http";import{mkdirSync as bP,appendFileSync as kP}from"node:fs";import{dirname as wP}from"node:path";import{execFile as SP}from"node:child_process";import{promisify as vP}from"node:util";import*as Cg from"node-cron";import{promises as Je,existsSync as wg,createReadStream as aP}from"node:fs";import{join as Ns}from"node:path";import{createInterface as lP}from"node:readline";var cP=36e5;function dP(e){let t=e.trim().split(/\n\n+/),n=[];for(let r of t){let o=r.split(`
|
|
1991
|
+
`),s="",a="",i="",l=!1,c=!1,u=!1;for(let d of o)d.startsWith("worktree ")?s=d.slice(9).trim():d.startsWith("HEAD ")?a=d.slice(5).trim():d.startsWith("branch ")?i=d.slice(7).trim():d.trim()==="locked"?l=!0:d.trim()==="prunable"?c=!0:d.trim()==="bare"&&(u=!0);s&&n.push({path:s,head:a,branch:i,locked:l,prunable:c,isBare:u})}return n}function uP(e,t,n){if(e.locked)return"locked";let r=864e5,o=t*r,s=n*r;return e.commitsAhead===0&&!e.isDirty&&e.ageMs>=cP?"empty":e.isDirty&&e.ageMs>s?"stale-dirty":!e.isDirty&&e.ageMs>o?"stale-clean":"active"}async function pP(e){if(!wg(e))return 0;let t=0;try{let n=lP({input:aP(e),crlfDelay:1/0});for await(let r of n){let o=r.trim();if(o)try{let s=JSON.parse(o);s.taskId==="worktree-prune"&&(s.status==="success"||s.status==="error")&&t++}catch{}}}catch{}return t}var Us=class extends Error{constructor(t){super(`Worktree sweep lock contested: ${t} \u2014 another sweep may be running.`),this.name="LockContestedError"}};async function mP(e){let t=Ns(e,"..");await Je.mkdir(t,{recursive:!0}).catch(()=>{});let r=await(async()=>{try{return await Je.open(e,"wx")}catch(o){if(o.code!=="EEXIST")throw o;let a=null;try{let i=await Je.readFile(e,"utf-8");a=parseInt(i.trim(),10)}catch{}if(a!==null&&!Number.isNaN(a)){let i=!1;try{process.kill(a,0),i=!0}catch{}if(!i)return await Je.unlink(e).catch(()=>{}),await Je.open(e,"wx")}throw new Us(e)}})();return await r.writeFile(String(process.pid),"utf-8"),await r.close(),async()=>{await Je.unlink(e).catch(()=>{})}}async function Mr(e){let{execFile:t,repoRoot:n,maxAgeDaysClean:r=14,maxAgeDaysDirty:o=30,scope:s="all",telemetryPath:a}=e,i=a??yn(),l=xl(),c={removed:[],warnings:[],dryRun:e.dryRun??!1,candidates:[]},u=await pP(i),d=e.dryRun===!0||u<3;c.dryRun=d;let m=null;try{m=await mP(l)}catch(f){if(f instanceof Us)return c.warnings.push(`[WARN] ${f.message}`),c;throw f}try{let f=await t("git",["-C",n,"worktree","list","--porcelain"]),g=dP(f.stdout),y=Ns(n,".afk-worktrees"),S=new Set(g.map(T=>T.path)),h=[];try{h=(await Je.readdir(y,{withFileTypes:!0})).filter(A=>A.isDirectory()).map(A=>Ns(y,A.name))}catch{}let b=h.filter(T=>!S.has(T));if(s==="all"||s==="interactive")for(let T of b){let A=0;try{let x=await Je.stat(T);A=Date.now()-x.birthtimeMs}catch{}if(c.candidates.push({path:T,verdict:"orphaned-dir",owner:"interactive",ageMs:A}),!d)try{await Je.rm(T,{recursive:!0,force:!0}),c.removed.push(T)}catch(x){c.warnings.push(`[ERROR] Failed to remove orphaned dir ${T}: ${x instanceof Error?x.message:String(x)}`)}}let w=!1,C=g[0]?.path;for(let T of g){if(T.path===C||T.isBare||!T.path.startsWith(y))continue;let A;try{let _=await Je.readFile(Ns(T.path,".afk-worktree-meta.json"),"utf-8");A=JSON.parse(_)}catch{}if(s!=="all"&&A?.owner!==s)continue;let x=A?.owner==="interactive"||A?.owner==="diagnose"?A.owner:"unknown";if(!wg(T.path)){c.candidates.push({path:T.path,verdict:"orphaned-registration",owner:x,ageMs:0}),d||(w=!0);continue}let v=0,E=A?.createdAt;if(E)v=Date.now()-new Date(E).getTime();else try{let _=await Je.stat(T.path);v=Date.now()-_.birthtimeMs}catch{}let R=!1,I=0;try{R=(await t("git",["-C",T.path,"status","--porcelain"])).stdout.trim().length>0}catch{R=!0}if(!R&&T.head){let _=A?.baseSha??T.head;try{let M=await t("git",["-C",n,"rev-list",`${_}..${T.head}`,"--count"]);I=parseInt(M.stdout.trim(),10)||0}catch{I=0}}let D={path:T.path,head:T.head,branch:T.branch,locked:T.locked,prunable:T.prunable,meta:A,ageMs:v,isDirty:R,commitsAhead:I},F=uP(D,r,o);if(c.candidates.push({path:T.path,verdict:F,owner:x,ageMs:v}),!d)try{F==="empty"?(await t("git",["-C",n,"worktree","remove","--force",T.path]),T.branch&&await t("git",["-C",n,"branch","-d",T.branch]).catch(()=>{}),c.removed.push(T.path)):F==="stale-clean"?(await t("git",["-C",n,"worktree","remove","--force",T.path]),c.removed.push(T.path)):F==="stale-dirty"&&c.warnings.push(`[WARN] stale-dirty worktree preserved (uncommitted changes): ${T.path}`)}catch(_){c.warnings.push(`[ERROR] Failed to process ${T.path} (${F}): ${_ instanceof Error?_.message:String(_)}`)}}if(w&&!d)try{await t("git",["-C",n,"worktree","prune"])}catch(T){c.warnings.push(`[ERROR] git worktree prune failed: ${T instanceof Error?T.message:String(T)}`)}}finally{m&&await m()}return c}function Sg(e){if(!e.taskId)throw new Error("ScheduledTask.taskId is required");if(!e.command)throw new Error(`task ${e.taskId}: command is required`);if((e.trigger==="cron"||e.trigger==="both")&&!e.cronExpression)throw new Error(`task ${e.taskId}: cronExpression required for trigger=${e.trigger}`)}import{existsSync as vg,readFileSync as fP,readdirSync as gP}from"node:fs";var Tg=360*60*1e3;function xg(){return bt()}function hP(e,t){if(!vg(t))return null;let n;try{n=fP(t,"utf-8")}catch{return null}let r=n.split(`
|
|
1992
|
+
`);for(let o=r.length-1;o>=0;o-=1){let s=r[o];if(s)try{let a=JSON.parse(s);if(a.taskId!==e||typeof a.triggeredAt!="string")continue;let i=Date.parse(a.triggeredAt);if(Number.isNaN(i))continue;return i}catch{continue}}return null}function yP(e){if(!vg(e))return 0;try{return gP(e).filter(t=>!t.startsWith(".")).length}catch{return 0}}function Eg(e){let t=hP(e.taskId,e.telemetryPath);if(t!==null&&e.cooldownMs>0){let r=e.nowMs-t;if(r<e.cooldownMs)return{fire:!1,skipReason:"cooldown",lastFiredAtMs:t,cooldownRemainingMs:e.cooldownMs-r}}let n=yP(e.briefsDir);return n>0?{fire:!1,skipReason:"briefs_pending",pendingBriefCount:n,...t!==null?{lastFiredAtMs:t}:{}}:{fire:!0,...t!==null?{lastFiredAtMs:t}:{}}}var TP=vP(SP),js=class{registry=new Map;options;defaultCooldownMs;briefsDir;now;constructor(t={}){this.options=t,this.defaultCooldownMs=t.cooldownMs??Tg,this.briefsDir=t.briefsDir??xg(),this.now=t.now??Date.now,this.ensureTelemetrySink()}register(t){if(Sg(t),this.registry.has(t.taskId))throw new Error(`task ${t.taskId} is already registered`);let n;(t.trigger==="cron"||t.trigger==="both")&&(n=Cg.schedule(t.cronExpression,()=>{this.runOnce(t,"cron").catch(()=>{})},{name:t.taskId})),this.registry.set(t.taskId,{task:t,cronTask:n})}unregister(t){let n=this.registry.get(t);n&&(n.cronTask&&(Promise.resolve(n.cronTask.stop()).catch(()=>{}),Promise.resolve(n.cronTask.destroy()).catch(()=>{})),this.registry.delete(t))}list(){return Array.from(this.registry.values()).map(t=>t.task)}async tick(t){let n=this.registry.get(t);if(!n)throw new Error(`task ${t} is not registered`);return this.runOnce(n.task,"cron")}async fireOnStart(){let t=Array.from(this.registry.values()).map(r=>r.task).filter(r=>r.trigger==="sessionstart"||r.trigger==="both"),n=[];for(let r of t){let o=r.debounceMs??this.defaultCooldownMs,s=Eg({taskId:r.taskId,cooldownMs:o,nowMs:this.now(),telemetryPath:this.telemetryPath(),briefsDir:this.briefsDir});s.fire?n.push(await this.runOnce(r,"sessionstart")):n.push(this.recordSkip(r,s))}return n}async stop(){for(let t of Array.from(this.registry.keys()))this.unregister(t)}async runOnce(t,n){if(t.command==="__BUILTIN_WORKTREE_PRUNE__")return this.runBuiltinWorktreePrune(t,n);let r=new Date(this.now()),o=this.now(),s={taskId:t.taskId,command:$o(t.command),trigger:n,...t.cronExpression!==void 0?{cronExpression:t.cronExpression}:{},triggeredAt:r.toISOString()},a=null,i=null;try{let l=this.spawnSession();a=l.session,i=l.memoryStore;let c=await a.sendMessage(t.command),u={...s,durationMs:this.now()-o,status:"success",responseExcerpt:$o(c.content.slice(0,280))};return this.writeTelemetry(u),u}catch(l){let c=l instanceof Error?l.message:String(l),u={...s,durationMs:this.now()-o,status:"error",errorMessage:c};return this.writeTelemetry(u),u}finally{if(a)try{await a.close()}catch{}i?.close()}}recordSkip(t,n){let r=new Date(this.now()),o={taskId:t.taskId,command:t.command,trigger:"sessionstart",...t.cronExpression!==void 0?{cronExpression:t.cronExpression}:{},triggeredAt:r.toISOString(),durationMs:0,status:"skipped",...n.skipReason!==void 0?{skipReason:n.skipReason}:{}};return this.writeTelemetry(o),o}async runBuiltinWorktreePrune(t,n){let r=new Date(this.now()),o=this.now(),s={taskId:t.taskId,command:t.command,trigger:n,...t.cronExpression!==void 0?{cronExpression:t.cronExpression}:{},triggeredAt:r.toISOString()};try{let a=process.env.AFK_WORKTREE_SWEEP_ROOT??process.cwd(),i=parseInt(process.env.AFK_WORKTREE_MAX_AGE_CLEAN??"",10)||14,l=parseInt(process.env.AFK_WORKTREE_MAX_AGE_DIRTY??"",10)||30,c=await Mr({execFile:TP,repoRoot:a,dryRun:!1,maxAgeDaysClean:i,maxAgeDaysDirty:l,scope:"all",telemetryPath:this.telemetryPath()}),u=new Set(["empty","stale-clean","orphaned-dir","orphaned-registration"]),d=c.dryRun?`\u{1F50D} worktree-prune (dry-run): would remove ${c.candidates.filter(f=>u.has(f.verdict)).length} worktree(s)`:`\u2702\uFE0F worktree-prune: removed ${c.removed.length}, warned ${c.warnings.length}`,m={...s,durationMs:this.now()-o,status:"success",responseExcerpt:d};return this.writeTelemetry(m),m}catch(a){let i={...s,durationMs:this.now()-o,status:"error",errorMessage:a instanceof Error?a.message:String(a)};return this.writeTelemetry(i),i}}spawnSession(){let{registry:t,memoryStore:n}=Mn(void 0,"daemon"),r={model:"sonnet",permissionMode:"bypassPermissions",hookRegistry:t,...this.options.sessionConfig};return{session:this.options.sessionFactory?this.options.sessionFactory(r):new Ae(en(r)),memoryStore:n}}telemetryPath(){return this.options.telemetryPath??yn()}ensureTelemetrySink(){try{bP(wP(this.telemetryPath()),{recursive:!0})}catch{}}writeTelemetry(t){try{kP(this.telemetryPath(),`${JSON.stringify(t)}
|
|
1993
|
+
`,"utf-8"),this.fireOnTaskComplete(t)}catch(n){let r=n instanceof Error?n.message:String(n);console.error(`[daemon] telemetry write failed: ${r}`)}}fireOnTaskComplete(t){let n=this.options.onTaskComplete;if(n)try{let r=n(t);r instanceof Promise&&r.catch(o=>{let s=o instanceof Error?o.message:String(o);console.error(`[daemon] onTaskComplete callback failed: ${s}`)})}catch(r){let o=r instanceof Error?r.message:String(r);console.error(`[daemon] onTaskComplete callback failed: ${o}`)}}};var EP=7777;async function Pg(e={}){let t=new js({...e.sessionConfig!==void 0?{sessionConfig:e.sessionConfig}:{},...e.telemetryPath!==void 0?{telemetryPath:e.telemetryPath}:{},...e.sessionFactory!==void 0?{sessionFactory:e.sessionFactory}:{},...e.cooldownMs!==void 0?{cooldownMs:e.cooldownMs}:{},...e.briefsDir!==void 0?{briefsDir:e.briefsDir}:{},...e.now!==void 0?{now:e.now}:{},...e.onTaskComplete!==void 0?{onTaskComplete:e.onTaskComplete}:{}});for(let o of e.tasks??[])t.register(o);let n=xP((o,s)=>CP(o,s,t));return{port:await PP(n,e.port??EP),scheduler:t,registerTask(o){t.register(o)},unregisterTask(o){t.unregister(o)},tickOnce(o){return t.tick(o)},fireOnStart(){return t.fireOnStart()},async stop(){await t.stop(),await AP(n)}}}function CP(e,t,n){let r=e.url??"/";if(e.method==="GET"&&r==="/health"){let o=JSON.stringify({status:"ok",tasks:n.list().length});t.writeHead(200,{"Content-Type":"application/json"}),t.end(o);return}if(e.method==="GET"&&r==="/tasks"){t.writeHead(200,{"Content-Type":"application/json"}),t.end(JSON.stringify(n.list()));return}t.writeHead(404,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"not found"}))}function PP(e,t){return new Promise((n,r)=>{e.once("error",r),e.listen(t,()=>{e.removeListener("error",r);let o=e.address();n(typeof o=="object"&&o?o.port:t)})})}function AP(e){return new Promise((t,n)=>{e.close(r=>{r?n(r):t()})})}Mo();function Ag(e,t){let n=e??t;if(n===void 0||n==="")return;let r=Number(n);if(!Number.isFinite(r)||!Number.isInteger(r)||r<=0)throw new Error(`Invalid timeout-ms: '${n}' \u2014 must be a positive integer (milliseconds).`);return r}function _g(e,t){let n=e??t;if(n===void 0||n==="")return;let r=Number(n);if(!Number.isFinite(r)||!Number.isInteger(r)||r<0)throw new Error(`Invalid sessionstart-cooldown-ms: '${n}' \u2014 must be a non-negative integer (milliseconds).`);return r}function Rg(e){if(e===void 0||e==="")return"cron";if(e==="cron"||e==="sessionstart"||e==="both")return e;throw new Error(`Invalid trigger: '${e}' \u2014 must be one of cron | sessionstart | both.`)}var Ja="/forge-friction --auto",Xa="default";function qn(e){if(e!==void 0&&e.trim()!=="")return e}function Ig(e,t,n){return qn(e)??qn(t)??qn(n)??Ja}function Mg(e,t,n){return qn(e)??qn(t)??qn(n)??Xa}function IP(e){let t=e.status==="success"?"\u2705":e.status==="skipped"?"\u23ED\uFE0F":"\u274C",n=(e.durationMs/1e3).toFixed(1),r=[`${t} daemon task: ${e.taskId} (${e.status})`,`trigger=${e.trigger} duration=${n}s`];return e.skipReason&&r.push(`skipReason=${e.skipReason}`),e.errorMessage&&r.push(`error: ${e.errorMessage.slice(0,400)}`),e.responseExcerpt&&r.push("",e.responseExcerpt.slice(0,600)),r.join(`
|
|
1994
|
+
`)}function $g(e){e.command("daemon").description("Run agent-afk as a daemon that fires scheduled tasks (e.g. /forge-friction --auto)").option("-p, --port <number>","Control HTTP port","7777").option("-t, --task <command>",`Command to fire on each tick (default: ${Ja})`).option("-c, --cron <expression>",'Cron expression (e.g. "0 */6 * * *"). Required when --trigger includes cron.').option("-i, --task-id <id>",`Task identifier (default: ${Xa})`).option("--once","Fire one tick and exit (for testing)",!1).option("--timeout-ms <ms>","Per-tick session timeout in ms. Overrides AFK_TIMEOUT_MS. Defaults to the session default (120000).").option("--thinking <mode>","Thinking mode: 'adaptive' | 'disabled' | 'enabled:<N>'").option("--effort <level>","Effort level: low|medium|high|xhigh|max").option("--trigger <mode>","Trigger mode: cron | sessionstart | both. Defaults to cron.").option("--sessionstart-cooldown-ms <ms>","Cooldown between Phase 6 sessionstart fires. Overrides AFK_SESSIONSTART_COOLDOWN_MS. Defaults to 6h.").option("--briefs-dir <path>","Override directory scanned for pending briefs (defaults to ~/.afk/agent-framework/briefs).").option("--dump-prompt [path]",'Dump resolved SDK prompt+options+provenance to file (default: ~/.afk/logs/prompt-dump-<ISO>.json) or "stderr"').action(async t=>{let n=parseInt(t.port,10);(Number.isNaN(n)||n<=0)&&z(new Error(`Invalid port: ${t.port}`));let r=je(),o=Ig(t.task,process.env.AFK_DAEMON_TASK,r.daemon?.task),s=Mg(t.taskId,process.env.AFK_DAEMON_TASK_ID,r.daemon?.taskId),a,i,l;try{a=Ag(t.timeoutMs,process.env.AFK_TIMEOUT_MS),i=_g(t.sessionstartCooldownMs,process.env.AFK_SESSIONSTART_COOLDOWN_MS),l=Rg(t.trigger)}catch(T){z(T)}(l==="cron"||l==="both")&&!t.cron&&z(new Error(`--cron is required when --trigger is '${l}'.`));let c,u;try{c=Mt(t.thinking)??En(),u=$t(t.effort)??Cn()}catch(T){z(T)}let d={taskId:s,command:o,trigger:l,...t.cron!==void 0?{cronExpression:t.cron}:{}},m=r.daemon?.worktreePrune,f=process.env.AFK_WORKTREE_PRUNE_DISABLE==="1",g=m?.cron??"0 4 * * *",y={taskId:"worktree-prune",command:"__BUILTIN_WORKTREE_PRUNE__",trigger:"cron",cronExpression:g},S=[d];if(!f&&m?.enabled!==!1&&S.push(y),t.dumpPrompt!==void 0&&t.dumpPrompt!==!1){let T=t.dumpPrompt===!0?_P.join(RP.homedir(),".afk","logs",`prompt-dump-${new Date().toISOString().replace(/[:.]/g,"-")}.json`):t.dumpPrompt;process.env.AFK_DUMP_PROMPT=T}let h=0,b=6e4,w=(T,A)=>{let x=Date.now();if(x-h<b)return;h=x;let v=A instanceof Error?`${A.name}: ${A.message}`:String(A);Io(`\u{1F6D1} agent-afk daemon ${T}
|
|
1995
|
+
${v.slice(0,500)}`).catch(E=>{console.error("[daemon] crash notification push failed:",E instanceof Error?E.message:String(E))})};process.on("uncaughtException",T=>{w("uncaughtException",T),process.exit(1)}),process.on("unhandledRejection",T=>{w("unhandledRejection",T),process.exit(1)});let C=process.env.AFK_DAEMON_CWD;try{let T=await Pg({port:n,sessionConfig:{model:ve(),...J()!==void 0?{apiKey:J()}:{},...a!==void 0?{timeoutMs:a}:{},...c!==void 0?{thinking:c}:{},...u!==void 0?{effort:u}:{},...C!==void 0&&C.length>0?{cwd:C}:{}},...i!==void 0?{cooldownMs:i}:{},...t.briefsDir!==void 0?{briefsDir:t.briefsDir}:{},tasks:S,onTaskComplete:x=>{Io(IP(x)).catch(()=>{})}});if(t.once){console.log(p.info(`\u25B6 Firing task '${s}' once...`));let x=await T.tickOnce(s);console.log(JSON.stringify(x,null,2)),await T.stop(),process.exit(x.status==="success"?0:1)}if(l==="sessionstart"||l==="both"){let x=await T.fireOnStart();for(let v of x){let E=v.status==="success"?"\u2714":v.status==="skipped"?"\u23ED":"\u2717";console.log(p.info(`${E} sessionstart: ${JSON.stringify(v)}`))}}console.log(p.success(`\u2714 Daemon listening on http://localhost:${T.port}`)),console.log(p.dim(` task='${s}' command='${o}' trigger='${l}'${t.cron?` cron='${t.cron}'`:""}`)),S.length>1&&console.log(p.meta(` + built-in: worktree-prune (cron: ${g})`)),console.log(p.dim(" Press Ctrl+C to stop."));let A=async()=>{console.log(p.dim(`
|
|
1996
|
+
\xB7 Shutting down daemon...`)),await T.stop(),process.exit(0)};process.on("SIGINT",A),process.on("SIGTERM",A)}catch(T){z(T)}})}import Yn from"chalk";import{existsSync as MP,readFileSync as $P,writeFileSync as OP,mkdirSync as DP}from"fs";import{dirname as FP}from"path";import{createInterface as LP}from"readline";import Og from"chalk";function zt(e,t,n,r=[]){DP(FP(e),{recursive:!0});let o="";MP(e)&&(o=$P(e,"utf-8"));for(let i of r){let l=new RegExp(`^${i}=.*$
|
|
1997
1997
|
?`,"m");o=o.replace(l,"")}let s=`${t}=${n}`,a=new RegExp(`^${t}=.*$`,"m");a.test(o)?o=o.replace(a,s):(o&&!o.endsWith(`
|
|
1998
1998
|
`)&&(o+=`
|
|
1999
1999
|
`),o+=s+`
|
|
2000
|
-
`)
|
|
2001
|
-
Installed plugins:`));for(let r of n){let o=e.plugins[r];if(!o)continue;let s=o.enabled?Z.green("enabled "):Z.yellow("disabled"),a=o.ref?Z.blue(o.ref):Z.gray("(local)"),i=Z.gray(o.source);t.log(` ${Z.bold(r.padEnd(30))} ${s} ${a.padEnd(12)} ${i}`)}t.log("")}function jg(e){switch(e.status){case"updated":return`${Z.green("\u2713")} ${Z.bold(e.name)}: ${e.fromRef??"(none)"} \u2192 ${e.toRef}`;case"up-to-date":return`${Z.gray("\xB7")} ${Z.bold(e.name)}: up-to-date (${e.ref})`;case"skipped-local":return`${Z.gray("\xB7")} ${Z.bold(e.name)}: skipped (local source)`;case"missing-dir":return`${Z.yellow("!")} ${Z.bold(e.name)}: plugin dir missing (${e.dir})`}}function
|
|
2000
|
+
`),OP(e,o,{mode:384})}function Dg(){let e=LP({input:process.stdin,output:process.stdout});return new Promise(t=>{e.question("Anthropic API key or OAuth token: ",n=>{e.close(),t(n.trim())})})}async function Bs(e){let t=e??await Dg();t||(console.error(Og.red("No token provided. Nothing saved.")),process.exit(1));let n=Ce(),r,o;t.startsWith("sk-ant-oat")?(r="CLAUDE_CODE_OAUTH_TOKEN",o=["ANTHROPIC_API_KEY"]):(r="ANTHROPIC_API_KEY",o=["CLAUDE_CODE_OAUTH_TOKEN"]),zt(n,r,t,o),console.log(Og.green(`\u2713 Saved ${r} to ${n}`)),console.log(p.meta("Restart any running afk daemon to pick up the new token."))}function Fg(e){e.command("login [token]").description("Save an Anthropic API key or OAuth token for afk to use").action(async t=>{if(Be(ve())==="openai-codex"){console.log(Yn.yellow("`afk login` is Anthropic-only.")),console.log(""),console.log("For Codex-backed models (gpt-*, o1*, o3*, o4*, codex-*), authenticate with one of:"),console.log(Yn.cyan(" codex login")),console.log(Yn.cyan(" codex login --device-auth")),console.log("or export an API key before running afk:"),console.log(Yn.cyan(" export OPENAI_API_KEY=sk-proj-...")),console.log(Yn.cyan(" # or: export CODEX_API_KEY=...")),console.log(""),console.log(Yn.gray("To save an Anthropic key for Claude models instead, re-run with AFK_MODEL=sonnet (or similar) first."));return}await Bs(t)})}import Z from"chalk";import Ws from"ora";import{existsSync as NP}from"fs";import{join as UP}from"path";async function Za(e,t={},n={}){let r=n.pluginsDir??we(),o=n.indexPath??Y(),s=n.now??(()=>new Date),a=n.gitRunner?{runner:n.gitRunner}:{},l=ne(o).plugins[e];if(!l)throw new Error(`plugin "${e}" is not installed`);let c=UP(r,e);if(!NP(c))return{name:e,status:"missing-dir",dir:c};if(l.sourceType==="local")return{name:e,status:"skipped-local"};await ks(c,a);let u;if(t.ref)u=t.ref;else{let g=await Wt(c,a);u=Kt(g)??l.ref??await it(c,a)}if(u===l.ref){let g=await st(c,a);return{name:e,status:"up-to-date",ref:u,commit:g}}await Ht(c,u,a);let d=await st(c,a),m=s().toISOString(),f={...l,ref:u,commit:d,updatedAt:m};return Pt(e,f,o),{name:e,status:"updated",fromRef:l.ref,toRef:u,commit:d}}async function Lg(e={}){let t=e.indexPath??Y(),n=ne(t),r=[];for(let o of Object.keys(n.plugins))try{r.push(await Za(o,{},e))}catch(s){let a=s instanceof Error?s.message:String(s);r.push({name:o,status:"missing-dir",dir:a})}return r}import{existsSync as jP,lstatSync as BP,rmSync as WP,unlinkSync as HP}from"fs";import{join as KP}from"path";function Ng(e,t={}){let n=t.pluginsDir??we(),r=t.indexPath??Y(),o=KP(n,e),s=!1;GP(o)?(HP(o),s=!0):jP(o)&&(WP(o,{recursive:!0,force:!0}),s=!0);let a=ne(r),i=Object.prototype.hasOwnProperty.call(a.plugins,e);return i&&_c(e,r),{name:e,removedDir:s,removedIndexEntry:i}}function GP(e){try{return BP(e).isSymbolicLink()}catch{return!1}}function Ug(e,t={}){let n=t.logger??console,r=t.pluginsDir??we(),o=t.indexPath??Y(),s={...t,pluginsDir:r,indexPath:o},a=e.command("plugin").description("Manage AFK plugins (install / update / list / remove / enable / disable)");a.command("install <source> [name]").description("Install a plugin from a git URL, owner/repo shorthand, local path, or <marketplace>:<plugin>").option("-r, --ref <ref>","Install a specific tag, branch, or SHA").option("-f, --force","Replace an existing plugin with the same name").action(async(i,l,c)=>{let u;try{u=Wn(i)}catch(m){Ws(`Installing ${i}\u2026`).start().fail("Failed"),z(m)}if(u.type==="marketplace-ref"){let m=Ws(`Installing ${u.marketplace}:${u.plugin}\u2026`).start();try{let f=await Gn(u.marketplace,u.plugin,{...c.ref?{ref:c.ref}:{},...c.force?{force:!0}:{}},s);m.succeed(Z.green(`Installed ${Z.bold(f.key)}`)+Z.gray(` at ${f.dir}`))}catch(f){m.fail("Failed"),z(f)}return}let d=Ws(`Installing ${i}\u2026`).start();try{let m={...l?{name:l}:{},...c.ref?{ref:c.ref}:{},...c.force?{force:!0}:{}},f=await vs(i,m,s);d.succeed(Z.green(`Installed ${Z.bold(f.name)}`)+Z.gray(` at ${f.dir}${f.entry.ref?` (ref: ${f.entry.ref})`:""}`))}catch(m){d.fail("Failed"),z(m)}}),a.command("update [name]").description("Update one plugin, or all if no name is given").option("-r, --ref <ref>","Pin to a specific ref instead of the latest tag").action(async(i,l)=>{try{if(i){let c=Ws(`Updating ${i}\u2026`).start(),u=await Za(i,l.ref?{ref:l.ref}:{},s);qP(u,c)}else{n.log(Z.cyan("Updating all plugins\u2026"));let c=await Lg(s);if(c.length===0){n.log(Z.gray(" (nothing installed)"));return}for(let u of c)n.log(" "+jg(u))}}catch(c){z(c)}}),a.command("list").description("List installed plugins with their source, version, and enabled state").option("-f, --format <format>","Output format (text|json)","text").action(i=>{let l=ne(o);if(i.format==="json"){let c=Object.entries(l.plugins).map(([u,d])=>({name:u,enabled:d.enabled,...d.ref?{ref:d.ref}:{},source:d.source}));n.log(JSON.stringify({plugins:c},null,2))}else zP(l,n)}),a.command("remove <name>").description("Remove a plugin (directory + index entry)").action(i=>{let l=Ng(i,{pluginsDir:r,indexPath:o});if(!l.removedDir&&!l.removedIndexEntry){n.log(Z.gray(`No plugin named "${i}" to remove.`));return}let c=[l.removedDir?"directory":null,l.removedIndexEntry?"index entry":null].filter(Boolean);n.log(Z.green(`Removed ${i}: ${c.join(" + ")}`))}),a.command("enable <name>").description("Re-enable a previously disabled plugin").action(i=>{try{fi(i,!0,o),n.log(Z.green(`Enabled ${i}`))}catch(l){z(l)}}),a.command("disable <name>").description("Keep the plugin on disk but skip it from SDK init").action(i=>{try{fi(i,!1,o),n.log(Z.yellow(`Disabled ${i} (dir preserved at ${r}/${i})`))}catch(l){z(l)}})}function zP(e,t){let n=Object.keys(e.plugins).sort();if(n.length===0){t.log(Z.gray("No plugins installed.")),t.log(Z.gray(" Try: afk plugin install anthropics/claude-plugins-official"));return}t.log(Z.cyan.bold(`
|
|
2001
|
+
Installed plugins:`));for(let r of n){let o=e.plugins[r];if(!o)continue;let s=o.enabled?Z.green("enabled "):Z.yellow("disabled"),a=o.ref?Z.blue(o.ref):Z.gray("(local)"),i=Z.gray(o.source);t.log(` ${Z.bold(r.padEnd(30))} ${s} ${a.padEnd(12)} ${i}`)}t.log("")}function jg(e){switch(e.status){case"updated":return`${Z.green("\u2713")} ${Z.bold(e.name)}: ${e.fromRef??"(none)"} \u2192 ${e.toRef}`;case"up-to-date":return`${Z.gray("\xB7")} ${Z.bold(e.name)}: up-to-date (${e.ref})`;case"skipped-local":return`${Z.gray("\xB7")} ${Z.bold(e.name)}: skipped (local source)`;case"missing-dir":return`${Z.yellow("!")} ${Z.bold(e.name)}: plugin dir missing (${e.dir})`}}function qP(e,t){let n=jg(e);e.status==="updated"?t.succeed(n):e.status==="up-to-date"||e.status==="skipped-local"?t.info(n):t.warn(n)}import K from"chalk";import Qa from"ora";function Bg(e,t={}){let n=t.logger??console,r=t.cacheDir??ct(),o=t.indexPath??Y(),s={...t,cacheDir:r,indexPath:o},a=e.command("marketplace").description("Manage AFK plugin marketplaces (install / list / plugins / install-plugin / remove / update)");a.command("install <source> [name]").description("Clone or symlink a marketplace into the local plugin cache").option("-r, --ref <ref>","Install a specific tag, branch, or SHA").option("-f, --force","Replace an existing marketplace with the same name").action(async(i,l,c)=>{let u=Qa(`Installing marketplace ${i}\u2026`).start();try{let d={...l?{name:l}:{},...c.ref?{ref:c.ref}:{},...c.force?{force:!0}:{}},m=await xs(i,d,s),f=m.entry.ref?` (ref: ${m.entry.ref})`:"";u.succeed(K.green(`Installed marketplace ${K.bold(m.name)}`)+K.gray(`${f} at ${m.dir}`)),n.log(K.gray(` ${m.plugins.length} plugin(s) available \u2014 run \`afk marketplace plugins ${m.name}\` to list.`))}catch(d){u.fail("Failed"),z(d)}}),a.command("list").description("List installed marketplaces with their source and ref").option("-f, --format <format>","Output format (text|json)","text").action(i=>{let l=ne(o),c=Object.entries(l.marketplaces);if(i.format==="json"){n.log(JSON.stringify({marketplaces:c.map(([u,d])=>({name:u,source:d.source,sourceType:d.sourceType,...d.ref?{ref:d.ref}:{}}))},null,2));return}if(c.length===0){n.log(K.gray("No marketplaces installed.")),n.log(K.gray(" Try: afk marketplace install griffinwork40/awa-private"));return}n.log(K.cyan.bold(`
|
|
2002
2002
|
Installed marketplaces:`));for(let[u,d]of c.sort()){let m=d.ref?K.blue(d.ref):K.gray("(local)"),f=K.gray(d.source);n.log(` ${K.bold(u.padEnd(30))} ${m.padEnd(12)} ${f}`)}n.log("")}),a.command("plugins <name>").description("List plugins inside a marketplace, with [installed] / [available] markers").option("-f, --format <format>","Output format (text|json)","text").action((i,l)=>{try{let c=Ps(i,s);if(l.format==="json"){n.log(JSON.stringify({marketplace:i,plugins:c},null,2));return}if(c.length===0){n.log(K.gray(`Marketplace "${i}" lists no plugins.`));return}n.log(K.cyan.bold(`
|
|
2003
2003
|
Plugins in ${i}:`)),c.forEach((u,d)=>{let m=u.installed?K.green("[\u2713]"):K.gray("[ ]"),f=u.description?K.gray(` \u2014 ${u.description}`):"";n.log(` ${m} ${K.bold((d+1).toString().padStart(2))}. ${K.bold(u.name)}${f}`)}),n.log(K.gray(`
|
|
2004
|
-
Install one: afk plugin install ${i}:<plugin>`))}catch(c){z(c)}}),a.command("install-plugin <marketplace> <plugin>").description("Install a single plugin from a marketplace").option("-r, --ref <ref>","For git-sourced plugins, pin to a specific tag/branch/SHA").option("-f, --force","Replace an existing plugin with the same key").action(async(i,l,c)=>{let u=Qa(`Installing ${i}:${l}\u2026`).start();try{let d=await Gn(i,l,{...c.ref?{ref:c.ref}:{},...c.force?{force:!0}:{}},s);u.succeed(K.green(`Installed ${K.bold(d.key)}`)+K.gray(` at ${d.dir}`))}catch(d){u.fail("Failed"),z(d)}}),a.command("remove <name>").description("Remove a marketplace and cascade-delete its installed plugins").action(i=>{let l=Es(i,{cacheDir:r,indexPath:o});if(!l.removedDir&&!l.removedIndexEntry&&l.removedPluginEntries.length===0){n.log(K.gray(`No marketplace named "${i}" to remove.`));return}let c=[l.removedDir?"directory":null,l.removedIndexEntry?"index entry":null,l.removedPluginEntries.length>0?`${l.removedPluginEntries.length} plugin entry`:null].filter(Boolean);if(n.log(K.green(`Removed ${i}: ${c.join(" + ")}`)),l.removedPluginEntries.length>0)for(let u of l.removedPluginEntries)n.log(K.gray(` - ${u}`))}),a.command("update [name]").description("Update one marketplace, or all if no name is given").option("-r, --ref <ref>","Pin to a specific ref instead of the latest tag").action(async(i,l)=>{try{if(i){let c=Qa(`Updating ${i}\u2026`).start(),u=await Rr(i,l.ref?{ref:l.ref}:{},s);
|
|
2005
|
-
Summary: ${o.passed} passed, ${o.warned} warned, ${o.failed} failed`)),process.exit(o.failed>0?1:0)})}var
|
|
2004
|
+
Install one: afk plugin install ${i}:<plugin>`))}catch(c){z(c)}}),a.command("install-plugin <marketplace> <plugin>").description("Install a single plugin from a marketplace").option("-r, --ref <ref>","For git-sourced plugins, pin to a specific tag/branch/SHA").option("-f, --force","Replace an existing plugin with the same key").action(async(i,l,c)=>{let u=Qa(`Installing ${i}:${l}\u2026`).start();try{let d=await Gn(i,l,{...c.ref?{ref:c.ref}:{},...c.force?{force:!0}:{}},s);u.succeed(K.green(`Installed ${K.bold(d.key)}`)+K.gray(` at ${d.dir}`))}catch(d){u.fail("Failed"),z(d)}}),a.command("remove <name>").description("Remove a marketplace and cascade-delete its installed plugins").action(i=>{let l=Es(i,{cacheDir:r,indexPath:o});if(!l.removedDir&&!l.removedIndexEntry&&l.removedPluginEntries.length===0){n.log(K.gray(`No marketplace named "${i}" to remove.`));return}let c=[l.removedDir?"directory":null,l.removedIndexEntry?"index entry":null,l.removedPluginEntries.length>0?`${l.removedPluginEntries.length} plugin entry`:null].filter(Boolean);if(n.log(K.green(`Removed ${i}: ${c.join(" + ")}`)),l.removedPluginEntries.length>0)for(let u of l.removedPluginEntries)n.log(K.gray(` - ${u}`))}),a.command("update [name]").description("Update one marketplace, or all if no name is given").option("-r, --ref <ref>","Pin to a specific ref instead of the latest tag").action(async(i,l)=>{try{if(i){let c=Qa(`Updating ${i}\u2026`).start(),u=await Rr(i,l.ref?{ref:l.ref}:{},s);YP(u,c)}else{n.log(K.cyan("Updating all marketplaces\u2026"));let c=await hf(s);if(c.length===0){n.log(K.gray(" (no marketplaces installed)"));return}for(let u of c)n.log(" "+Wg(u))}}catch(c){z(c)}})}function Wg(e){switch(e.status){case"updated":{let t=e.addedPlugins.length>0?` +${e.addedPlugins.join(", ")}`:"",n=e.removedPlugins.length>0?` -${e.removedPlugins.join(", ")}`:"";return`${K.green("\u2713")} ${K.bold(e.name)}: ${e.fromRef??"(none)"} \u2192 ${e.toRef}${K.gray(t+n)}`}case"up-to-date":return`${K.gray("\xB7")} ${K.bold(e.name)}: up-to-date (${e.ref})`;case"skipped-local":return`${K.gray("\xB7")} ${K.bold(e.name)}: skipped (local source)`;case"missing-dir":return`${K.yellow("!")} ${K.bold(e.name)}: marketplace dir missing (${e.dir})`}}function YP(e,t){let n=Wg(e);e.status==="updated"?t.succeed(n):e.status==="up-to-date"||e.status==="skipped-local"?t.info(n):t.warn(n)}import{access as VP,constants as JP,mkdir as XP,readFile as ZP}from"fs/promises";import{execSync as QP}from"child_process";async function eA(){return J()?{name:"Anthropic API Key",state:"pass",detail:"ANTHROPIC_API_KEY set"}:{name:"Anthropic API Key",state:"fail",fix:"Set ANTHROPIC_API_KEY or run `afk login`"}}async function tA(){return lr()?{name:"Codex/OpenAI API Key",state:"pass",detail:"OPENAI_API_KEY or CODEX_API_KEY set"}:{name:"Codex/OpenAI API Key",state:"warn",fix:"Set OPENAI_API_KEY or CODEX_API_KEY to use Codex models"}}async function nA(){try{let t=`${QP("npm config get prefix",{timeout:2e3,encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim().replace(/\/$/,"")}/bin`;return(process.env.PATH??"").split(":").map(r=>r.replace(/\/$/,"")).includes(t)?{name:"npm bin on PATH",state:"pass",detail:t}:{name:"npm bin on PATH",state:"fail",detail:t,fix:`Add ${t} to PATH: echo 'export PATH="${t}:$PATH"' >> ~/.zshrc`}}catch{return{name:"npm bin on PATH",state:"warn",detail:"could not query npm prefix"}}}async function el(e,t){let n=t();try{return await VP(n,JP.W_OK),{name:e,state:"pass",detail:n}}catch{try{return await XP(n,{recursive:!0}),{name:e,state:"pass",detail:`${n} (created)`}}catch{return{name:e,state:"fail",detail:n,fix:`Unable to create or write to ${n}`}}}}async function rA(){let e=bn();try{let t=await ZP(e,"utf-8");return JSON.parse(t),{name:"Config File",state:"pass",detail:`${e} (valid JSON)`}}catch(t){return t.code==="ENOENT"?{name:"Config File",state:"pass",detail:"no config file (using defaults)"}:{name:"Config File",state:"fail",detail:e,fix:`Unable to parse config file: ${t instanceof Error?t.message:"unknown error"}`}}}async function oA(){let e=process.env.AFK_TELEGRAM_BOT_TOKEN;if(!e)return null;try{let t=new AbortController,n=setTimeout(()=>t.abort(),5e3),r=await fetch(`https://api.telegram.org/bot${e}/getMe`,{signal:t.signal});if(clearTimeout(n),r.ok){let s=(await r.json()).result?.username;return{name:"Telegram Bot",state:"pass",detail:s?`@${s}`:"connected"}}return{name:"Telegram Bot",state:"fail",fix:`Telegram API returned ${r.status}. Check AFK_TELEGRAM_BOT_TOKEN.`}}catch(t){return t.name==="AbortError"?{name:"Telegram Bot",state:"warn",detail:"connection timeout"}:{name:"Telegram Bot",state:"warn",detail:`network error: ${t instanceof Error?t.message:"unknown"}`}}}function Hg(e){e.command("doctor").description("Check system health and configuration").option("-f, --format <format>","Output format (text|json)","text").action(async t=>{let n=[];n.push(await eA()),n.push(await tA()),n.push(await nA()),n.push(await el("Config Directory",Br)),n.push(await el("State Directory",qe)),n.push(await el("Logs Directory",Hr)),n.push(await rA());let r=await oA();r!==null&&n.push(r);let o={passed:n.filter(s=>s.state==="pass").length,warned:n.filter(s=>s.state==="warn").length,failed:n.filter(s=>s.state==="fail").length};t.format==="json"?console.log(JSON.stringify({checks:n,summary:o},null,2)):(n.forEach(s=>{let a;s.state==="pass"?a=p.success("\u2713"):s.state==="warn"?a=p.warning("\u26A0"):a=p.error("\u2717");let i=`${a} ${s.name}`;s.detail&&(i+=` \u2014 ${s.detail}`),console.log(i),s.state==="fail"&&s.fix&&console.log(` Fix: ${s.fix}`)}),console.log(`
|
|
2005
|
+
Summary: ${o.passed} passed, ${o.warned} warned, ${o.failed} failed`)),process.exit(o.failed>0?1:0)})}var sA=["chat","interactive","status","config","daemon","login","plugin","doctor","completion"],iA=["install","update","list","remove","enable","disable"],tl=["sonnet","opus","haiku"],nl=["json","text"],rl=["cron","sessionstart","both"];function Xe(e){return e.join(" ")}function aA(){let e=Xe(tl),t=Xe(nl),n=Xe(rl);return`#compdef afk
|
|
2006
2006
|
|
|
2007
2007
|
_afk() {
|
|
2008
2008
|
local -a commands
|
|
@@ -2049,7 +2049,7 @@ _afk() {
|
|
|
2049
2049
|
esac
|
|
2050
2050
|
}
|
|
2051
2051
|
|
|
2052
|
-
compdef _afk afk`}function
|
|
2052
|
+
compdef _afk afk`}function lA(){let e=Xe(sA),t=Xe(iA),n=Xe(tl),r=Xe(nl),o=Xe(rl);return`_afk_complete() {
|
|
2053
2053
|
local cur prev
|
|
2054
2054
|
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
2055
2055
|
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
@@ -2076,7 +2076,7 @@ compdef _afk afk`}function aA(){let e=Xe(oA),t=Xe(sA),n=Xe(tl),r=Xe(nl),o=Xe(rl)
|
|
|
2076
2076
|
esac
|
|
2077
2077
|
}
|
|
2078
2078
|
|
|
2079
|
-
complete -F _afk_complete afk`}function
|
|
2079
|
+
complete -F _afk_complete afk`}function cA(){let e=Xe(tl),t=Xe(nl),n=Xe(rl);return`complete -c afk -f
|
|
2080
2080
|
# afk subcommands
|
|
2081
2081
|
complete -c afk -n '__fish_use_subcommand' -a 'chat' -d 'Send a single chat message'
|
|
2082
2082
|
complete -c afk -n '__fish_use_subcommand' -a 'interactive' -d 'Start an interactive REPL'
|
|
@@ -2099,32 +2099,32 @@ complete -c afk -n '__fish_seen_subcommand_from plugin' -a 'disable' -d 'Disable
|
|
|
2099
2099
|
# flags: --model, --format, --trigger
|
|
2100
2100
|
complete -c afk -l model -s m -x -a '${e}' -d 'Model to use'
|
|
2101
2101
|
complete -c afk -l format -s f -x -a '${t}' -d 'Output format'
|
|
2102
|
-
complete -c afk -l trigger -x -a '${n}' -d 'Trigger type'`}function Kg(e){e.command("completion <shell>").description("Emit shell completion script (zsh|bash|fish)").action(t=>{let n=["zsh","bash","fish"];if(!n.includes(t)){e.error(`unknown shell: ${t}. Choose from: ${n.join(", ")}`);return}let r="";switch(t){case"zsh":r=
|
|
2103
|
-
`);return r.length>0&&r[r.length-1]===""&&r.pop(),r.slice(-t)}catch{return[]}}function
|
|
2104
|
-
`)){let o=r.trim();if(!o||o.startsWith("#"))continue;let s=o.indexOf("=");if(s===-1||o.slice(0,s).trim()!==t)continue;let i=o.slice(s+1).trim();return(i.startsWith('"')&&i.endsWith('"')||i.startsWith("'")&&i.endsWith("'"))&&(i=i.slice(1,-1)),i}}async function Jg(e){let t=Vg(e,"TELEGRAM_BOT_TOKEN");if(!t)return{set:!1,valid:!1,reason:"unset"};let n=await ul(t);return n?{set:!0,valid:!0,botId:n.id,...n.username!==void 0?{username:n.username}:{}}:{set:!0,valid:!1,reason:"unauthorized"}}async function Xg(e,t={}){let n=Vg(e,"TELEGRAM_BOT_TOKEN");if(!n)return{found:!1,chats:[],reason:"unset"};let r=t.timeoutSec??60,o=2e3,s=Math.max(1,Math.ceil(r*1e3/o)),a=await Zg(n,{maxAttempts:s,intervalMs:o});return a.length===0?{found:!1,chats:[],reason:"timeout"}:{found:!0,chats:a}}async function ul(e){try{let t=await fetch(`${Yg}/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
|
|
2102
|
+
complete -c afk -l trigger -x -a '${n}' -d 'Trigger type'`}function Kg(e){e.command("completion <shell>").description("Emit shell completion script (zsh|bash|fish)").action(t=>{let n=["zsh","bash","fish"];if(!n.includes(t)){e.error(`unknown shell: ${t}. Choose from: ${n.join(", ")}`);return}let r="";switch(t){case"zsh":r=aA();break;case"bash":r=lA();break;case"fish":r=cA();break}console.log(r)})}import oe from"chalk";import{spawn as TA}from"child_process";import{existsSync as xA,readFileSync as EA}from"fs";import{spawn as dA}from"child_process";import{existsSync as gn,mkdirSync as Gg,readFileSync as Hs,statSync as uA,unlinkSync as Ks,writeFileSync as pA,openSync as zg}from"fs";import{join as $r,dirname as sl}from"path";import{fileURLToPath as mA}from"url";var ol=sl(mA(import.meta.url));function al(){let e=$r(qe(),"telegram");return{pidFile:$r(e,"bot.pid"),logFile:$r(Hr(),"telegram.log")}}function Or(e){if(!gn(e))return null;let t=Hs(e,"utf-8").trim(),n=Number.parseInt(t,10);if(!Number.isFinite(n)||n<=0)return Ks(e),null;try{return process.kill(n,0),n}catch{return Ks(e),null}}function fA(){let e=$r(ol,"..","telegram.js");if(gn(e))return e;let t=$r(ol,"..","telegram.ts");if(gn(t))return t;throw new Error(`Telegram entrypoint not found near ${ol}`)}async function ll(){let{pidFile:e,logFile:t}=al(),n=Or(e);if(n!==null)return{kind:"already-running",pid:n,message:`Bot already running (PID ${n}). Use 'afk telegram stop' first.`};Gg(sl(e),{recursive:!0}),Gg(sl(t),{recursive:!0});let r=fA(),o=zg(t,"a"),s=zg(t,"a"),a;try{a=dA(process.execPath,[r],{detached:!0,stdio:["ignore",o,s],env:process.env})}catch(i){return{kind:"spawn-failed",message:`Failed to spawn bot: ${i.message}`}}return a.pid===void 0?{kind:"spawn-failed",message:"Spawned child has no PID"}:(pA(e,String(a.pid),{mode:420}),a.unref(),await new Promise(i=>setTimeout(i,1500)),Or(e)===null?{kind:"exited-immediately",logTail:il(t,20),message:"Bot exited immediately after launch. Check the log for details."}:{kind:"started",pid:a.pid,logFile:t})}async function cl(){let{pidFile:e}=al(),t=Or(e);if(t===null)return{kind:"not-running"};try{process.kill(t,"SIGTERM")}catch{return gn(e)&&Ks(e),{kind:"stopped",pid:t}}for(let n=0;n<50;n++)if(await new Promise(r=>setTimeout(r,100)),Or(e)===null)return{kind:"stopped",pid:t};try{process.kill(t,"SIGKILL")}catch{}return gn(e)&&Ks(e),{kind:"force-killed",pid:t}}function dl(){let{pidFile:e,logFile:t}=al(),n=Or(e),r={running:n!==null,pidFile:e,logFile:t};if(n===null)return{...r,logTail:il(t,10)};let o=gA(n);return{...r,pid:n,...o,logTail:il(t,10)}}function il(e,t){if(!gn(e))return[];try{let r=Hs(e,"utf-8").split(`
|
|
2103
|
+
`);return r.length>0&&r[r.length-1]===""&&r.pop(),r.slice(-t)}catch{return[]}}function gA(e){try{if(process.platform==="linux"){let t=`/proc/${e}/stat`;if(!gn(t))return{};let r=Hs(t,"utf-8").split(" "),o=Number.parseInt(r[21]??"0",10),l=uA("/proc/1").mtimeMs/1e3+o/100,c=Math.floor(Date.now()/1e3-l),d=Hs(`/proc/${e}/status`,"utf-8").match(/VmRSS:\s+(\d+)\s+kB/),m=d?Math.round(Number.parseInt(d[1]??"0",10)/1024):void 0;return{uptimeSec:c,memoryMb:m}}if(process.platform==="darwin"){let{execFileSync:t}=Th("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:hA(r??""),memoryMb:o?Math.round(Number.parseInt(o,10)/1024):void 0}}}catch{}return{}}function hA(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{existsSync as yA,readFileSync as bA}from"fs";import{createInterface as kA}from"readline";import le from"chalk";var Yg="https://api.telegram.org";function Vg(e,t){if(!yA(e))return;let n=bA(e,"utf-8");for(let r of n.split(`
|
|
2104
|
+
`)){let o=r.trim();if(!o||o.startsWith("#"))continue;let s=o.indexOf("=");if(s===-1||o.slice(0,s).trim()!==t)continue;let i=o.slice(s+1).trim();return(i.startsWith('"')&&i.endsWith('"')||i.startsWith("'")&&i.endsWith("'"))&&(i=i.slice(1,-1)),i}}async function Jg(e){let t=Vg(e,"TELEGRAM_BOT_TOKEN");if(!t)return{set:!1,valid:!1,reason:"unset"};let n=await ul(t);return n?{set:!0,valid:!0,botId:n.id,...n.username!==void 0?{username:n.username}:{}}:{set:!0,valid:!1,reason:"unauthorized"}}async function Xg(e,t={}){let n=Vg(e,"TELEGRAM_BOT_TOKEN");if(!n)return{found:!1,chats:[],reason:"unset"};let r=t.timeoutSec??60,o=2e3,s=Math.max(1,Math.ceil(r*1e3/o)),a=await Zg(n,{maxAttempts:s,intervalMs:o});return a.length===0?{found:!1,chats:[],reason:"timeout"}:{found:!0,chats:a}}async function ul(e){try{let t=await fetch(`${Yg}/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 wA(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 SA(e){try{let t=await fetch(`${Yg}/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 Zg(e,t={}){let n=t.maxAttempts??30,r=t.intervalMs??2e3;for(let o=0;o<n;o++){let s=await SA(e),a=wA(s);if(a.length>0)return a;o<n-1&&await new Promise(i=>setTimeout(i,r))}return[]}function qg(e){let t=kA({input:process.stdin,output:process.stdout});return new Promise(n=>{t.question(e,r=>{t.close(),n(r.trim())})})}function vA(e){return process.stdin.isTTY||(console.error(le.red(`Cannot securely prompt for secret on a non-TTY stdin: "${e.trim()}"`)),console.error(le.gray(" Supply TELEGRAM_BOT_TOKEN via environment variable or ~/.afk/config/afk.env instead.")),process.exit(1)),new Promise(t=>{process.stdout.write(e);let n=[];process.stdin.setRawMode(!0),process.stdin.resume(),process.stdin.setEncoding("utf-8");let r=o=>{o==="\r"||o===`
|
|
2105
2105
|
`||o===""?(process.stdin.setRawMode(!1),process.stdin.pause(),process.stdin.removeListener("data",r),process.stdout.write(`
|
|
2106
2106
|
`),t(n.join("").trim())):o===""?(process.stdin.setRawMode(!1),process.stdin.pause(),process.stdout.write(`
|
|
2107
|
-
`),process.exit(1)):o==="\x7F"?n.pop():n.push(o)};process.stdin.on("data",r)})}async function Qg(){let e=Ce();console.log(""),console.log(le.bold("\u{1F916} Telegram bot setup")),console.log(""),console.log(le.gray(`Config will be written to ${e}`)),console.log("");let t=process.env.TELEGRAM_BOT_TOKEN?.trim()??"",n=null;for(t&&(console.log(le.gray("Validating existing TELEGRAM_BOT_TOKEN...")),n=await ul(t),n?console.log(le.green(`\u2713 Token valid for @${n.username??n.firstName} (id ${n.id})`)):(console.log(le.yellow("\u26A0 Existing TELEGRAM_BOT_TOKEN is invalid; prompting for a new one")),t=""));!n;)t=await
|
|
2107
|
+
`),process.exit(1)):o==="\x7F"?n.pop():n.push(o)};process.stdin.on("data",r)})}async function Qg(){let e=Ce();console.log(""),console.log(le.bold("\u{1F916} Telegram bot setup")),console.log(""),console.log(le.gray(`Config will be written to ${e}`)),console.log("");let t=process.env.TELEGRAM_BOT_TOKEN?.trim()??"",n=null;for(t&&(console.log(le.gray("Validating existing TELEGRAM_BOT_TOKEN...")),n=await ul(t),n?console.log(le.green(`\u2713 Token valid for @${n.username??n.firstName} (id ${n.id})`)):(console.log(le.yellow("\u26A0 Existing TELEGRAM_BOT_TOKEN is invalid; prompting for a new one")),t=""));!n;)t=await vA("Paste your bot token (from @BotFather): "),t||(console.error(le.red("No token provided. Aborting.")),process.exit(1)),n=await ul(t),n||console.log(le.red("\u2717 Token rejected by getMe. Try again or Ctrl-C to abort."));zt(e,"TELEGRAM_BOT_TOKEN",t),console.log(le.green(`\u2713 Saved TELEGRAM_BOT_TOKEN \u2192 ${e}`)),console.log(""),console.log(le.bold("Now DM your bot to authorize your account."));let r=n.username?`@${n.username}`:`"${n.firstName}"`;console.log(` 1. Open Telegram and find ${le.cyan(r)}`),console.log(' 2. Send any message (e.g. "hi")'),console.log(""),console.log(le.gray("Polling for your chat ID (up to 60s)..."));let o=await Zg(t);if(o.length===0){console.error(le.red("\u2717 No chats found after 60s.")),console.error(le.gray(" Send a message to the bot and run `afk telegram setup` again,")),console.error(le.gray(" or paste your chat ID manually:"));let a=await qg("Chat ID: "),i=Number.parseInt(a,10);return Number.isFinite(i)||(console.error(le.red("Invalid chat ID. Aborting.")),process.exit(1)),zt(e,"AFK_TELEGRAM_ALLOWED_CHAT_IDS",String(i)),console.log(le.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(le.bold(`
|
|
2108
2108
|
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 qg("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(le.green(`\u2713 Found chat with ${a} (id ${s.chatId})`))}return zt(e,"AFK_TELEGRAM_ALLOWED_CHAT_IDS",String(s.chatId)),console.log(le.green(`\u2713 Saved AFK_TELEGRAM_ALLOWED_CHAT_IDS=${s.chatId} \u2192 ${e}`)),console.log(""),console.log(le.bold("Setup complete. Start the bot with:")),console.log(le.cyan(" afk telegram start")),console.log(""),{envPath:e,bot:n,chatId:s.chatId}}function eh(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 Qg()}catch(n){console.error(oe.red(`Setup failed: ${n.message}`)),process.exit(1)}}),t.command("check-token").description("Validate TELEGRAM_BOT_TOKEN via getMe; emit JSON {set, valid, username?, botId?, reason?}").action(async()=>{let n=await Jg(Ce());process.stdout.write(JSON.stringify(n)+`
|
|
2109
2109
|
`)}),t.command("discover-chat").description("Poll getUpdates for chats that have DM'd the bot; emit JSON {found, chats, reason?}").option("--timeout-sec <n>","How long to poll before giving up","60").action(async n=>{let r=Number.parseInt(n.timeoutSec??"60",10);(!Number.isFinite(r)||r<1)&&(console.error(oe.red("--timeout-sec must be a positive integer")),process.exit(2));let o=await Xg(Ce(),{timeoutSec:r});process.stdout.write(JSON.stringify(o)+`
|
|
2110
2110
|
`)}),t.command("set-allowed-chat <chatId>").description("Persist AFK_TELEGRAM_ALLOWED_CHAT_IDS=<chatId> to ~/.afk/config/afk.env; emit JSON {ok, path}").action(n=>{let r=Number.parseInt(n,10);Number.isFinite(r)||(process.stdout.write(JSON.stringify({ok:!1,reason:"invalid-chat-id"})+`
|
|
2111
2111
|
`),process.exit(2));let o=Ce();zt(o,"AFK_TELEGRAM_ALLOWED_CHAT_IDS",String(r)),process.stdout.write(JSON.stringify({ok:!0,path:o})+`
|
|
2112
|
-
`)}),t.command("start").description("Start the bot as a background daemon").action(async()=>{let n=await ll();if(n.kind==="started"){console.log(oe.green(`\u2713 Bot started (PID ${n.pid})`)),console.log(oe.gray(` Logs: ${n.logFile}`)),console.log(oe.gray(" Tail with: afk telegram logs --follow"));return}if(n.kind==="already-running"&&(console.log(oe.yellow(`\u26A0 ${n.message}`)),process.exit(1)),n.kind==="exited-immediately"){if(console.error(oe.red(`\u2717 ${n.message}`)),n.logTail&&n.logTail.length>0){console.error(""),console.error(oe.bold("Last log entries:"));for(let r of n.logTail)console.error(oe.gray(` ${r}`))}process.exit(1)}console.error(oe.red(`\u2717 ${n.message}`)),process.exit(1)}),t.command("stop").description("Stop the bot (SIGTERM, then SIGKILL after 5s)").action(async()=>{let n=await cl();if(n.kind==="not-running"){console.log(oe.yellow("\u26A0 Bot is not running"));return}if(n.kind==="stopped"){console.log(oe.green(`\u2713 Bot stopped (PID ${n.pid})`));return}console.log(oe.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 cl();(n.kind==="stopped"||n.kind==="force-killed")&&console.log(oe.gray(`Stopped (PID ${n.pid})`));let r=await ll();if(r.kind==="started"){console.log(oe.green(`\u2713 Bot restarted (PID ${r.pid})`));return}console.error(oe.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=dl();
|
|
2112
|
+
`)}),t.command("start").description("Start the bot as a background daemon").action(async()=>{let n=await ll();if(n.kind==="started"){console.log(oe.green(`\u2713 Bot started (PID ${n.pid})`)),console.log(oe.gray(` Logs: ${n.logFile}`)),console.log(oe.gray(" Tail with: afk telegram logs --follow"));return}if(n.kind==="already-running"&&(console.log(oe.yellow(`\u26A0 ${n.message}`)),process.exit(1)),n.kind==="exited-immediately"){if(console.error(oe.red(`\u2717 ${n.message}`)),n.logTail&&n.logTail.length>0){console.error(""),console.error(oe.bold("Last log entries:"));for(let r of n.logTail)console.error(oe.gray(` ${r}`))}process.exit(1)}console.error(oe.red(`\u2717 ${n.message}`)),process.exit(1)}),t.command("stop").description("Stop the bot (SIGTERM, then SIGKILL after 5s)").action(async()=>{let n=await cl();if(n.kind==="not-running"){console.log(oe.yellow("\u26A0 Bot is not running"));return}if(n.kind==="stopped"){console.log(oe.green(`\u2713 Bot stopped (PID ${n.pid})`));return}console.log(oe.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 cl();(n.kind==="stopped"||n.kind==="force-killed")&&console.log(oe.gray(`Stopped (PID ${n.pid})`));let r=await ll();if(r.kind==="started"){console.log(oe.green(`\u2713 Bot restarted (PID ${r.pid})`));return}console.error(oe.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=dl();CA(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}=dl();if(!xA(r)){console.log(oe.yellow(`No log file at ${r}`)),console.log(oe.gray("Start the bot first: afk telegram start"));return}let o=Number.parseInt(n.lines??"50",10);if(n.follow){TA("tail",["-n",String(o),"-f",r],{stdio:"inherit"}).on("error",i=>{console.error(oe.red(`Failed to spawn tail: ${i.message}`))});return}let s=EA(r,"utf-8").split(`
|
|
2113
2113
|
`).slice(-o-1);console.log(s.join(`
|
|
2114
|
-
`))})}function
|
|
2115
|
-
`,"utf8"),u}function
|
|
2116
|
-
`,"utf8"),n}import{spawn as
|
|
2117
|
-
`,"utf8"),o}function Fr(e){let t=e.filter(r=>r.score!==null),n=e.filter(r=>r.score===null).map(r=>r.index).sort((r,o)=>r-o);return t.sort((r,o)=>{let s=r.score,a=o.score,i=oh(s),l=oh(a);if(i!==l)return l-i;let c=sh(s.lint_ok),u=sh(a.lint_ok);return c!==u?u-c:s.loc_delta!==a.loc_delta?s.loc_delta-a.loc_delta:r.index-o.index}),[...t.map(r=>r.index),...n]}async function
|
|
2118
|
-
`)}async function mh(e,t){let n=
|
|
2114
|
+
`))})}function CA(e){if(console.log(oe.bold("\u{1F4CA} Telegram Bot Status")),console.log(""),e.running?(console.log(` ${oe.green("\u25CF")} Running (PID ${e.pid})`),e.uptimeSec!==void 0&&console.log(` Uptime: ${PA(e.uptimeSec)}`),e.memoryMb!==void 0&&console.log(` Memory: ${e.memoryMb} MB`)):console.log(` ${oe.red("\u25CF")} Stopped`),console.log(` PID: ${e.pidFile}`),console.log(` Logs: ${e.logFile}`),e.logTail&&e.logTail.length>0){console.log(""),console.log(oe.bold("Recent log entries:"));for(let t of e.logTail)console.log(oe.gray(` ${t}`))}}function PA(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{execFile as n_}from"node:child_process";import{promisify as r_}from"node:util";import Q from"chalk";import{execFile as AA}from"node:child_process";import{randomBytes as _A}from"node:crypto";import{promises as Vn}from"node:fs";import{join as Gs}from"node:path";import{promisify as RA}from"node:util";var IA=RA(AA),th=16;var xe=class extends Error{cause;code;constructor(t,n,r){super(t),this.name="WorktreeError",this.cause=n,this.code=r}};function pl(e,t=40){return e.toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,t).replace(/-+$/g,"")||"task"}function MA(){return _A(4).toString("hex").slice(0,4)}function $A(e){let t=n=>String(n).padStart(2,"0");return`${e.getUTCFullYear()}${t(e.getUTCMonth()+1)}${t(e.getUTCDate())}T${t(e.getUTCHours())}${t(e.getUTCMinutes())}${t(e.getUTCSeconds())}`}function OA(e,t={}){let n=(t.now??(()=>new Date))(),r=(t.randomSuffix??MA)();return`${$A(n)}-${pl(e,32)}-${r}`}async function hn(e,t){try{let n=await IA("git",t,{cwd:e,maxBuffer:4194304});return{stdout:n.stdout.trim(),stderr:n.stderr.trim()}}catch(n){let r=n,o=(r.stderr??r.stdout??r.message??"").toString().trim();throw new xe(`git ${t.join(" ")} failed: ${o}`,n)}}async function DA(e){let{stdout:t}=await hn(e,["rev-parse","--show-toplevel"]);if(!t)throw new xe(`not a git repository: ${e}`);return t}async function FA(e,t){if(t){let{stdout:o}=await hn(e,["rev-parse",t]);return{sha:o}}let{stdout:n}=await hn(e,["rev-parse","HEAD"]),r;try{let{stdout:o}=await hn(e,["symbolic-ref","--quiet","HEAD"]);o&&(r=o)}catch{}return{sha:n,branch:r}}function LA(e,t,n){let r=n?pl(n,32):`branch-${t}`;return`afk/farm/${e}/${t}-${r}`}function NA(e,t){return Gs(e,`branch-${t}`)}async function UA(e,t){try{await hn(e,["worktree","remove","--force",t])}catch{}}async function jA(e,t){try{await hn(e,["branch","-D",t])}catch{}}async function nh(e){if(e.count<1||e.count>th)throw new xe(`count must be between 1 and ${th}, got ${e.count}`);if(e.labels&&e.labels.length!==e.count)throw new xe(`labels.length (${e.labels.length}) must equal count (${e.count})`);let t=e.cwd??process.cwd(),n=await DA(t),{sha:r,branch:o}=await FA(n,e.baseRef),s=(e.now??(()=>new Date))(),a=e.taskSlug??OA(e.taskName,{now:()=>s,randomSuffix:e.randomSuffix}),i=e.taskSlug??a,l=Zs(a);try{throw await Vn.access(l),new xe(`farm directory already exists: ${l}`)}catch(d){if(d.code!=="ENOENT")throw d instanceof xe?d:new xe(`failed to check farm dir ${l}`,d)}await Vn.mkdir(l,{recursive:!0});let c=[];try{for(let d=1;d<=e.count;d++){let m=e.labels?.[d-1],f=LA(a,d,m),g=NA(l,d);await hn(n,["worktree","add","-b",f,g,r]),c.push({index:d,label:m?pl(m,32):void 0,path:g,branch:f})}}catch(d){for(let m of c.slice().reverse())await UA(n,m.path),await jA(n,m.branch);throw await Vn.rm(l,{recursive:!0,force:!0}).catch(()=>{}),d instanceof xe?d:new xe("farm creation failed",d)}let u={schemaVersion:3,taskId:i,taskSlug:a,taskName:e.taskName,repoRoot:n,baseRef:r,baseBranch:o,farmDir:l,createdAt:s.toISOString(),branches:c};return await Vn.writeFile(Gs(l,"farm.json"),JSON.stringify(u,null,2)+`
|
|
2115
|
+
`,"utf8"),u}function BA(e){let t=e;return t.respawnedAt===void 0&&(t.respawnedAt=void 0),t.respawnedAs===void 0&&(t.respawnedAs=void 0),t.prUrl===void 0&&(t.prUrl=void 0),t.prCreatedAt===void 0&&(t.prCreatedAt=void 0),t}async function WA(e){let t=Gs(Zs(e),"farm.json");try{let n=await Vn.readFile(t,"utf8"),r=JSON.parse(n);if(r.schemaVersion!==1&&r.schemaVersion!==2&&r.schemaVersion!==3)throw new xe(`unsupported farm manifest schema: ${r.schemaVersion} (expected 1, 2, or 3)`,void 0,"unsupported-schema");return BA(r)}catch(n){if(n.code==="ENOENT")return null;throw n instanceof xe?n:new xe(`failed to load farm manifest ${t}`,n,"invalid")}}async function rh(e,t){let n=await WA(e);if(!n)throw new xe(`farm not found: ${e}`);return n.memoryFactId=t,n.schemaVersion=3,await Vn.writeFile(Gs(n.farmDir,"farm.json"),JSON.stringify(n,null,2)+`
|
|
2116
|
+
`,"utf8"),n}import{spawn as HA}from"child_process";import{promises as zs}from"fs";import{join as Dr,dirname as q4}from"path";var KA=1,qs=12e4;async function ah(e){let{branchPath:t,baseSha:n,testCmd:r,timeoutMs:o=qs,_spawn:s=HA,_readPackageJson:a=GA,_now:i=Date.now,_nowIso:l=()=>new Date().toISOString()}=e,c=r??await zA(t,a),u=0,d=0,m=0,f;if(c){let h=await ch(c,t,o,s,i);m=h.durationMs,h.timedOut?(d=1,f=`tests timed out after ${o}ms`):h.crashed?(d=1,f=`test runner crashed: ${VA(h.stderr,200)}`):h.exitCode===0?u=1:d=1}else f="no test command found (no package.json scripts.test)";let g=await qA(t,o,s,i),y=await YA(t,n,s),S={schemaVersion:KA,pass:u,fail:d,loc_delta:y,lint_ok:g,duration_ms:m,branchPath:t,baseSha:n,scoredAt:l()};return f!==void 0&&(S.error=f),c!==void 0&&(S.testCmd=c),S}async function lh(e,t,n){let r=Dr(e,"scores");await zs.mkdir(r,{recursive:!0});let o=Dr(r,`branch-${t}.json`);return await zs.writeFile(o,JSON.stringify(n,null,2)+`
|
|
2117
|
+
`,"utf8"),o}function Fr(e){let t=e.filter(r=>r.score!==null),n=e.filter(r=>r.score===null).map(r=>r.index).sort((r,o)=>r-o);return t.sort((r,o)=>{let s=r.score,a=o.score,i=oh(s),l=oh(a);if(i!==l)return l-i;let c=sh(s.lint_ok),u=sh(a.lint_ok);return c!==u?u-c:s.loc_delta!==a.loc_delta?s.loc_delta-a.loc_delta:r.index-o.index}),[...t.map(r=>r.index),...n]}async function GA(e){try{let t=await zs.readFile(e,"utf8");return JSON.parse(t)}catch{return null}}async function zA(e,t){let n=await t(Dr(e,"package.json"));if(!ih(n))return;let r=n.scripts;return!ih(r)||typeof r.test!="string"?void 0:await dh(Dr(e,"pnpm-lock.yaml"))?"pnpm test":"npm test"}async function ch(e,t,n,r,o){let s=o();return new Promise(a=>{let i;try{i=r(e,{cwd:t,shell:!0,stdio:["ignore","pipe","pipe"],env:{...process.env,CI:"1"}})}catch(m){a({exitCode:null,durationMs:o()-s,stderr:m instanceof Error?m.message:String(m),timedOut:!1,crashed:!0});return}let l="",c=!1,u=!1,d=setTimeout(()=>{c=!0,i.kill("SIGKILL")},n);i.stderr?.on("data",m=>{l+=String(m),l.length>64e3&&(l=l.slice(-32e3))}),i.on("error",m=>{u||(u=!0,clearTimeout(d),a({exitCode:null,durationMs:o()-s,stderr:m.message,timedOut:!1,crashed:!0}))}),i.on("close",m=>{u||(u=!0,clearTimeout(d),a({exitCode:m,durationMs:o()-s,stderr:l,timedOut:c,crashed:!1}))})})}async function qA(e,t,n,r){if(!await dh(Dr(e,"tsconfig.json")))return null;let o=await ch("npx --no-install tsc --noEmit",e,t,n,r);return o.crashed||o.timedOut?null:o.exitCode===0}async function YA(e,t,n){return new Promise(r=>{let o;try{o=n("git",["diff","--shortstat",`${t}..HEAD`],{cwd:e,stdio:["ignore","pipe","pipe"]})}catch{r(0);return}let s="";o.stdout?.on("data",a=>{s+=String(a)}),o.on("error",()=>r(0)),o.on("close",()=>{let a=/(\d+) insertions?\(\+\)/.exec(s),i=/(\d+) deletions?\(-\)/.exec(s),l=a?Number(a[1]):0,c=i?Number(i[1]):0;r(l-c)})})}function oh(e){let t=e.pass+e.fail;return t===0?0:e.pass/t}function sh(e){return e===!0?2:e===!1?1:0}function VA(e,t){return e.length<=t?e:e.slice(0,t)+"\u2026"}function ih(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}async function dh(e){try{return await zs.access(e),!0}catch{return!1}}function uh(e,t){let n;try{n=t?._store??new Re}catch(r){return{skipped:!0,reason:r instanceof Error?r.message:String(r)}}try{let r=JA(e);return{factId:n.storeFact({category:"learning",content:JSON.stringify(r),source_surface:"afk"})}}catch(r){return{skipped:!0,reason:r instanceof Error?r.message:String(r)}}}function JA(e){let t=XA(e.branches),n=e.winner??null,r=ZA(e,t);return{type:"farm-run",task:e.taskName,taskSlug:e.taskSlug,winner:n,why:r,scores:t,human_decision:e.human_decision??null,baseSha:e.baseSha,completedAt:e.completedAt}}function XA(e){return e.map(t=>{let n=t.score??null;return{index:t.index,branch:t.branch,pass:n?.pass??0,fail:n?.fail??0,loc_delta:n?.loc_delta??0,lint_ok:n?.lint_ok??null,duration_ms:n?.duration_ms??0}})}function ZA(e,t){let{winner:n,branches:r}=e;if(n==null)return r.some(m=>m.score!=null)?`no winner: all ${r.length} branches failed tests`:"no winner: scoring data unavailable";let o=t.find(d=>d.index===n);if(!o)return`branch-${n} wins`;let s=o.pass>0?"\u2713":"\u2717",a=o.lint_ok===!0?"\u2713":o.lint_ok===!1?"\u2717":"?",i=o.loc_delta>=0?`+${o.loc_delta}`:String(o.loc_delta),c=t.filter(d=>d.index!==n).map(d=>d.loc_delta>=0?`+${d.loc_delta}`:String(d.loc_delta)),u=c.length>0?` (vs ${c.join(", ")} LoC)`:"";return`branch-${n} wins: tests${s}, lint${a}, ${i} LoC${u}`}var QA="afk:f:";var e_=/^[a-z0-9T][a-z0-9T-]{0,62}$/;function Lr(e,t){if(!e_.test(t))throw new Error(`buildFarmCallback: invalid taskSlug ${JSON.stringify(t)}`);let n=`${QA}${e}:${t}`,r=Buffer.byteLength(n,"utf8");if(r>64)throw new Error(`buildFarmCallback: payload ${r} bytes exceeds Telegram's 64-byte limit (slug=${t})`);return n}function ph(e){return{inline_keyboard:[[{text:"\u2705 Open PR",callback_data:Lr("p",e)},{text:"\u{1F501} Respawn from winner",callback_data:Lr("r",e)}],[{text:"\u{1F50D} Full diff",callback_data:Lr("d",e)},{text:"\u274C Discard all",callback_data:Lr("x",e)}]]}}function t_(e){let{taskName:t,taskSlug:n,baseSha:r,branches:o,winner:s}=e,a=o.filter(h=>h.ok),i=o.filter(h=>!h.ok),l=o.length,c=a.length,u=a.map(h=>({index:h.index,score:h.score??null})),d=Fr(u),m=new Map(o.map(h=>[h.index,h])),f=[];f.push(`\u{1F331} Farm complete: ${c}/${l} branches \u2014 ${t}`),f.push("");let g=1;for(let h of d){let b=m.get(h);if(!b)continue;let w=s!==void 0&&s===b.index,C=b.label?` (${b.label})`:"",T=b.score??null,A=T===null?"\u2014":T.pass>0?"\u2713":"\u2717",x=T===null?"\u2014":T.lint_ok===!0?"\u2713":T.lint_ok===!1?"\u2717":"?",v=T===null?"?":T.loc_delta>0?`+${T.loc_delta}`:T.loc_delta<0?`${T.loc_delta}`:"0",E=w?" \u2190 winner":"";f.push(`#${g} ${b.branch}${C} tests${A} lint${x} ${v} LoC${E}`),g++}let y=[...i].sort((h,b)=>h.index-b.index);for(let h of y){let b=h.label?` (${h.label})`:"",w=h.error??"unknown error";f.push(`#${g} ${h.branch}${b} failed: ${w}`),g++}f.push(""),s===void 0&&(f.push("\u26A0 no branch won (no successful + scored branches)"),f.push(""));let S=r.slice(0,7);return f.push(`base: ${S}`),f.push(`farm: ~/.afk/farms/${n}/`),f.join(`
|
|
2118
|
+
`)}async function mh(e,t){let n=t_(e),r=ph(e.taskSlug),o=t?._push??await Promise.resolve().then(()=>(Mo(),lu)).then(s=>s.pushIfConfigured);try{let s=await o(n,{replyMarkup:r});return s===null?{sent:!1,reason:"telegram unconfigured"}:{sent:!0,chatCount:s.length}}catch(s){return{sent:!1,reason:s instanceof Error?s.message:String(s)}}}var fh=r_(n_);async function o_(e,t){try{let{stdout:n}=await fh("git",["-C",e,"rev-list",`${t}..HEAD`,"--count"],{maxBuffer:4194304});return parseInt(n.trim(),10)||0}catch{return 0}}async function s_(e){try{let{stdout:t}=await fh("git",["-C",e,"status","--porcelain"],{maxBuffer:4194304});return t.trim()?t.trim().split(`
|
|
2119
2119
|
`).filter(Boolean):[]}catch{return[]}}var ml=class extends Error{dirtyFiles;constructor(t){super(`Source repository has uncommitted changes after farm run. Dirty files:
|
|
2120
2120
|
${t.map(n=>` ${n}`).join(`
|
|
2121
|
-
`)}`),this.name="FarmIsolationViolation",this.dirtyFiles=t}};function
|
|
2122
|
-
`)),model:E,idPrefix:`farm-${x.taskSlug}-branch-${$.index}`,cwd:$.path,readRoots:[$.path],writeRoots:[$.path]})),D=new AbortController,F=new U({parentAbortSignal:D.signal}),_={sessionId:`farm-${x.taskSlug}`,abortSignal:D.signal},M;try{M=await g({manager:F,parentSession:_,nodes:I,edges:[],failFast:i})}catch($){D.abort(),console.error(Q.red(`Farm dispatch failed: ${$ instanceof Error?$.message:String($)}`)),process.exit(1)}finally{D.abort()}let N=[];for(let $ of x.branches){let L=M.failed.find(P=>P.id===`branch-${$.index}`),ue=M.skipped.includes(`branch-${$.index}`);if(L||ue){let P=L?L.error.message:"skipped";console.log(`[branch-${$.index}] \u2717 failed: ${P}`),N.push({index:$.index,ok:!1,commitCount:0,error:P});continue}let q=await y($.path,v);if(q===0){let P="no commits made";console.log(`[branch-${$.index}] \u2717 failed: ${P}`),N.push({index:$.index,ok:!1,commitCount:0,error:P})}else console.log(`[branch-${$.index}] \u2713 done`),N.push({index:$.index,ok:!0,commitCount:q})}let V=await S(a);if(c)for(let $ of N){if(!$.ok){$.score=null;continue}let L=x.branches.find(q=>q.index===$.index);console.log(`[branch-${$.index}] scoring\u2026`);let ue=await h({branchPath:L.path,baseSha:v,timeoutMs:u});$.score=ue;try{await b(x.farmDir,$.index,ue)}catch(q){console.error(Q.yellow(`[branch-${$.index}] score.json write failed: ${q instanceof Error?q.message:String(q)}`))}}if(
|
|
2123
|
-
\u26A0 ISOLATION VIOLATION`)),console.error(Q.red($.message)),process.exit(1)}let be=N.every($=>$.ok);process.exit(be?0:1)}function gh(e){e.command("farm").description("Run a task across N speculative git worktree branches in parallel").argument("<task>","Task description to run on each branch").option("-n, --branches <number>","Number of branches to spawn (1-16)","3").option("--labels <labels>","Comma-separated branch labels (count must equal --branches)").option("-m, --model <model>","Model to use",ve()).option("--base-ref <ref>","Base git ref (default: HEAD)").option("--cwd <path>","Source repo root (default: process.cwd())").option("--fail-fast","Abort remaining branches on first failure",!1).option("--task-slug <slug>","Deterministic task slug override (for tests)").option("--no-score","Skip the post-run scorer (tests + lint + LoC)").option("--score-timeout <ms>",`Per-branch test timeout in ms (default ${qs})`).option("--no-memory","Skip writing the farm-run fact to cross-session memory").option("--no-digest","Skip pushing the Telegram digest on completion").action(async(t,n)=>{let r=parseInt(n.branches,10),o=n.labels?n.labels.split(",").map(a=>a.trim()).filter(Boolean):void 0,s=n.scoreTimeout?parseInt(n.scoreTimeout,10):void 0;s!==void 0&&(!Number.isFinite(s)||s<1)&&(console.error(Q.red(`--score-timeout must be a positive integer (got "${n.scoreTimeout}")`)),process.exit(1)),await
|
|
2124
|
-
`);let a=await Ya();if(a===void 0){console.log(p.warning("Could not reach the npm registry to check for updates.")),console.log(p.dim(` Current: ${n}`)),process.exitCode=1;return}if(
|
|
2125
|
-
`),r=await Ya(),r===void 0){console.error(p.warning("Could not reach the npm registry. Aborting.")),process.exitCode=1;return}if(r===n){console.log(`agent-afk ${p.bold(n)} is up to date.`);return}}console.log(`Updating agent-afk: ${p.dim(n)} \u2192 ${p.bold(r)}`),console.log(p.dim(` npm install -g agent-afk@${r}`));let{code:o,signal:s}=await
|
|
2121
|
+
`)}`),this.name="FarmIsolationViolation",this.dirtyFiles=t}};function i_(e,t){return e.length>=t?e:e+" ".repeat(t-e.length)}function a_(e){if(e===void 0)return Q.dim("\u2014");if(e===null)return Q.dim("skipped");let t=e.fail===0&&e.pass>0?Q.green("tests\u2713"):Q.red("tests\u2717"),n=e.lint_ok===!0?Q.green("lint\u2713"):e.lint_ok===!1?Q.red("lint\u2717"):Q.dim("lint?"),r=e.loc_delta>0?"+":"",o=Q.dim(`${r}${e.loc_delta} LoC`);return`${t} ${n} ${o}`}function l_(e,t,n,r){let o="\u2500".repeat(45);console.log(Q.dim(o)),console.log(`farm: ${e}`),console.log(`slug: ${t}`),console.log("");let s=r.some(u=>u.score!=null),a=s?Fr(r.map(u=>({index:u.index,score:u.score??null}))).map(u=>r.find(d=>d.index===u)):r;for(let u=0;u<a.length;u++){let d=a[u],m=n.find(b=>b.index===d.index),f=d.ok?Q.green("\u2713"):Q.red("\u2717"),g=i_(m.branch,40),y=d.ok?Q.dim(`(${d.commitCount} commit${d.commitCount===1?"":"s"})`):Q.red(`[error: ${d.error}]`),S=s?Q.cyan(`#${u+1} `):"",h=s?` ${a_(d.score)}`:"";console.log(`${S}branch-${d.index} ${f} ${g} ${y}${h}`),console.log(Q.dim(` worktree: ${m.path}`))}console.log(Q.dim(o));let i=r.filter(u=>u.ok).length,l=r.length;console.log(`${i}/${l} branches completed.`);let c=r.some(u=>u.score!=null&&u.score.pass>0);s&&!c&&console.log(Q.yellow("\u26A0 no branch passed tests \u2014 ranking falls back to lint + LoC"))}function c_(e,t,n){let r=t.map(i=>{let l=e.branches.find(u=>u.index===i.index),c={index:i.index,branch:l?.branch??`(unknown-${i.index})`,ok:i.ok,commitCount:i.commitCount};return l?.label!==void 0&&(c.label=l.label),i.error!==void 0&&(c.error=i.error),i.score!==void 0&&(c.score=i.score),c}),o=Fr(t.map(i=>({index:i.index,score:i.score??null}))),s;for(let i of o){let l=t.find(c=>c.index===i);if(!(!l||!l.ok||!l.score)&&l.score.pass>0&&l.score.fail===0){s=i;break}}if(s===void 0)for(let i of o){let l=t.find(c=>c.index===i);if(l?.ok&&l.score){s=i;break}}let a={taskName:e.taskName,taskSlug:e.taskSlug,baseSha:e.baseRef,startedAt:n,completedAt:new Date().toISOString(),branches:r};return s!==void 0&&(a.winner=s),e.human_decision!==void 0&&(a.human_decision=e.human_decision),a}async function d_(e){let{task:t,branches:n,labels:r,model:o,baseRef:s,cwd:a=process.cwd(),failFast:i,taskSlug:l,score:c=!0,scoreTimeoutMs:u=qs,memoryWrite:d=!0,digest:m=!0,_createFarm:f=nh,_runSubagentDAG:g=No,_getCommitCount:y=o_,_getSourceRepoDirtyFiles:S=s_,_scoreBranch:h=ah,_writeScore:b=lh,_writeFarmFact:w=uh,_sendFarmDigest:C=mh,_setFarmMemoryFactId:T=rh}=e,A=new Date().toISOString();(!Number.isInteger(n)||n<1||n>16)&&(console.error(Q.red(`--branches must be between 1 and 16 (got ${n})`)),process.exit(1)),r!==void 0&&r.length!==n&&(console.error(Q.red(`--labels count (${r.length}) must equal --branches (${n})`)),process.exit(1));let x;try{x=await f({taskName:t,count:n,labels:r,cwd:a,baseRef:s,taskSlug:l})}catch($){console.error(Q.red(`Farm creation failed: ${$ instanceof Error?$.message:String($)}`)),process.exit(1)}let v=x.baseRef,E=o??ve(),R=xn()??Tn()??"",I=x.branches.map($=>({id:`branch-${$.index}`,agentType:`branch-${$.index}${$.label?` (${$.label})`:""}`,systemPrompt:R,promptBuilder:L=>(console.log(`[branch-${$.index}] started`),[`Task: ${t}`,"",`You are working in a dedicated git worktree. Your working directory has been set to: ${$.path}`,`Your branch is: ${$.branch}`,"","Complete the task. All file operations are restricted to this worktree by the runtime."].join(`
|
|
2122
|
+
`)),model:E,idPrefix:`farm-${x.taskSlug}-branch-${$.index}`,cwd:$.path,readRoots:[$.path],writeRoots:[$.path]})),D=new AbortController,F=new U({parentAbortSignal:D.signal}),_={sessionId:`farm-${x.taskSlug}`,abortSignal:D.signal},M;try{M=await g({manager:F,parentSession:_,nodes:I,edges:[],failFast:i})}catch($){D.abort(),console.error(Q.red(`Farm dispatch failed: ${$ instanceof Error?$.message:String($)}`)),process.exit(1)}finally{D.abort()}let N=[];for(let $ of x.branches){let L=M.failed.find(P=>P.id===`branch-${$.index}`),ue=M.skipped.includes(`branch-${$.index}`);if(L||ue){let P=L?L.error.message:"skipped";console.log(`[branch-${$.index}] \u2717 failed: ${P}`),N.push({index:$.index,ok:!1,commitCount:0,error:P});continue}let q=await y($.path,v);if(q===0){let P="no commits made";console.log(`[branch-${$.index}] \u2717 failed: ${P}`),N.push({index:$.index,ok:!1,commitCount:0,error:P})}else console.log(`[branch-${$.index}] \u2713 done`),N.push({index:$.index,ok:!0,commitCount:q})}let V=await S(a);if(c)for(let $ of N){if(!$.ok){$.score=null;continue}let L=x.branches.find(q=>q.index===$.index);console.log(`[branch-${$.index}] scoring\u2026`);let ue=await h({branchPath:L.path,baseSha:v,timeoutMs:u});$.score=ue;try{await b(x.farmDir,$.index,ue)}catch(q){console.error(Q.yellow(`[branch-${$.index}] score.json write failed: ${q instanceof Error?q.message:String(q)}`))}}if(l_(t,x.taskSlug,x.branches,N),d||m){let $=c_(x,N,A);if(d){let L=w($);if("skipped"in L)console.error(Q.yellow(`[memory] write skipped: ${L.reason}`));else{let{factId:ue}=L;try{await T(x.taskSlug,ue)}catch(q){console.error(Q.yellow(`[memory] setFarmMemoryFactId failed: ${q.message}`))}}}if(m){let L=await C($);L.sent?console.log(Q.dim(`[telegram] digest sent (${L.chatCount} chat${L.chatCount===1?"":"s"})`)):L.reason&&L.reason!=="telegram unconfigured"&&console.error(Q.yellow(`[telegram] digest failed: ${L.reason}`))}}if(V.length>0){let $=new ml(V);console.error(Q.red(`
|
|
2123
|
+
\u26A0 ISOLATION VIOLATION`)),console.error(Q.red($.message)),process.exit(1)}let be=N.every($=>$.ok);process.exit(be?0:1)}function gh(e){e.command("farm").description("Run a task across N speculative git worktree branches in parallel").argument("<task>","Task description to run on each branch").option("-n, --branches <number>","Number of branches to spawn (1-16)","3").option("--labels <labels>","Comma-separated branch labels (count must equal --branches)").option("-m, --model <model>","Model to use",ve()).option("--base-ref <ref>","Base git ref (default: HEAD)").option("--cwd <path>","Source repo root (default: process.cwd())").option("--fail-fast","Abort remaining branches on first failure",!1).option("--task-slug <slug>","Deterministic task slug override (for tests)").option("--no-score","Skip the post-run scorer (tests + lint + LoC)").option("--score-timeout <ms>",`Per-branch test timeout in ms (default ${qs})`).option("--no-memory","Skip writing the farm-run fact to cross-session memory").option("--no-digest","Skip pushing the Telegram digest on completion").action(async(t,n)=>{let r=parseInt(n.branches,10),o=n.labels?n.labels.split(",").map(a=>a.trim()).filter(Boolean):void 0,s=n.scoreTimeout?parseInt(n.scoreTimeout,10):void 0;s!==void 0&&(!Number.isFinite(s)||s<1)&&(console.error(Q.red(`--score-timeout must be a positive integer (got "${n.scoreTimeout}")`)),process.exit(1)),await d_({task:t,branches:r,labels:o,model:n.model,baseRef:n.baseRef,cwd:n.cwd,failFast:n.failFast,taskSlug:n.taskSlug,score:n.score,memoryWrite:n.memory,digest:n.digest,...s!==void 0?{scoreTimeoutMs:s}:{}})})}import Ze from"chalk";import{execFile as u_}from"node:child_process";import{promisify as p_}from"node:util";var fl=p_(u_);async function hh(){try{return(await fl("git",["rev-parse","--show-toplevel"])).stdout.trim()}catch{throw new Error("Not in a git repository.")}}function m_(e){return["empty","stale-clean","orphaned-dir","orphaned-registration"].includes(e)?Ze.red("yes"):e==="stale-dirty"?Ze.yellow("warn"):Ze.green("no")}var yh=["interactive","diagnose","all"];function f_(e){if(yh.includes(e))return e;throw new Error(`Invalid --scope value: '${e}'. Allowed: ${yh.join(" | ")}.`)}function g_(e){if(e<=0)return"-";let t=e/864e5;return t<1?`${Math.max(1,Math.round(e/36e5))}h`:`${Math.round(t)}d`}function bh(e){let t=e.command("worktree").description("Manage git worktrees created by afk");t.command("list").description("List all afk-managed worktrees and show prune candidates (dry-run only)").action(async()=>{let n;try{n=await hh()}catch(s){z(s)}let r;try{r=await Mr({execFile:fl,repoRoot:n,dryRun:!0})}catch(s){z(new Error(`Sweep failed: ${s.message}`))}let o=["PATH".padEnd(45),"OWNER".padEnd(12),"AGE".padEnd(6),"STATUS".padEnd(22),"PRUNE?"].join(" | ");console.log(Ze.bold(o)),console.log("-".repeat(o.length));for(let s of r.candidates){let a=[s.path.slice(-44).padEnd(45),s.owner.padEnd(12),g_(s.ageMs).padEnd(6),s.verdict.padEnd(22),m_(s.verdict)].join(" | ");console.log(a)}if(r.candidates.length===0&&console.log(Ze.dim(" (no afk-managed worktrees found)")),r.warnings.length>0){console.log("");for(let s of r.warnings)console.log(Ze.yellow(s))}}),t.command("prune").description("Remove stale, empty, and orphaned worktrees").option("--apply","Execute removals (default is dry-run)",!1).option("--max-age-days-clean <n>","Max age (days) for clean worktrees before removal").option("--max-age-days-dirty <n>","Max age (days) for dirty worktrees before warning").option("--scope <scope>","Scope: interactive | diagnose | all","all").action(async n=>{let r;try{r=await hh()}catch(b){z(b)}let s=je().daemon?.worktreePrune,a=parseInt(process.env.AFK_WORKTREE_MAX_AGE_CLEAN??"",10),i=parseInt(process.env.AFK_WORKTREE_MAX_AGE_DIRTY??"",10),l=n.maxAgeDaysClean!==void 0?parseInt(n.maxAgeDaysClean,10):s?.maxAgeDaysClean??(Number.isNaN(a)?14:a),c=n.maxAgeDaysDirty!==void 0?parseInt(n.maxAgeDaysDirty,10):s?.maxAgeDaysDirty??(Number.isNaN(i)?30:i),u;try{u=f_(n.scope)}catch(b){z(b)}let d={execFile:fl,repoRoot:r,dryRun:!n.apply,maxAgeDaysClean:l,maxAgeDaysDirty:c,scope:u},m;try{m=await Mr(d)}catch(b){z(new Error(`Sweep failed: ${b.message}`))}m.dryRun&&console.log(Ze.yellow("\u{1F50D} Dry-run mode \u2014 no changes made."));let f={};for(let b of m.candidates)f[b.verdict]=(f[b.verdict]??0)+1;let g=m.warnings.filter(b=>b.startsWith("[WARN]")).length,y=m.warnings.filter(b=>b.startsWith("[ERROR]")).length,S=Object.entries(f).sort(([b],[w])=>b.localeCompare(w)).map(([b,w])=>`${b}=${w}`);console.log(`Removed: ${m.removed.length}, Warned: ${g}, Errors: ${y}`+(S.length>0?` [${S.join(" ")}]`:""));for(let b of m.candidates){let C=m.removed.includes(b.path)?Ze.red("\u2717"):Ze.green("\u2713");console.log(` ${C} [${b.verdict.padEnd(22)}] ${b.path}`)}if(m.warnings.length>0){console.log("");for(let b of m.warnings)b.startsWith("[ERROR]")?console.error(Ze.red(b)):console.log(Ze.yellow(b))}m.warnings.some(b=>b.startsWith("[ERROR]"))&&process.exit(1)})}import{spawn as h_}from"child_process";var y_=/^\d+\.\d+\.\d+(-[\da-z.]+)?$/i;function b_(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 kh(e){e.command("update").alias("upgrade").description("Update agent-afk to the latest published version").option("--check","Only check whether an update is available; do not install").option("--pin <version>","Install a specific version instead of latest (must be valid semver)").action(async t=>{let n=fn();if(t.check===!0){process.stderr.write(`Checking for updates\u2026
|
|
2124
|
+
`);let a=await Ya();if(a===void 0){console.log(p.warning("Could not reach the npm registry to check for updates.")),console.log(p.dim(` Current: ${n}`)),process.exitCode=1;return}if(b_(n,a)){console.log(`${p.bold("Update available:")} ${p.dim(n)} \u2192 ${p.bold(a)}`),console.log(p.dim(" Run `afk update` to install."));return}console.log(`agent-afk ${p.bold(n)} is up to date.`);return}if(t.pin!==void 0&&!y_.test(t.pin)){console.error(p.warning(`Invalid version: ${JSON.stringify(t.pin)}. Must be valid semver (e.g. 1.2.3 or 1.2.3-beta.1).`)),process.exitCode=1;return}let r=t.pin;if(r===void 0){if(process.stderr.write(`Fetching latest version\u2026
|
|
2125
|
+
`),r=await Ya(),r===void 0){console.error(p.warning("Could not reach the npm registry. Aborting.")),process.exitCode=1;return}if(r===n){console.log(`agent-afk ${p.bold(n)} is up to date.`);return}}console.log(`Updating agent-afk: ${p.dim(n)} \u2192 ${p.bold(r)}`),console.log(p.dim(` npm install -g agent-afk@${r}`));let{code:o,signal:s}=await k_(r);o===0?(qa(r),console.log(p.success(`\u2713 agent-afk@${r} installed.`))):s!==null?(console.error(p.warning(`npm install was killed by signal ${s}.`)),process.exitCode=1):(console.error(p.warning(`npm install exited with code ${o??1}.`)),process.exitCode=o??1)})}function k_(e){return new Promise(t=>{let n=h_("npm",["install","-g",`agent-afk@${e}`],{stdio:"inherit"});n.on("error",()=>t({code:1,signal:null})),n.on("exit",(r,o)=>t({code:r,signal:o}))})}import{realpathSync as v_}from"fs";gl();gl({path:Ce(),override:!1});process.env.AFK_FRAMEWORK_DIR??=lt();process.env.AGENT_SURFACE??="afk";_l();var fe=new w_;fe.name("afk").description("AI agent CLI. Starts interactive REPL by default; use `afk chat` for one-shot.").version(fn()).option("--no-update-check","Skip update version check");hp(fe);kg(fe);$g(fe);yg(fe);Fg(fe);Ug(fe);Bg(fe);bg(fe);Hg(fe);Kg(fe);eh(fe);gh(fe);bh(fe);kh(fe);fe.commands.find(e=>e.name()==="chat")?.alias("c");fe.commands.find(e=>e.name()==="interactive")?.alias("i");fe.commands.find(e=>e.name()==="status")?.alias("s");fe.addHelpText("after",`
|
|
2126
2126
|
Examples:
|
|
2127
2127
|
$ afk # start interactive REPL
|
|
2128
2128
|
$ afk --model opus # REPL with specific model
|
|
2129
2129
|
$ afk chat "What is 2+2?" # one-shot message
|
|
2130
|
-
$ afk status --format json`);async function
|
|
2130
|
+
$ afk status --format json`);async function S_(){let e=ar(),t=Be(ve());if(!e&&t==="anthropic-direct"){if(!process.stdin.isTTY){process.stderr.write("agent-afk: No Anthropic credential found. Run `afk login` to authenticate.\n"),process.exit(1);return}try{await Bs(),gl({path:Ce(),override:!0})}catch{}}}var wh=process.argv[1]??"",T_=import.meta.url===`file://${wh}`||import.meta.url===`file://${v_(wh)}`;T_&&(async()=>{await S_();let e=je(),n=process.argv.slice(2).some(i=>i==="--no-update-check")?"off":e.updatePolicy,r=mg(n),o=null,s=process.stderr.write.bind(process.stderr);process.stderr.write=(i,...l)=>typeof i=="string"&&i.includes("Updated to agent-afk")?(o=(o??"")+i,!0):s(i,...l),fg(),process.stderr.write=s,hg(r,o),process.argv.length<=2||process.argv[2]==="interactive"||process.argv[2]==="i"?r&&n==="auto"&&Va(r.latestVersion):(o!==null&&process.stderr.write(o),r&&(Fs(r),n==="auto"&&Va(r.latestVersion))),fe.parse()})();export{Pi as getMaxBudgetUsd,cr as getMaxOutputTokens,Ai as getTaskBudget,Pn as parseBudget,$t as parseEffort,An as parseMaxOutputTokens,Mt as parseThinking,S_ as runFirstRunDetector};
|