agent-afk 0.1.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.
@@ -0,0 +1,1270 @@
1
+ #!/usr/bin/env node
2
+ import{Telegraf as so}from"telegraf";import{promises as me}from"fs";import{join as Dt}from"path";var Ee=class{sessions=new Map;sessionData=new Map;options;constructor(e){this.options={dataDir:e.dataDir||"./data/telegram-sessions",defaultModel:e.defaultModel||"sonnet",apiKey:e.apiKey,settingSources:e.settingSources,thinking:e.thinking,effort:e.effort,createSession:e.createSession}}getSessionIfExists(e){return this.sessions.get(e)}async getSession(e){let n=this.sessions.get(e);if(!n){let o=this.sessionData.get(e)||{chatId:e,model:this.options.defaultModel,createdAt:new Date().toISOString(),lastActivity:new Date().toISOString()},s={model:o.model,apiKey:this.options.apiKey};this.options.settingSources?.length&&(s.settingSources=this.options.settingSources),this.options.thinking!==void 0&&(s.thinking=this.options.thinking),this.options.effort!==void 0&&(s.effort=this.options.effort),n=await this.options.createSession(s),this.sessions.set(e,n),this.sessionData.set(e,o)}let r=this.sessionData.get(e);return r&&(r.lastActivity=new Date().toISOString()),n}async resetSession(e){let n=this.sessions.get(e);n&&(await n.close(),this.sessions.delete(e));let r=this.sessionData.get(e);r&&(r.lastActivity=new Date().toISOString())}async switchModel(e,n){let r=this.sessions.get(e);r&&(await r.close(),this.sessions.delete(e));let o=this.sessionData.get(e);o?(o.model=n,o.lastActivity=new Date().toISOString()):(o={chatId:e,model:n,createdAt:new Date().toISOString(),lastActivity:new Date().toISOString()},this.sessionData.set(e,o))}getModel(e){return this.sessionData.get(e)?.model||this.options.defaultModel}async loadSessions(){try{await me.mkdir(this.options.dataDir,{recursive:!0});let e=await me.readdir(this.options.dataDir);for(let n of e)if(n.endsWith(".json")){let r=Dt(this.options.dataDir,n),o=await me.readFile(r,"utf-8"),s=JSON.parse(o);this.sessionData.set(s.chatId,s)}}catch(e){e.code!=="ENOENT"&&console.error("Failed to load sessions:",e)}}async saveSessions(){try{await me.mkdir(this.options.dataDir,{recursive:!0});for(let[e,n]of this.sessionData.entries()){let r=Dt(this.options.dataDir,`${e}.json`);await me.writeFile(r,JSON.stringify(n,null,2))}}catch(e){console.error("Failed to save sessions:",e)}}async closeAll(){await this.saveSessions();let e=Array.from(this.sessions.values()).map(n=>n.close().catch(r=>console.error("Error closing session:",r)));await Promise.all(e),this.sessions.clear()}getSessionCount(){return this.sessions.size}getChatCount(){return this.sessionData.size}};function Ae(t,e=4096){if(t.length<=e)return[t];let n=[],r=t;for(;r.length>0;){if(r.length<=e){n.push(r);break}let o=e,s=r.lastIndexOf(`
3
+ `,e);if(s>e-500&&s>0)o=s+1;else{let i=r.slice(0,e).match(/[.!?]\s+(?=[A-Z])/g);if(i&&i.length>0){let a=i[i.length-1];if(a){let l=r.lastIndexOf(a,e);l>e-200&&l>0&&(o=l+2)}}else{let a=r.lastIndexOf(" ",e);a>e-100&&a>0&&(o=a+1)}}n.push(r.slice(0,o).trim()),r=r.slice(o).trim()}return n}function et(t){let e=t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");return e=e.replace(/^```[\w]*\n?([\s\S]*?)```/gm,"<pre>$1</pre>"),e=e.replace(/`([^`]+)`/g,"<code>$1</code>"),e=e.replace(/\*\*([^*]+)\*\*/g,"<b>$1</b>"),e=e.replace(/__([^_]+)__/g,"<b>$1</b>"),e=e.replace(/\*([^*]+)\*/g,"<i>$1</i>"),e=e.replace(/_([^_]+)_/g,"<i>$1</i>"),e=e.replace(/~~([^~]+)~~/g,"<s>$1</s>"),e=e.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(n,r,o)=>'<a href="'+o.replace(/&/g,"&amp;").replace(/"/g,"&quot;")+'">'+r+"</a>"),e=e.replace(/^#{1,6}\s+/gm,""),e}function O(t){return`\u274C Error: ${t instanceof Error?t.message:t}`}var Ot=[{cmd:"/start",desc:"Show welcome and this command list"},{cmd:"/help",desc:"Show this command list"},{cmd:"/clear",desc:"Clear conversation history (SDK /clear)"},{cmd:"/compact",desc:"Compact conversation history (summarize older messages)"},{cmd:"/model [opus|sonnet|haiku]",desc:"Switch Claude model"}];function Ft(t){let e=["\u{1F4CB} Bot commands (aligned with agent-afk CLI):","",...Ot.map(n=>` ${n.cmd}
4
+ ${n.desc}`)];return t&&t.length>0&&e.push("","\u{1F4CB} Session commands (from SDK, when using settingSources):","",...t.map(n=>` /${n.replace(/^\//,"")}`)),e.push("","Just send a message to chat with Claude."),e.join(`
5
+ `)}function $t(){return`\u{1F44B} Welcome to Agent AFK Bot!
6
+
7
+ I'm powered by Claude and can help you with various tasks.
8
+
9
+ Available commands:
10
+ ${Ot.map(e=>`${e.cmd} - ${e.desc}`).join(`
11
+ `)}
12
+
13
+ Just send me a message to get started!`}function Lt(t){return`${{opus:"\u{1F680}",sonnet:"\u26A1",haiku:"\u{1F338}"}[t]||"\u{1F916}"} Switched to Claude ${t.toUpperCase()}`}function Te(){return"\u{1F504} Conversation history cleared!"}function jt(t){if(!t)return"\u{1F4E6} Conversation compacted (older messages summarized).";let e=t.tokensSavedEstimate!==void 0&&t.tokensSavedEstimate>0?` (~${to(t.tokensSavedEstimate)} input tokens saved)`:"";return`\u{1F4E6} Compacted ${t.before} \u2192 ${t.after} messages${e}.`}function Ht(t){return t==="aborted"?"\u{1F4E6} Compaction cancelled.":t.startsWith("summarization-failed")?`\u26A0\uFE0F Compaction failed: ${t}. History unchanged.`:`\u{1F4E6} Nothing to compact (${t}).`}function to(t){return t>=1e3?`${Math.round(t/100)/10}k`:String(t)}async function tt(t){await t.reply($t())}async function nt(t,e){let n=t.chat?.id,r,o=n?e.getSessionIfExists(n):void 0;if(o)try{await Promise.race([o.waitForInitialization(),new Promise((i,a)=>setTimeout(()=>a(new Error("timeout")),2e3))]);let s=o.getSessionMetadata();s.slashCommands?.length&&(r=s.slashCommands)}catch{}await t.reply(Ft(r))}async function rt(t,e,n,r){let o=t.chat?.id;if(!o){await t.reply(O("Could not identify chat"));return}try{await e.resetSession(o),n.delete(o),await t.reply(Te())}catch(s){r("Clear error:",s),await t.reply(O(s))}}async function Ut(t,e,n){let r=t.chat?.id;if(!r){await t.reply(O("Could not identify chat"));return}try{let o=await e.getSession(r);await t.sendChatAction("typing").catch(()=>{});let s=await o.compact();s.compacted?await t.reply(jt({before:s.messagesBefore,after:s.messagesAfter,...s.tokensSavedEstimate!==void 0?{tokensSavedEstimate:s.tokensSavedEstimate}:{}})):await t.reply(Ht(s.reason??"unknown"))}catch(o){n("Compact error:",o),await t.reply(O(o))}}async function ot(t,e,n){let r=t.chat?.id;if(!r){await t.reply(O("Could not identify chat"));return}let s=t.message.text.split(/\s+/).slice(1);if(s.length===0){let c=e.getModel(r);await t.reply(`Current model: ${c.toUpperCase()}
14
+
15
+ Usage: /model [opus|sonnet|haiku]`);return}let i=s[0];if(!i){await t.reply(O("Please specify a model: opus, sonnet, or haiku"));return}let a=i.toLowerCase();if(!["opus","sonnet","haiku"].includes(a)){await t.reply(O(`Invalid model: ${i}
16
+ Valid options: opus, sonnet, haiku`));return}try{await e.switchModel(r,a),await t.reply(Lt(a))}catch(c){n("Model switch error:",c),await t.reply(O(c))}}function st(t){let e=t instanceof Error?t.message:String(t);return e.toLowerCase().includes("rate limit")||e.toLowerCase().includes("too many requests")}function it(t){let e=t instanceof Error?t.message:String(t);return e.toLowerCase().includes("network")||e.toLowerCase().includes("connect")||e.toLowerCase().includes("timeout")}var no=300,ro=9e4,oo=6e4;async function Nt(t,e,n,r){let o="",s=null,i=0,a=async(l,c=!1)=>{let d=et(l||"\u2026"),u=Date.now();if(!s){let f=Ae(d);s=await t.reply(f[0]??"\u2026",{parse_mode:"HTML"});return}if(!c&&u-i<no&&l.length<100)return;i=u;let p=Ae(d);try{await t.telegram.editMessageText(t.chat?.id,s.message_id,void 0,p[0]??d,{parse_mode:"HTML"})}catch{}};try{let l="sendMessageStream"in e&&typeof e.sendMessageStream=="function"?e.sendMessageStream(n):(async function*(){let f=await e.sendMessage(n,{stream:!1});yield{type:"message",message:f},yield{type:"done",metadata:f.metadata}})();await a("Thinking\u2026");let c=l[Symbol.asyncIterator](),d=!1,u=null,p=()=>{let f=d?oo:ro;return new Promise((g,h)=>{u=setTimeout(()=>{u=null,h(new Error(d?"Response timed out. Try sending a shorter message or try again.":"Request timed out. The agent may still be starting (first message can take a minute). Try again in a moment."))},f),c.next().then(m=>{u!=null&&(clearTimeout(u),u=null),g(m)},m=>{u!=null&&(clearTimeout(u),u=null),h(m)})})};for(;;){let f=await p();if(f.done)break;let g=f.value;if(d||(d=!0,console.log("\u{1F4E1} First stream event received:",g.type),r?.("First stream event received:",g.type)),g.type==="chunk"&&g.chunk.type==="content"&&(o+=g.chunk.content,await a(o)),g.type==="message"&&g.message.role==="assistant"&&(o=g.message.content,await a(o)),g.type==="progress"){let{description:h,summary:m,lastToolName:b}=g.progress,S=b?`
17
+ \u25E6 ${h} (${b})`:`
18
+ \u25E6 ${h}`;o+=S,m&&(o+=`
19
+ ${m}`),await a(o)}if(g.type==="suggestion"&&(o+=`
20
+
21
+ \u{1F4A1} ${g.suggestion}`,await a(o)),g.type==="done"){o.trim()&&await a(o,!0);break}if(g.type==="error")throw g.error}if(o&&s){let f=Ae(et(o));if(f.length>1)for(let g=1;g<f.length;g++){let h=f[g];h&&await t.reply(h,{parse_mode:"HTML"})}}}catch(l){throw r?.("Streaming error:",l),l}}async function Bt(t,e,n,r,o){if(!r.has(e))try{await Promise.race([n.waitForInitialization(),new Promise((a,l)=>setTimeout(()=>l(new Error("timeout")),5e3))]);let s=n.getSessionMetadata(),i=[{command:"start",description:"Show welcome and command list"},{command:"help",description:"Show this command list"},{command:"clear",description:"Clear conversation history"},{command:"compact",description:"Compact conversation history"},{command:"model",description:"Switch Claude model (opus/sonnet/haiku)"}];if(s.slashCommands?.length)for(let a of s.slashCommands){let l=a.replace(/^\//,"");i.push({command:l,description:`SDK command: ${l}`})}if(s.skills?.length)for(let a of s.skills)i.push({command:a,description:`Run ${a} skill`});await t.telegram.setMyCommands(i,{scope:{type:"chat",chat_id:e}}),r.add(e),o(`Registered ${i.length} commands for chat ${e}`)}catch(s){o(`Could not register dynamic commands for chat ${e}:`,s)}}var Ie=class{sessionManager;messageQueues=new Map;registeredCommandChats;log;bot;constructor(e,n,r,o){this.bot=e,this.sessionManager=n,this.registeredCommandChats=r,this.log=o}async handle(e){let n=e.chat?.id,r=e.message.text;if(!(!n||!r)&&(console.log(`\u{1F4EC} Message from chat ID: ${n}`),!r.startsWith("/")))try{let o=await this.sessionManager.getSession(n);if(Bt(this.bot,n,o,this.registeredCommandChats,this.log).catch(s=>this.log("Failed to register chat commands:",s)),o.state!=="idle"){this.enqueueMessage(n,e,r),await e.reply("Message queued.");return}await this.processOne(n,e,r)}catch(o){console.error("\u274C Message handling error:",o),this.log("Message handling error:",o);let s=o;if((s?.message??"").includes("session is busy")){this.enqueueMessage(n,e,r),await e.reply("Message queued.");return}st(o)?await e.reply("\u23F3 Rate limit reached. Please wait a moment and try again."):it(o)?await e.reply("\u{1F310} Network error. Please check your connection and try again."):await e.reply(O(s))}}async processClearDirect(e,n){try{await this.sessionManager.resetSession(e),this.registeredCommandChats.delete(e),await n.reply(Te())}catch(r){this.log("Clear error:",r),await n.reply(O(r))}}enqueueMessage(e,n,r){let o=this.messageQueues.get(e);o||(o=[],this.messageQueues.set(e,o)),o.push({type:"message",ctx:n,text:r})}enqueueClear(e,n){let r=this.messageQueues.get(e);r||(r=[],this.messageQueues.set(e,r)),r.push({type:"clear",ctx:n})}async processOne(e,n,r){try{let o=await this.sessionManager.getSession(e);await n.sendChatAction("typing").catch(()=>{}),await Nt(n,o,r,this.log)}catch(o){console.error("\u274C Message handling error:",o),this.log("Message handling error:",o);let s=o;st(o)?await n.reply("\u23F3 Rate limit reached. Please wait a moment and try again."):it(o)?await n.reply("\u{1F310} Network error. Please check your connection and try again."):await n.reply(O(s))}finally{this.drainQueue(e)}}async drainQueue(e){let n=this.messageQueues.get(e);if(!n?.length)return;let r=n.shift();r.type==="message"?await this.processOne(e,r.ctx,r.text):await this.processClearDirect(e,r.ctx)}};function Kt(t,e=()=>{}){let n=new Set;if(!t)return n;for(let r of t.split(",")){let o=r.trim();if(o){if(!/^-?\d+$/.test(o)){e("[allowlist] Ignoring non-numeric chat ID:",o);continue}n.add(Number(o))}}return n}function Gt(t,e=()=>{}){return async(n,r)=>{let o=n.chat?.id;if(o===void 0||!t.has(o)){e("[allowlist] Rejecting update from chat:",o??"<unknown>");return}await r()}}var Ce=class{bot;sessionManager;options;running=!1;registeredCommandChats=new Set;messageHandler;constructor(e){this.options=e,this.bot=new so(e.botToken),this.sessionManager=new Ee(e),this.messageHandler=new Ie(this.bot,this.sessionManager,this.registeredCommandChats,this.log.bind(this)),this.setupHandlers()}setupHandlers(){this.bot.use(Gt(this.options.allowedChatIds,this.log.bind(this))),this.bot.command("start",e=>tt(e)),this.bot.command("help",e=>nt(e,this.sessionManager)),this.bot.command("clear",async e=>{let n=e.chat?.id;if(!n){await e.reply(O("Could not identify chat"));return}(await this.sessionManager.getSession(n)).state!=="idle"?(this.messageHandler.enqueueClear(n,e),await e.reply("Clear queued.")):await rt(e,this.sessionManager,this.registeredCommandChats,this.log.bind(this))}),this.bot.command("compact",e=>Ut(e,this.sessionManager,this.log.bind(this))),this.bot.command("model",e=>ot(e,this.sessionManager,this.log.bind(this))),this.bot.on("text",e=>this.messageHandler.handle(e)),this.bot.catch((e,n)=>{this.log("Bot error:",e),n.reply(O("An unexpected error occurred. Please try again.")).catch(r=>this.log("Failed to send error message:",r))})}async start(){if(this.running)throw new Error("Bot is already running");this.log("Loading sessions..."),await this.sessionManager.loadSessions(),this.log("Starting bot..."),await this.bot.launch(),this.log("Registering bot commands..."),await this.bot.telegram.setMyCommands([{command:"start",description:"Show welcome and command list"},{command:"help",description:"Show this command list"},{command:"clear",description:"Clear conversation history"},{command:"compact",description:"Compact conversation history"},{command:"model",description:"Switch Claude model (opus/sonnet/haiku)"}]),this.running=!0,this.log("Bot started successfully");let e=async n=>{this.log(`Received ${n}, shutting down...`),await this.stop(),process.exit(0)};process.once("SIGINT",()=>e("SIGINT")),process.once("SIGTERM",()=>e("SIGTERM"))}async stop(){if(this.running){this.log("Stopping bot..."),this.running=!1,this.log("Closing sessions..."),await this.sessionManager.closeAll(),this.log("Stopping bot polling...");try{this.bot.stop()}catch(e){this.log("Error stopping bot (may not have been started):",e)}this.log("Bot stopped")}}getStats(){return{running:this.running,activeSessions:this.sessionManager.getSessionCount(),totalChats:this.sessionManager.getChatCount()}}async handleStart(e){return tt(e)}async handleHelp(e){return nt(e,this.sessionManager)}async handleClear(e){let n=e.chat?.id;if(!n){await e.reply(O("Could not identify chat"));return}if((await this.sessionManager.getSession(n)).state!=="idle")this.messageHandler.enqueueClear(n,e),await e.reply("Clear queued.");else return rt(e,this.sessionManager,this.registeredCommandChats,this.log.bind(this))}async handleMessage(e){return this.messageHandler.handle(e)}async handleModelSwitch(e){return ot(e,this.sessionManager,this.log.bind(this))}log(...e){this.options.verbose&&console.log("[TelegramBot]",...e)}};function io(){return process.env.AFK_DEBUG==="1"||process.env.DEBUG==="1"}function A(...t){io()&&console.log(...t)}var G=class extends Error{constructor(e){super(e),this.name="AbortError"}},Me=class extends Error{constructor(n,r){super(n);this.timeoutMs=r;this.name="TimeoutError"}timeoutMs},U=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 ge=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};var _e=class{queue=[];waiters=[];closed=!1;error=null;push(e){if(this.closed)throw new Error("Cannot push to closed queue");if(process.env.AFK_CODEX_DEBUG&&console.log("[queue] push:",e.type),A("\u{1F4E6} MessageQueue.push: event type=",e.type,"waiters=",this.waiters.length,"queue size=",this.queue.length),this.waiters.length>0){let n=this.waiters.shift();A("\u{1F4E6} MessageQueue.push: Resolving waiter immediately"),n?.({value:e,done:!1})}else this.queue.push(e),A("\u{1F4E6} MessageQueue.push: Added to queue, new size=",this.queue.length)}complete(){for(this.closed=!0;this.waiters.length>0;)this.waiters.shift()?.({value:void 0,done:!0})}fail(e){this.error=e,this.closed=!0;let n={type:"error",error:e};if(this.waiters.length>0)for(this.waiters.shift()?.({value:n,done:!1});this.waiters.length>0;)this.waiters.shift()?.({value:void 0,done:!0});else this.queue.push(n)}isClosed(){return this.closed}hasError(){return this.error}size(){return this.queue.length}async*[Symbol.asyncIterator](){for(A("\u{1F4E6} MessageQueue: Iterator started");;){if(this.queue.length>0){let n=this.queue.shift();if(A("\u{1F4E6} MessageQueue: Yielding queued event, type=",n?.type),n&&(yield n,n.type==="error")){A("\u{1F4E6} MessageQueue: Stopping after error");return}continue}if(this.closed){A("\u{1F4E6} MessageQueue: Closed and empty, stopping");return}A("\u{1F4E6} MessageQueue: Waiting for next event...");let e=await new Promise(n=>{this.waiters.push(n)});if(A("\u{1F4E6} MessageQueue: Got result, done=",e.done,"type=",e.value?.type),e.done)return;if(yield e.value,e.value.type==="error"){A("\u{1F4E6} MessageQueue: Stopping after error");return}}}};import ra from"@anthropic-ai/sdk";var ao="claude-code-20250219,oauth-2025-04-20",lo="claude-cli/1.0.0 (external, cli)",co="x-anthropic-billing-header: cc_version=1.0.0.test; cc_entrypoint=cli; cch=00000;";function zt(t){return t.startsWith("sk-ant-oat01-")?"oauth":"api-key"}function Vt(t,e){return e==="oauth"?{authToken:t}:{apiKey:t}}function at(t,e,n){return t!=="oauth"?{}:{"anthropic-beta":ao,"x-app":"cli","User-Agent":lo,"X-Claude-Code-Session-Id":e,"x-client-request-id":n}}function qt(t){return t!=="oauth"?null:[{type:"text",text:co}]}import{randomUUID as Et}from"node:crypto";function Re(){let t=process.env.AFK_DISABLE_PROMPT_CACHE;if(t===void 0||t.length===0)return!0;let e=t.toLowerCase();return!(e==="1"||e==="true"||e==="yes"||e==="on")}function De(){let t=process.env.AFK_PROMPT_CACHE_TTL;return t==="5m"?"5m":"1h"}function Wt(t,e){if(t.length===0)return t;let n=t[t.length-1],r=Jt(n,e);return r===n?t:[...t.slice(0,-1),r]}function Yt(t,e){if(t.length===0)return t;let n=t[t.length-1],r=uo(n,e);return r===n?t:[...t.slice(0,-1),r]}function uo(t,e){let n=t.content;if(typeof n=="string")return n.length===0?t:{...t,content:[{type:"text",text:n,cache_control:{type:"ephemeral",ttl:e}}]};if(!Array.isArray(n)||n.length===0)return t;let r=n[n.length-1],o=Jt(r,e);return o===r?t:{...t,content:[...n.slice(0,-1),o]}}function Jt(t,e){return t.type==="thinking"||t.type==="redacted_thinking"?t:{...t,cache_control:{type:"ephemeral",ttl:e}}}import{randomUUID as mo}from"node:crypto";function Qt(t,e){if(!t)return{stopReason:e??null};let n={inputTokens:t.input_tokens,outputTokens:t.output_tokens,stopReason:e??null};return t.cache_read_input_tokens!=null&&(n.cachedInputTokens=t.cache_read_input_tokens),t.cache_creation_input_tokens!=null&&(n.cacheCreationTokens=t.cache_creation_input_tokens),n.totalTokens=(t.input_tokens??0)+(t.output_tokens??0),n}function Xt(t,e){let n=(c,d)=>{if(!(c==null&&d==null))return(c??0)+(d??0)},r={stopReason:e.stopReason??t.stopReason??null},o=n(t.inputTokens,e.inputTokens);o!==void 0&&(r.inputTokens=o);let s=n(t.outputTokens,e.outputTokens);s!==void 0&&(r.outputTokens=s);let i=n(t.cachedInputTokens,e.cachedInputTokens);i!==void 0&&(r.cachedInputTokens=i);let a=n(t.cacheCreationTokens,e.cacheCreationTokens);a!==void 0&&(r.cacheCreationTokens=a);let l=n(t.totalTokens,e.totalTokens);return l!==void 0&&(r.totalTokens=l),r}function po(t){let e=t.trim();if(e.length===0)return{};try{return JSON.parse(e)}catch{return{}}}function fo(t,e,n){let r=[],o=[];for(let a of t)a&&(a.kind==="text"?(r.push({type:"text",text:a.text}),o.push(a.text)):a.kind==="thinking"?r.push({type:"thinking",thinking:a.thinking,signature:a.signature}):r.push({type:"tool_use",id:a.id,name:a.name,input:po(a.partialJson)}));let s=a=>a.type==="tool_use",i=r.filter(s);return{stopReason:e,assistantBlocks:r,toolUseBlocks:i,usage:n,text:o.join("")}}async function*Zt(t,e){let n=[],r=null,o=null,s=!1;try{for await(let i of t){switch(i.type){case"message_start":{let a=i.message?.usage;a&&(o={...a});break}case"content_block_start":{let a=i.content_block;a.type==="text"?n[i.index]={kind:"text",text:""}:a.type==="thinking"?n[i.index]={kind:"thinking",thinking:"",signature:""}:a.type==="tool_use"&&(n[i.index]={kind:"tool_use",id:a.id,name:a.name,partialJson:""});break}case"content_block_delta":{let a=n[i.index],l=i.delta;l.type==="text_delta"?(a&&a.kind==="text"&&(a.text+=l.text),yield{kind:"event",event:{type:"delta.text",text:l.text,sessionId:e.sessionId}}):l.type==="input_json_delta"?a&&a.kind==="tool_use"&&(a.partialJson+=l.partial_json):l.type==="thinking_delta"?(a&&a.kind==="thinking"&&(a.thinking+=l.thinking),yield{kind:"event",event:{type:"delta.reasoning",text:l.thinking,sessionId:e.sessionId}}):l.type==="signature_delta"&&a&&a.kind==="thinking"&&(a.signature=l.signature);break}case"content_block_stop":{let a=n[i.index];a&&a.kind==="tool_use"&&(yield{kind:"event",event:{type:"tool.use",summary:a.name,toolUseIds:[a.id],sessionId:e.sessionId}});break}case"message_delta":{i.delta&&i.delta.stop_reason!==void 0&&(r=i.delta.stop_reason);let a=i.usage;a&&(o!==null?(o.output_tokens=a.output_tokens,a.cache_creation_input_tokens!=null&&(o.cache_creation_input_tokens=a.cache_creation_input_tokens),a.cache_read_input_tokens!=null&&(o.cache_read_input_tokens=a.cache_read_input_tokens),a.input_tokens!=null&&(o.input_tokens=a.input_tokens)):o={cache_creation:null,cache_creation_input_tokens:a.cache_creation_input_tokens??null,cache_read_input_tokens:a.cache_read_input_tokens??null,inference_geo:null,input_tokens:a.input_tokens??0,output_tokens:a.output_tokens,server_tool_use:null,service_tier:null});break}case"message_stop":{s=!0;break}default:break}if(s)break}}catch(i){yield{kind:"event",event:{type:"error",error:i instanceof Error?i:new Error(String(i))}};return}yield{kind:"turn-result",result:fo(n,r,o)}}var go=0;function ho(t){if(!t||typeof t!="object")return"";let e=t,n=e.file_path??e.path??e.filePath;if(typeof n=="string")return" "+n;let r=e.command??e.cmd;if(typeof r=="string"){let s=r.split(`
22
+ `)[0];return" "+(s.length>80?s.slice(0,77)+"\u2026":s)}let o=e.query??e.pattern??e.url??e.description;return typeof o=="string"?" "+o:""}async function*en(t){let e=t.maxToolUseIterations??go,n={stopReason:null},r=0,o=mo(),s=Date.now();for(;;){if(t.signal.aborted)return;let i=Re()?Yt(t.messages,De()):t.messages,a={model:t.model,max_tokens:t.maxTokens,messages:i,stream:!0,...t.system!==null?{system:t.system}:{},...t.tools!==null&&t.tools.length>0?{tools:t.tools}:{}},l;try{l=await Promise.resolve(t.client.messages.create(a,{headers:t.headers,signal:t.signal}))}catch(m){if(t.signal.aborted)return;yield{type:"error",error:m instanceof Error?m:new Error(String(m))};return}let c=null,d=!1;try{for await(let m of Zt(l,t.ctx))if(m.kind==="event"){if(m.event.type==="error"){yield m.event,d=!0;break}yield m.event}else{c=m.result;break}}catch(m){if(t.signal.aborted)return;yield{type:"error",error:m instanceof Error?m:new Error(String(m))};return}if(d)return;if(c===null){yield{type:"turn.completed",usage:n,sessionId:t.ctx.sessionId};return}if(n=Xt(n,Qt(c.usage,c.stopReason)),c.stopReason!=="tool_use"){c.text.length>0&&(yield{type:"assistant.message",text:c.text,sessionId:t.ctx.sessionId},c.text.length<=200&&(yield{type:"suggestion",suggestion:c.text,sessionId:t.ctx.sessionId})),yield{type:"turn.completed",usage:n,sessionId:t.ctx.sessionId};return}t.messages.push({role:"assistant",content:c.assistantBlocks});let u=[];for(let m of c.toolUseBlocks)u.push({id:m.id,name:m.name,input:m.input,signal:t.signal}),yield{type:"tool.use.start",toolUseId:m.id,toolName:m.name,toolInput:ho(m.input),sessionId:t.ctx.sessionId};if(t.signal.aborted)return;let p;if(t.toolDispatcher.executeBatch)p=await t.toolDispatcher.executeBatch(u);else{p=[];for(let m of u){if(t.signal.aborted){p.push({content:"Tool call aborted",isError:!0});continue}try{p.push(await t.toolDispatcher.execute(m))}catch(b){let S=b instanceof Error?b.message:String(b);p.push({content:`Tool execution threw: ${S}`,isError:!0})}}}let f=[];for(let m=0;m<u.length;m++){let b=u[m],S=p[m];yield{type:"tool.output",toolUseId:b.id,content:S.content,...S.isError===!0?{isError:!0}:{},sessionId:t.ctx.sessionId},f.push({type:"tool_result",tool_use_id:b.id,content:S.content,...S.isError===!0?{is_error:!0}:{}})}let g={role:"user",content:f};t.messages.push(g),r+=1;let h=c.toolUseBlocks[c.toolUseBlocks.length-1];if(yield{type:"progress",progress:{taskId:o,description:"Tool-use loop",summary:`Iteration ${r}: used ${h?.name??"unknown"}`,lastToolName:h?.name,totalTokens:n.totalTokens??0,toolUses:r,durationMs:Date.now()-s},sessionId:t.ctx.sessionId},e>0&&r>=e){yield{type:"turn.completed",usage:{...n,stopReason:"tool_use_loop_capped"},sessionId:t.ctx.sessionId};return}}}var yo=["You are a conversation-summarization assistant. The user will paste a","prior conversation between a user and an AI assistant that includes tool","calls and tool results. Produce a concise but complete summary that lets","the AI continue the conversation without losing track.","","Preserve, in this priority order:","1. The user's original intent, explicit asks, constraints, corrections,"," and preferences stated during the conversation.","2. Tool decisions and their outcomes \u2014 file paths read or written, shell"," commands run, search queries, URLs fetched, code edits made, tests"," run, errors observed, and whether each action succeeded or failed.","3. Current state: what has been completed, what remains unresolved, and"," the safest next action.","4. Open questions, pending decisions, blockers, and assumptions.","5. Key facts the assistant discovered (function locations, schemas,"," observed behaviors, important external findings).","","Drop prose narration, conversational filler, and exploratory dead-ends.","Drop verbatim tool output unless an exact snippet, error, path, command,","or result is needed for continuation.","Do not invent details. If something is uncertain, mark it explicitly.","Output plain text, no markdown headers. Aim for ~250 words; use up to","~400 only when needed to preserve tool state or unresolved tasks."].join(`
23
+ `),tn="[Compacted summary of earlier conversation]",nn="Acknowledged. Continuing from the summary above.";function bo(t){if(t.role!=="user")return!1;let e=t.content;if(typeof e=="string")return!0;if(!Array.isArray(e))return!1;for(let n of e)if(n.type==="tool_result")return!1;return!0}function rn(t,e){if(e<=0)return t.length;let n=0;for(let r=t.length-1;r>=0;r--){let o=t[r];if(o&&bo(o)&&(n+=1,n===e))return r}return-1}function on(t,e,n){let r=vo(t);return{model:e,max_tokens:n,system:yo,messages:[{role:"user",content:`Summarize the following conversation transcript. Follow the system instructions exactly.
24
+
25
+ <transcript>
26
+ `+r+`
27
+ </transcript>`}],stream:!0}}function sn(t,e,n){return[{role:"user",content:tn+`
28
+
29
+ `+n},{role:"assistant",content:nn},...t.slice(e)]}function an(t,e,n){let r=wo(t.slice(0,e)),o=tn.length+2+n.length+nn.length,s=Math.max(0,r-o);return Math.round(s/4)}function vo(t){let e=[];for(let n of t){let r=n.role==="user"?"User":"Assistant";if(e.push(r+":"),typeof n.content=="string")e.push(n.content);else if(Array.isArray(n.content))for(let o of n.content){let s=o.type;if(s==="text"&&"text"in o)e.push(o.text);else if(s==="tool_use"){let i=o.name??"unknown",a=ln(o.input);e.push(`[tool call: ${i} ${a}]`)}else if(s==="tool_result"){let i=o.content;e.push(`[tool result: ${cn(i)}]`)}else s==="image"?e.push("[image]"):s==="document"&&e.push("[document]")}e.push("")}return e.join(`
30
+ `).trim()}function ln(t){try{let e=JSON.stringify(t);return e.length>240?e.slice(0,237)+"...":e}catch{return"{}"}}function cn(t){if(typeof t=="string")return t.length>320?t.slice(0,317)+"...":t;if(Array.isArray(t)){let e=[];for(let r of t)r.type==="text"&&"text"in r&&e.push(r.text);let n=e.join(" ");return n.length>320?n.slice(0,317)+"...":n}return""}function wo(t){let e=0;for(let n of t)if(typeof n.content=="string")e+=n.content.length;else if(Array.isArray(n.content))for(let r of n.content){let o=r.type;o==="text"&&"text"in r?e+=r.text.length:o==="tool_use"?e+=ln(r.input).length:o==="tool_result"&&(e+=cn(r.content).length)}return e}import{z as I}from"zod";import{mkdir as Dn,appendFile as On}from"fs/promises";import{join as be}from"path";var dn={"audit-fit":{"01-skill-inspector.md":`# Skill Inspector
31
+
32
+ You are an inspector auditing skills for correct type categorization. Skills come from two sources:
33
+ - **User-scope** \u2014 authored directly by the user under \`~/.afk/skills/<name>/SKILL.md\`
34
+ - **Plugin-scope** \u2014 shipped by an installed plugin under \`~/.afk/plugins/<plugin>/skills/<name>/SKILL.md\`
35
+
36
+ The handler has already discovered every skill path in TypeScript and templates them into the section below. **Do not Glob**; just read each path and emit a verdict.
37
+
38
+ ## Task
39
+
40
+ For each skill path, read the SKILL.md and extract:
41
+ - Frontmatter: \`disable-model-invocation\`, \`argument-hint\`
42
+ - Body length (word count)
43
+ - Presence of \`scripts/\`, \`references/\`, \`assets/\` subdirectories
44
+ - Orchestration language indicators (sub-agent dispatch, decision branching, multi-step workflow)
45
+ - Progressive-disclosure value (does the body teach a methodology that benefits from multi-prompt loading?)
46
+
47
+ For each skill, apply the decision heuristics and return a JSON verdict with the matching \`source\` and (for plugin-scope) \`plugin_key\` from the templated section.
48
+
49
+ ## Decision Heuristics (Authoritative)
50
+
51
+ **Skill is correct** if it meets ANY of:
52
+ - Has \`scripts/\` OR \`references/\` subdirectory (supporting resources)
53
+ - Body >200 words AND demonstrates progressive-disclosure value (multi-prompt structure teaches methodology; reader benefits from incremental loading)
54
+ - Clear model-chosen activation lift (Claude auto-invokes when the task description matches the skill's domain)
55
+
56
+ **Skill \u2192 command (misfit)** if ALL of:
57
+ - \`disable-model-invocation: true\`
58
+ - No \`scripts/\` or \`references/\` subdirectory
59
+ - Body <150 words
60
+
61
+ **Outliers** (orthogonal to misfit):
62
+ - Body >1000 words (split candidate \u2014 too large for one skill)
63
+ - Missing frontmatter (required \`name\`, \`description\`)
64
+ - Duplicate frontmatter keys
65
+
66
+ ## Output Format
67
+
68
+ End your response with a single fenced JSON array containing one verdict object per skill. The runtime extracts the structured output from the last fenced JSON block in your response, so this array must be the final fenced block:
69
+
70
+ \`\`\`json
71
+ [
72
+ {
73
+ "path": "<absolute path from the templated list>",
74
+ "type": "skill",
75
+ "source": "user|plugin",
76
+ "plugin_key": "<key from the templated list, omit when source is user>",
77
+ "verdict": "correct|misfit|outlier",
78
+ "recommended_type": "skill|command",
79
+ "rationale": "...",
80
+ "confidence": "high|med|low"
81
+ }
82
+ ]
83
+ \`\`\`
84
+
85
+ Emit one entry per skill discovered.
86
+
87
+ ## Tools
88
+
89
+ Use Read, Grep, Glob only. Do not use Edit, Write, or Bash. Use Glob only when you need to inspect a skill's \`scripts/\`/\`references/\`/\`assets/\` subdirectories \u2014 never to discover additional skills (the list below is exhaustive).
90
+
91
+ ## Process
92
+
93
+ 1. Iterate the templated skill list below.
94
+ 2. Read each SKILL.md.
95
+ 3. Extract the signals above.
96
+ 4. Apply the heuristics.
97
+ 5. Emit a JSON verdict per skill, copying \`source\` and \`plugin_key\` straight from the list entry.
98
+ `,"02-command-inspector.md":`# Command Inspector
99
+
100
+ You are an inspector auditing commands for correct type categorization. Commands come from two sources:
101
+ - **User-scope** \u2014 authored directly by the user under \`~/.afk/commands/<name>.md\`
102
+ - **Plugin-scope** \u2014 shipped by an installed plugin under \`~/.afk/plugins/<plugin>/commands/<name>.md\`
103
+
104
+ The handler has already discovered every command path in TypeScript and templates them into the section below. **Do not Glob**; just read each path and emit a verdict.
105
+
106
+ ## Task
107
+
108
+ For each command path, read the file and extract:
109
+ - \`\${ARGUMENTS}\` usage pattern (parameterized or hardcoded)
110
+ - Body length (word count)
111
+ - Orchestration language (mentions of sub-agent dispatch, multi-step workflows, decision branching)
112
+ - User-triggered workflow (is this a user-initiated request or automatic behavior?)
113
+
114
+ For each command, apply the decision heuristics and return a JSON verdict with the matching \`source\` and (for plugin-scope) \`plugin_key\` from the templated section.
115
+
116
+ ## Decision Heuristics (Authoritative)
117
+
118
+ **Command is correct** if:
119
+ - User-triggered static prompt, no orchestration, minimal branching
120
+ - Single step or closely coupled multi-step (e.g., fetch data + format)
121
+
122
+ **Command \u2192 skill (misfit)** if:
123
+ - Body describes multi-step workflow with decision points
124
+ - Explicitly dispatches sub-agents or agents
125
+ - Benefits from progressive disclosure (body teaches methodology that incremental prompt-loading would benefit)
126
+ - Has significant branching logic based on context
127
+
128
+ **Note:** Commands are back-compat aliases for skills (as of 2026); new multi-step work should use skills.
129
+
130
+ **Outliers**:
131
+ - Empty body (broken command)
132
+ - Duplicate frontmatter
133
+ - Unresolved variable references
134
+
135
+ ## Output Format
136
+
137
+ End your response with a single fenced JSON array containing one verdict object per command. The runtime extracts the structured output from the last fenced JSON block in your response, so this array must be the final fenced block:
138
+
139
+ \`\`\`json
140
+ [
141
+ {
142
+ "path": "<absolute path from the templated list>",
143
+ "type": "command",
144
+ "source": "user|plugin",
145
+ "plugin_key": "<key from the templated list, omit when source is user>",
146
+ "verdict": "correct|misfit|outlier",
147
+ "recommended_type": "skill|command",
148
+ "rationale": "...",
149
+ "confidence": "high|med|low"
150
+ }
151
+ ]
152
+ \`\`\`
153
+
154
+ Emit one entry per command discovered.
155
+
156
+ ## Tools
157
+
158
+ Use Read, Grep, Glob only. Do not use Edit, Write, or Bash. Do not Glob to discover commands \u2014 the list below is exhaustive.
159
+
160
+ ## Process
161
+
162
+ 1. Iterate the templated command list below.
163
+ 2. Read each file.
164
+ 3. Extract the signals above.
165
+ 4. Apply the heuristics.
166
+ 5. Emit a JSON verdict per command, copying \`source\` and \`plugin_key\` straight from the list entry.
167
+ `,"03-agent-inspector.md":`# Agent Inspector
168
+
169
+ You are an inspector auditing agents for correct type categorization. Agents come from two sources:
170
+ - **User-scope** \u2014 authored directly by the user under \`~/.afk/agents/<name>.md\`
171
+ - **Plugin-scope** \u2014 shipped by an installed plugin under \`~/.afk/plugins/<plugin>/agents/<name>.md\`
172
+
173
+ The handler has already discovered every agent path in TypeScript and templates them into the section below. **Do not Glob**; just read each path and emit a verdict.
174
+
175
+ ## Task
176
+
177
+ For each agent path, read the file and extract:
178
+ - Frontmatter: \`tools\` whitelist, \`model\` override
179
+ - Body length (word count)
180
+ - Isolation rationale (does the body explain why isolated context is needed?)
181
+ - Tool restrictions (does frontmatter restrict which tools are allowed?)
182
+ - Whether the agent references any tools in the prompt
183
+
184
+ For each agent, apply the decision heuristics and return a JSON verdict with the matching \`source\` and (for plugin-scope) \`plugin_key\` from the templated section.
185
+
186
+ ## Decision Heuristics (Authoritative)
187
+
188
+ **Agent is correct** if it meets ANY of:
189
+ - Needs isolated context (body explains isolation requirement, e.g., "prevent side effects", "sandbox", "independent reasoning")
190
+ - Has \`tools\` whitelist in frontmatter (explicit tool restriction)
191
+ - Has \`model\` override in frontmatter (different model for this isolated task)
192
+
193
+ **Agent \u2192 skill with \`context: fork\` (misfit)** if ALL of:
194
+ - NO \`tools\` whitelist in frontmatter (no tool restriction)
195
+ - NO \`model\` override in frontmatter
196
+ - Body is a plain prompt with no isolation rationale
197
+ - Does not reference specific tools to restrict
198
+
199
+ **Outliers**:
200
+ - References no tools at all (not task-specific; borderline wrong domain)
201
+ - Missing frontmatter
202
+ - Malformed YAML
203
+
204
+ ## Output Format
205
+
206
+ End your response with a single fenced JSON array containing one verdict object per agent. The runtime extracts the structured output from the last fenced JSON block in your response, so this array must be the final fenced block:
207
+
208
+ \`\`\`json
209
+ [
210
+ {
211
+ "path": "<absolute path from the templated list>",
212
+ "type": "agent",
213
+ "source": "user|plugin",
214
+ "plugin_key": "<key from the templated list, omit when source is user>",
215
+ "verdict": "correct|misfit|outlier",
216
+ "recommended_type": "skill|agent",
217
+ "rationale": "...",
218
+ "confidence": "high|med|low"
219
+ }
220
+ ]
221
+ \`\`\`
222
+
223
+ Emit one entry per agent discovered.
224
+
225
+ ## Tools
226
+
227
+ Use Read, Grep, Glob only. Do not use Edit, Write, or Bash. Do not Glob to discover agents \u2014 the list below is exhaustive.
228
+
229
+ ## Process
230
+
231
+ 1. Iterate the templated agent list below.
232
+ 2. Read each file.
233
+ 3. Extract the signals above.
234
+ 4. Apply the heuristics.
235
+ 5. Emit a JSON verdict per agent, copying \`source\` and \`plugin_key\` straight from the list entry.
236
+ `,"04-hook-inspector.md":`# Hook Inspector
237
+
238
+ You are an inspector auditing pre-discovered AFK hooks for correct type categorization. In the agent-afk runtime, hooks live in \`~/.afk/settings.json\` (mirroring Claude Code's \`~/.claude/settings.json\` shape), but the entries you must audit have already been pre-read and inlined into the **Discovered hooks** section appended to this prompt. Use only those entries \u2014 do **not** Read the settings file yourself, and do **not** transform \`~\` into a guessed home directory. Hooks are always **user-scope** \u2014 plugins do not contribute hooks at this layer.
239
+
240
+ ## Task
241
+
242
+ For each hook listed in the **Discovered hooks** section:
243
+ - Note its event type (SessionStart, SubagentStop, etc.) \u2014 encoded in the hook ID as \`<event>-<index>\`
244
+ - Read the referenced script file. The script path appears inside the inlined \`command\` field; use it verbatim and do not alter \`~\` (script paths in settings.json are typically already absolute)
245
+ - Determine if the script performs deterministic side-effects (logging, telemetry, enforcement) vs. reasoning content
246
+
247
+ For each hook, apply the decision heuristics and return a JSON verdict.
248
+
249
+ ## Decision Heuristics (Authoritative)
250
+
251
+ **Hook is correct** if it performs deterministic side-effects:
252
+ - Logging, telemetry, metrics recording
253
+ - Enforcement (permission checks, validation)
254
+ - Simple state transitions (flag setting, cleanup)
255
+ - No model reasoning required
256
+
257
+ **Hook \u2192 skill (misfit)** if:
258
+ - Script describes model reasoning or decision logic
259
+ - Body describes multi-step workflow with decision points
260
+ - Could benefit from tool access or Claude's judgment
261
+ - Contains natural language instruction that looks like a prompt
262
+
263
+ **Outliers**:
264
+ - Broken reference (script doesn't exist)
265
+ - Malformed hook configuration
266
+ - Event type not recognized
267
+
268
+ ## Output Format
269
+
270
+ End your response with a single fenced JSON array containing one verdict object per hook. Use the absolute settings-file path provided in the Discovered hooks section as the \`path\` field \u2014 never substitute a tilde-prefixed form. Always set \`source: "user"\` (hooks have no plugin scope). The runtime extracts the structured output from the last fenced JSON block in your response, so this array must be the final fenced block:
271
+
272
+ \`\`\`json
273
+ [
274
+ {
275
+ "path": "<absolute settings.json path from Discovered hooks section>",
276
+ "hook_id": "<event_type>-<index>",
277
+ "type": "hook",
278
+ "source": "user",
279
+ "verdict": "correct|misfit|outlier",
280
+ "recommended_type": "hook|skill",
281
+ "rationale": "...",
282
+ "confidence": "high|med|low"
283
+ }
284
+ ]
285
+ \`\`\`
286
+
287
+ Emit one entry per hook discovered.
288
+
289
+ ## Tools
290
+
291
+ Use Read, Grep, Glob only. Do not use Edit, Write, or Bash.
292
+
293
+ ## Process
294
+
295
+ 1. Iterate the entries in the **Discovered hooks** section (one entry per hook ID)
296
+ 2. Extract the \`command\` (or other script reference) field from the inlined entry
297
+ 3. Read the referenced script file using the path as written
298
+ 4. Extract the signals above
299
+ 5. Apply the heuristics
300
+ 6. Emit JSON verdicts
301
+ `},diagnose:{"hypothesis.md":`# Hypothesis Synthesis Prompt
302
+
303
+ You are synthesizing ranked hypotheses from parallel research findings (codebase analysis + git history audit).
304
+
305
+ Given:
306
+ - Research findings from codebase investigation (code paths, logic issues, type mismatches)
307
+ - Research findings from git history (recent commits, blame info, dependency changes)
308
+ - The original failure description and reproducer
309
+
310
+ Your job:
311
+ 1. Cross-reference findings from both research subagents
312
+ 2. Group related findings into coherent root-cause hypotheses
313
+ 3. Rank them by confidence (evidence quality + relevance)
314
+ 4. Generate 2\u20134 hypotheses maximum (HARD CAP at 4)
315
+ 5. For each hypothesis, specify:
316
+ - A short claim (what is broken)
317
+ - A specific code location (where to look)
318
+ - A proposed minimal fix (what change would validate it)
319
+ - Confidence score (0\u20131)
320
+ - Evidence sources (which findings support this hypothesis)
321
+ - \`coverage_gaps\` (optional): things you could not read or verify that would strengthen the hypothesis \u2014 list as strings, leave empty/omitted when there are none. Be honest; "none" is a valid answer.
322
+ - \`boundary_flag\` (optional): set to a short string when you hit an epistemic boundary (timeout, blocked tool, ambiguous evidence) that the caller should know about; omit when none.
323
+
324
+ These epistemic fields feed a downstream confidence gate: low-confidence, gap-bearing, or boundary-flagged hypotheses get independently re-checked by /shadow-verify before worktree testing. Reporting gaps honestly is rewarded, not penalized \u2014 a confident claim with an unresolved gap is more useful than a confident claim that hides one.
325
+
326
+ Output as JSON conforming to:
327
+ \`\`\`json
328
+ {
329
+ "hypotheses": [
330
+ {
331
+ "id": "h1",
332
+ "claim": "Type mismatch in function signature at src/file.ts:42",
333
+ "location": "src/file.ts:42",
334
+ "proposed_fix": "Change parameter type from string to number",
335
+ "confidence": 0.85,
336
+ "evidence_sources": ["codebase-finding-1", "git-finding-2"],
337
+ "coverage_gaps": ["could not read src/types/user.ts \u2014 outside search scope"],
338
+ "boundary_flag": "Grep timed out on node_modules"
339
+ }
340
+ ]
341
+ }
342
+ \`\`\`
343
+
344
+ Rank by confidence (highest first). Always cap at 4 hypotheses.
345
+ `,"research.md":`# Research Prompt
346
+
347
+ You are a code researcher tasked with identifying potential root causes for a bug or test failure.
348
+
349
+ Given:
350
+ - A failing test or bug description
351
+ - A specific focus area (codebase OR git history)
352
+ - A repository path
353
+
354
+ Your job:
355
+ - For **codebase focus**: Search for code paths related to the failure. Look for recent changes, missing error handling, type mismatches, race conditions, or incorrect logic. Identify specific file locations and line numbers.
356
+ - For **git focus**: Analyze recent commits and diffs that could have introduced the regression. Check blame history, related changes, and dependency updates. Link findings to specific commits.
357
+
358
+ Output findings as structured data:
359
+ \`\`\`json
360
+ {
361
+ "findings": [
362
+ {
363
+ "location": "src/path/file.ts:42",
364
+ "category": "logic|type|error-handling|dependency|race-condition",
365
+ "description": "Brief description of the finding",
366
+ "confidence": 0.8,
367
+ "related_commits": ["abc1234", "def5678"]
368
+ }
369
+ ],
370
+ "summary": "Overall summary of the investigation"
371
+ }
372
+ \`\`\`
373
+
374
+ Focus on evidence-based findings with specific locations and confidence levels.
375
+ `,"system.md":`# Diagnose System Prompt
376
+
377
+ You are a parallel root-cause analysis expert for bugs and failing tests.
378
+
379
+ Your role:
380
+ 1. Ensure there's a concrete reproducer (minimal failing test or verification command) before forming hypotheses
381
+ 2. Coordinate two parallel research subagents (codebase analysis + git history audit)
382
+ 3. Synthesize 2\u20134 ranked hypotheses from their findings
383
+ 4. Coordinate isolated hypothesis testing in separate git worktrees
384
+ 5. Validate the root cause and propose a minimal fix
385
+
386
+ Key principles:
387
+ - **Hypothesis focus**: each hypothesis must have a specific code location and proposed cause
388
+ - **Isolation**: each hypothesis is tested in its own worktree to avoid contamination
389
+ - **Parallelism**: research and testing happen concurrently
390
+ - **Evidence-driven**: rank hypotheses by likelihood; prefer those with the most supporting evidence
391
+ - **Hard cap**: never form more than 4 hypotheses (per parallelization constraints)
392
+
393
+ When the user provides a failure (test output, bug description, or error message):
394
+ 1. Check if a reproducer exists; if not, request or write a minimal one
395
+ 2. Request parallel research on codebase paths and git history
396
+ 3. Synthesize findings into ranked hypotheses (max 4)
397
+ 4. Request hypothesis testing in isolated worktrees
398
+ 5. Report the validated root cause and any regressions
399
+
400
+ Output structured findings as JSON.
401
+ `,"verify.md":`# Verification Prompt
402
+
403
+ You are testing a hypothesis in an isolated worktree to determine if a proposed fix resolves the failure.
404
+
405
+ Given:
406
+ - A hypothesis with a specific code location and proposed fix
407
+ - A reproducer command or failing test
408
+ - An isolated git worktree (NOT main branch)
409
+
410
+ Your job:
411
+ 1. Apply the proposed minimal fix to the code
412
+ 2. Run the reproducer to check if the test/command now passes
413
+ 3. Run related test suite to check for regressions
414
+ 4. Report findings:
415
+ - Did the fix pass the reproducer? (pass/fail)
416
+ - Were there any regressions? (list any new failures)
417
+ - Confidence that this is the root cause (0\u20131)
418
+ - Verification log (command outputs, key observations)
419
+
420
+ Output as JSON:
421
+ \`\`\`json
422
+ {
423
+ "hypothesis_id": "h1",
424
+ "reproducer_passed": true,
425
+ "regressions": [],
426
+ "confidence": 0.9,
427
+ "verification_log": "Applied fix at src/file.ts:42. Ran test suite: all 15 tests passed."
428
+ }
429
+ \`\`\`
430
+
431
+ Be thorough: test not only the specific fix but also adjacent code paths that might be affected.
432
+
433
+ IMPORTANT: You are working in an isolated worktree with read-only restrictions. Do not commit changes \u2014 only read, test, and report findings. Edit, Write, and Bash tools are disabled for safety.
434
+ `},"example-template":{"system.md":`# System Prompt
435
+
436
+ You are an example template skill demonstrating the multi-prompt loader pattern.
437
+
438
+ Your role is to showcase how skills load markdown prompts from a \`prompts/\` directory and merge them into a single system prompt for subagent dispatch.
439
+ `,"user.md":`# User Instruction
440
+
441
+ Example user instruction for the template skill.
442
+
443
+ This prompt demonstrates how multiple markdown files are loaded, sorted alphabetically, and merged into a single prompt for subagent execution.
444
+ `},forge:{"gap-discovery.md":`## Autonomous gap discovery
445
+
446
+ Dispatch two parallel sub-agents:
447
+
448
+ **Agent 1: Skill Catalog & Convention Extraction**
449
+ - Read every existing \`skills/*/SKILL.md\` in this plugin
450
+ - Extract and catalog what workflows are covered (e.g., planning, diagnosis, verification, code generation)
451
+ - Identify the amplifier conventions: frontmatter format, section headings, sub-agent contracts, writing style, compactness
452
+ - List gaps in orchestration coverage \u2014 workflows that would benefit from a new amplifier skill but don't have one yet
453
+ - Return a structured list of gaps with brief rationales
454
+
455
+ **Agent 2: Emerging Patterns & Best Practices**
456
+ - Research the web for emerging agent orchestration patterns (multi-agent systems, parallel verification, iterative improvement loops)
457
+ - Identify common pain points in LLM-based automation (e.g., tool safety, output validation, error recovery)
458
+ - Find new capabilities worth amplifying (e.g., novel approaches to verification, constraint handling, or multi-step planning)
459
+ - Return key findings and references
460
+
461
+ When both return, synthesize findings:
462
+ 1. Identify the **most impactful uncovered workflow** (highest leverage for agent automation)
463
+ 2. Propose a **new skill concept** \u2014 name, description, high-level orchestration (sub-agents involved, decision points, flow)
464
+ 3. Return the synthesis as a candidate brief/concept for qualification
465
+ `,"generate.md":`## Skill generation
466
+
467
+ Given a brief or autonomous gap-discovery concept, create a compact SKILL.md following the amplifier conventions:
468
+
469
+ **Output format:**
470
+ \`\`\`markdown
471
+ ---
472
+ name: <skill-name>
473
+ description: "<one-line description, 50-100 words, emphasizing the force multiplier>"
474
+ ---
475
+
476
+ ## Sub-agent contract
477
+ /<subagent-type-ref>
478
+
479
+ <2-3 short paragraphs explaining the orchestration: what sub-agents run, decision points, output structure>
480
+ \`\`\`
481
+
482
+ **Style guidelines:**
483
+ - Skill names are lowercase with hyphens (e.g., \`forge\`, \`shadow-verify\`)
484
+ - Descriptions are imperative and action-focused ("Creates...", "Dispatches...", "Validates...")
485
+ - Each skill references one or more sub-agent contracts (e.g., \`awa-dev:qualify\`, \`contract\`)
486
+ - Keep the SKILL.md under 200 lines total \u2014 orchestration, not prose
487
+ - Prioritize clarity over completeness; implementation details go in the subagent contracts
488
+
489
+ **Amplifier conventions (study existing skills for reference):**
490
+ - Skill solves a recurring orchestration problem (multi-agent coordination, verification, iteration)
491
+ - Each skill dispatches at least one subagent
492
+ - Outputs are deterministic and machine-readable where possible
493
+ - Error handling is explicit (e.g., "max 3 iterations", "APPROVE/SALVAGE/REJECT verdicts")
494
+
495
+ Return the generated SKILL.md as a complete markdown string, ready to write to disk.
496
+ `,"qualify-rework.md":`## Rework on SALVAGE feedback
497
+
498
+ You received SALVAGE feedback on a skill draft. Your job is to refine it based on the feedback and re-qualify:
499
+
500
+ **Feedback from qualify:**
501
+ {feedback}
502
+
503
+ **Original skill draft:**
504
+ {original_skill}
505
+
506
+ **Rework plan:**
507
+ 1. Analyze the feedback \u2014 identify specific issues: missing detail, unclear orchestration, weak motivation, incorrect conventions
508
+ 2. Refine the skill draft to address these issues
509
+ 3. Preserve the core insight and orchestration pattern; improve clarity and convention compliance
510
+ 4. Return the revised SKILL.md (complete, ready to qualify again)
511
+
512
+ **Output:**
513
+ Return only the revised SKILL.md markdown block. No preamble, no explanation \u2014 just the refined skill definition.
514
+ `,"system.md":`## Sub-agent contract
515
+ /agent-workflow-amplifiers:contract
516
+
517
+ You are orchestrating the creation of a new amplifier skill. Your job is to guide the user or autonomous workflow through:
518
+
519
+ 1. **Gap discovery** (if no brief provided): catalog existing skills, identify orchestration gaps, and propose a new skill concept.
520
+ 2. **Skill generation**: create a compact SKILL.md following the amplifier conventions (concise description, orchestration idioms, sub-agent contracts, clear implementation steps).
521
+ 3. **Qualification loop**: dispatch the qualify agent up to 3 times to validate the skill against the force multiplier criteria.
522
+ 4. **Approval and archival**: on APPROVE, write the skill to the plugin; on final REJECT, report the best attempt and archive to failed/.
523
+
524
+ Always stamp outputs with \`surface: "atlas"\` for telemetry.
525
+ `},mint:{"build.md":`# Phase 5: Build
526
+
527
+ You are a developer executing an implementation plan. Your task is to write code that realizes the specification and passes the tests defined in the plan.
528
+
529
+ ## Input
530
+ You are given:
531
+ - The implementation plan from Phase 3 (files, order, test strategy, verification commands)
532
+ - Optionally: a wave orchestration plan from Phase 4 (if the work is complex enough to parallelize)
533
+
534
+ ## Your Task
535
+
536
+ **TDD-first approach:**
537
+ 1. Read the plan carefully
538
+ 2. Write tests first for the most critical functionality
539
+ 3. Implement the code to pass those tests
540
+ 4. Run the verification commands to ensure nothing breaks
541
+
542
+ **Implementation steps:**
543
+ 1. Start with the foundational pieces (lowest dependencies first)
544
+ 2. Write clean, well-tested code
545
+ 3. Follow the project's conventions and patterns
546
+ 4. Run tests and type-checks frequently
547
+
548
+ **Verification:**
549
+ - Run all specified test commands
550
+ - Run linting and type-checking
551
+ - Build the project if applicable
552
+
553
+ ## Output
554
+
555
+ Respond with a single fenced JSON code block and no prose outside it. The JSON must conform to:
556
+
557
+ \`\`\`json
558
+ {
559
+ "status": "PASS",
560
+ "status_reason": "short reason \u2014 only when status is FAIL, omit otherwise",
561
+ "files_changed": ["src/example.ts"],
562
+ "tests_passed": true,
563
+ "build_passed": true,
564
+ "verification_passed": true,
565
+ "notes": "Concise summary of what was built, what verification ran, and any issues or decisions."
566
+ }
567
+ \`\`\`
568
+
569
+ Field semantics:
570
+ - \`status\` \u2014 \`"PASS"\` if implementation is complete and all tests pass; \`"FAIL"\` otherwise.
571
+ - \`status_reason\` \u2014 short reason when \`FAIL\`; omit when \`PASS\`.
572
+ - \`files_changed\` \u2014 every file you created or modified, as repo-relative paths.
573
+ - \`tests_passed\` \u2014 did all specified tests pass?
574
+ - \`build_passed\` / \`verification_passed\` \u2014 optional booleans for projects with a build step or extra verification commands; omit when not applicable.
575
+ - \`notes\` \u2014 human-readable summary that the next phase will read. Keep it concise.
576
+ `,"heal.md":`# Phase 7: Heal
577
+
578
+ You are a fixer. Your task is to resolve failures identified in the verify phase. This phase runs in a loop, capped at 2 iterations.
579
+
580
+ ## Input
581
+ You are given:
582
+ - **Failure diagnosis**: From \`/diagnose\` (root-cause analysis for bugs)
583
+ - **Current implementation**: The code and plan from previous phases
584
+ - **Verification report**: What failed (test failures, lint errors, design-review reds)
585
+
586
+ ## Your Task
587
+
588
+ 1. **Read the diagnosis** \u2014 what's the root cause?
589
+ 2. **Apply targeted fixes** \u2014 make minimal, focused changes to resolve the failure.
590
+ 3. **Verify the fix** \u2014 run the verification commands to confirm the issue is resolved.
591
+ 4. **Document** \u2014 explain what was fixed and why.
592
+
593
+ **Healing strategy:**
594
+ - Fix one issue at a time when possible.
595
+ - Prefer small, surgical changes over large refactors.
596
+ - Test immediately after each fix.
597
+
598
+ **Constraints:**
599
+ - This phase runs at most 2 times. After 2 iterations, if issues remain, the run exits as \`heal-failed\`.
600
+ - Do not attempt massive rewrites. If an issue requires fundamental redesign, document that and exit.
601
+
602
+ ## Output
603
+
604
+ The **first line** of your response MUST be a machine-readable marker:
605
+
606
+ - \`FIX_APPLIED: true\` \u2014 you actually applied at least one fix to the codebase.
607
+ - \`FIX_APPLIED: false\` \u2014 you could not apply a fix this iteration (root cause unclear, fix would require redesign, environment problem, etc.).
608
+
609
+ After the marker line, provide a prose narrative covering:
610
+ - **Fixed items** \u2014 what did you fix?
611
+ - **Verification status** \u2014 do tests pass now?
612
+ - **Remaining issues** \u2014 if any, what are they?
613
+ - **Next steps** \u2014 if healed, ready for ship; if not, what blockers remain?
614
+
615
+ When \`FIX_APPLIED: false\`, the orchestrator skips the immediate re-verification and increments the heal counter directly. Be honest \u2014 claiming \`true\` when no fix landed wastes an iteration on a re-verify that will fail with the same issues.
616
+ `,"plan.md":`# Phase 3: Plan
617
+
618
+ You are a technical planner. Your task is to create a concrete, actionable implementation plan based on the specification and research context.
619
+
620
+ ## Input
621
+ You are given:
622
+ - The specification from Phase 1 (problem statement, scope, success criteria)
623
+ - The research brief from Phase 2 (existing patterns, architectural context, recommendations)
624
+
625
+ ## Your Task
626
+
627
+ 1. **Identify the files and modules**:
628
+ - What files need to be created or modified?
629
+ - Group them by functional area or layer
630
+ - Note any interdependencies (file A must be done before B)
631
+
632
+ 2. **Define implementation lanes**:
633
+ - Can this work be parallelized?
634
+ - What must be sequential vs. what can run in parallel?
635
+ - If it's complex, we'll send this plan to Phase 4 (parallelize) to create optimized waves
636
+
637
+ 3. **Test plan**:
638
+ - What tests are needed? (unit, integration, e2e)
639
+ - TDD approach: what should tests cover first?
640
+ - Verification commands to run after implementation
641
+
642
+ 4. **Verification**:
643
+ - What commands verify the implementation? (npm test, linting, type-checking, build)
644
+ - What specific criteria must pass?
645
+
646
+ ## Output
647
+
648
+ Return a detailed implementation plan (800\u20131200 words) that includes:
649
+ - **Files to touch** (create/modify), with a brief description of each
650
+ - **Implementation order**: What must be done first, what depends on what
651
+ - **Test-first approach**: Write tests before implementation; specify what each test validates
652
+ - **Verification commands**: Exact commands to validate the work (npm test, lint, type-check, build)
653
+ - **Potential blockers**: Anything that might complicate the work
654
+
655
+ Format the plan clearly so that an automated system can parse file lists, dependencies, and commands.
656
+ `,"research.md":`# Phase 2: Research
657
+
658
+ You are a context researcher. Your task is to gather internal and external context needed to plan and build the feature described in the specification.
659
+
660
+ ## Input
661
+ You are given the specification from Phase 1. Your job is to surface:
662
+ - Existing patterns in the codebase (similar implementations, utilities, libraries already in use)
663
+ - External research (API docs, best practices, reference implementations)
664
+ - Architectural constraints or patterns this project follows
665
+ - Known pain points or related code that might interact with this change
666
+
667
+ ## Your Task
668
+
669
+ 1. **Codebase exploration**:
670
+ - Search for existing similar functionality
671
+ - Identify relevant utilities or shared patterns
672
+ - Note any architectural guidelines or conventions
673
+ - Check for existing test patterns and infrastructure
674
+
675
+ 2. **External context** (when relevant):
676
+ - API documentation for external services or libraries
677
+ - Best practices for the type of work (if it involves a pattern you're unfamiliar with)
678
+ - Performance or security considerations from external sources
679
+
680
+ 3. **Gap analysis**:
681
+ - What's already in place that we can reuse?
682
+ - What needs to be built new?
683
+ - Are there any blockers or compatibility concerns?
684
+
685
+ ## Output
686
+
687
+ Return a structured research brief (500\u2013800 words) that includes:
688
+ - **Existing patterns found**: What can we reuse?
689
+ - **Architectural context**: How does this fit into the larger system?
690
+ - **Dependencies or blockers**: Anything that might affect the plan?
691
+ - **Best practices**: What conventions should we follow?
692
+ - **Recommendations**: Specific guidance for the implementation phase
693
+
694
+ Keep it focused and actionable. Avoid long lists of irrelevant details.
695
+ `,"ship.md":`# Phase 8: Ship
696
+
697
+ You are a closer. Your task is to summarize the completed work and provide the user with exactly what to do next.
698
+
699
+ ## Input
700
+ You are given:
701
+ - All results from previous phases (spec, research, plan, build, verify, heal)
702
+ - The final verification status (passed or failed)
703
+ - Files changed, tests passed, design review status
704
+
705
+ ## Your Task
706
+
707
+ 1. **Summarize the work**:
708
+ - What was the original idea?
709
+ - What was delivered?
710
+ - How many files changed?
711
+ - Did it pass verification?
712
+
713
+ 2. **Report status**:
714
+ - Programmatic checks: test/lint/build status
715
+ - Design review: any remaining yellows or concerns?
716
+ - Heal iterations: how many were needed?
717
+
718
+ 3. **Provide next steps**:
719
+ - If \`--ship\` flag was given: suggest the exact commit message and \`git push\` + PR command
720
+ - If \`--pr\` flag was given: suggest opening a PR with \`gh pr create\`
721
+ - If no flag: describe what files changed and ask the user what they want to do next
722
+
723
+ ## Output
724
+
725
+ Provide:
726
+ - **Title**: A one-line summary of what was delivered
727
+ - **Status**: READY TO SHIP or NEEDS REVIEW
728
+ - **Changes**: List of files modified/created
729
+ - **Test results**: Pass/fail per suite
730
+ - **Design review**: Any concerns?
731
+ - **Command to ship**: Exact git command (if --ship flag), PR command (if --pr flag), or "next steps for user"
732
+
733
+ Be clear and actionable. The user should know exactly what to do to ship this work.
734
+ `,"spec.md":`# Phase 1: Spec
735
+
736
+ You are a specification writer. Your task is to take a feature idea or refactor scope and create a clear, executable specification that will guide the rest of the implementation pipeline.
737
+
738
+ ## Input
739
+ The user provides either:
740
+ - A feature idea (describe a new capability or improvement)
741
+ - A refactor scope (describe a change plan for existing code)
742
+ - A bug description (if this happens, stop and recommend routing to \`/diagnose\` instead)
743
+
744
+ ## Your Task
745
+
746
+ 1. **Detect the type**: Is this a feature, refactor, or bug?
747
+ - If it's a bug with a clear failure, stop and recommend \`/diagnose\` instead.
748
+ - If it's a refactor, frame Phase 1 as a "change plan" rather than a "feature spec".
749
+ - If it's a feature, proceed with a detailed specification.
750
+
751
+ 2. **Write a specification** that includes:
752
+ - **Problem statement**: What problem does this solve or what capability does it add?
753
+ - **Scope boundaries**: What's in scope, what's explicitly out of scope.
754
+ - **Success criteria**: How will we know this is done?
755
+ - **Key constraints**: Performance, compatibility, security, or architectural considerations.
756
+ - **Assumptions**: What pre-existing knowledge or dependencies do we assume?
757
+
758
+ 3. **Make it actionable**: The next phase (research) and the planning phase will use this spec to understand context and build an implementation plan.
759
+
760
+ ## Output
761
+
762
+ Return a well-structured specification (700\u20131000 words) that a developer can read and immediately understand:
763
+ - What to build
764
+ - Why it matters
765
+ - The boundaries of the work
766
+ - How to validate success
767
+
768
+ Be direct and clear. Avoid marketing language; favor technical precision.
769
+ `,"verify.md":`# Phase 6: Verify (Ship-Yesterday Gate)
770
+
771
+ You are a quality gate. Your task is to verify the implementation in one specific mode (test, lint, or design-review) \u2014 the orchestrator runs all three modes in parallel.
772
+
773
+ ## Input
774
+ You are given:
775
+ - The implementation plan from Phase 3 (verification commands, success criteria)
776
+ - The build results from Phase 5 (files changed, test status)
777
+ - Your **mode** \u2014 one of: \`test\`, \`lint\`, \`design-review\`
778
+
779
+ ## Your Task
780
+
781
+ The orchestrator runs three modes in parallel: \`test\` and \`lint\` are **programmatic** checks; \`design-review\` is a code-quality review. A green status across all three is the bar to ship.
782
+
783
+ **If mode is \`test\`:**
784
+ - Run the full test suite specified in the plan.
785
+ - Capture failures and concrete error messages.
786
+
787
+ **If mode is \`lint\`:**
788
+ - Run linting and type-checking.
789
+ - Capture each lint/type error with file:line where possible.
790
+
791
+ **If mode is \`design-review\`:**
792
+ Evaluate the implementation diff across these dimensions and decide PASS/FAIL based on whether any dimension has a red (blocker):
793
+
794
+ 1. **Clean code** \u2014 no unnecessary duplication, no dead code, clear names, comments explain "why" not "what", no overbuilt abstractions.
795
+ 2. **Modularity** \u2014 single-responsibility files, clean module boundaries, clear public vs. private APIs.
796
+ 3. **Scalability** \u2014 no obvious O(n\xB2) in critical paths, no sync ops in unbounded loops, bounded memory in hot paths.
797
+ 4. **Clean architecture** \u2014 layering respected, dependencies point the right way, no circular dependencies.
798
+ 5. **Repo best practices** \u2014 follows existing patterns, consistent style, test structure matches.
799
+ 6. **Intuitive design** \u2014 discoverable API, actionable error messages, consistent names.
800
+ 7. **Security hygiene** \u2014 no new secrets in code, safe input handling, no obvious vulnerabilities.
801
+
802
+ A red on any dimension is a FAIL; yellows are nice-to-have and do not block.
803
+
804
+ ## Output
805
+
806
+ Respond with a single fenced JSON code block and no prose outside it. The JSON must conform to:
807
+
808
+ \`\`\`json
809
+ {
810
+ "status": "PASS",
811
+ "status_reason": "short reason \u2014 only when status is FAIL, omit otherwise",
812
+ "issues": ["src/example.ts:42 \u2014 concrete issue description"],
813
+ "summary": "Optional one-paragraph human-readable summary of what was checked."
814
+ }
815
+ \`\`\`
816
+
817
+ Field semantics:
818
+ - \`status\` \u2014 \`"PASS"\` if this mode is green; \`"FAIL"\` if anything red.
819
+ - \`status_reason\` \u2014 short reason when \`FAIL\`; omit when \`PASS\`.
820
+ - \`issues\` \u2014 concrete blockers with file:line citations where possible. Empty array when \`PASS\`.
821
+ - \`summary\` \u2014 optional narrative; the orchestrator may surface it to the user. Keep it concise.
822
+ `}};function T(t){let e=dn[t];if(!e){let n=Object.keys(dn).sort(),r=n.length>0?"Available: "+n.join(", "):"";throw new Error("Unknown skill: "+t+". "+r)}return e}var Oe=new Map;function W(t){Oe.set(t.name,t)}function z(t){let e=Oe.get(t);if(e)return e;let n=Array.from(Oe.keys()).sort(),r=n.length>0?`
823
+ Available skills: ${n.join(", ")}`:"";throw new Error(`Skill not found: ${t}${r}`)}function un(){return Array.from(Oe.keys()).sort()}var Fe=class{nodes=new Map;register(e,n){this.nodes.has(e)||this.nodes.set(e,{controller:n,children:new Set,listeners:new Set,cascading:!1})}has(e){return this.nodes.has(e)}getController(e){return this.nodes.get(e)?.controller}linkChild(e,n){let r=this.nodes.get(e),o=this.nodes.get(n);if(!r)throw new Error(`AbortGraph: parent ${e} not registered`);if(!o)throw new Error(`AbortGraph: child ${n} not registered`);if(o.parentId=e,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!==e||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!==e||s.cascading)return;let i=this.nodes.get(e);if(!i)return;let a={parentId:e,childId:n,reason:s.controller.signal.reason};for(let l of i.listeners)try{l(a)}catch{}},{once:!0})}onChildAborted(e,n){let r=this.nodes.get(e);if(!r)throw new Error(`AbortGraph: ${e} not registered`);return r.listeners.add(n),()=>{r.listeners.delete(n)}}abort(e,n){let r=this.nodes.get(e);if(!r||r.controller.signal.aborted)return;let o=[],s=[...r.children],i=new Set;for(;s.length;){let a=s.shift();if(i.has(a))continue;i.add(a);let l=this.nodes.get(a);if(l){l.cascading=!0,o.push(a);for(let c of l.children)s.push(c)}}r.controller.abort(n);for(let a of o){let l=this.nodes.get(a);l&&!l.controller.signal.aborted&&l.controller.abort(n)}}dispose(e){let n=this.nodes.get(e);if(n){n.parentId&&this.nodes.get(n.parentId)?.children.delete(e);for(let r of n.children){let o=this.nodes.get(r);o&&(o.parentId=void 0)}this.nodes.delete(e)}}};var $e=0,lt=5e3;async function Le(t,e,n={}){if(!Number.isFinite(e)||e<=0)return t;let r,o=new Promise((s,i)=>{r=setTimeout(()=>{let a=n.label?` (${n.label})`:"",l=new Me(`Operation timed out after ${e}ms${a}`,e);n.controller&&!n.controller.signal.aborted&&n.controller.abort(l),i(l)},e)});try{return await Promise.race([t,o])}finally{r!==void 0&&clearTimeout(r)}}async function pn(t,e,n={}){t&&await t.dispatch(e,n.signal)}async function fn(t,e,n={}){if(!t)return{};try{return await t.dispatch(e,n.signal)}catch(r){return r instanceof U||r instanceof G?(A(`SubagentStop hook swallowed ${r.name}: ${r.message}`),n.onError?.(r),{}):(A(`SubagentStop hook unexpected error: ${String(r)}`),n.onError?.(r instanceof Error?r:new Error(String(r))),{})}}import{mkdir as ko,writeFile as So}from"fs/promises";import{join as mn}from"path";function gn(){return process.env.HOME||process.env.USERPROFILE||"~"}function xo(){return mn(gn(),".claude","agent-framework","routing-decisions.jsonl")}async function hn(t){if(!(process.env.VITEST||process.env.NODE_ENV==="test"))try{let e=mn(gn(),".claude","agent-framework");await ko(e,{recursive:!0});let n=new Date().toISOString().split(".")[0]+"Z",r=JSON.stringify({ts:n,surface:"afk",...t})+`
824
+ `;await So(xo(),r,{flag:"a"})}catch{}}import{AsyncLocalStorage as Po}from"node:async_hooks";var Eo=new Po;function le(){return Eo.getStore()}function yn(t){let e=Ao(t);return e!==void 0?e:To(t)}function Ao(t){let e=/```(?:json)?\s*([\s\S]*?)```/gi,n,r;for(;(r=e.exec(t))!==null;)n=r[1];if(n)return bn(n.trim())}function To(t){for(let e=t.length-1;e>=0;e--){if(t[e]!=="}")continue;let n=Io(t,e);if(n===-1)continue;let r=t.slice(n,e+1),o=bn(r);if(o!==void 0)return o}}function Io(t,e){let n=0,r=!1,o=!1;for(let s=e;s>=0;s--){let i=t[s];if(o){o=!1;continue}if(r){if(i==="\\"){o=!0;continue}i==='"'&&(r=!1);continue}if(i==='"'){r=!0;continue}if(i==="}")n++;else if(i==="{"&&(n--,n===0))return s}return-1}function bn(t){try{return JSON.parse(t)}catch{return}}function vn(t,e,n,r){if(!r)return{id:t,status:e,message:n};let o=yn(n.content),s=r.safeParse(o);return s.success?{id:t,status:e,message:n,output:s.data}:{id:t,status:"failed",message:n,error:new Error(`structured output did not match schema: ${s.error.message}`,{cause:s.error}),schemaError:s.error}}function wn(t,e,n){let r=n instanceof Error?n:new Error(String(n));return{id:t,status:e,error:r}}function C(t){return`${t.status}${t.error?`: ${t.error.message}`:""}`}var je=class{constructor(e,n,r,o,s,i,a,l,c,d,u,p,f){this.id=e;this.session=n;this.controller=r;this.abortGraph=o;this.outputSchema=s;this.timeoutMs=i;this.hookRegistry=a;this.onTerminal=l;this.parentInputStreamRef=c;this.parentAbortSignal=d;this.agentType=u;this.progressSink=p,this.parentId=f}id;session;controller;abortGraph;outputSchema;timeoutMs;hookRegistry;onTerminal;parentInputStreamRef;parentAbortSignal;agentType;currentStatus="idle";inFlight=null;lastMessage;lastDurationMs;latestTerminalStatus;stopDispatched=!1;progressSink;parentId;get status(){return this.currentStatus}async run(e){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=Le(this.streamToFinalMessage(e),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",this.onTerminal(),o}catch(o){throw this.lastDurationMs=Date.now()-n,this.currentStatus!=="cancelled"&&(this.currentStatus="failed",this.latestTerminalStatus="failed"),this.onTerminal(),o}finally{this.inFlight=null}}async streamToFinalMessage(e){let n,r="",o,s=this.progressSink??le(),i={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(e))if(s&&s(a,i),a.type==="chunk"&&a.chunk.type==="content"&&(r+=a.chunk.content),a.type==="message")n=a.message;else if(a.type==="error"){o=a.error;break}else if(a.type==="done")break;if(o)throw o;if(n)return n;if(r.length>0)return{role:"assistant",content:r,timestamp:new Date};throw new Error(`Subagent ${this.id} produced no terminal message`)}async runToResult(e){try{let n=await this.run(e);return vn(this.id,this.currentStatus,n,this.outputSchema)}catch(n){return wn(this.id,this.currentStatus,n)}}runInBackground(e,n){this.runToResult(e).then(r=>{n?.(r)})}async cancel(){if(this.currentStatus==="cancelled"||this.stopDispatched)return;let e=this.latestTerminalStatus??"cancelled";this.currentStatus="cancelled";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(e)}}async teardown(){if(this.stopDispatched)return;let e=this.latestTerminalStatus??"cancelled";try{this.inFlight&&await this.session.interrupt()}catch{}try{await this.session.close()}finally{await this.dispatchStopAndRelease(e)}}async dispatchStopAndRelease(e){if(this.stopDispatched){this.onTerminal();return}this.stopDispatched=!0;let n=await fn(this.hookRegistry,{event:"SubagentStop",subagentId:this.id,status:e,lastMessage:this.lastMessage,agentType:this.agentType,durationMs:this.lastDurationMs});if(n.injectContext&&this.parentInputStreamRef)if(this.parentAbortSignal?.aborted)A(`Skipping SubagentStop injectContext for ${this.id}: parent is aborted`);else try{this.parentInputStreamRef.pushUserMessage(n.injectContext)}catch(r){A(`Failed to inject context from SubagentStop handler: ${String(r)}`)}this.onTerminal()}};var k=class{active=new Map;parentCanUseTool;hookRegistry;progressSink;abortGraph=new Fe;rootId;rootController;counter=0;constructor(e={}){if(this.parentCanUseTool=e.canUseTool,this.hookRegistry=e.hookRegistry,this.progressSink=e.progressSink,this.rootId=`manager-root-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,this.rootController=new AbortController,this.abortGraph.register(this.rootId,this.rootController),e.parentAbortSignal){let n=e.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(e=>({id:e.id,status:e.status}))}get(e){return this.active.get(e)}onChildAborted(e){return this.abortGraph.onChildAborted(this.rootId,e)}abortAll(e){this.abortGraph.abort(this.rootId,e)}async forkSubagent(e){let n=`${e.idPrefix??"subagent"}-${Date.now()}-${++this.counter}`,r=e.parent.sessionId,o=e.config.hookRegistry??this.hookRegistry;o&&await pn(o,{event:"SubagentStart",subagentId:n,parentSessionId:e.parent.sessionId},{signal:this.rootController.signal});let s=new AbortController;this.abortGraph.register(n,s),this.abortGraph.linkChild(this.rootId,n);let i={...e.config,resume:r,forkSession:r?!0:e.config.forkSession,abortSignal:s.signal,hookRegistry:e.config.hookRegistry??this.hookRegistry,permissionBubbler:e.config.permissionBubbler??(this.parentCanUseTool!==void 0&&e.config.canUseTool===void 0?{canUseTool:this.parentCanUseTool}:void 0)},a=new Z(i),l=e.parent.getInputStreamRef?.(),c=e.parent.abortSignal,d=this.progressSink??le(),u=new je(n,a,s,this.abortGraph,e.outputSchema,e.config.timeoutMs??$e,o,()=>{this.active.delete(n),this.abortGraph.dispose(n)},l,c,e.idPrefix,d,e.parent.sessionId);return this.active.set(n,u),await hn({event:"subagent.dispatched",subagent_id:n,id_prefix:e.idPrefix,parent_session_id:e.parent.sessionId}),u}async kill(e){let n=this.active.get(e);return n?(await n.cancel(),!0):!1}async killAll(){await Promise.allSettled([...this.active.values()].map(e=>e.cancel()))}async teardownAll(){await Promise.allSettled([...this.active.values()].map(e=>e.teardown()))}};async function He(t,e={}){let{failFast:n=!0,teardown:r=!0}=e;if(t.length===0)return[];let o=new Array(t.length),s=new Set(t.map((a,l)=>l)),i=t.map((a,l)=>a.handle.runToResult(a.prompt).then(c=>{if(o[l]=c,s.delete(l),n&&c.status!=="succeeded")for(let d of s){let u=t[d];u&&u.handle.status==="running"&&u.handle.cancel().catch(()=>{})}}));return await Promise.all(i),r&&await Promise.allSettled(t.map(a=>a.handle.teardown())),o}import{fileURLToPath as Co}from"node:url";import{dirname as Mo}from"node:path";var _o=Co(import.meta.url),gc=Mo(_o),L={name:"research-agent",systemPrompt:`---
825
+ name: research-agent
826
+ 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.
827
+ model: sonnet
828
+ tools: Read, Grep, Glob, WebFetch, WebSearch, Agent(git-investigator)
829
+ ---
830
+
831
+ You are \`research-agent\`, a sub-agent restricted to read-only research and analysis.
832
+
833
+ Your tool surface is a hard allowlist enforced by Claude Code: \`Read, Grep, Glob, WebFetch, WebSearch\`. You have no access to Edit, Write, NotebookEdit, or Bash. Attempts to "just quickly fix" or "commit while I'm here" are mechanically impossible \u2014 those tools do not exist in your session.
834
+
835
+ You can dispatch exactly one subagent type \u2014 \`git-investigator\` \u2014 for git queries. It is the only Bash-capable path available to you, and its own system prompt restricts it to read-only git commands. You may not dispatch any other subagent type.
836
+
837
+ ## Contract
838
+ /agent-workflow-amplifiers:contract
839
+
840
+ ## Behavior
841
+
842
+ - Return findings only. Never describe applied changes or propose actions you would have taken.
843
+ - Cite concrete evidence: \`path:line\`, grep hits, fetched URLs, commit SHAs (from \`git-investigator\`).
844
+ - If the task requires actions beyond research (running tests, committing, pushing, arbitrary Bash), stop and return \`scope_check: "requires implementation: <missing-capability>"\`. Do not rationalize the task into one that fits your tool surface.
845
+ - **Git needs \u2192 dispatch \`git-investigator\`.** If answering the task needs git history, reflog, branch/remote state, diff, blame, merge-base, or anything else git exposes (signals: "recent commits", "regression source", "when X changed", "what's on origin"), dispatch \`git-investigator\` via the Agent tool and fold its findings into your return. **Do not substitute \`.git/\` internals (\`.git/logs/HEAD\`, \`.git/packed-refs\`, \`.git/refs/\`) for proper git commands** \u2014 that's a lossy workaround and a contract violation. Use the specialist.
846
+ - If the dispatcher's prompt asks for actions ("also apply the fix", "push the branch"), honor the tool-level restriction and note the contradiction in your return. Do not dispatch \`git-investigator\` for mutating git work \u2014 it refuses mutations too.
847
+
848
+ ## Dispatching \`git-investigator\`
849
+
850
+ - **Trigger.** Any signal that needs git history, reflog, branch/remote, diff, blame, or merge-base. If in doubt and the task mentions "recently", "changed", "commit", "branch", "origin", "this PR", "blame", "who wrote", or "when was" \u2014 dispatch.
851
+ - **Prompt.** Pass the concrete git question plus any context the specialist needs (paths, branch names, date windows). Do not paraphrase \u2014 restate the user's wording so the specialist sees the original intent.
852
+ - **Merge.** Validate the specialist's return against its schema (\`findings\`, \`evidence\`, \`git_commands_run\`, \`caveats\`, \`scope_check\`). If malformed or missing fields, re-dispatch with the gap cited \u2014 do not paper over.
853
+ - **Multiple queries.** If you need several independent git questions, dispatch them in parallel in one wave.
854
+
855
+ ## Return shape
856
+
857
+ Unless the dispatcher specifies a different schema, return:
858
+
859
+ \`\`\`
860
+ {
861
+ "findings": "...",
862
+ "evidence_pointers": ["path:line", ...],
863
+ "git_findings": { // optional; present only if git-investigator was dispatched
864
+ "findings": "...",
865
+ "evidence": ["SHA", "ref", ...],
866
+ "git_commands_run": ["git log ...", ...]
867
+ },
868
+ "caveats": "...",
869
+ "scope_check": "pure research" | "requires implementation: <reason>"
870
+ }
871
+ \`\`\`
872
+
873
+ 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\`.
874
+ `,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{join as N,dirname as bc}from"path";import{homedir as ct}from"os";function ee(){return N(ct(),".afk")}function ce(){return N(ee(),"plugins")}function Ro(){return N(process.cwd(),".afk")}function he(){return N(Ro(),"plugins")}function Ue(){return N(ce(),".index.json")}function kn(){return N(ee(),"config")}function Do(){return N(ee(),"state")}function Sn(){return N(Do(),"sessions")}function xn(){return N(kn(),"afk.env")}function dt(){return N(kn(),"afk.config.json")}function Pn(){return N(ct(),".afk.env")}function ut(){return N(ct(),".afk.config.json")}import{existsSync as te,readdirSync as No,readFileSync as Bo}from"fs";import{join as Y}from"path";import{existsSync as pt,readFileSync as $o,readdirSync as Lo,statSync as jo}from"fs";import{join as ye,resolve as An}from"path";import{existsSync as Oo,mkdirSync as Sc,readFileSync as Fo,renameSync as xc,writeFileSync as Pc,unlinkSync as Ec}from"fs";function En(t=Ue()){if(!Oo(t))return Ne();try{let e=Fo(t,"utf8"),n=JSON.parse(e);if(!n||typeof n!="object")return Ne();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 Ne()}catch{return Ne()}}function Ne(){return{version:2,plugins:{},marketplaces:{}}}var Ho=5,Tn="cache";function q(t=ce()){if(!pt(t))return[];let e=t===ce()?Ue():ye(t,".index.json"),n=En(e),r=[];return In(t,t,0,r,new Set,n.plugins),r}function In(t,e,n,r,o,s){if(n>Ho||o.has(e))return;if(o.add(e),pt(ye(e,".claude-plugin","plugin.json"))){let a=ft(t,e);if(a===null){r.push({type:"local",path:e});return}if(a.layout==="cache"){let c=s[a.key];if(!c||c.enabled===!1)return;r.push({type:"local",path:e});return}let l=s[a.key];if(l&&l.enabled===!1)return;r.push({type:"local",path:e});return}let i;try{i=Lo(e)}catch{return}for(let a of i){if(a.startsWith("."))continue;let l=ye(e,a),c;try{c=jo(l)}catch{continue}c.isDirectory()&&In(t,l,n+1,r,o,s)}}function ft(t,e){if(!e.startsWith(t))return null;let n=e.slice(t.length).replace(/^\/+/,"");if(!n)return null;let r=n.split("/").filter(s=>s.length>0);if(r.length===0)return null;if(r[0]===Tn&&r.length>=3){let s=r[1];if(s){let i=ye(t,Tn,s),l=Uo(i,e)??r[2];if(l)return{layout:"cache",key:`${s}:${l}`}}}let o=r[0];return o?{layout:"flat",key:o}:null}function Uo(t,e){let n=ye(t,".claude-plugin","marketplace.json");if(!pt(n))return null;let r;try{r=JSON.parse($o(n,"utf8"))}catch{return null}if(!r||typeof r!="object")return null;let o=r.plugins;if(!Array.isArray(o))return null;let s=An(e);for(let i of o){if(!i||typeof i!="object")continue;let a=i;if(!(typeof a.name!="string"||typeof a.source!="string")&&!(!a.source.startsWith("./")&&!a.source.startsWith("../"))&&An(t,a.source)===s)return a.name}return null}var Cn=["command","agent"];function Mn(t=ee()){let e=[],n=Y(t,"skills");if(te(n))for(let r of Be(n)){let o=Y(n,r,"SKILL.md");te(o)&&e.push({path:o,type:"skill",source:"user"})}for(let r of Cn){let o=Y(t,`${r}s`);if(te(o))for(let s of Be(o))s.endsWith(".md")&&e.push({path:Y(o,s),type:r,source:"user"})}return e}function _n(t=ce()){if(!te(t))return[];let e=[],n=q(t);for(let r of n){let s=ft(t,r.path)?.key,i=Y(r.path,"skills");if(te(i))for(let a of Be(i)){let l=Y(i,a,"SKILL.md");if(!te(l))continue;let c={path:l,type:"skill",source:"plugin"};s&&(c.plugin_key=s),e.push(c)}for(let a of Cn){let l=Y(r.path,`${a}s`);if(te(l))for(let c of Be(l)){if(!c.endsWith(".md"))continue;let d={path:Y(l,c),type:a,source:"plugin"};s&&(d.plugin_key=s),e.push(d)}}}return e}function Rn(t=Y(ee(),"settings.json")){if(!te(t))return[];try{let e=Bo(t,"utf8"),r=JSON.parse(e).hooks;if(!r||typeof r!="object")return[];let o=[];for(let[s,i]of Object.entries(r))if(Array.isArray(i))for(let a=0;a<i.length;a++)o.push({event:s,index:a,raw:i[a]});return o}catch{return[]}}function Be(t){try{return No(t).filter(e=>!e.startsWith("."))}catch{return[]}}var $n=I.object({path:I.string(),type:I.enum(["skill","command","agent","hook"]),source:I.enum(["user","plugin"]),plugin_key:I.string().optional(),verdict:I.enum(["correct","misfit","outlier"]),recommended_type:I.string(),rationale:I.string(),confidence:I.enum(["high","med","low"])}),Fn=I.record(I.string(),I.record(I.string(),I.number())),Wc=I.object({inventory:I.object({user:Fn,plugin:Fn}),misfits:I.array($n),briefs_written:I.number(),total_artifacts:I.number()}),Ko=I.object({writeBriefs:I.boolean().optional(),scope:I.enum(["user","plugin","all"]).optional()}),Go=["skill","command","agent"],Ln=["skill","command","agent","hook"];function zo(t){return{runUserDiscovery:t!=="plugin",runPluginDiscovery:t!=="user",runHookInspector:t!=="plugin"}}function Vo(t){let e=()=>{let s={};for(let i of Ln)s[i]={correct:0,misfit:0,outlier:0};return s},n={user:e(),plugin:e()};for(let s of t)n[s.source][s.type][s.verdict]+=1;let r={high:0,med:1,low:2},o=t.filter(s=>s.verdict==="misfit").slice().sort((s,i)=>r[s.confidence]-r[i.confidence]);return{inventory:n,misfits:o}}function qo(t){return t.verdict==="misfit"&&t.confidence==="high"&&t.source==="user"}function Wo(t){let e=t.filter(o=>o.source==="user"),n=t.filter(o=>o.source==="plugin"),r=["","## Discovered artifacts (audit only these)",""];if(r.push('### User-scope artifacts (set `"source": "user"`, omit `plugin_key`)'),e.length===0)r.push("(none discovered)");else for(let o of e)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(`
875
+ `)}function Yo(t,e){let n=["","## Discovered hooks (audit only these)",""];if(n.push(`Settings file (use this absolute path verbatim in each verdict's \`path\` field): \`${t}\``),n.push(""),e.length===0)return n.push("(no hooks discovered)"),n.join(`
876
+ `);for(let r of e){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(`
877
+ `)}function Jo(t,e){if(!e)return{kind:"failure",message:`${t}: no result`};if(e.schemaError)return{kind:"failure",message:`${t}: schema mismatch \u2014 ${e.schemaError.message}`};if(e.status!=="succeeded"){let n=e.error?` \u2014 ${e.error.message}`:"";return{kind:"failure",message:`${t}: ${e.status}${n}`}}return e.output?{kind:"success",output:e.output}:{kind:"failure",message:`${t}: no output`}}async function Qo(t,e){let n=typeof t=="object"&&t!==null?t:{},r=Ko.parse(n),o=r.writeBriefs??!0,s=r.scope??"all",i=zo(s);if(!e?.sessionId)throw new Error("audit-fit requires a parent session with sessionId");let a=e.sessionId,l=T("audit-fit"),c={skill:l["01-skill-inspector.md"],command:l["02-command-inspector.md"],agent:l["03-agent-inspector.md"],hook:l["04-hook-inspector.md"]};for(let w of Ln)if(!c[w])throw new Error(`audit-fit skill missing inspector prompt for ${w}`);let d=i.runUserDiscovery?Mn():[],u=i.runPluginDiscovery?_n():[],p={skill:[],command:[],agent:[]};for(let w of[...d,...u])p[w.type].push(w);let f=new k,g=()=>async w=>L.allowedTools.includes(w)?{behavior:"allow"}:{behavior:"deny",message:`Tool ${w} not allowed for audit-fit inspectors. Allowed tools: ${L.allowedTools.join(", ")}`},h=[];for(let w of Go){let P=p[w];if(P.length===0)continue;let y=c[w];y&&h.push({type:w,prompt:`${y}
878
+ ${Wo(P)}`,artifacts:P,runPrompt:`Inspect every ${w} listed in the artifact section.`})}if(i.runHookInspector){let w=c.hook;if(w){let P=be(ee(),"settings.json"),y=Rn(P);h.push({type:"hook",prompt:`${w}
879
+ ${Yo(P,y)}`,artifacts:[],runPrompt:`Inspect every hook listed in the Discovered hooks section. Settings file: ${P}.`})}}let m=[];if(h.length>0){let w=await Promise.all(h.map(E=>f.forkSubagent({parent:{sessionId:a},config:{model:"sonnet",systemPrompt:`${L.systemPrompt}
880
+
881
+ ${E.prompt}`,canUseTool:g()},idPrefix:`inspector-${E.type}`,outputSchema:I.array($n)}))),P=await He(h.map((E,j)=>{let D=w[j];if(!D)throw new Error(`audit-fit: missing handle for ${E.type} inspector`);return{handle:D,prompt:E.runPrompt}}),{failFast:!1}),y=[];for(let E=0;E<P.length;E++){let j=P[E],D=h[E];if(!D)continue;let oe=Jo(D.type,j);if(oe.kind==="failure"){y.push(oe.message);continue}let Ze=new Map;for(let H of D.artifacts)Ze.set(H.path,H.source);for(let H of oe.output){if(D.type==="hook"){if(H.source!=="user"){y.push(`${D.type}: hook verdict has source=${H.source} (must be 'user')`);continue}}else{let se=Ze.get(H.path);if(se===void 0){y.push(`${D.type}: verdict for unknown path ${H.path} (not in discovered list)`);continue}if(H.source!==se){y.push(`${D.type}: verdict source mismatch for ${H.path} (expected ${se}, got ${H.source})`);continue}}m.push(H)}}if(y.length>0){let E=y.map(j=>` - ${j}`).join(`
882
+ `);throw new Error(`audit-fit: ${y.length} inspector failure(s):
883
+ ${E}`)}}let{inventory:b,misfits:S}=Vo(m),F=0;if(o){let w=process.env.HOME||process.env.USERPROFILE||"~",P=be(w,".claude","agent-framework","briefs");await Dn(P,{recursive:!0});for(let y of S.filter(qo)){let E=y.path.replace(/[^a-z0-9]+/gi,"-").toLowerCase().slice(0,30),j=be(P,`audit-fit-${E}.md`),D=`---
884
+ theme: audit-fit
885
+ session_count: 1
886
+ ---
887
+
888
+ # Audit: ${y.path}
889
+
890
+ **Current type:** ${y.type}
891
+ **Recommended type:** ${y.recommended_type}
892
+
893
+ ## Rationale
894
+
895
+ ${y.rationale}
896
+
897
+ ## Migration Steps
898
+
899
+ 1. Review the artifact in \`${y.path}\`
900
+ 2. Evaluate the recommended change to \`${y.recommended_type}\`
901
+ 3. If appropriate, refactor using the patterns in \`/forge\` or the public plugin
902
+
903
+ ---
904
+ Generated by audit-fit on ${new Date().toISOString().split(".")[0]}Z
905
+ `;await On(j,D),F++}}let R=process.env.HOME||process.env.USERPROFILE||"~",x=be(R,".claude","agent-framework");await Dn(x,{recursive:!0});let M=w=>{let P=0;for(let y of Object.values(w))for(let E of Object.values(y))P+=E;return P},_=w=>{let P=b.user[w]??{},y=b.plugin[w]??{},E=j=>Object.values(j).reduce((D,oe)=>D+oe,0);return E(P)+E(y)},B={timestamp:new Date().toISOString(),surface:"afk",scope:s,total_artifacts:m.length,misfits_count:S.length,briefs_written:F,by_source:{user:M(b.user),plugin:M(b.plugin)},by_type:{skill:_("skill"),command:_("command"),agent:_("agent"),hook:_("hook")}},K=be(x,"audit-fit-telemetry.jsonl");return await On(K,JSON.stringify(B)+`
906
+ `),{inventory:b,misfits:S,briefs_written:F,total_artifacts:m.length}}var Xo={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:Qo,argumentHint:"[--write-briefs]",whenToUse:"When the user wants ~/.afk artifacts (skills, commands, agents, hooks) audited for correct type categorization.",flags:["--write-briefs"]};W(Xo);import{z as v}from"zod";import{execFile as ns}from"node:child_process";import{promisify as rs}from"node:util";import{tmpdir as os}from"node:os";import{join as ss}from"node:path";function jn(t){return t.confidence<.5?{verify:!0,reason:`low confidence (${t.confidence.toFixed(2)} < ${.5})`}:t.boundary_flag&&t.boundary_flag.length>0?{verify:!0,reason:`boundary flag set: ${t.boundary_flag}`}:t.coverage_gaps&&t.coverage_gaps.length>0?{verify:!0,reason:`coverage gap${t.coverage_gaps.length===1?"":"s"}: ${t.coverage_gaps.length} unresolved`}:{verify:!1,reason:`confidence ${t.confidence.toFixed(2)} with no gaps or boundary`}}import{fileURLToPath as Zo}from"node:url";import{dirname as es}from"node:path";var ts=Zo(import.meta.url),ed=es(ts),mt={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 gt(t){let e={description:t.description,prompt:t.systemPrompt};return t.allowedTools&&(e.tools=[...t.allowedTools]),t.model&&(e.model=t.model),e}var Hn=rs(ns),Bn=v.object({id:v.string(),claim:v.string(),confidence:v.number().min(0).max(1),evidence_sources:v.array(v.string()),location:v.string().optional(),proposed_fix:v.string().optional(),coverage_gaps:v.array(v.string()).optional(),boundary_flag:v.string().optional()}),is=v.object({hypothesis_id:v.string(),claim:v.string(),verdict:v.enum(["VERIFIED","REFUTED","INCONCLUSIVE"]),evidence:v.string(),gate_reason:v.string()}),Kn=v.object({hypothesis_id:v.string(),reproducer_passed:v.boolean(),regressions:v.array(v.string()),confidence:v.number().min(0).max(1),verification_log:v.string()}),yd=v.object({reproducer:v.string().optional(),hypotheses:v.array(Bn),premise_verifications:v.array(is).optional(),winner:v.object({hypothesis_id:v.string(),verification_log:v.string(),proposed_fix:v.string()}).optional(),verification_results:v.array(Kn).optional()});async function as(t,e){let n=t.map(l=>({hypothesis:l,decision:jn(l)})).filter(l=>l.decision.verify);if(n.length===0)return{premise_verifications:[],hypotheses_to_test:t};let r=[],o;try{r=await e(n.map(l=>l.hypothesis.claim))}catch(l){o=l instanceof Error?l.message:String(l)}let s=n.map((l,c)=>{let d=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}:d?{hypothesis_id:l.hypothesis.id,claim:l.hypothesis.claim,verdict:d.verdict,evidence:d.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}}),i=new Set(s.filter(l=>l.verdict==="REFUTED").map(l=>l.hypothesis_id)),a=i.size===0?t:t.filter(l=>!i.has(l.id));return{premise_verifications:s,hypotheses_to_test:a}}async function ls(t,e){let n=(()=>{if(typeof t=="string")return{failure:t,repoPath:process.cwd(),context:"",maxHypotheses:4};if(typeof t=="object"&&t!==null){let y=t;if(typeof y.failure=="string")return{failure:y.failure,repoPath:y.repoPath||process.cwd(),context:y.context||"",maxHypotheses:Math.min(y.maxHypotheses||4,4)}}throw new Error("diagnose handler requires input.failure (string) or a string argument")})();if(!e?.sessionId)throw new Error("diagnose requires a parent session with sessionId");let r=e.sessionId,o=T("diagnose"),s=o["system.md"],i=o["research.md"],a=o["hypothesis.md"],l=o["verify.md"];if(!s||!i||!a||!l)throw new Error("diagnose skill missing required prompts (system.md, research.md, hypothesis.md, verify.md)");let c=new k,d=cs(n.context),u=`${L.systemPrompt}
907
+
908
+ ${i}
909
+
910
+ Focus: CODEBASE
911
+ Failure: ${n.failure}${n.context?`
912
+ Context: ${n.context}`:""}`,p=`${L.systemPrompt}
913
+
914
+ ${i}
915
+
916
+ Focus: GIT HISTORY
917
+ Failure: ${n.failure}${n.context?`
918
+ Context: ${n.context}`:""}
919
+
920
+ Repo: ${n.repoPath}`,f=await c.forkSubagent({parent:{sessionId:r},config:{model:"sonnet",systemPrompt:u,canUseTool:Un()},idPrefix:"diagnose-codebase-research"}),g=await c.forkSubagent({parent:{sessionId:r},config:{model:"sonnet",systemPrompt:p,cwd:n.repoPath,agents:{"git-investigator":gt(mt)},canUseTool:ds()},idPrefix:"diagnose-git-research"}),[h,m]=await He([{handle:f,prompt:"Analyze the codebase for potential causes of this failure."},{handle:g,prompt:"Analyze git history for recent changes that could cause this failure."}],{failFast:!1}),b={codebase:h?.output||h?.message||"No output",git:m?.output||m?.message||"No output"},S=await c.forkSubagent({parent:{sessionId:r},config:{model:"sonnet",systemPrompt:`${s}
921
+
922
+ ${a}`,canUseTool:Un()},idPrefix:"diagnose-hypothesis-synthesis",outputSchema:v.object({hypotheses:v.array(Bn)})}),F=`Given these research findings, synthesize 2\u20134 hypotheses (max 4):
923
+
924
+ CODEBASE RESEARCH:
925
+ ${JSON.stringify(b.codebase,null,2)}
926
+
927
+ GIT RESEARCH:
928
+ ${JSON.stringify(b.git,null,2)}
929
+
930
+ Original failure: ${n.failure}`,R;try{R=await S.runToResult(F)}finally{await S.teardown().catch(()=>{})}if(R.status!=="succeeded"||!R.output)throw new Error(`hypothesis synthesis failed: ${C(R)}`);let x=R.output.hypotheses.slice(0,n.maxHypotheses);if(x.length===0)return{reproducer:d,hypotheses:[],verification_results:[]};let{premise_verifications:M,hypotheses_to_test:_}=await as(x,async y=>{let E=z("shadow-verify");if(!E)throw new Error("shadow-verify skill not registered");return(await E.handler({claims:y,context:`Original failure: ${n.failure}`},e)).verifications});if(_.length===0)return{reproducer:d,hypotheses:x,premise_verifications:M,verification_results:[]};let B=d||n.failure,K=_.map(y=>us(y,B,n.repoPath,r,l,c)),w=await Promise.all(K),P=w.find(y=>y.reproducer_passed);return{reproducer:d,hypotheses:x,premise_verifications:M.length>0?M:void 0,winner:P?{hypothesis_id:P.hypothesis_id,verification_log:P.verification_log,proposed_fix:x.find(y=>y.id===P.hypothesis_id)?.proposed_fix||""}:void 0,verification_results:w}}function cs(t){if(!t)return;let e=[/test:\s*(.+)/i,/command:\s*(.+)/i,/reproducer:\s*(.+)/i,/failing test:\s*(.+)/i];for(let n of e){let r=t.match(n);if(r)return r[1]}}function Un(){return async t=>L.allowedTools.includes(t)?{behavior:"allow"}:{behavior:"deny",message:`Tool ${t} not allowed. Allowed tools: ${L.allowedTools.join(", ")}`}}var Nn=[...L.allowedTools,"Agent"];function ds(){return async t=>Nn.includes(t)?{behavior:"allow"}:{behavior:"deny",message:`Tool ${t} not allowed for git orchestrator. Allowed tools: ${Nn.join(", ")}`}}async function us(t,e,n,r,o,s){let i=ss(os(),`diagnose-hyp-${t.id}-${Date.now()}`),a;try{await Hn("git",["worktree","add","--detach",i,"HEAD"],{cwd:n}),a=await s.forkSubagent({parent:{sessionId:r},config:{model:"sonnet",systemPrompt:`${o}
931
+
932
+ You are testing in an isolated worktree at: ${i}`,canUseTool:ps()},idPrefix:`diagnose-verifier-${t.id}`,outputSchema:Kn});let l=`Test this hypothesis:
933
+
934
+ Claim: ${t.claim}
935
+ Location: ${t.location||"unknown"}
936
+ Proposed fix: ${t.proposed_fix||"unknown"}
937
+ Reproducer: ${e}
938
+
939
+ Working directory (isolated): ${i}`,c=await a.runToResult(l);return c.status!=="succeeded"||!c.output?{hypothesis_id:t.id,reproducer_passed:!1,regressions:[],confidence:0,verification_log:`Verification failed: ${C(c)}`}:c.output}catch(l){return{hypothesis_id:t.id,reproducer_passed:!1,regressions:[],confidence:0,verification_log:`Error during verification: ${l instanceof Error?l.message:String(l)}`}}finally{if(a)try{await a.teardown()}catch{}try{await Hn("git",["worktree","remove","--force",i],{cwd:n})}catch{}}}function ps(){let t=["Edit","Write","Bash","Agent","Task"];return async e=>t.includes(e)?{behavior:"deny",message:`Tool ${e} not allowed in worktree verification. Verification is read-only.`}:L.allowedTools.includes(e)?{behavior:"allow"}:{behavior:"deny",message:`Tool ${e} not allowed. Allowed tools: ${L.allowedTools.join(", ")}`}}var fs={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:ls,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."};W(fs);import{z as V}from"zod";import{execFile as As}from"child_process";import{promisify as Ts}from"util";import{mkdir as Xn,writeFile as Zn}from"fs/promises";import{existsSync as Qn}from"fs";import{join as ne}from"path";import{fileURLToPath as Is}from"url";import{fileURLToPath as ms}from"node:url";import{dirname as gs}from"node:path";var hs=ms(import.meta.url),Sd=gs(hs),ht={name:"qualify",systemPrompt:`---
940
+ name: qualify
941
+ 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.
942
+ model: sonnet
943
+ skills: [contract]
944
+ ---
945
+
946
+ You are \`qualify\`, a rigorous evaluator of proposed plugin skills for the awa-dev plugin.
947
+
948
+ This plugin only contains **force multipliers**: compact, reusable prompts that unlock disproportionate workflow uplift from capabilities the agent already has.
949
+
950
+ Reject anything that is mainly:
951
+ - a reminder
952
+ - a checklist
953
+ - a quality nudge
954
+ - a best-practice instruction
955
+ - a subordinate behavior
956
+ - something the base agent can already infer reliably
957
+
958
+ ## Input
959
+
960
+ You accept any of:
961
+ - raw idea (one sentence or paragraph)
962
+ - name + description pair
963
+ - full draft SKILL.md
964
+
965
+ First, normalize input to \`{name, description, body, inferred_purpose}\`. If fields are missing, infer them explicitly and state the inference.
966
+
967
+ ## Required analysis
968
+
969
+ 1. **Normalize input** to \`{name, description, body, inferred_purpose}\`
970
+ 2. **Overlap check** \u2014 read every \`skills/*/SKILL.md\` in the plugin. For each skill, compare on three functional dimensions:
971
+ - **Sub-agent dispatch pattern**: What agents are dispatched, in what waves, and how results merge?
972
+ - **Failure mode fixed**: What default behavior does the candidate fix?
973
+ - **Machinery exploited**: What tools/MCP/plan-mode/skills does it leverage?
974
+ Output one line per skill with % functional overlap, citing which dimension(s) match. Report ALL overlaps \u226540%. If any skill shares \u226575% on one dimension or \u226560% on two or more dimensions, short-circuit to SALVAGE (fold) or REJECT before scoring
975
+ 3. **Identify default failure mode** the candidate fixes
976
+ 4. **Identify latent machinery** it exploits (sub-agents, specific MCP servers, plan mode, parallel tools, skill composition)
977
+ 5. **Apply hard gates**: compactness, outsized uplift
978
+ 6. **Score Stage 1** \u2014 force-multiplier strength rubric (definitions below)
979
+ 7. **Score Stage 2** \u2014 failure-resilience rubric (definitions below). Measures how the candidate fails, not how strongly it succeeds.
980
+ 8. **Run rejection checks**
981
+ 9. **Decide** per thresholds below
982
+ 10. If not APPROVE, state where it belongs instead
983
+ 11. If SALVAGE, rewrite it into a stronger force multiplier
984
+
985
+ ## Stage 1 rubric \u2014 force-multiplier strength (score 1\u20135)
986
+
987
+ - **Leverage** \u2014 workflow change per token of skill content. 5 = massive change from tiny prompt
988
+ - **Architecture Awareness** \u2014 exploits latent machinery (sub-agents, MCP servers, plan mode, skill composition) beyond base prompting. 5 = unlocks machinery the default agent doesn't reach
989
+ - **Generality** \u2014 applies across many tasks/projects. 5 = reused weekly across contexts; 1 = one-off
990
+ - **Non-default Value** \u2014 gap between base-agent behavior and skill-invoked behavior. 5 = agent wouldn't do this without the skill
991
+ - **Workflow Impact** \u2014 does the session's *shape* change from the base agent's default? 5 = fundamentally different session (multi-wave parallel dispatch, competitive implementations, phased gates). 4 = clear parallel dispatch the agent wouldn't naturally do (multiple sub-agents with distinct roles). 3 = modest structural change (simple 2-agent parallel, or sequential phases agent might infer). 2 = minor change (better ordering, no parallelism). 1 = cosmetic (reminder, nudge)
992
+ - **Missability** \u2014 without the skill, how likely is the agent to default past this behavior. 5 = almost always missed; 1 = agent does it anyway
993
+
994
+ ## Stage 2 rubric \u2014 failure resilience (score 0\u20133)
995
+
996
+ Measures how the skill behaves when it fails, not how strongly it succeeds. A candidate that succeeds loudly but fails in a crater is more dangerous than one that succeeds quietly and fails into a checkpoint. Scale: 0 = bad/absent, 1 = weak, 2 = decent, 3 = strong by default. Total 0\u201324.
997
+
998
+ - **Bounded Damage** \u2014 when it fails, how much can it mess up? 3 = naturally sandboxed or reversible; 0 = broad, irreversible damage.
999
+ - **State Preservation** \u2014 does failure leave usable progress (checkpoints, artifacts, resumable state)? 3 = clear ladder back; 0 = wipes progress or leaves nothing.
1000
+ - **Legibility** \u2014 can you tell what happened? 3 = failure is named, localized, easy to interpret; 0 = opaque.
1001
+ - **Assumption Exposure** \u2014 does failure reveal what it was counting on? 3 = key assumptions visible before or during action; 0 = hidden assumptions stay hidden.
1002
+ - **Recovery Guidance** \u2014 does failure point to the next move? 3 = specific safest next step; 0 = dead end.
1003
+ - **Value Before Completion** \u2014 even if it cannot finish, does partial output help? 3 = useful value emerges well before completion; 0 = all-or-nothing.
1004
+ - **Failure Elevation** \u2014 does it trade a low-level dumb failure for a higher-level diagnosable one? 3 = consistently pushes failure upward into strategy/dependency/ambiguity space; 0 = fails dumb and low-level.
1005
+ - **Default Reversibility** \u2014 are early moves safe by default (map, diff, dry-run, isolate, draft first)? 3 = strongly defaults to reconnaissance; 0 = commits/edits/sends too early.
1006
+
1007
+ ### Stage 2 score bands
1008
+ - **0\u20138 \u2192 Fragile** \u2014 breaks are mostly wasteful; triggers Stage-2 downgrade (see Decision rule 6).
1009
+ - **9\u201314 \u2192 Functional but crude** \u2014 sometimes useful, failure still clumsy.
1010
+ - **15\u201319 \u2192 Strong** \u2014 usually breaks in ways that preserve momentum.
1011
+ - **20\u201324 \u2192 Operator-grade** \u2014 failure is part of the workflow.
1012
+
1013
+ ### Optional \`failure_modes\` frontmatter (for skill authors)
1014
+
1015
+ Authors may pre-declare the named ways a skill is expected to break by adding an optional \`failure_modes: [...]\` list to the SKILL.md YAML frontmatter. The field is the author-side companion to the Stage 2 rubric above: declaring expected failures up front makes them legible, scoreable, and easier to harden. The field is optional and unvalidated \u2014 no gate enforces its presence, and its absence does not block APPROVE. When present, use the shared taxonomy below so entries compare across skills.
1016
+
1017
+ Taxonomy (free-form strings, shared vocabulary):
1018
+
1019
+ - \`premature execution\` \u2014 acts before mapping
1020
+ - \`bad decomposition\` \u2014 splits work along the wrong seam
1021
+ - \`dependency blindness\` \u2014 misses a required predecessor
1022
+ - \`false completeness\` \u2014 declares done while blockers remain
1023
+ - \`tool thrash\` \u2014 repeats the same tool call hoping for a different result
1024
+ - \`confident fabrication\` \u2014 produces plausible-sounding output with no source
1025
+ - \`over-scaffolding\` \u2014 builds machinery that isn't used
1026
+ - \`local optimization trap\` \u2014 improves one step while worsening the whole
1027
+
1028
+ Example:
1029
+
1030
+ \`\`\`yaml
1031
+ ---
1032
+ name: parallelize
1033
+ description: Transforms a linear plan into waves of parallel sub-agents.
1034
+ failure_modes:
1035
+ - bad decomposition
1036
+ - tool thrash
1037
+ ---
1038
+ \`\`\`
1039
+
1040
+ When scoring Stage 2, cross-check the skill's declared \`failure_modes\` against the dimensions scored 0\u20131. A skill that declares \`tool thrash\` but scores 3 on Legibility and Recovery Guidance is self-aware and well-hardened; one that declares nothing and scores poorly on Assumption Exposure is likely shipping blind.
1041
+
1042
+ ## Rejection checks (Yes/No)
1043
+
1044
+ - Reminder-like
1045
+ - Checklist-like
1046
+ - Best-practice nudge
1047
+ - Subordinate behavior (lives better inside another skill's body)
1048
+ - Better as normal prompting (the agent already infers this)
1049
+ - Better folded into another skill
1050
+ - No material workflow shape change (WI \u22642 AND body is >50% spec/reference AND no sub-agent dispatch in body)
1051
+
1052
+ ## Decision thresholds
1053
+
1054
+ Apply in order \u2014 first match wins:
1055
+
1056
+ 1. Any hard gate FAIL \u2192 **REJECT** (SALVAGE if trivially fixable)
1057
+ 2. Max overlap \u226575% on one dimension or \u226560% on two+ dimensions \u2192 **SALVAGE** (fold) or **REJECT**
1058
+ 3. Any rejection check = Yes \u2192 **REJECT** (SALVAGE only if the sole Yes is "better folded into another skill")
1059
+ 4. Any single Stage 1 rubric dimension \u22642 \u2192 downgrade one tier from the rubric-total result (APPROVE\u2192SALVAGE, SALVAGE\u2192REJECT)
1060
+ 5. Workflow Impact \u22643 \u2192 downgrade one tier (session shape must materially change for this plugin)
1061
+ 6. Stage 2 failure-resilience total \u22648 (Fragile band) \u2192 downgrade one tier (a fragile force multiplier is still dangerous). Note which dimensions scored 0\u20131 in the Rewrite target so the skill can be hardened.
1062
+ - Rules 4, 5, and 6 do not stack \u2014 apply at most one downgrade per candidate. If multiple fire, prefer rule 6 (failure behavior is the most costly to miss).
1063
+ 7. Stage 1 total \u226524/30 \u2192 **APPROVE**
1064
+ 8. Stage 1 total 18\u201323/30 \u2192 **SALVAGE**
1065
+ 9. Stage 1 total <18/30 \u2192 **REJECT**
1066
+
1067
+ Cite the rule number that produced the decision.
1068
+
1069
+ ## Output format
1070
+
1071
+ ### Candidate
1072
+ - Name:
1073
+ - Input form: (idea | name+description | draft SKILL.md)
1074
+ - Inferred purpose:
1075
+ - Default failure it fixes:
1076
+ - Latent machinery exploited:
1077
+
1078
+ ### Overlap check
1079
+ One line per existing skill: \`<skill-name>: X% \u2014 <dimension(s)>: <reason>\`.
1080
+ Report all \u226540%. Max overlap: X% (<skill-name>, <dimension>).
1081
+
1082
+ ### Hard gate
1083
+ - Compactness: PASS/FAIL \u2014 <reason>
1084
+ - Outsized uplift: PASS/FAIL \u2014 <reason>
1085
+
1086
+ ### Stage 1 rubric \u2014 force-multiplier strength
1087
+ - Leverage: X/5
1088
+ - Architecture Awareness: X/5
1089
+ - Generality: X/5
1090
+ - Non-default Value: X/5
1091
+ - Workflow Impact: X/5
1092
+ - Missability: X/5
1093
+ - **Stage 1 total: X/30**
1094
+
1095
+ ### Stage 2 rubric \u2014 failure resilience
1096
+ - Bounded Damage: X/3
1097
+ - State Preservation: X/3
1098
+ - Legibility: X/3
1099
+ - Assumption Exposure: X/3
1100
+ - Recovery Guidance: X/3
1101
+ - Value Before Completion: X/3
1102
+ - Failure Elevation: X/3
1103
+ - Default Reversibility: X/3
1104
+ - **Stage 2 total: X/24** (band: Fragile | Functional but crude | Strong | Operator-grade)
1105
+
1106
+ ### Rejection checks
1107
+ - Reminder-like: Yes/No
1108
+ - Checklist-like: Yes/No
1109
+ - Best-practice nudge: Yes/No
1110
+ - Subordinate behavior: Yes/No
1111
+ - Better as normal prompting: Yes/No
1112
+ - Better folded into another skill: Yes/No
1113
+ - No material workflow shape change: Yes/No
1114
+
1115
+ ### Decision
1116
+ **APPROVE | SALVAGE | REJECT** \u2014 triggered by rule #N.
1117
+
1118
+ ### Reasoning
1119
+ 2\u20134 sentences.
1120
+
1121
+ ### Placement
1122
+ Where it belongs if not APPROVE.
1123
+
1124
+ ### Rewrite
1125
+ Include only if SALVAGE.
1126
+
1127
+ ### Emit telemetry
1128
+
1129
+ After producing the output above, append one JSONL line to the qualify ledger so scores become a queryable corpus. Do this for every verdict \u2014 APPROVE, SALVAGE, and REJECT \u2014 the ledger is a decision record, not a success log.
1130
+
1131
+ \`\`\`bash
1132
+ mkdir -p ~/.claude/agent-framework
1133
+ cat >> ~/.claude/agent-framework/qualify-telemetry.jsonl <<EOF
1134
+ {"timestamp":"$(date -u +%Y-%m-%dT%H:%M:%SZ)","candidate_name":"<name>","verdict":"<APPROVE|SALVAGE|REJECT>","rubric_total":<int 0-30>,"failure_resilience_total":<int 0-24>,"rule_triggered":<int 1-9>}
1135
+ EOF
1136
+ \`\`\`
1137
+
1138
+ Substitute: \`<name>\` with the normalized hyphen-case slug from Step 1; \`<APPROVE|SALVAGE|REJECT>\` with the verdict from the Decision section; \`<int 0-30>\` with the Stage 1 total; \`<int 0-24>\` with the Stage 2 total; \`<int 1-9>\` with the rule number you cited in Decision.
1139
+
1140
+ If the append fails (permissions, disk full, unwritable path), do not retry and do not surface an error in the final output \u2014 the verdict prose above is the primary contract. Telemetry is observability; verdict integrity comes first.
1141
+
1142
+ ## Calibration
1143
+
1144
+ **APPROVE example \u2014 \`parallelize\`**
1145
+ - Stage 1: Leverage 5, Arch 5, Generality 4, Non-default 5, Workflow 5, Missability 5 \u2192 **29/30**
1146
+ - Stage 2: Bounded Damage 3, State Preservation 3, Legibility 2, Assumption Exposure 2, Recovery Guidance 2, Value Before Completion 3, Failure Elevation 2, Default Reversibility 3 \u2192 **20/24** (Operator-grade)
1147
+ - Changes session shape (waves of parallel sub-agents). Exploits Agent tool + plan mode. Compact. Agent almost never parallelizes by default. Stage 2 passes \u2014 per-wave isolation bounds damage; wave outputs are usable individually. Rule 7 \u2192 APPROVE.
1148
+
1149
+ **REJECT example \u2014 "remind Claude to write tests before shipping"**
1150
+ - Stage 1: Leverage 1, Arch 1, Generality 3, Non-default 1, Workflow 1, Missability 2 \u2192 **9/30**
1151
+ - Stage 2: not scored (decision reached at rule 3 before Stage 1 completes the gauntlet).
1152
+ - Reminder-like: Yes. No latent machinery. Base agent writes tests when task warrants. Rule 3 \u2192 REJECT. Belongs in CLAUDE.md.
1153
+
1154
+ **Stage-2 downgrade example \u2014 hypothetical "auto-push on every green test"**
1155
+ - Stage 1: Leverage 4, Arch 3, Generality 4, Non-default 4, Workflow 3, Missability 4 \u2192 **22/30**
1156
+ - Stage 2: Bounded Damage 0 (pushes to remote on trigger), State Preservation 2, Legibility 2, Assumption Exposure 0, Recovery Guidance 1, Value Before Completion 1, Failure Elevation 0, Default Reversibility 0 \u2192 **6/24** (Fragile)
1157
+ - 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).
1158
+
1159
+ Be skeptical. Protect the plugin from fluff. Stage 2 catches patterns that are strong when they work and catastrophic when they don't.
1160
+ `,sourcePath:"agent-framework-local/agents/qualify.md"};import{fileURLToPath as ys}from"node:url";import{dirname as bs}from"node:path";var vs=ys(import.meta.url),Td=bs(vs);import{mkdir as Gn,writeFile as zn}from"fs/promises";import{join as Ke}from"path";function ie(){return process.env.HOME||process.env.USERPROFILE||"~"}function ws(){return Ke(ie(),".claude","agent-framework","forge-telemetry.jsonl")}async function J(t){let e=ws(),n=Ke(ie(),".claude","agent-framework");await Gn(n,{recursive:!0});let r=new Date().toISOString().split(".")[0]+"Z",o={timestamp:r,surface:"atlas",...t},s=JSON.stringify(o)+`
1161
+ `;return await zn(e,s,{flag:"a"}),r}async function Vn(){let t=Ke(ie(),".claude","agent-framework","ceiling-ledger"),e=Ke(t,"forge-thaw-history.jsonl");await Gn(t,{recursive:!0});let r={timestamp:new Date().toISOString().split(".")[0]+"Z",surface:"atlas",event:"forge.thaw_override",thaw_triggered:!0},o=JSON.stringify(r)+`
1162
+ `;await zn(e,o,{flag:"a"})}import{readFile as qn,readdir as ks,writeFile as Ss,mkdir as xs,unlink as Ps}from"fs/promises";import{join as ve}from"path";import{existsSync as Es}from"fs";function yt(){return ve(ie(),".claude","agent-framework","briefs")}async function Wn(t){let e=ve(yt(),t+".md"),n=await qn(e,"utf-8");return{id:t,content:n}}async function Yn(){let t=yt();return Es(t)?(await ks(t,{withFileTypes:!0})).filter(r=>r.isFile()&&r.name.endsWith(".md")).map(r=>r.name.slice(0,-3)):[]}async function bt(t,e){let n=yt(),r=ve(n,t+".md"),o=ve(n,e),s=ve(o,t+".md");await xs(o,{recursive:!0});let i=await qn(r,"utf-8");await Ss(s,i,"utf-8"),await Ps(r)}function Jn(t){let e=t.split(`
1163
+ `).map(l=>l.trim()).filter(l=>l),n=e.find(l=>/^(APPROVE|SALVAGE|REJECT)/.test(l));if(!n)return{verdict:"REJECT",feedback:t};let r=n.match(/^(APPROVE|SALVAGE|REJECT)/)?.[1];if(!r)return{verdict:"REJECT",feedback:t};let o=t.match(/score:\s*(\d+)/i),s=o&&o[1]?parseInt(o[1],10):void 0,i=e.indexOf(n),a=e.slice(i+1).join(`
1164
+ `).trim();return{verdict:r,score:s,feedback:a||n}}var Cs=Ts(As);function Ms(){let t=process.env.AFK_EVAL_HARNESS_ROOT;if(t){let o=ne(t,"scripts","eval-harness","runner.py");if(Qn(o))return o}let e=Is(import.meta.url),n=ne(e,"../../../.."),r=ne(n,"..","awa-private","scripts","eval-harness","runner.py");if(Qn(r))return r;throw new Error(`Could not find eval-harness runner.py. Tried: ${r}`)}function _s(t){return ne(t,"..","..","..","plugins","awa-private")}function Rs(){let t=process.env.HOME||process.env.USERPROFILE||"~";return ne(t,".claude","agent-framework","ceiling-ledger")}function Ds(t){let e=t.split(`
1165
+ `),n=[],r=/^\s+✗\s+(\S+):/;for(let o of e){let s=o.match(r);s&&s[1]&&n.push(s[1])}return n}async function Os(t){let e=Rs(),n=ne(e,"qualifications.jsonl");await Xn(e,{recursive:!0});let o=new Date().toISOString().split(".")[0]+"Z",i=JSON.stringify({timestamp:o,surface:"atlas",refers_to_run_id:t,source:"forge-gate-check-ts"})+`
1166
+ `;return await Zn(n,i,{flag:"a"}),o}async function Fs(){let t;try{t=Ms()}catch(l){throw new Error(`Failed to resolve eval-harness runner.py: ${l instanceof Error?l.message:String(l)}`)}let e=_s(t),n="",r="",o=0;try{let l=await Cs("python3",[t,"--plugin-root",e],{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 ${t}.`)}let s=o===0?"OPEN":"CLOSED",i=s==="CLOSED"?Ds(n):void 0,a;if(s==="OPEN"){let l=new Date().toISOString().split(".")[0]+"Z";a=await Os(l)}return{gate_status:s,exit_code:o,stdout:n,stderr:r||void 0,tasks_failed:i,ledger_entry_ref:a}}var $s=V.object({iteration:V.number().int().positive(),verdict:V.enum(["APPROVE","SALVAGE","REJECT"]),score:V.number().optional(),feedback:V.string()}),iu=V.object({status:V.enum(["APPROVED","REJECTED","GATE_CLOSED","MAX_ITERATIONS"]),skill_path:V.string().optional(),qualify_verdicts:V.array($s),brief_id:V.string().optional(),telemetry_ref:V.string()});async function Ls(t,e){let n=typeof t=="string"?{brief:t}:typeof t=="object"&&t!==null?t:{},r=n.brief,o=n.forceThaw??!1,s=n.maxIterations??3,i="",a=[],l="REJECTED",c,d;try{let u=await Fs();if(u.gate_status==="CLOSED"&&!o)return i=await J({event:"forge.gate_check",gate_status:"CLOSED"}),{status:"GATE_CLOSED",qualify_verdicts:[],telemetry_ref:i};o&&u.gate_status==="CLOSED"&&(await Vn(),i=await J({event:"forge.thaw_override",gate_status:"CLOSED"})),i=await J({event:"forge.gate_check",gate_status:"OPEN"});let p="",f=!1;if(r)p=r,f=!0;else{let x=await Yn();if(x.length>0){let M=x[0],_=await Wn(M);p=_.content,d=_.id,f=!0}else{if(!e?.sessionId)throw new Error("forge requires parent session for gap discovery");let _=T("forge")["gap-discovery.md"];if(!_)throw new Error("forge skill missing gap-discovery.md prompt");let w=await(await new k().forkSubagent({parent:{sessionId:e.sessionId},config:{model:"sonnet",systemPrompt:_},idPrefix:"forge-gap-discovery"})).runToResult("Identify the most impactful skill gap.");if(w.status!=="succeeded")throw new Error(`gap discovery failed: ${C(w)}`);if(p=w.message?.content||"",!p)throw new Error("gap discovery returned no concept")}}if(i=await J({event:"forge.brief_loaded",used_brief:f,brief_id:d||null}),!e?.sessionId)throw new Error("forge requires parent session for skill generation");let g=T("forge"),h=g["generate.md"],m=g["system.md"];if(!h)throw new Error("forge skill missing generate.md prompt");if(!m)throw new Error("forge skill missing system.md prompt");let F=await(await new k().forkSubagent({parent:{sessionId:e.sessionId},config:{model:"sonnet",systemPrompt:m},idPrefix:"forge-generate"})).runToResult(`Generate a new amplifier skill based on this concept:
1167
+
1168
+ ${p}`);if(F.status!=="succeeded")throw new Error(`skill generation failed: ${C(F)}`);let R=F.message?.content||"";if(!R)throw new Error("skill generation returned no output");for(let x=1;x<=s;x++){let M=ht.systemPrompt;if(!M)throw new Error("qualify agent missing system prompt");let K=await(await new k().forkSubagent({parent:{sessionId:e.sessionId},config:{model:"sonnet",systemPrompt:M},idPrefix:`forge-qualify-${x}`})).runToResult(`Evaluate this amplifier skill against the force-multiplier criteria:
1169
+
1170
+ ${R}`);if(K.status!=="succeeded")throw new Error(`qualify iteration ${x} failed: ${C(K)}`);let w=K.message?.content||"",{verdict:P,score:y,feedback:E}=Jn(w),j={iteration:x,verdict:P,score:y,feedback:E};if(a.push(j),i=await J({event:"forge.qualify_iteration",iteration:x,verdict:P,score:y||null}),P==="APPROVE"){l="APPROVED";break}else if(P==="SALVAGE"&&x<s){let D=g["qualify-rework.md"];if(!D)throw new Error("forge skill missing qualify-rework.md prompt");let oe=D.replace("{feedback}",E).replace("{original_skill}",R),se=await(await new k().forkSubagent({parent:{sessionId:e.sessionId},config:{model:"sonnet",systemPrompt:oe},idPrefix:`forge-rework-${x}`})).runToResult("Refine the skill based on the feedback.");if(se.status!=="succeeded")throw new Error(`rework iteration ${x} failed: ${C(se)}`);if(R=se.message?.content||"",!R)throw new Error(`rework iteration ${x} returned no output`)}else P==="REJECT"&&x>=s&&(l="MAX_ITERATIONS")}if(l==="APPROVED"){let x=R.match(/^name:\s*([^\n]+)/m),M=x&&x[1]?x[1].trim().replace(/^["']|["']$/g,""):"unknown",_=ne(ie(),".claude","agent-framework-local","skills",M);await Xn(_,{recursive:!0});let B=ne(_,"SKILL.md");await Zn(B,R,"utf-8"),c=B,f&&d&&await bt(d,"consumed"),i=await J({event:"forge.complete",status:"APPROVED",skill_name:M,iterations:a.length})}else l==="MAX_ITERATIONS"&&(f&&d&&await bt(d,"failed"),i=await J({event:"forge.complete",status:"MAX_ITERATIONS",iterations:a.length}))}catch(u){throw i=await J({event:"forge.error",error:u instanceof Error?u.message:String(u)}),u}return{status:l,skill_path:c,qualify_verdicts:a,brief_id:d,telemetry_ref:i}}var js={name:"forge",description:'Creates new amplifier skills gated by forge-gate-check, with autonomous gap discovery, skill generation, and qualify iteration loop \u22643\xD7. Writes approved skills and appends telemetry to shared JSONL with surface: "atlas".',handler:Ls,argumentHint:"[--brief <path>]",whenToUse:"When the user wants to grow the plugin with a new amplifier skill \u2014 autonomously generates and validates one.",flags:["--brief"]};W(js);var Hs={name:"bash",description:"Execute a shell command and return its stdout and stderr. Use for running programs, installing packages, git operations, and any task that requires a shell. Commands run in the user's default shell. Long-running commands should use timeout_ms. Output is capped at ~100KB; excess is truncated with a notice.",input_schema:{type:"object",properties:{command:{type:"string",description:"The shell command to execute."},timeout_ms:{type:"number",description:"Optional timeout in milliseconds (default 120000, max 600000). The command is killed if it exceeds this duration."}},required:["command"]}},Us={name:"read_file",description:"Read a file from the filesystem. Returns the file content with line numbers. Use offset and limit to read specific sections of large files. When the read returns a partial view, the response ends with a `... (showing lines X-Y of Z [\u2014 pass offset=N to continue])` annotation indicating the full file size and how to continue. Binary files are detected and rejected. Missing files return an error.",input_schema:{type:"object",properties:{file_path:{type:"string",description:"Absolute path to the file to read."},offset:{type:"number",description:"Line number to start reading from (1-based). Defaults to 1."},limit:{type:"number",description:"Maximum number of lines to read. Defaults to 2000."}},required:["file_path"]}},Ns={name:"write_file",description:"Write content to a file, creating it if it does not exist or overwriting if it does. Parent directories are created automatically. Prefer edit_file for modifying existing files \u2014 use write_file only for new files or complete rewrites.",input_schema:{type:"object",properties:{file_path:{type:"string",description:"Absolute path to the file to write."},content:{type:"string",description:"The full content to write to the file."}},required:["file_path","content"]}},Bs={name:"edit_file",description:"Perform an exact string replacement in a file. Finds old_string and replaces it with new_string. The edit fails if old_string is not found or matches multiple locations (unless replace_all is true). Always use read_file first to verify the exact content before editing.",input_schema:{type:"object",properties:{file_path:{type:"string",description:"Absolute path to the file to edit."},old_string:{type:"string",description:"The exact string to find and replace. Must match file content exactly."},new_string:{type:"string",description:"The replacement string."},replace_all:{type:"boolean",description:"If true, replace all occurrences. If false (default), fail when multiple matches exist."}},required:["file_path","old_string","new_string"]}},Ks={name:"glob",description:'Find files matching a glob pattern. Returns matching file paths, capped at 500 results. Use for discovering files before reading them. Patterns follow standard glob syntax (e.g., "src/**/*.ts", "*.json").',input_schema:{type:"object",properties:{pattern:{type:"string",description:'Glob pattern to match (e.g., "src/**/*.ts").'},path:{type:"string",description:"Base directory to search from. Defaults to the current working directory."}},required:["pattern"]}},Gs={name:"grep",description:"Search file contents for lines matching a pattern. Returns matches in file:line:content format. Uses grep -rn (or ripgrep if available). Output is capped to prevent overflow. Use for finding symbols, strings, or patterns across the codebase.",input_schema:{type:"object",properties:{pattern:{type:"string",description:"Search pattern (basic regex by default)."},path:{type:"string",description:"Directory or file to search. Defaults to current working directory."},include:{type:"string",description:'File glob to restrict search (e.g., "*.ts"). Passed as --include to grep.'}},required:["pattern"]}},zs={name:"list_directory",description:"List the contents of a directory. Returns file and subdirectory names with type annotations (directories end with /). Use for exploring project structure.",input_schema:{type:"object",properties:{path:{type:"string",description:"Absolute path to the directory to list."}},required:["path"]}},er={name:"agent",description:"Dispatch a subtask to an independent agent session. The agent runs with its own conversation context and tool access. Use for tasks that benefit from isolated context (research, parallel work, specialized focus). The agent runs to completion and returns its final response.",input_schema:{type:"object",properties:{prompt:{type:"string",description:"The task for the agent to perform."},model:{type:"string",description:"Model for the agent. Defaults to parent session model. Override per-call to right-size cost vs. capability \u2014 `haiku` (cheapest/fastest), `sonnet` (general-use), `opus` (most capable). Append `_1m` (e.g. `sonnet_1m`) for 1M-context variants. Full model IDs are also accepted."},max_turns:{type:"number",description:"Maximum conversation turns (default 10, max 50)."},id_prefix:{type:"string",description:"Label prefix for log correlation."}},required:["prompt"]}},tr={name:"skill",description:"Invoke a registered skill by name. Skills are specialized capabilities that dispatch subagents with domain-specific prompts. Check the system prompt for the list of available skills and their descriptions.",input_schema:{type:"object",properties:{name:{type:"string",description:'Skill name (e.g., "mint", "diagnose", "shadow-verify").'},arguments:{type:"string",description:"Arguments to pass to the skill."}},required:["name"]}},Ge=[Hs,Us,Ns,Bs,Ks,Gs,zs],we=Ge.map(t=>t.name);import{readFileSync as ei,existsSync as ir}from"fs";import{join as ar}from"path";import{config as ti}from"dotenv";var nr={opus:"claude-opus-4-7",opus_1m:"claude-opus-4-7",sonnet:"claude-sonnet-4-6",sonnet_1m:"claude-sonnet-4-6",haiku:"claude-haiku-4-5-20251001"};function ze(t){return t in nr}function rr(t){let e=nr[t];if(!e)throw new Error(`Invalid model: ${t}`);return e}function ae(t){if(t!==void 0)return typeof t=="string"&&ze(t)?rr(t):t}import{execFileSync as Vs}from"child_process";import{existsSync as qs,readFileSync as Ws}from"fs";import{homedir as Ys,userInfo as Js}from"os";import{join as Qs}from"path";function or(){let t=Xs();if(t===void 0)return;let e=Zs(t);if(e!==void 0){if(e.expiresAt!==void 0&&e.expiresAt<=Date.now()){process.stderr.write("agent-afk: Claude Code OAuth token in keychain is expired. Run `claude login` to refresh.\n");return}return e.accessToken}}function Xs(){if(process.platform==="darwin")try{return Vs("security",["find-generic-password","-s","Claude Code-credentials","-a",Js().username,"-w"],{stdio:["ignore","pipe","ignore"],encoding:"utf-8"}).trim()}catch{return}if(process.platform==="linux"){let t=Qs(Ys(),".claude",".credentials.json");if(!qs(t))return;try{return Ws(t,"utf-8")}catch{return}}}function Zs(t){let e;try{e=JSON.parse(t)}catch{return}if(typeof e!="object"||e===null)return;let n=e.claudeAiOauth;if(typeof n!="object"||n===null)return;let r=n,o=r.accessToken;if(typeof o!="string"||o.length===0)return;let s=r.expiresAt,i={accessToken:o};return typeof s=="number"&&(i.expiresAt=s),i}var Ve={model:"sonnet",maxTokens:4096,temperature:1},sr=!1;function vt(){return process.env.ANTHROPIC_API_KEY||process.env.CLAUDE_CODE_OAUTH_TOKEN||or()}function ni(){if(!sr){let r=[ar(process.cwd(),".env"),xn(),Pn()];for(let o of r)if(ir(o)){ti({path:o});break}sr=!0}let t={},e=vt();e!==void 0&&(t.apiKey=e);let n=process.env.AFK_MODEL??process.env.CLAUDE_MODEL;if(n){let r=n.toLowerCase();t.model=ze(r)?r:n}if(process.env.AFK_MAX_TOKENS&&(t.maxTokens=parseInt(process.env.AFK_MAX_TOKENS,10)),process.env.AFK_TEMPERATURE&&(t.temperature=parseFloat(process.env.AFK_TEMPERATURE)),process.env.AFK_SYSTEM_PROMPT&&(t.systemPrompt=process.env.AFK_SYSTEM_PROMPT),process.env.AFK_AUTO_ROUTING){let r=process.env.AFK_AUTO_ROUTING.toLowerCase()==="true";t.autoRouting={interactive:r,chat:r,telegram:r,daemon:r}}return t}function ri(){let t=[ar(process.cwd(),"afk.config.json"),dt(),ut()];for(let e of t)if(ir(e))try{let n=ei(e,"utf-8"),r=JSON.parse(n),o={};if(typeof r.model=="string"&&r.model.length>0&&(o.model=(ze(r.model),r.model)),typeof r.maxTokens=="number"&&(o.maxTokens=r.maxTokens),typeof r.temperature=="number"&&(o.temperature=r.temperature),r.systemPrompt&&(o.systemPrompt=r.systemPrompt),r.autoRouting&&typeof r.autoRouting=="object"){let s={};typeof r.autoRouting.interactive=="boolean"&&(s.interactive=r.autoRouting.interactive),typeof r.autoRouting.chat=="boolean"&&(s.chat=r.autoRouting.chat),typeof r.autoRouting.telegram=="boolean"&&(s.telegram=r.autoRouting.telegram),typeof r.autoRouting.daemon=="boolean"&&(s.daemon=r.autoRouting.daemon),o.autoRouting=s}if(r.daemon&&typeof r.daemon=="object"){let s={};typeof r.daemon.task=="string"&&(s.task=r.daemon.task),typeof r.daemon.taskId=="string"&&(s.taskId=r.daemon.taskId),o.daemon=s}return o}catch(n){console.error(`Warning: Failed to parse ${e}:`,n)}return{}}function lr(t){let e=ni(),n=ri(),r={...Ve,...e,...n,...t};return{model:r.model??Ve.model,maxTokens:r.maxTokens??Ve.maxTokens,temperature:r.temperature??Ve.temperature,...r.apiKey!==void 0?{apiKey:r.apiKey}:{},...r.systemPrompt!==void 0?{systemPrompt:r.systemPrompt}:{},...r.autoRouting!==void 0?{autoRouting:r.autoRouting}:{},...r.daemon!==void 0?{daemon:r.daemon}:{}}}function $(){return vt()}function wt(){let t=process.env.AFK_DEFAULT_SUBAGENT_MODEL;return!t||t.length===0?"sonnet":t}function oi(t){if(t===void 0)return;if(t==="max")return Number.POSITIVE_INFINITY;if(t===""||t==="NaN")throw new Error(`Invalid --max-output-tokens value: ${JSON.stringify(t)}. Expected a positive integer or 'max'.`);if(!/^\d+$/.test(t))throw new Error(`Invalid --max-output-tokens value: ${JSON.stringify(t)}. Expected a positive integer or 'max'.`);let e=Number(t);if(!Number.isFinite(e)||!Number.isInteger(e)||e<=0)throw new Error(`Invalid --max-output-tokens value: ${JSON.stringify(t)}. Must be a positive integer.`);return e}function cr(){return oi(process.env.AFK_MAX_OUTPUT_TOKENS)}async function dr(t,e){let r=T("mint")["spec.md"];if(!r)throw new Error("mint skill missing spec.md prompt");let i=await(await new k().forkSubagent({parent:{sessionId:e},config:{model:"sonnet",systemPrompt:r,apiKey:$()},idPrefix:"mint-spec"})).runToResult(`Create a detailed specification for: ${t}`);if(i.status!=="succeeded"||!i.message)throw new Error(`spec phase failed: ${C(i)}`);return i.message.content}async function ur(t,e){let r=T("mint")["research.md"];if(!r)throw new Error("mint skill missing research.md prompt");let i=await(await new k().forkSubagent({parent:{sessionId:e},config:{model:"sonnet",systemPrompt:r,apiKey:$()},idPrefix:"mint-research"})).runToResult(`Gather context and research for this specification:
1171
+
1172
+ ${t}`);if(i.status!=="succeeded"||!i.message)throw new Error(`research phase failed: ${C(i)}`);return i.message.content}async function pr(t,e,n){let o=T("mint")["plan.md"];if(!o)throw new Error("mint skill missing plan.md prompt");let i=await new k().forkSubagent({parent:{sessionId:n},config:{model:"sonnet",systemPrompt:o,apiKey:$()},idPrefix:"mint-plan"}),a=`Specification:
1173
+ ${t}
1174
+
1175
+ Research findings:
1176
+ ${e}
1177
+
1178
+ Create a detailed implementation plan based on the spec and research.`,l=await i.runToResult(a);if(l.status!=="succeeded"||!l.message)throw new Error(`plan phase failed: ${C(l)}`);return l.message.content}function si(t){let e=t.match(/\.\w+\s/g)||[],n=t.match(/Files?:\s*(.+?)(?:\n|$)/gi)||[],r=e.length;for(let o of n){let s=o.replace(/Files?:\s*/i,"").split(/[,;]/g).filter(i=>i.trim().length>0);r+=s.length}return r}async function fr(t,e){if(si(t)<3)return null;try{return await z("parallelize").handler({plan:t})}catch(r){return console.warn(`Parallelize dispatch failed: ${r instanceof Error?r.message:String(r)}`),null}}import{z as X}from"zod";function ue(t){let e=le();e&&e({type:"panel",spec:t},{subagentId:"__main__"})}var ii=X.object({status:X.enum(["PASS","FAIL"]),status_reason:X.string().optional(),files_changed:X.array(X.string()),tests_passed:X.boolean(),build_passed:X.boolean().optional(),verification_passed:X.boolean().optional(),notes:X.string()});async function mr(t,e,n){let o=T("mint")["build.md"];if(!o)throw new Error("mint skill missing build.md prompt");let i=await new k().forkSubagent({parent:{sessionId:n},config:{model:"sonnet",systemPrompt:o,apiKey:$()},idPrefix:"mint-build",outputSchema:ii}),a=`Implementation plan:
1179
+ ${t}
1180
+
1181
+ `+(e?`Wave orchestration plan:
1182
+ ${JSON.stringify(e,null,2)}
1183
+
1184
+ `:"")+"Execute the implementation plan following TDD (test-first) principles.",l=await i.runToResult(a);if(l.status!=="succeeded"||!l.output)throw new Error(`build phase failed: ${C(l)}`);let c=l.output,d={filesChanged:c.files_changed,testsPassed:c.tests_passed,notes:c.notes};return ue({kind:"checkpoint",title:"build",body:[`Files changed: ${d.filesChanged.length}`,`Tests: ${d.testsPassed?"passed":"failed"}`,"Next: verify"]}),d}import{z as pe}from"zod";var ai=pe.object({status:pe.enum(["PASS","FAIL"]),status_reason:pe.string().optional(),issues:pe.array(pe.string()).default([]),summary:pe.string().optional()});async function kt(t,e,n,r,o){let i=await new k().forkSubagent({parent:{sessionId:r},config:{model:"sonnet",systemPrompt:o,apiKey:$()},idPrefix:`mint-verify-${t}`,outputSchema:ai}),a=`Plan:
1185
+ ${e}
1186
+
1187
+ Build results:
1188
+ ${JSON.stringify(n,null,2)}
1189
+
1190
+ Mode: ${t}
1191
+
1192
+ Run ${t} verification on the implementation.`,l;try{l=await i.runToResult(a)}finally{await i.teardown().catch(()=>{})}if(l.status!=="succeeded"||!l.output)return{passed:!1,issues:[`${t} verification failed: ${C(l)}`]};let c=l.output,d=c.status==="PASS";return{passed:d,issues:d?void 0:c.issues}}async function qe(t,e,n){let o=T("mint")["verify.md"];if(!o)throw new Error("mint skill missing verify.md prompt");let[s,i,a]=await Promise.all([kt("test",t,e,n,o),kt("lint",t,e,n,o),kt("design-review",t,e,n,o)]),l=[];s.issues&&l.push(...s.issues),i.issues&&l.push(...i.issues),a.issues&&l.push(...a.issues);let c={testsPassed:s.passed,lintPassed:i.passed,designReviewPassed:a.passed,...l.length>0?{issues:l}:{}},d=c.testsPassed&&c.lintPassed&&c.designReviewPassed,u=p=>p?"passed":"failed";return ue({kind:d?"checkpoint":"diagnosis",title:"verify",body:[`Tests: ${u(c.testsPassed)} \xB7 Lint: ${u(c.lintPassed)}`,`Design review: ${u(c.designReviewPassed)}`,...d?["Next: ship"]:[`Issues: ${l.length} (heal loop will retry)`]]}),c}async function gr(t,e,n,r,o){if(n.testsPassed&&n.lintPassed&&n.designReviewPassed)return{healed:!0,newHealIterations:r,newVerifyResults:n};if(r>=2)return{healed:!1,newHealIterations:r,newVerifyResults:n};try{let s=z("diagnose"),i=`Verification failures:
1193
+ Tests: ${n.testsPassed?"PASS":"FAIL"}
1194
+ Lint: ${n.lintPassed?"PASS":"FAIL"}
1195
+ Design: ${n.designReviewPassed?"PASS":"FAIL"}
1196
+ Issues: ${n.issues?.join(`
1197
+ `)||"none"}`,a=await s.handler({failure:i,repoPath:process.cwd(),context:t}),l="";if(typeof a=="object"&&a!==null&&"winner"in a&&typeof a.winner=="object"&&a.winner!==null){let F=a.winner;typeof F.proposed_fix=="string"&&(l=F.proposed_fix)}let d=T("mint")["heal.md"];if(!d)throw new Error("mint skill missing heal.md prompt");let p=await new k().forkSubagent({parent:{sessionId:o.sessionId},config:{model:"sonnet",systemPrompt:d,apiKey:$()},idPrefix:"mint-heal"}),f=n.issues?.join(`
1198
+ `)??"none",g=`Plan:
1199
+ ${t}
1200
+
1201
+ Proposed fix from diagnosis:
1202
+ ${l}
1203
+
1204
+ Verification issues:
1205
+ ${f}
1206
+
1207
+ Apply the fix and update the implementation.`,h=await p.runToResult(g);if(h.status!=="succeeded"||!h.message)throw new Error(`heal phase failed: ${C(h)}`);let m=/^\s*FIX_APPLIED:\s*(true|false)/im.exec(h.message.content)?.[1]?.toLowerCase()==="true",b=r+1;if(!m)return{healed:!1,newHealIterations:b,newVerifyResults:n};if(!o.sessionId)throw new Error("Parent session ID required for verification");let S=await qe(t,e,o.sessionId);return{healed:S.testsPassed&&S.lintPassed&&S.designReviewPassed,newHealIterations:b,newVerifyResults:S}}catch{return{healed:!1,newHealIterations:r+1,newVerifyResults:n}}}async function hr(t,e){let r=T("mint")["ship.md"];if(!r)throw new Error("mint skill missing ship.md prompt");let s=await new k().forkSubagent({parent:{sessionId:e},config:{model:"sonnet",systemPrompt:r,apiKey:$()},idPrefix:"mint-ship"}),i=`Idea: ${t.idea}
1208
+
1209
+ Specification:
1210
+ ${t.spec}
1211
+
1212
+ Plan:
1213
+ ${t.plan}
1214
+
1215
+ Build results:
1216
+ ${JSON.stringify(t.buildResults,null,2)}
1217
+
1218
+ Verification results:
1219
+ ${JSON.stringify(t.verifyResults,null,2)}
1220
+
1221
+ Create a ship-ready summary with next steps.`,a=await s.runToResult(i);if(a.status!=="succeeded"||!a.message)throw new Error(`ship phase failed: ${C(a)}`);let l=t.buildResults?.filesChanged.length??0,c=t.healIterations;return ue({kind:"checkpoint",title:"ship \u2014 done",body:[`Files changed: ${l}`,`Heal iterations: ${c}`,`Idea: ${t.idea}`]}),a.message.content}import{existsSync as yr,mkdirSync as li,readFileSync as ci,unlinkSync as di,writeFileSync as ui}from"fs";import{dirname as pi,join as fi}from"path";function St(t){return fi(Sn(),t,"mint-state.json")}function br(t,e){let n=St(t);li(pi(n),{recursive:!0}),ui(n,JSON.stringify(e,null,2),"utf-8")}function mi(t){if(typeof t!="object"||t===null)return!1;let e=t;return typeof e.currentPhase=="string"&&typeof e.idea=="string"&&typeof e.spec=="string"&&typeof e.healIterations=="number"&&Array.isArray(e.history)}function vr(t){let e=St(t);if(!yr(e))return null;try{let n=JSON.parse(ci(e,"utf-8"));return mi(n)?n:null}catch{return null}}function xt(t){let e=St(t);if(yr(e))try{di(e)}catch{}}var gi=2,wr=/^\s*--continue(?:\s+(?:approved|yes|y))?\s*$/i,hi="To approve and run the rest of the pipeline, invoke /mint --continue approved (or call mint with {userApproved: true} \u2014 no idea field needed). The handler will reload the spec state from disk.";function re(t,e,n){t.history.push({phase:e,output:n,timestamp:Date.now()})}function yi(t){if(typeof t=="string")return wr.test(t)?{userApproved:!0}:{idea:t};if(typeof t=="object"&&t!==null){let e=t,n=typeof e.idea=="string"?e.idea:void 0;if(n!==void 0&&wr.test(n))return{userApproved:!0};if("idea"in e||"resumeFrom"in e||e.userApproved===!0)return e}throw new Error("mint handler requires input.idea (string), input as string, or {userApproved: true} to resume")}async function kr(t,e){if(!e.sessionId)throw new Error("runPhasesAfterSpec requires parentSession.sessionId");let n=e.sessionId;try{t.currentPhase="research",t.research=await ur(t.spec,n),re(t,"research",t.research),t.currentPhase="plan",t.plan=await pr(t.spec,t.research,n),re(t,"plan",t.plan),t.currentPhase="parallelize",t.waveOrchestrationPlan=await fr(t.plan,e),re(t,"parallelize",JSON.stringify(t.waveOrchestrationPlan||"skipped")),t.currentPhase="build",t.buildResults=await mr(t.plan,t.waveOrchestrationPlan,n),re(t,"build",JSON.stringify(t.buildResults)),t.currentPhase="verify",t.verifyResults=await qe(t.plan,t.buildResults,n),re(t,"verify",JSON.stringify(t.verifyResults)),t.currentPhase="heal";let r=t.verifyResults.testsPassed&&t.verifyResults.lintPassed&&t.verifyResults.designReviewPassed;for(;!r&&t.healIterations<gi;){let s=await gr(t.plan,t.buildResults,t.verifyResults,t.healIterations,e);t.healIterations=s.newHealIterations,t.verifyResults=s.newVerifyResults,r=s.healed,re(t,"heal",`Iterations: ${t.healIterations}, Success: ${r}`)}if(!r)return{paused:!0,phase:"heal-failed",reason:`Heal capped at ${t.healIterations} iterations; still have failures`,state:t,nextStep:"Heal loop exhausted. Inspect verifyResults, fix manually, then re-invoke /mint with a fresh idea \u2014 resume is not supported from heal-failed."};t.currentPhase="ship";let o=await hr(t,n);return re(t,"ship",o),{completed:!0,artifact:o,state:t}}catch(r){throw new Error(`mint failed at ${t.currentPhase}: ${r}`)}}function Sr(t,e){return("completed"in e||e.phase==="heal-failed")&&xt(t),e}async function bi(t,e){let n=yi(t);if(!e?.sessionId)throw new Error("mint handler requires a parent session to fork subagents");let r=e.sessionId;if(n.userApproved){let i=n.resumeFrom??vr(r);if(!i)throw new Error("mint: no paused spec found for this session to continue. Run /mint <idea> first, then /mint --continue approved.");let a=await kr(i,e);return Sr(r,a)}if(!n.idea)throw new Error("mint: no idea provided. Run /mint <idea> to start, or /mint --continue approved to resume a paused spec.");xt(r);let o={currentPhase:"spec",idea:n.idea,healIterations:0,history:[]};try{o.spec=await dr(n.idea,r),re(o,"spec",o.spec)}catch(i){throw new Error(`mint failed at spec: ${i}`)}if(!n.autoApprove)return br(r,o),{paused:!0,phase:"spec",spec:o.spec,state:o,nextStep:hi};let s=await kr(o,e);return Sr(r,s)}var vi={name:"mint",description:"Takes a feature idea or refactor scope and delivers a ship-ready, verified implementation end-to-end",handler:bi,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, invoke `/mint --continue approved` (or call mint with `{userApproved: true}`) to resume \u2014 the handler reloads the spec state from disk.",flags:["--continue"]};W(vi);import{existsSync as wi,readdirSync as ki,readFileSync as Si,statSync as xi}from"fs";import{join as Pi}from"path";function Pt(t){let e=[];function n(r,o=0){if(o>10||!wi(r))return;let s;try{s=ki(r)}catch{return}for(let i of s){if(i.startsWith("."))continue;let a=Pi(r,i),l;try{l=xi(a)}catch{continue}if(l.isFile()&&i==="SKILL.md"){let c=Ei(a);c.name&&e.push(c)}else l.isDirectory()&&n(a,o+1)}}return n(t),e}function Ei(t){try{let e=Si(t,"utf-8");if(!e.startsWith(`---
1222
+ `))return{};let n=e.slice(4),r=n.indexOf(`
1223
+ ---`);if(r===-1)return{};let o=n.slice(0,r),s=n.slice(r+4).trim(),i={},a=o.split(`
1224
+ `);for(let l of a){if(!l)continue;let c=l.indexOf(":");if(c===-1)continue;let d=l.slice(0,c).trim(),u=l.slice(c+1).trim();d==="name"?i.name=u.replace(/^["']|["']$/g,""):d==="description"?i.description=u.replace(/^["']|["']$/g,""):d==="argumentHint"&&(i.argumentHint=u.replace(/^["']|["']$/g,""))}return s.length>0&&(i.body=s),i}catch{return{}}}function xr(t){let e=ke(t);if(e.length===0)return"";let n=[];for(let r of e){let o=r.argumentHint?`${r.argumentHint}`:"",s=o?`- \`${r.name} ${o}\`: ${r.description}`:`- ${r.name}: ${r.description}`;n.push(s),r.whenToUse&&n.push(` When to use: ${r.whenToUse}`)}return["Available skills (invoke via the `skill` tool):",...n].join(`
1225
+ `)}function ke(t){let e=[],n=new Set;for(let o of un()){let s=z(o);e.push({name:o,description:s.description,source:s.origin==="user"?"user":s.origin==="project"?"project":"builtin",argumentHint:s.argumentHint,whenToUse:s.whenToUse}),n.add(o)}let r=t??[...q(he()),...q()];for(let o of r){if(o.type!=="local")continue;let s=Pt(o.path);for(let i of s)!i.name||n.has(i.name)||(e.push({name:i.name,description:i.description??`Skill from plugin at ${o.path}`,source:"plugin"}),n.add(i.name))}return e}function Pr(t){let e=new Map,n=t??[...q(he()),...q()];for(let r of n){if(r.type!=="local")continue;let o=Pt(r.path);for(let s of o)s.name&&s.body&&s.body.length>0&&e.set(s.name,s.body)}return e}var Ai=3,Ti="claude-haiku-4-5-20251001",Ii=1024,Ci=[{value:"claude-sonnet-4-5-20250929",displayName:"Claude Sonnet 4.5",description:"Latest balanced Claude \u2014 recommended default"},{value:"claude-opus-4-5-20250929",displayName:"Claude Opus 4.5",description:"Highest-capability Claude"},{value:"claude-haiku-4-5-20250929",displayName:"Claude Haiku 4.5",description:"Fastest, cheapest Claude"}],We=class{client;authMode;initSessionId;promptStream;toolDispatcher;maxTokens;tools;systemPrefix;userSystem;currentModel;currentPermissionMode;messages=[];closed=!1;abortController=null;pendingAbortReason=null;closedPromise;closeResolve=null;lastUsage=null;constructor(e){this.client=e.client,this.authMode=e.authMode,this.initSessionId=Et(),this.promptStream=e.promptStream,this.toolDispatcher=e.toolDispatcher,this.maxTokens=e.maxTokens,this.tools=e.tools,this.systemPrefix=e.systemPrefix,this.userSystem=e.userSystem,this.currentModel=e.model,this.currentPermissionMode=e.permissionMode??"default",this.closedPromise=new Promise(n=>{this.closeResolve=()=>n("__closed__")})}async*[Symbol.asyncIterator](){yield{type:"session.init",info:{sessionId:this.initSessionId,model:this.currentModel,permissionMode:this.currentPermissionMode,cwd:process.cwd(),tools:[],slashCommands:[],skills:[],plugins:[],mcpServers:[],apiKeySource:this.authMode,version:"anthropic-direct-v1"}};let n=this.promptStream[Symbol.asyncIterator]();try{for(;!this.closed;){let r=await Promise.race([n.next(),this.closedPromise]);if(r==="__closed__")break;let o=r;if(o.done)break;let s=o.value,i=new AbortController;if(this.abortController=i,this.pendingAbortReason!==null&&!i.signal.aborted&&(i.abort(this.pendingAbortReason),this.pendingAbortReason=null),i.signal.aborted)return;this.messages.push({role:"user",content:s.content});let a=this.composeSystem(),l=at(this.authMode,this.initSessionId,Et()),c={client:this.client,messages:this.messages,system:a,tools:this.tools,toolDispatcher:this.toolDispatcher,model:this.currentModel,maxTokens:this.maxTokens,headers:l,signal:i.signal,ctx:{sessionId:this.initSessionId}};try{for await(let d of en(c)){if(this.closed)return;d.type==="turn.completed"&&(this.lastUsage=d.usage),yield d}}catch(d){if(i.signal.aborted)return;yield{type:"error",error:d instanceof Error?d:new Error(String(d))};return}finally{this.abortController===i&&(this.abortController=null)}}}catch(r){yield{type:"error",error:r instanceof Error?r:new Error(String(r))}}finally{try{await n.return?.()}catch{}}}composeSystem(){let e=this.systemPrefix,n=this.userSystem,r=[];return e&&e.length>0&&r.push(...e),n&&n.length>0&&r.push({type:"text",text:n}),r.length===0?null:Re()?Wt(r,De()):r}async interrupt(){let e=this.abortController;if(e&&!e.signal.aborted){e.abort("interrupted");return}this.pendingAbortReason="interrupted"}async setModel(e){e!==void 0&&e.length>0&&(this.currentModel=e)}async setPermissionMode(e){this.currentPermissionMode=e}async supportedCommands(){try{return ke().map(n=>{let r={name:n.name,description:n.description};return n.argumentHint&&(r.argumentHint=n.argumentHint),r})}catch{return[]}}async supportedModels(){return Ci.map(e=>({...e}))}async supportedAgents(){return[]}async getContextUsage(){return{tools:[],agents:[],isAutoCompactEnabled:!1,apiUsage:this.lastUsage}}async mcpServerStatus(){return[]}async accountInfo(){return{subscriptionType:this.authMode==="oauth"?"claude-subscription":"api-key"}}async rewindFiles(e,n){return{canRewind:!1,error:"anthropic-direct provider does not support file checkpoint rewind"}}async compact(){let e=this.messages.length;if(this.closed)return{compacted:!1,reason:"session-closed",messagesBefore:e,messagesAfter:e};if(this.abortController!==null)return{compacted:!1,reason:"turn-in-flight",messagesBefore:e,messagesAfter:e};let n=Mi(),r=rn(this.messages,n);if(r<=0)return{compacted:!1,reason:"history-too-short",messagesBefore:e,messagesAfter:e};let o=this.messages.slice(0,r),s=_i(),i=on(o,s,Ii),a=new AbortController;this.abortController=a,this.pendingAbortReason!==null&&!a.signal.aborted&&(a.abort(this.pendingAbortReason),this.pendingAbortReason=null);let l;try{if(a.signal.aborted)return{compacted:!1,reason:"aborted",messagesBefore:e,messagesAfter:e};let u=at(this.authMode,this.initSessionId,Et()),p=this.client,f=await Promise.resolve(p.messages.create(i,{headers:u,signal:a.signal}));l=await Ri(f)}catch(u){return a.signal.aborted?{compacted:!1,reason:"aborted",messagesBefore:e,messagesAfter:e}:{compacted:!1,reason:"summarization-failed: "+(u instanceof Error?u.message:String(u)),messagesBefore:e,messagesAfter:e}}finally{this.abortController===a&&(this.abortController=null)}if(l.trim().length===0)return{compacted:!1,reason:"empty-summary",messagesBefore:e,messagesAfter:e};let c=an(this.messages,r,l),d=sn(this.messages,r,l);return this.messages.splice(0,this.messages.length,...d),{compacted:!0,messagesBefore:e,messagesAfter:this.messages.length,tokensSavedEstimate:c}}close(){this.closed=!0;let e=this.abortController;e&&!e.signal.aborted?e.abort("closed"):this.pendingAbortReason="closed",this.closeResolve?.()}};function Mi(){let t=process.env.AFK_COMPACT_KEEP_LAST_TURNS;if(t!==void 0&&t.length>0){let e=Number.parseInt(t,10);if(Number.isFinite(e)&&e>0)return e}return Ai}function _i(){let t=process.env.AFK_COMPACT_MODEL;return t!==void 0&&t.length>0?t:Ti}async function Ri(t){let e="";for await(let n of t)if(n.type==="content_block_delta"){let r=n.delta;r.type==="text_delta"&&typeof r.text=="string"&&(e+=r.text)}return e}var Di=new Set(["read_file","glob","grep","list_directory"]);function At(t,e){return e?.allowedTools?e.allowedTools.includes(t)?{allowed:!0}:{allowed:!1,reason:`Tool "${t}" is not in the configured allowlist`}:Di.has(t)?{allowed:!0}:{allowed:!1,reason:`Tool "${t}" requires explicit permission (add to allowedTools config)`}}var Oi=new Set(["agent","read_file","glob","grep","list_directory"]);function Fi(t){return Oi.has(t)}function $i(t,e){return t.reduce((n,r,o)=>{let s=e(r.name,r.input),i=n[n.length-1];return i&&s&&i.isConcurrencySafe?i.indices.push(o):n.push({isConcurrencySafe:s,indices:[o]}),n},[])}var Se=class{handlers;schemas;hookRegistry;permissions;subagentExecutor;skillExecutor;classifier;constructor(e){this.handlers=e.handlers,this.schemas=e.schemas,this.hookRegistry=e.hookRegistry,this.permissions=e.permissions,this.subagentExecutor=e.subagentExecutor,this.skillExecutor=e.skillExecutor,this.classifier=e.concurrencyClassifier??Fi}get toolDefs(){return this.schemas}async execute(e){if(e.signal.aborted)return{content:"Tool call aborted",isError:!0};if(this.hookRegistry){let s={event:"PreToolUse",toolName:e.name,input:e.input};try{await this.hookRegistry.dispatch(s,e.signal)}catch(i){if(i instanceof U)return{content:`Tool "${e.name}" blocked by PreToolUse hook: ${i.message}`,isError:!0};throw i}}let n=At(e.name,this.permissions);if(!n.allowed)return{content:n.reason??`Tool "${e.name}" is not permitted`,isError:!0};if(e.name==="agent"){if(!this.subagentExecutor)return{content:"Agent tool is not available in this session configuration",isError:!0};let s;try{s=await this.subagentExecutor.execute(e)}catch(i){s={content:`Agent tool error: ${i instanceof Error?i.message:String(i)}`,isError:!0}}if(this.hookRegistry){let i={event:"PostToolUse",toolName:e.name,output:s.content};try{await this.hookRegistry.dispatch(i,e.signal)}catch{}}return s}if(e.name==="skill"){if(!this.skillExecutor)return{content:"Skill tool is not available in this session configuration",isError:!0};let s;try{s=await this.skillExecutor.execute(e)}catch(i){s={content:`Skill tool error: ${i instanceof Error?i.message:String(i)}`,isError:!0}}if(this.hookRegistry){let i={event:"PostToolUse",toolName:e.name,output:s.content};try{await this.hookRegistry.dispatch(i,e.signal)}catch{}}return s}let r=this.handlers.get(e.name);if(!r)return{content:`Unknown tool "${e.name}". Available tools: ${[...this.handlers.keys()].join(", ")}`,isError:!0};let o;try{o=await r(e.input,e.signal)}catch(s){o={content:`Tool execution error: ${s instanceof Error?s.message:String(s)}`,isError:!0}}if(this.hookRegistry){let s={event:"PostToolUse",toolName:e.name,output:o.content};try{await this.hookRegistry.dispatch(s,e.signal)}catch{}}return o}async executeBatch(e){if(e.length===0)return[];if(e.length===1)return[await this.execute(e[0])];let n=new Array(e.length),r=new Set;for(let i=0;i<e.length;i++){let a=e[i];if(a.signal.aborted){n[i]={content:"Tool call aborted",isError:!0},r.add(i);continue}if(this.hookRegistry){let c={event:"PreToolUse",toolName:a.name,input:a.input};try{await this.hookRegistry.dispatch(c,a.signal)}catch(d){if(d instanceof U){n[i]={content:`Tool "${a.name}" blocked by PreToolUse hook: ${d.message}`,isError:!0},r.add(i);continue}throw d}}let l=At(a.name,this.permissions);l.allowed||(n[i]={content:l.reason??`Tool "${a.name}" is not permitted`,isError:!0},r.add(i))}let o=e.map((i,a)=>({call:i,originalIndex:a})).filter((i,a)=>!r.has(a));if(o.length===0)return n;let s=$i(o.map(i=>i.call),this.classifier);for(let i of s){if(e[0].signal.aborted){for(let a of i.indices){let l=o[a].originalIndex;n[l]={content:"Tool call aborted",isError:!0}}continue}if(i.isConcurrencySafe){let a=await Promise.allSettled(i.indices.map(async l=>{let{call:c,originalIndex:d}=o[l];return{result:await this.executeCore(c),originalIndex:d}}));for(let l of a)if(l.status==="fulfilled")n[l.value.originalIndex]=l.value.result;else{let c=l.reason instanceof Error?l.reason.message:String(l.reason),d=i.indices[a.indexOf(l)];n[o[d].originalIndex]={content:`Tool execution error: ${c}`,isError:!0}}}else for(let a of i.indices){let{call:l,originalIndex:c}=o[a];if(l.signal.aborted){n[c]={content:"Tool call aborted",isError:!0};continue}n[c]=await this.executeCore(l)}}return n}async executeCore(e){if(e.name==="agent"){if(!this.subagentExecutor)return{content:"Agent tool is not available in this session configuration",isError:!0};let o;try{o=await this.subagentExecutor.execute(e)}catch(s){o={content:`Agent tool error: ${s instanceof Error?s.message:String(s)}`,isError:!0}}return this.firePostToolUse(e.name,o.content,e.signal),o}if(e.name==="skill"){if(!this.skillExecutor)return{content:"Skill tool is not available in this session configuration",isError:!0};let o;try{o=await this.skillExecutor.execute(e)}catch(s){o={content:`Skill tool error: ${s instanceof Error?s.message:String(s)}`,isError:!0}}return this.firePostToolUse(e.name,o.content,e.signal),o}let n=this.handlers.get(e.name);if(!n)return{content:`Unknown tool "${e.name}". Available tools: ${[...this.handlers.keys()].join(", ")}`,isError:!0};let r;try{r=await n(e.input,e.signal)}catch(o){r={content:`Tool execution error: ${o instanceof Error?o.message:String(o)}`,isError:!0}}return this.firePostToolUse(e.name,r.content,e.signal),r}firePostToolUse(e,n,r){if(!this.hookRegistry)return;let o={event:"PostToolUse",toolName:e,output:n};this.hookRegistry.dispatch(o,r).catch(()=>{})}};import{spawn as Li}from"child_process";function ji(t){if(typeof t!="object"||t===null)throw new Error("Input must be an object");let e=t;if(typeof e.command!="string")throw new Error('Input must have a "command" field of type string');let n=12e4;if(e.timeout_ms!==void 0){if(typeof e.timeout_ms!="number")throw new Error("timeout_ms must be a number");if(e.timeout_ms<0||e.timeout_ms>6e5)throw new Error("timeout_ms must be between 0 and 600000");n=e.timeout_ms}return{command:e.command,timeout_ms:n}}function Hi(t){return t.replace(/\x1b\[[0-9;]*[a-zA-Z]/g,"")}var Er=async(t,e)=>{let{command:n,timeout_ms:r}=ji(t);return e.aborted?{content:"Command aborted",isError:!0}:new Promise(o=>{let s=!1;function i(p){s||(s=!0,clearTimeout(l),e.removeEventListener("abort",u),o(p))}let a=Li(n,{shell:!0,stdio:["ignore","pipe","pipe"]}),l=setTimeout(()=>{a.kill(),i({content:`Command timed out after ${r}ms`,isError:!0})},r),c="",d="";a.stdout.on("data",p=>{c+=p.toString()}),a.stderr.on("data",p=>{d+=p.toString()});let u=()=>{a.kill(),i({content:"Command aborted",isError:!0})};e.addEventListener("abort",u),a.on("close",()=>{let p=(c+d).trimEnd();p=Hi(p);let f=1e5;p.length>f&&(p=p.slice(0,f)+`
1226
+ [output truncated \u2014 exceeded 100KB]`),i({content:p})}),a.on("error",p=>{i({content:`Failed to execute: ${p.message}`,isError:!0})})})};import{promises as Ui}from"fs";var Ar=async(t,e)=>{if(!t||typeof t!="object")return{content:"Invalid input: expected an object",isError:!0};let n=t,r=n.file_path,o=n.offset??1,s=n.limit??2e3;if(typeof r!="string")return{content:"Invalid input: file_path must be a string",isError:!0};if(typeof o!="number"||o<1)return{content:"Invalid input: offset must be a positive number",isError:!0};if(typeof s!="number"||s<1)return{content:"Invalid input: limit must be a positive number",isError:!0};try{let i=await Ui.readFile(r),a=Math.min(8192,i.length);for(let m=0;m<a;m++)if(i[m]===0)return{content:`File appears to be binary: ${r}`,isError:!0};let l=i.toString("utf-8");if(l.length===0)return{content:""};let c=l.split(`
1227
+ `),d=Math.max(0,o-1),u=Math.min(c.length,d+s),p=c.slice(d,u),f=c.length;if(p.length===0)return{content:`... (offset ${o} is past end of file \u2014 file has ${f} lines)`};let g=String(f).length,h=p.map((m,b)=>{let S=d+b+1;return`${String(S).padStart(g," ")} ${m}`}).join(`
1228
+ `);if(p.length<f){let m=d+1,b=d+p.length,S=b<f?` \u2014 pass offset=${b+1} to continue`:"";return{content:`${h}
1229
+ ... (showing lines ${m}-${b} of ${f}${S})`}}return{content:h}}catch(i){if(i instanceof Error){let a=i;return a.code==="ENOENT"?{content:`File not found: ${r}`,isError:!0}:a.code==="EACCES"?{content:`Permission denied: ${r}`,isError:!0}:{content:`Error reading file: ${i.message}`,isError:!0}}return{content:"Unknown error reading file",isError:!0}}};import{writeFile as Ni}from"fs/promises";import{mkdir as Bi}from"fs/promises";import{dirname as Ki}from"path";function Gi(t){if(typeof t!="object"||t===null)throw new Error("Input must be an object");let e=t;if(typeof e.file_path!="string")throw new Error('Input must have a "file_path" field of type string');if(typeof e.content!="string")throw new Error('Input must have a "content" field of type string');return{file_path:e.file_path,content:e.content}}var Tr=async(t,e)=>{if(e.aborted)return{content:"Aborted",isError:!0};let{file_path:n,content:r}=Gi(t);try{let o=Ki(n);return await Bi(o,{recursive:!0}),await Ni(n,r,{signal:e}),{content:`Wrote ${Buffer.byteLength(r,"utf8")} bytes to ${n}`}}catch(o){return o instanceof Error?"code"in o&&o.code==="EACCES"?{content:`Permission denied: ${n}`,isError:!0}:{content:`Error writing file: ${o.message}`,isError:!0}:{content:"Unknown error writing file",isError:!0}}};import{readFile as zi,writeFile as Vi}from"fs/promises";function qi(t){if(typeof t!="object"||t===null)throw new Error("Input must be an object");let e=t;if(typeof e.file_path!="string")throw new Error('Input must have a "file_path" field of type string');if(typeof e.old_string!="string")throw new Error('Input must have an "old_string" field of type string');if(typeof e.new_string!="string")throw new Error('Input must have a "new_string" field of type string');let n=!1;if(e.replace_all!==void 0){if(typeof e.replace_all!="boolean")throw new Error("replace_all must be a boolean");n=e.replace_all}return{file_path:e.file_path,old_string:e.old_string,new_string:e.new_string,replace_all:n}}function Wi(t,e){if(e.length===0)return 0;let n=0,r=0;for(;(r=t.indexOf(e,r))!==-1;)n++,r+=e.length;return n}function Yi(t,e,n){let r=t.split(`
1230
+ `),o=0,s=0;for(let c=0;c<r.length;c++){let d=r[c]?.length??0,u=o+d+1;if(o+d>=n+e.length){s=c;break}o=u}let i=Math.max(0,s-2),a=Math.min(r.length,s+3);return`...${r.slice(i,a).join(`
1231
+ `)}...`}var Ir=async(t,e)=>{if(e.aborted)return{content:"Aborted",isError:!0};let{file_path:n,old_string:r,new_string:o,replace_all:s}=qi(t);try{let i=await zi(n,"utf-8"),a=Wi(i,r);if(a===0)return{content:`old_string not found in ${n}`,isError:!0};if(a>1&&!s)return{content:`old_string matches ${a} locations in ${n}. Use replace_all: true or provide more context.`,isError:!0};let l,c;s?(l=i.split(r).join(o),c=i.indexOf(r)):(c=i.indexOf(r),l=i.slice(0,c)+o+i.slice(c+r.length)),await Vi(n,l,"utf-8");let d=Yi(i,r,c);return{content:`${a===1?`Replaced 1 occurrence in ${n}`:`Replaced ${a} occurrences in ${n}`}
1232
+
1233
+ ${d}`}}catch(i){return{content:`Error: ${i instanceof Error?i.message:String(i)}`,isError:!0}}};import{promises as Mr}from"fs";import Ji from"path";function Qi(t,e){let n=t.replace(/\\/g,"/"),r=e.replace(/\\/g,"/");if(r.includes("**")){let s=r.split("**"),i=0;for(let a=0;a<s.length;a++){let l=s[a]??"",c=Cr(l);if(a===0){let d=n.match(new RegExp(`^${c}`));if(!d)return!1;i=d[0].length}else if(a===s.length-1){let d=new RegExp(`${c}$`);if(!n.slice(i).match(d))return!1}else{let d=new RegExp(c),u=n.slice(i).match(d);if(!u)return!1;let p=u.index??0;i+=p+u[0].length}}return!0}return new RegExp(`^${Cr(r)}$`).test(n)}function Cr(t){return t.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,"[^/]*").replace(/\?/g,"[^/]")}async function Xi(t,e){let n=[];async function o(s,i){if(n.length>=500)return!0;try{let a=await Mr.readdir(s,{withFileTypes:!0});for(let l of a){if(n.length>=500)return!0;let c=Ji.join(s,l.name),d=i?`${i}/${l.name}`:l.name;if(Qi(d,e)&&n.push(d),l.isDirectory()&&await o(c,d))return!0}}catch{}return!1}return await o(t,""),n}var _r=async(t,e)=>{if(!t||typeof t!="object")return{content:"Invalid input: expected an object",isError:!0};let n=t,r=n.pattern,o=n.path??process.cwd();if(typeof r!="string")return{content:"Invalid input: pattern must be a string",isError:!0};if(r.trim()==="")return{content:"Invalid input: pattern cannot be empty",isError:!0};if(typeof o!="string")return{content:"Invalid input: path must be a string",isError:!0};try{if(!(await Mr.stat(o)).isDirectory())return{content:`Invalid input: path is not a directory: ${o}`,isError:!0};let i=await Xi(o,r);if(i.length===0)return{content:`No files matched pattern '${r}' in ${o}`};let a=i.join(`
1234
+ `);return i.length>=500&&(a+=`
1235
+ [results capped at 500 entries]`),{content:a}}catch(s){return s instanceof Error?"code"in s&&s.code==="ENOENT"?{content:`Path not found: ${o}`,isError:!0}:"code"in s&&s.code==="EACCES"?{content:`Permission denied: ${o}`,isError:!0}:{content:`Error scanning directory: ${s.message}`,isError:!0}:{content:"Unknown error scanning directory",isError:!0}}};import{spawn as Zi}from"child_process";function ea(t){if(typeof t!="object"||t===null)throw new Error("Input must be an object");let e=t;if(typeof e.pattern!="string")throw new Error('Input must have a "pattern" field of type string');let n=typeof e.path=="string"?e.path:process.cwd(),r;if(e.include!==void 0){if(typeof e.include!="string")throw new Error("include must be a string");r=e.include}return{pattern:e.pattern,path:n,include:r}}function ta(t){return t.replace(/\x1b\[[0-9;]*[a-zA-Z]/g,"")}var Rr=async(t,e)=>{let{pattern:n,path:r,include:o}=ea(t);return e.aborted?{content:"Search aborted",isError:!0}:new Promise(s=>{let i=!1;function a(f){i||(i=!0,e.removeEventListener("abort",p),s(f))}let l=["-rn"];o&&l.push(`--include=${o}`),l.push(n,r);let c=Zi("grep",l),d="",u="";c.stdout.on("data",f=>{d+=f.toString()}),c.stderr.on("data",f=>{u+=f.toString()});let p=()=>{c.kill(),a({content:"Search aborted",isError:!0})};e.addEventListener("abort",p),c.on("close",f=>{if(f===1){a({content:`No matches found for '${n}' in ${r}`});return}if(f===2){a({content:`grep error: ${u.trim()}`,isError:!0});return}let g=d.trimEnd();g=ta(g);let h=1e5;g.length>h&&(g=g.slice(0,h)+`
1236
+ [output truncated]`),a({content:g})}),c.on("error",f=>{a({content:`Failed to execute grep: ${f.message}`,isError:!0})})})};import{promises as na}from"fs";var Dr=async(t,e)=>{if(!t||typeof t!="object")throw new Error("Invalid input: expected an object");let r=t.path;if(typeof r!="string")throw new Error("Invalid input: path must be a string");try{let o=await na.readdir(r,{withFileTypes:!0}),s=o.filter(c=>c.isDirectory()).map(c=>`${c.name}/`),i=o.filter(c=>!c.isDirectory()).map(c=>c.name);s.sort(),i.sort();let a=[...s,...i];return a.length===0?{content:"(empty directory)"}:{content:a.join(`
1237
+ `)}}catch(o){if(o instanceof Error){let s=o;return s.code==="ENOENT"?{content:`Directory not found: ${r}`,isError:!0}:s.code==="ENOTDIR"?{content:`Not a directory: ${r}`,isError:!0}:s.code==="EACCES"?{content:`Permission denied: ${r}`,isError:!0}:{content:`Error listing directory: ${o.message}`,isError:!0}}return{content:"Unknown error listing directory",isError:!0}}};function Or(){return new Map([["bash",Er],["read_file",Ar],["write_file",Tr],["edit_file",Ir],["glob",_r],["grep",Rr],["list_directory",Dr]])}var Fr=`You have access to tools for working with the filesystem and running commands. Follow these conventions:
1238
+
1239
+ - Use read_file before editing to verify the exact content you want to change.
1240
+ - Prefer edit_file over write_file for modifying existing files \u2014 write_file is for new files or complete rewrites.
1241
+ - Quote file paths that contain spaces with double quotes.
1242
+ - Do not run destructive shell commands (rm -rf, git reset --hard, etc.) unless the user explicitly asks.
1243
+ - Use glob and grep to discover files before reading individual files.
1244
+ - When bash output is very long, it may be truncated. If you need the full output, redirect to a file and read it.
1245
+ - Use absolute paths for file operations.
1246
+
1247
+ When you see a \`<command-name>\` tag in the current conversation turn, the skill has ALREADY been loaded by the user typing a slash command. Do NOT re-invoke the skill tool to dispatch the same skill again. Instead, treat the \`<command-message>\` as the skill name and \`<command-args>\` as its arguments, then follow the instructions in the body block immediately following the tag.`;var $r="anthropic-direct",oa=8192,sa="claude-sonnet-4-5-20250929",ia=null;var Q=class{name=$r;tools;providerFactory;skillExecutor;constructor(e={}){let n=[...Ge];e.subagentExecutor&&n.push(er),e.skillExecutor&&n.push(tr),this.tools=e.tools??new Se({handlers:Or(),schemas:n,hookRegistry:e.hookRegistry,permissions:e.permissions,subagentExecutor:e.subagentExecutor,skillExecutor:e.skillExecutor}),this.skillExecutor=e.skillExecutor,e.clientFactory&&(this.providerFactory=e.clientFactory)}query(e){let n=e.config,r=n.apiKey&&n.apiKey.length>0?n.apiKey:process.env.ANTHROPIC_API_KEY||process.env.CLAUDE_CODE_OAUTH_TOKEN||"";if(!r||r.length===0)throw new Error(`${$r} provider requires config.apiKey (resolved from ANTHROPIC_API_KEY or CLAUDE_CODE_OAUTH_TOKEN)`);let o=zt(r),s=Vt(r,o),i=this.providerFactory??ia,a=i?i(s):new ra(s),l=qt(o),c=aa(n.systemPrompt),d=typeof n.model=="string"&&n.model.length>0?ae(n.model)??n.model:sa,u=la(n),p=this.tools instanceof Se?[...this.tools.toolDefs]:[...Ge],f=[...q(he()),...q()],g=n.plugins??[],h=[...f,...g],m=this.skillExecutor?xr(h):"",b=[Fr];m.length>0&&b.push(m),c&&b.push(c);let S=b.join(`
1248
+
1249
+ `);return new We({client:a,authMode:o,promptStream:e.prompt,toolDispatcher:this.tools,model:d,...n.permissionMode!==void 0?{permissionMode:n.permissionMode}:{},maxTokens:u,tools:p,userSystem:S,systemPrefix:l})}};function aa(t){if(t===void 0)return null;if(typeof t=="string")return t.length>0?t:null;if(typeof t=="object"&&t!==null&&"append"in t){let e=t.append;return e&&e.length>0?e:null}return null}function la(t){let e=t.maxOutputTokens;return typeof e=="number"&&Number.isFinite(e)&&e>0?Math.floor(e):oa}var Lr=new Q;import{Codex as Hr}from"@openai/codex-sdk";import{mkdtempSync as ca,rmSync as da,writeFileSync as ua}from"node:fs";import{tmpdir as pa}from"node:os";import{join as jr}from"node:path";var xe="openai-codex",fa=[{value:"gpt-5.4",displayName:"GPT-5.4",description:"Codex default"},{value:"gpt-5.4-mini",displayName:"GPT-5.4 mini",description:"Faster, cheaper Codex variant"}];function ma(t){let e=[];if(t.continue&&e.push("continue"),t.resumeSessionAt!==void 0&&e.push("resumeSessionAt"),t.forkSession&&e.push("forkSession"),t.persistSession===!1&&e.push("persistSession=false"),t.enableFileCheckpointing&&e.push("enableFileCheckpointing"),t.thinking!==void 0&&e.push("thinking"),t.maxBudgetUsd!==void 0&&e.push("maxBudgetUsd"),t.taskBudget!==void 0&&e.push("taskBudget"),t.plugins&&t.plugins.length>0&&e.push("plugins"),t.agents&&e.push("agents"),t.agent!==void 0&&e.push("agent"),t.onElicitation&&e.push("onElicitation"),t.hooks&&e.push("hooks"),t.canUseTool&&e.push("canUseTool"),t.mcpServers&&e.push("mcpServers"),t.includeHookEvents&&e.push("includeHookEvents"),t.agentProgressSummaries&&e.push("agentProgressSummaries"),t.includePartialMessages&&e.push("includePartialMessages"),e.length>0)throw new ge(xe,e.join(", "),`${xe} provider does not support AgentConfig fields: ${e.join(", ")}`)}function Ur(t){return t==="plan"?{sandboxMode:"read-only",approvalPolicy:"untrusted"}:{sandboxMode:"workspace-write",approvalPolicy:"never"}}function ga(t){if(t)switch(t){case"minimal":case"low":case"medium":case"high":case"xhigh":return t;case"max":return"xhigh";default:return}}function ha(t){let e=t.systemPrompt;if(e!==void 0){if(typeof e=="string")return e.length>0?e:void 0;if(typeof e=="object"&&e!==null&&"append"in e){let n=e.append;return n&&n.length>0?n:void 0}}}function ya(t){let e=ca(jr(pa(),"afk-codex-instr-")),n=jr(e,"instructions.md");return ua(n,t,"utf-8"),{path:n,dispose:()=>{try{da(e,{recursive:!0,force:!0})}catch{}}}}function ba(t){if(t.apiKey)return t.apiKey;let e=process.env.OPENAI_API_KEY??process.env.CODEX_API_KEY;return e&&e.length>0?e:void 0}function*va(t,e,n,r){if(t.type!=="thread.started"&&t.type!=="turn.started"){if(t.type==="turn.completed"){let o=t.usage;yield{type:"turn.completed",usage:{inputTokens:o.input_tokens,outputTokens:o.output_tokens,cachedInputTokens:o.cached_input_tokens,totalTokens:o.input_tokens+o.output_tokens+o.cached_input_tokens,resultSubtype:"success",isError:!1,raw:{input_tokens:o.input_tokens,output_tokens:o.output_tokens,cached_input_tokens:o.cached_input_tokens}},...e!==void 0?{sessionId:e}:{}};return}if(t.type==="turn.failed"){yield{type:"error",error:new Error(t.error.message)};return}if(t.type==="error"){yield{type:"error",error:new Error(t.message)};return}(t.type==="item.started"||t.type==="item.updated"||t.type==="item.completed")&&(yield*wa(t.item,t.type==="item.completed",e,n,r))}}function*wa(t,e,n,r,o){if(t.type==="agent_message"){let s=r.get(t.id)??"";if(t.text!==s){let i=t.text.startsWith(s)?t.text.slice(s.length):t.text;r.set(t.id,t.text),i.length>0&&(yield{type:"delta.text",text:i,...n!==void 0?{sessionId:n}:{}})}e&&(yield{type:"assistant.message",text:t.text,...n!==void 0?{sessionId:n}:{}},r.delete(t.id));return}if(t.type==="reasoning"){let s=o.get(t.id)??"";if(t.text!==s){let i=t.text.startsWith(s)?t.text.slice(s.length):t.text;o.set(t.id,t.text),i.length>0&&(yield{type:"delta.reasoning",text:i,...n!==void 0?{sessionId:n}:{}})}e&&o.delete(t.id);return}if(t.type==="command_execution"){if(e){let s=t.status==="failed",i=t.exit_code!==void 0?` (exit ${t.exit_code})`:"",a=`$ ${t.command}${i}
1250
+ `+(t.aggregated_output??"");yield{type:"tool.output",toolUseId:t.id,content:a,isError:s,...n!==void 0?{sessionId:n}:{}}}return}if(t.type==="file_change"){if(e){let s=t.changes.map(i=>`${i.kind} ${i.path}`).join(`
1251
+ `);yield{type:"tool.output",toolUseId:t.id,content:s,isError:t.status==="failed",...n!==void 0?{sessionId:n}:{}}}return}if(t.type==="mcp_tool_call"){if(e){let s=t.status==="failed",i;t.error?i=t.error.message:t.result?i=JSON.stringify(t.result,null,2):i="",yield{type:"tool.output",toolUseId:t.id,content:i,isError:s,...n!==void 0?{sessionId:n}:{}}}return}if(t.type==="web_search"){e&&(yield{type:"tool.output",toolUseId:t.id,content:`web_search: ${t.query}`,...n!==void 0?{sessionId:n}:{}});return}if(t.type!=="todo_list"&&t.type==="error"){e&&(yield{type:"error",error:new Error(t.message)});return}}var Tt=class{startOpts;promptStream;codex;thread;currentModel;currentSandbox;currentApproval;abortController=null;pendingAbortReason=null;closed=!1;initSessionId;dispose;closeResolve=null;closedPromise;constructor(e,n,r){this.startOpts=e,this.promptStream=n,this.initSessionId=r,this.codex=new Hr(e.codexOptions),this.thread=e.resumeId?this.codex.resumeThread(e.resumeId,e.threadOptions):this.codex.startThread(e.threadOptions),this.currentModel=e.threadOptions.model,this.currentSandbox=e.threadOptions.sandboxMode??"workspace-write",this.currentApproval=e.threadOptions.approvalPolicy??"never",e.instructionsDispose!==void 0&&(this.dispose=e.instructionsDispose),this.closedPromise=new Promise(o=>{this.closeResolve=()=>o("__closed__")})}async*[Symbol.asyncIterator](){yield{type:"session.init",info:{sessionId:this.initSessionId,...this.currentModel!==void 0?{model:this.currentModel}:{},permissionMode:this.sandboxToPermissionMode(),cwd:this.startOpts.threadOptions.workingDirectory??process.cwd(),tools:["Bash","Read","Write","Edit"],slashCommands:[],skills:[],plugins:[],mcpServers:[],apiKeySource:this.startOpts.codexOptions.apiKey!==void 0?"apiKey":"codex-cli",version:"codex-sdk"}};let n=new Map,r=new Map,o=this.initSessionId,s=this.promptStream[Symbol.asyncIterator]();try{for(;!this.closed;){let i=await Promise.race([s.next(),this.closedPromise]);if(i==="__closed__")break;let a=i;if(a.done)break;let l=a.value,c=new AbortController;if(this.abortController=c,this.pendingAbortReason!==null&&!c.signal.aborted&&(c.abort(this.pendingAbortReason),this.pendingAbortReason=null),c.signal.aborted)return;let d;try{let u=typeof l.content=="string"?l.content:l.content.map(p=>{if(typeof p=="object"&&p&&"type"in p){if(p.type==="text")return p.text;if(p.type==="image")return"[image omitted]"}return""}).join(`
1252
+ `);d=await this.thread.runStreamed(u,{signal:c.signal})}catch(u){if(c.signal.aborted)return;yield{type:"error",error:u instanceof Error?u:new Error(String(u))};return}try{for await(let u of d.events){if(this.closed)return;u.type==="thread.started"&&(o=u.thread_id),yield*va(u,o,n,r)}}catch(u){if(c.signal.aborted)return;yield{type:"error",error:u instanceof Error?u:new Error(String(u))};return}finally{this.abortController===c&&(this.abortController=null)}}}catch(i){yield{type:"error",error:i instanceof Error?i:new Error(String(i))}}finally{try{await s.return?.()}catch{}}}sandboxToPermissionMode(){return this.currentSandbox==="read-only"||this.currentApproval==="untrusted"?"plan":"bypassPermissions"}async interrupt(){let e=this.abortController;if(e&&!e.signal.aborted){e.abort("interrupted");return}this.pendingAbortReason="interrupted"}async setModel(e){this.currentModel=e;let n={...this.startOpts.threadOptions,...e!==void 0?{model:e}:{},sandboxMode:this.currentSandbox,approvalPolicy:this.currentApproval},r=this.thread.id;this.thread=r?this.codex.resumeThread(r,n):this.codex.startThread(n),this.startOpts.threadOptions=n}async setPermissionMode(e){let{sandboxMode:n,approvalPolicy:r}=Ur(e);this.currentSandbox=n,this.currentApproval=r;let o={...this.startOpts.threadOptions,sandboxMode:n,approvalPolicy:r},s=this.thread.id;this.thread=s?this.codex.resumeThread(s,o):this.codex.startThread(o),this.startOpts.threadOptions=o}async supportedCommands(){return[]}async supportedModels(){return fa.map(e=>({...e}))}async supportedAgents(){return[]}async getContextUsage(){return{tools:[],agents:[],isAutoCompactEnabled:!1,apiUsage:null}}async mcpServerStatus(){return[]}async accountInfo(){return{}}async rewindFiles(e,n){throw new ge(xe,"rewindFiles",`${xe} provider does not support file checkpoint rewind.`)}close(){this.closed=!0;let e=this.abortController;e&&!e.signal.aborted?e.abort("closed"):this.pendingAbortReason="closed",this.closeResolve?.(),this.dispose?.()}getThread(){return this.thread}},ka=null;var Ye=class{name=xe;query(e){ma(e.config);let n=ba(e.config),r=ga(e.config.effort),{sandboxMode:o,approvalPolicy:s}=Ur(e.config.permissionMode),i={...e.config.model!==void 0?{model:e.config.model}:{},sandboxMode:o,approvalPolicy:s,...r!==void 0?{modelReasoningEffort:r}:{},skipGitRepoCheck:!0,workingDirectory:process.cwd()},a=ha(e.config),l={};n!==void 0&&(l.apiKey=n);let c;if(a!==void 0){let{path:g,dispose:h}=ya(a);l.config={...l.config??{},model_instructions_file:g},c=h}A(`\u{1F7E2} OpenAICodexProvider: creating Codex thread (model=${String(e.config.model)}, sandbox=${o}, approval=${s})`);let d=ka,u=d??(g=>new Hr(g)),p=`codex-pending-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,f=new Tt({threadOptions:i,codexOptions:l,...e.config.resume!==void 0?{resumeId:e.config.resume}:{},...c!==void 0?{instructionsDispose:c}:{}},e.prompt,p);if(d){let g=u(l);f.codex=g,f.thread=e.config.resume?g.resumeThread(e.config.resume,i):g.startThread(i)}return f}},Nr=new Ye;var Sa=new Set(["opus","opus_1m","sonnet","sonnet_1m","haiku","auto"]);function de(t){if(!t)return"anthropic-direct";let e=t.trim().toLowerCase();return!e||Sa.has(e)||e.startsWith("claude-")||e.startsWith("claude_")?"anthropic-direct":e.startsWith("gpt-")||e.startsWith("gpt_")||e.startsWith("o1")||e.startsWith("o3")||e.startsWith("o4")||e.startsWith("codex-")||e.startsWith("codex_")||e==="codex"?"openai-codex":"anthropic-direct"}function Br(t){return de(t)==="openai-codex"?Nr:Lr}async function Kr(t,e,n={}){t&&await t.dispatch(e,n.signal)}async function Gr(t,e,n={}){if(t)try{await t.dispatch(e,n.signal)}catch(r){if(r instanceof U||r instanceof G){A(`SessionEnd hook swallowed ${r.name}: ${r.message}`),n.onError?.(r);return}A(`SessionEnd hook unexpected error: ${String(r)}`),n.onError?.(r instanceof Error?r:new Error(String(r)))}}var Je=class{pendingResolve=null;bufferedMessage=null;getSessionId;constructor(e){this.getSessionId=e}pushUserMessage(e){if(this.pendingResolve){let n=this.pendingResolve;this.pendingResolve=null;let r=this.getSessionId();n({content:e,...r!==void 0?{sessionId:r}:{}});return}this.bufferedMessage=e}createIterable(){let e=this;return{[Symbol.asyncIterator](){return{next(){if(e.bufferedMessage!==null){let n=e.bufferedMessage;e.bufferedMessage=null;let r=e.getSessionId();return Promise.resolve({value:{content:n,...r!==void 0?{sessionId:r}:{}},done:!1})}return new Promise(n=>{e.pendingResolve=r=>n({value:r,done:!1})})},return(){return Promise.resolve({value:void 0,done:!0})}}}}}};function xa(t){let e=/Output too large \((\d+(?:\.\d+)?)\s*(B|KB|MB|GB)\)\.\s*Full output saved to:\s*(\/[^\n]+)/,n=t.match(e);if(!n||!n[1]||!n[2]||!n[3])return null;let r=n[1],o=n[2],s=n[3],i=parseFloat(r),a=i;o==="KB"?a=i*1024:o==="MB"?a=i*1024*1024:o==="GB"&&(a=i*1024*1024*1024);let l=r;return i%1===0&&(l=String(Math.floor(i))),l+=o,{sizeLabel:l,sizeBytes:Math.round(a),absolutePath:s.trim()}}function Pa(t){if(t<1024)return`${t}B`;let e=t/1024;if(e<1024)return e%1===0?`${Math.floor(e)}KB`:`${e.toFixed(1)}KB`;let n=e/1024;if(n<1024)return n%1===0?`${Math.floor(n)}MB`:`${n.toFixed(1)}MB`;let r=n/1024;return r%1===0?`${Math.floor(r)}GB`:`${r.toFixed(1)}GB`}function Ea(t){let e=Buffer.byteLength(t,"utf8"),n=Pa(e),r=t.split(`
1253
+ `);if(r.length<=1&&t.length<=80)return{content:t,truncated:!1,sizeBytes:e,sizeLabel:n};if(r.length<=1)return t.length<=80?{content:t,truncated:!1,sizeBytes:e,sizeLabel:n}:{content:t.substring(0,80)+"\u2026",truncated:!0,sizeBytes:e,sizeLabel:n};if(t.length<=80)return{content:t,truncated:!1,sizeBytes:e,sizeLabel:n};let o=r[0]??"",s=o;return o.length>80&&(s=o.substring(0,80)+"\u2026"),{content:s+`\u2026+${r.length} lines`,truncated:!0,lineCount:r.length,sizeBytes:e,sizeLabel:n}}function Aa(t,e){let n={...t.raw??{}};return t.inputTokens!==void 0&&(n.input_tokens=t.inputTokens),t.outputTokens!==void 0&&(n.output_tokens=t.outputTokens),t.cachedInputTokens!==void 0&&(n.cache_read_input_tokens=t.cachedInputTokens),t.cacheCreationTokens!==void 0&&(n.cache_creation_input_tokens=t.cacheCreationTokens),t.totalTokens!==void 0&&(n.total_tokens=t.totalTokens),{sessionId:e,stopReason:t.stopReason??void 0,resultSubtype:t.resultSubtype,durationMs:t.durationMs,durationApiMs:t.durationApiMs,totalCostUsd:t.totalCostUsd,isError:t.isError,usage:Object.keys(n).length>0?n:void 0,modelUsage:t.modelUsage,permissionDenials:t.permissionDenials,errors:t.errors}}function Ta(t,e){let n=e.info;t.setSessionMetadata(r=>({...r,sessionId:n.sessionId,model:n.model??r.model,...n.permissionMode!==void 0?{permissionMode:n.permissionMode}:{},...n.cwd!==void 0?{cwd:n.cwd}:{},tools:n.tools?[...n.tools]:r.tools,slashCommands:n.slashCommands?[...n.slashCommands]:r.slashCommands,skills:n.skills?[...n.skills]:r.skills,plugins:n.plugins?n.plugins.map(o=>({...o})):r.plugins,mcpServers:n.mcpServers?n.mcpServers.map(o=>({...o})):r.mcpServers,...n.apiKeySource!==void 0?{apiKeySource:n.apiKeySource}:{},...n.version!==void 0?{claudeCodeVersion:n.version}:{},...n.outputStyle!==void 0?{outputStyle:n.outputStyle}:{}})),t.updateSessionIdentity(n.sessionId),t.resolveInitialization()}function Ia(t,e){t.setSessionMetadata(n=>({...n,sessionId:e.sessionId,...e.permissionMode!==void 0?{permissionMode:e.permissionMode}:{permissionMode:n.permissionMode},...e.status!==void 0?{status:e.status}:{}}))}function Ca(t,e){let n=xa(e.content);if(n){t.push({type:"chunk",chunk:{type:"tool_result",toolUseId:e.toolUseId,content:`Output persisted (${n.sizeLabel}) \u2192 ${n.absolutePath}`,isError:e.isError===!0,persistedPath:n.absolutePath,sizeBytes:n.sizeBytes,sizeLabel:n.sizeLabel}});return}let{content:r,truncated:o,lineCount:s,sizeBytes:i,sizeLabel:a}=Ea(e.content);t.push({type:"chunk",chunk:{type:"tool_result",toolUseId:e.toolUseId,content:r,isError:e.isError===!0,sizeBytes:i,sizeLabel:a,...o&&{truncated:o},...s!==void 0&&{lineCount:s}}})}function Ma(t,e){if(!e)return;let n={role:"assistant",content:e,timestamp:new Date};t.conversationHistory.push(n),t.messageQueue.push({type:"message",message:n})}async function zr(t){try{for await(let e of t.providerStream)switch(e.type){case"session.init":Ta(t,e);break;case"session.status":Ia(t,e);break;case"delta.text":t.messageQueue.push({type:"chunk",chunk:{type:"content",content:e.text,metadata:{eventType:"delta",deltaType:"text_delta"}}});break;case"delta.reasoning":t.messageQueue.push({type:"chunk",chunk:{type:"thinking",content:e.text,metadata:{eventType:"delta",deltaType:"thinking_delta"}}});break;case"assistant.message":e.sessionId&&t.updateSessionIdentity(e.sessionId),Ma(t,e.text);break;case"tool.use.start":t.messageQueue.push({type:"chunk",chunk:{type:"tool_use_detail",toolUseId:e.toolUseId,toolName:e.toolName,toolInput:e.toolInput}});break;case"tool.use":t.messageQueue.push({type:"chunk",chunk:{type:"tool_use",content:e.summary,metadata:{eventType:"tool_use_summary",precedingToolUseIds:e.toolUseIds}}});break;case"tool.output":Ca(t.messageQueue,e);break;case"progress":t.messageQueue.push({type:"progress",progress:{taskId:e.progress.taskId,description:e.progress.description,...e.progress.summary!==void 0?{summary:e.progress.summary}:{},...e.progress.lastToolName!==void 0?{lastToolName:e.progress.lastToolName}:{},totalTokens:e.progress.totalTokens,toolUses:e.progress.toolUses,durationMs:e.progress.durationMs}});break;case"suggestion":t.messageQueue.push({type:"suggestion",suggestion:e.suggestion});break;case"turn.completed":let n=Aa(e.usage,e.sessionId??t.getSessionMetadata().sessionId);t.setLastResponseMetadata(n);for(let r=t.conversationHistory.length-1;r>=0;r--){let o=t.conversationHistory[r];if(o?.role==="assistant"){o.metadata=n;break}}t.messageQueue.push({type:"done",metadata:n});break;case"error":throw e.error}t.resolveInitializationIfNeeded(),t.messageQueue.complete()}catch(e){let n=e instanceof Error?e:new Error(String(e));throw t.resolveInitializationIfNeeded(),t.messageQueue.fail(n),n}}function Vr(t,e,n){t&&(t.aborted?e.abort(t.reason):t.addEventListener("abort",()=>{e.signal.aborted||e.abort(t.reason)},{once:!0})),e.signal.addEventListener("abort",n,{once:!0})}function qr(t,e){let n=t.permissionMode??"bypassPermissions",r=t.persistSession??!0,o={sessionId:t.sessionId,configuredSessionId:t.sessionId,resume:t.resume,resumeSessionAt:t.resumeSessionAt,continue:t.continue,forkSession:t.forkSession,persistSession:r},s={sessionId:t.sessionId,model:e,permissionMode:n};return{sessionIdentity:o,metadata:s}}async function Wr(t){try{await Kr(t.hookRegistry,{event:"SessionStart",sessionId:t.sessionId()},{signal:t.abortSignal}),await zr({providerStream:t.providerQuery,messageQueue:t.messageQueue,conversationHistory:t.conversationHistory,getSessionMetadata:()=>t.stateManager.getSessionMetadata(),setSessionMetadata:e=>t.stateManager.setSessionMetadata(e),updateSessionIdentity:e=>t.stateManager.updateSessionIdentity(e),resolveInitialization:()=>t.stateManager.resolveInitializationOnce(),resolveInitializationIfNeeded:()=>t.stateManager.resolveInitializationIfNeeded(),setLastResponseMetadata:t.setLastResponseMetadata})}catch(e){let n=e instanceof Error?e:new Error(String(e));t.stateManager.isInitializationSettled()||t.stateManager.rejectInitializationOnce(n),await t.dispatchEnd("error").catch(()=>{})}}var Qe=class{initializationPromise;resolveInitialization;rejectInitialization;initializationSettled=!1;sessionMetadata;sessionIdentity;constructor(e,n){this.sessionIdentity=e,this.sessionMetadata=n,this.initializationPromise=new Promise((r,o)=>{this.resolveInitialization=r,this.rejectInitialization=o})}waitForInitialization(){return this.initializationPromise}getSessionIdentity(){return{...this.sessionIdentity,sessionId:this.getSessionId()}}getSessionMetadata(){return{...this.sessionMetadata,sessionId:this.getSessionId()}}getSessionId(){return this.sessionMetadata.sessionId??this.sessionIdentity.sessionId}updateSessionIdentity(e){e&&(this.sessionIdentity={...this.sessionIdentity,sessionId:e},this.sessionMetadata={...this.sessionMetadata,sessionId:e})}setSessionMetadata(e){this.sessionMetadata=e(this.sessionMetadata)}resolveInitializationIfNeeded(){this.initializationSettled||(this.initializationSettled=!0,this.resolveInitialization(this.getSessionMetadata()))}resolveInitializationOnce(){this.initializationSettled||(this.initializationSettled=!0,this.resolveInitialization(this.getSessionMetadata()))}rejectInitializationOnce(e){this.initializationSettled||(this.initializationSettled=!0,this.rejectInitialization(e))}isInitializationSettled(){return this.initializationSettled}};async function Yr(t,e){return await new Promise((n,r)=>{let o=null,s="",i=!1,a=c=>{i||(i=!0,clearTimeout(l),c())},l=Number.isFinite(e)&&e>0?setTimeout(()=>{a(()=>r(new Error("Response timeout")))},e):void 0;(async()=>{try{for await(let c of t){if(process.env.AFK_CODEX_DEBUG&&console.log("[wait] got event:",c.type),c.type==="error"){a(()=>r(c.error));return}if(c.type==="chunk"&&c.chunk.type==="content"&&(s+=c.chunk.content),c.type==="message"&&c.message.role==="assistant"&&(o=c.message),c.type==="done"){if(process.env.AFK_CODEX_DEBUG&&console.log("[wait] settling with done; assistantMessage=",!!o,"streamedContent=",s.length),o){let d=o;a(()=>n({...d,metadata:c.metadata}));return}if(s){a(()=>n({role:"assistant",content:s,metadata:c.metadata,timestamp:new Date}));return}}}a(o?()=>n(o):s?()=>n({role:"assistant",content:s,timestamp:new Date}):()=>r(new Error("No assistant response received")))}catch(c){a(()=>r(c instanceof Error?c:new Error(String(c))))}})()})}var Z=class{config;currentState="idle";messageQueue;providerQuery;conversationHistory=[];turnCount=0;lastResponseMetadata=null;processingPromise=null;inputStream;abortController;hookRegistry;sessionEndDispatched=!1;stateManager;constructor(e){this.config=e,this.abortController=new AbortController,this.hookRegistry=e.hookRegistry,Vr(e.abortSignal,this.abortController,()=>{this.onAbort()}),this.initSdkLifecycle()}initSdkLifecycle(){this.messageQueue=new _e;let e=ae(this.config.model)??this.config.model,{sessionIdentity:n,metadata:r}=qr(this.config,e);this.stateManager=new Qe(n,r),this.inputStream=new Je(()=>this.sessionId);let o=this.config.provider??Br(e);A(`\u{1F7E2} AgentSession: Creating query session via provider=${o.name}`),this.providerQuery=o.query({prompt:this.inputStream.createIterable(),config:this.config}),this.conversationHistory=[],this.turnCount=0,this.lastResponseMetadata=null,this.sessionEndDispatched=!1,this.currentState="idle",this.processingPromise=Wr({providerQuery:this.providerQuery,messageQueue:this.messageQueue,conversationHistory:this.conversationHistory,stateManager:this.stateManager,hookRegistry:this.hookRegistry,abortSignal:this.abortController.signal,sessionId:()=>this.sessionId,setLastResponseMetadata:s=>this.lastResponseMetadata=s,dispatchEnd:s=>this.dispatchSessionEndOnce(s)})}get state(){return this.currentState}get sessionId(){return this.stateManager.getSessionId()}get abortSignal(){return this.abortController.signal}async sendMessage(e,n={}){this.assertCanSend(),this.currentState=n.stream?"streaming":"processing";let r={role:"user",content:e,timestamp:new Date};this.conversationHistory.push(r);let o=this.config.timeoutMs??$e;try{this.inputStream.pushUserMessage(e);let s=await Le(Yr(this.messageQueue,o),o,{controller:this.abortController,label:this.sessionId??"session"});return this.turnCount++,s}finally{this.state!=="closed"&&(this.currentState="idle")}}async*sendMessageStream(e){this.assertCanSend(),this.currentState="streaming";let r={role:"user",content:typeof e=="string"?e:this.summarizeContentBlocks(e),timestamp:new Date};this.conversationHistory.push(r),this.inputStream.pushUserMessage(e);try{for await(let o of this.messageQueue)if(o.type==="done"&&this.turnCount++,yield o,o.type==="done"||o.type==="error")break}finally{this.state!=="closed"&&(this.currentState="idle")}}summarizeContentBlocks(e){let n=[],r=0;for(let s of e)s.type==="text"?n.push(s.text):s.type==="image"&&r++;let o=n.join(" ");return r>0&&(o=o?`${o} [+ ${r} image(s)]`:`[+ ${r} image(s)]`),o||"[content block(s)]"}async interrupt(){this.currentState!=="streaming"&&this.currentState!=="processing"||(this.currentState="idle",await this.providerQuery.interrupt())}async reset(){if(this.currentState==="closed")throw new Error("Cannot reset: session is closed");if(this.abortController.signal.aborted)throw new G("Cannot reset: session aborted");if(this.currentState==="processing"||this.currentState==="streaming")try{await this.providerQuery.interrupt()}catch{}await this.dispatchSessionEndOnce("reset");try{await this.providerQuery.close()}catch{}this.processingPromise&&await Promise.race([this.processingPromise,new Promise(e=>setTimeout(e,lt))]).catch(()=>{}),this.messageQueue.complete(),this.stateManager.resolveInitializationIfNeeded();try{this.initSdkLifecycle()}catch(e){throw this.currentState="closed",new Error(`Session reset failed during lifecycle rebuild: ${e instanceof Error?e.message:String(e)}`,{cause:e})}}async onAbort(){try{await this.providerQuery.interrupt()}catch{}}async setModel(e){let n=ae(e),r=this.stateManager.getSessionMetadata();await this.providerQuery.setModel(n??r.model??""),n&&this.stateManager.setSessionMetadata(o=>({...o,model:n}))}async setPermissionMode(e){await this.providerQuery.setPermissionMode(e),this.stateManager.setSessionMetadata(n=>({...n,permissionMode:e}))}waitForInitialization(){return this.stateManager.waitForInitialization()}getSessionIdentity(){return this.stateManager.getSessionIdentity()}getSessionMetadata(){return this.stateManager.getSessionMetadata()}getQuery(){return this.providerQuery}supportedCommands(){return this.providerQuery.supportedCommands()}supportedModels(){return this.providerQuery.supportedModels()}supportedAgents(){return this.providerQuery.supportedAgents()}getContextUsage(){return this.providerQuery.getContextUsage()}mcpServerStatus(){return this.providerQuery.mcpServerStatus()}accountInfo(){return this.providerQuery.accountInfo()}rewindFiles(e,n){return this.providerQuery.rewindFiles(e,n)}async compact(){if(this.currentState==="closed")throw new Error("Cannot compact: session is closed");if(this.currentState!=="idle")return{compacted:!1,reason:"session-busy",messagesBefore:0,messagesAfter:0};let e=this.providerQuery.compact?.bind(this.providerQuery);return e?e():{compacted:!1,reason:"not-supported",messagesBefore:0,messagesAfter:0}}getLastResponseMetadata(){return this.lastResponseMetadata}getOutputStream(){return this.messageQueue}getInputStreamRef(){return{pushUserMessage:e=>this.inputStream.pushUserMessage(e)}}getHistory(){return[...this.conversationHistory]}getTurnCount(){return this.turnCount}async close(){if(this.currentState!=="closed"){this.currentState="closed",this.abortController.signal.aborted||this.abortController.abort("closed"),this.stateManager.resolveInitializationIfNeeded();try{this.providerQuery.close()}catch{}if(this.processingPromise)try{await Promise.race([this.processingPromise,new Promise(e=>setTimeout(e,lt))])}catch{}this.messageQueue.complete(),await this.dispatchSessionEndOnce("close")}}async dispatchSessionEndOnce(e){this.sessionEndDispatched||(this.sessionEndDispatched=!0,await Gr(this.hookRegistry,{event:"SessionEnd",sessionId:this.sessionId,reason:e}))}assertCanSend(){if(this.currentState==="closed")throw new Error("Cannot send message: session is closed");if(this.abortController.signal.aborted)throw new G("Cannot send message: session aborted");if(this.currentState==="processing"||this.currentState==="streaming")throw new Error("Cannot send message: session is busy");if(this.config.maxTurns&&this.turnCount>=this.config.maxTurns)throw new Error(`Maximum turns (${this.config.maxTurns}) exceeded`)}};var Ct=class{handlers=new Map;register(e,n){let r=this.handlers.get(e);return r||(r=[],this.handlers.set(e,r)),r.push(n),()=>{let o=this.handlers.get(e);if(!o)return;let s=o.indexOf(n);s>=0&&o.splice(s,1)}}count(e){return this.handlers.get(e)?.length??0}async dispatch(e,n){It(n,e.event);let r=this.handlers.get(e.event);if(!r||r.length===0)return{};let o=r.slice(),s={};for(let i of o){It(n,e.event);let a;try{a=await i(e)}catch(l){throw new U(`hook handler threw during ${e.event}`,e.event,l instanceof Error?l.message:String(l),{cause:l})}if(It(n,e.event),_a(a))throw new U(`hook handler blocked ${e.event}${a.reason?`: ${a.reason}`:""}`,e.event,a.reason);s=a}return s}};function _a(t){return t.continue===!1||t.decision==="block"}function It(t,e){if(t?.aborted){let n=t.reason,r=`aborted during ${e}${n?`: ${String(n)}`:""}`;throw new G(r)}}function Jr(){return new Ct}function Qr(){return Jr()}var Ra=["shadow-verify","shadow_verify","resolve","diagnose","appmap","qualify","mint"],Da=[/\bverdict(s)?\b/i,/\brecommend(ation)?s?\b/i,/\bshould\s+(delete|remove|rewrite|refactor|rename|reject|merge|revert|disable)\b/i,/\b(USELESS|KEEP|REJECT|APPROVE|SALVAGE|BLOCK|FAIL)\b/,/\b(redundant|duplicated|superseded|obsolete)\b/i,/\bvulnerab\w*\b/i,/\bunused\b/i,/\bbroken\b/i,/\bregress\w*\b/i,/\|\s*(status|verdict|decision|severity|risk|finding|priority|holds\??)\s*\|/i,/\bfound\s+\d+\s*(issue|problem|bug|error|finding|vulnerabilit)/i,/\b(critical|high|medium|low)\s+(severity|priority|risk)\b/i,/\bclaim(s)?\b[^\n]{0,80}\b(holds?|refuted|verified|partial|confirmed|disputed)\b/i,/\b(root\s*cause|incident)\b/i,/\brecommend\s+(removing|deleting|rewriting|refactoring|merging|reverting)\b/i,/\bI\s+(applied|committed|pushed|edited|wrote|fixed|patched|reset|restored|staged)\b/i,/\b(applied|committed|pushed|fixed|patched)\s+(the|these|those)\s+(change|commit|fix|patch|edit)/i],Oa=[/\bverifier_verdict\b/i,/"\s*claim\s*"\s*:/i,/\bre-derived\b[^.\n]{0,80}\bindependent/i,/\bindependently\s+(re-derived|re-verified|verified|checked)\b/i,/\bverifier\s+(agrees|disagrees|confirms|refutes)\b/i],Fa=`shadow-verify nudge:
1254
+
1255
+ The sub-agent that just finished returned output that reads like **decision-driving findings** (verdicts, recommendations, audit conclusions, or claim-style results that could drive file edits, deletions, commits, or external side-effects).
1256
+
1257
+ Single-pass sub-agent reports are prone to confident hallucination \u2014 polished output that falls apart on re-derivation. Before acting on these conclusions, consider dispatching \`/shadow-verify\`. Independent verifiers will re-derive the 2\u20133 most load-bearing claims from scratch (without seeing the original reasoning) and flag any that don't hold up.
1258
+
1259
+ Skip when: the findings are purely exploratory, the sub-agent ran inside an already-verifying orchestrator, the user is about to dismiss the report, or the stakes are low (read-only Q&A).`;function $a(t){if(!t)return!1;let e=t.toLowerCase();return Ra.some(n=>e.includes(n))}function La(t){return Oa.some(e=>e.test(t))}function ja(t){let e=0;for(let n of Da)n.test(t)&&e++;return e}function Xr(t){if(t.event!=="SubagentStop")return{};let e=t.lastMessage??"";return e.length<600?{}:$a(t.agentType)?{}:La(e)?{}:ja(e)<2?{}:{injectContext:Fa}}function Mt(t){let e=Qr();return e.register("SubagentStop",Xr),t&&e.register("SubagentStop",n=>n.event!=="SubagentStop"?{}:n.status==="idle"||n.status==="running"?{}:(t({subagentId:n.subagentId,status:n.status,durationMs:n.durationMs,agentType:n.agentType}),{})),e}var Ha="[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\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\nSkip orchestration for: single-line edits, trivial Q&A, and direct tool calls the user explicitly requested. The goal is leverage, not ceremony \u2014 if a skill would add overhead without adding value, don't invoke it.";function _t(t,e){return!t||!e?t:`${t}
1260
+
1261
+ ${Ha}`}function Ua(t){if(typeof t!="object"||t===null)throw new Error("Skill tool input must be an object");let e=t,n=e.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=e.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 fe=class{constructor(e){this.ctx=e}ctx;pluginBodies=null;async execute(e){if(e.signal.aborted)return{content:"Skill tool call aborted",isError:!0};let n=this.ctx.depth??0,r=this.ctx.maxDepth??Pe;if(n>=r)return{content:`Skill tool not available at nesting depth ${n} (max ${r})`,isError:!0};let o;try{o=Ua(e.input)}catch(l){return{content:`Skill tool input validation failed: ${l instanceof Error?l.message:String(l)}`,isError:!0}}try{let l=z(o.name);return await this.executeRegistrySkill(l,o.arguments,e.signal)}catch{}let s=this.getPluginSkillBody(o.name);if(s)return await this.executePluginSkill(o.name,s,o.arguments,e.signal);let a=ke(this.ctx.pluginConfigs).map(l=>l.name).join(", ");return{content:`Skill "${o.name}" not found. Available skills: ${a||"(none)"}`,isError:!0}}async executeRegistrySkill(e,n,r){if(r.aborted)return{content:"Skill call aborted",isError:!0};if(e.context==="fork")return this.executeForkedRegistrySkill(e,n,r);try{let o=await e.handler(n&&n.length>0?n:void 0,this.ctx.parentSession);return{content:typeof o=="string"?o:o!=null?JSON.stringify(o):"Skill completed successfully."}}catch(o){return{content:`Skill execution error: ${o instanceof Error?o.message:String(o)}`,isError:!0}}}async executeForkedRegistrySkill(e,n,r){if(r.aborted)return{content:"Skill call aborted",isError:!0};let o;try{if(o=T(e.name)["system.md"],!o)return{content:`Skill "${e.name}" has context: "fork" but no prompts/system.md found`,isError:!0}}catch(i){return{content:`Failed to load skill prompts: ${i instanceof Error?i.message:String(i)}`,isError:!0}}let s=new k({parentAbortSignal:r});try{let i=await s.forkSubagent({parent:this.ctx.parentSession,config:{model:e.model??this.ctx.defaultSubagentModel??this.ctx.defaultModel??"sonnet",systemPrompt:o},idPrefix:`skill-fork-${e.name}`}),a=n&&n.length>0?n:"Run the skill.",l=await i.runToResult(a);return l.status==="succeeded"&&l.message?{content:l.message.content}:{content:l.error?.message??"Forked skill failed with no output",isError:!0}}catch(i){return{content:`Forked skill execution error: ${i instanceof Error?i.message:String(i)}`,isError:!0}}finally{await s.teardownAll()}}async executePluginSkill(e,n,r,o){if(o.aborted)return{content:"Skill call aborted",isError:!0};let s=new k({parentAbortSignal:o});try{let i=await s.forkSubagent({parent:this.ctx.parentSession,config:{model:this.ctx.defaultSubagentModel??this.ctx.defaultModel??"sonnet",systemPrompt:n},idPrefix:`skill-${e}`}),a=r&&r.length>0?r:"Run the skill.",l=await i.runToResult(a);return l.status==="succeeded"&&l.message?{content:l.message.content}:{content:l.error?.message??"Plugin skill failed with no output",isError:!0}}catch(i){return{content:`Plugin skill execution error: ${i instanceof Error?i.message:String(i)}`,isError:!0}}finally{await s.teardownAll()}}getPluginSkillBody(e){return this.pluginBodies||(this.pluginBodies=Pr(this.ctx.pluginConfigs)),this.pluginBodies.get(e)}};var Pe=3;function Rt(t){return{sessionId:void 0,getInputStreamRef:()=>({pushUserMessage:()=>{}}),abortSignal:t}}var Na=[...we,"agent","skill"];function Zr(){return({childExecutor:t,childSkillExecutor:e})=>new Q({permissions:{allowedTools:Na},subagentExecutor:t,skillExecutor:e})}function eo(t){return(e,n,r)=>new fe({parentSession:Rt(r),defaultModel:t,depth:e,maxDepth:n})}function Ba(t){if(typeof t!="object"||t===null)throw new Error("Agent tool input must be an object");let e=t,n=e.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=e.model;if(o!==void 0){if(typeof o!="string")throw new Error("Agent tool model must be a string");r=o}let s=10,i=e.max_turns;if(i!==void 0){if(typeof i!="number")throw new Error("Agent tool max_turns must be a number");s=Math.max(1,Math.min(50,Math.floor(i)))}let a="agent-tool",l=e.id_prefix;if(l!==void 0){if(typeof l!="string")throw new Error("Agent tool id_prefix must be a string");a=l}return{prompt:n,model:r,max_turns:s,id_prefix:a}}var Xe=class t{constructor(e){this.ctx=e}ctx;async execute(e){if(e.signal.aborted)return{content:"Agent tool call aborted",isError:!0};let n;try{n=Ba(e.input)}catch(c){return{content:`Agent tool input validation failed: ${c instanceof Error?c.message:String(c)}`,isError:!0}}let r=this.ctx.depth??0,o=this.ctx.maxDepth??Pe,s,i={model:n.model??this.ctx.defaultSubagentModel??"sonnet",apiKey:this.ctx.defaultConfig.apiKey,systemPrompt:this.ctx.defaultConfig.systemPrompt,maxTurns:n.max_turns};if(this.ctx.childProviderFactory&&r<o){s=new k({parentAbortSignal:e.signal});let c=new t({subagentManager:s,parentSession:Rt(e.signal),defaultConfig:this.ctx.defaultConfig,defaultSubagentModel:this.ctx.defaultSubagentModel,childProviderFactory:this.ctx.childProviderFactory,childSkillExecutorFactory:this.ctx.childSkillExecutorFactory,depth:r+1,maxDepth:o}),d=this.ctx.childSkillExecutorFactory?this.ctx.childSkillExecutorFactory(r+1,o,e.signal):void 0;i.provider=this.ctx.childProviderFactory({childExecutor:c,childSkillExecutor:d})}let a;try{a=await this.ctx.subagentManager.forkSubagent({parent:this.ctx.parentSession,config:i,idPrefix:n.id_prefix})}catch(c){return{content:`Failed to fork subagent: ${c instanceof Error?c.message:String(c)}`,isError:!0}}let l=()=>{a.cancel()};e.signal.addEventListener("abort",l,{once:!0});try{let c=await a.runToResult(n.prompt);return c.status==="succeeded"&&c.message?{content:c.message.content}:{content:c.error?.message??"Subagent failed with no output",isError:!0}}finally{e.signal.removeEventListener("abort",l),await s?.teardownAll(),await a.teardown()}}};async function Ka(){let t;try{t=lr()}catch(s){console.error("\u274C Configuration error:",s.message),process.exit(1)}let e=de(t.model);if(e==="openai-codex"){let s=process.env.OPENAI_API_KEY||process.env.CODEX_API_KEY;console.log(s?"\u{1F4DD} Using OPENAI_API_KEY / CODEX_API_KEY for Codex auth":"\u{1F4DD} Using existing `codex login` state on disk for Codex auth")}else process.env.CLAUDE_CODE_OAUTH_TOKEN?console.log("\u{1F4DD} Using CLAUDE_CODE_OAUTH_TOKEN for Anthropic auth"):process.env.ANTHROPIC_API_KEY?console.log("\u{1F4DD} Using ANTHROPIC_API_KEY for Anthropic auth"):t.apiKey?(process.env.ANTHROPIC_API_KEY=t.apiKey,console.log("\u{1F4DD} Using API key from config for Anthropic auth")):(console.error("\u274C Claude models require ANTHROPIC_API_KEY or CLAUDE_CODE_OAUTH_TOKEN."),console.error(" Set one in your environment or run `afk login`."),process.exit(1));let n=process.env.TELEGRAM_BOT_TOKEN;n||(console.error("\u274C Error: TELEGRAM_BOT_TOKEN environment variable is required"),console.error(`
1262
+ How to get a bot token:`),console.error(" 1. Open Telegram and search for @BotFather"),console.error(" 2. Send /newbot and follow the instructions"),console.error(" 3. Copy the token to your .env file"),process.exit(1));let r=Kt(process.env.AFK_TELEGRAM_ALLOWED_CHAT_IDS,console.warn);r.size===0&&(console.error("\u274C Error: AFK_TELEGRAM_ALLOWED_CHAT_IDS must list at least one chat ID"),console.error(`
1263
+ This is an allowlist that gates who can message the bot.`),console.error("Set it to a comma-separated list of numeric Telegram chat IDs, e.g.:"),console.error(" AFK_TELEGRAM_ALLOWED_CHAT_IDS=123456789,-100987654321"),console.error(`
1264
+ To find your chat ID, DM the bot and inspect the update, or use @userinfobot.`),process.exit(1)),console.log("\u{1F916} Starting Agent AFK Telegram Bot..."),console.log(`\u{1F4E1} Model: ${t.model} \xB7 Provider: ${e}`),console.log(`\u{1F512} Allowlist: ${r.size} chat ID(s)`);let o=new Ce({botToken:n,apiKey:t.apiKey??"",dataDir:process.env.TELEGRAM_DATA_DIR||"./data/telegram-sessions",defaultModel:t.model,verbose:process.env.TELEGRAM_VERBOSE==="true",allowedChatIds:r,settingSources:["user","project"],createSession:async s=>{let i=ae(s.model)??s.model;console.log(`Creating session with model: ${s.model} -> ${i}`);let l=de(i)==="openai-codex",c=l?void 0:cr(),d;if(!l){let h,m=new k({}),b={get sessionId(){return h?.sessionId},getInputStreamRef(){return h?.getInputStreamRef?.()??{pushUserMessage:()=>{}}},get abortSignal(){return h?.abortSignal??new AbortController().signal}},S=Zr(),F=new Xe({subagentManager:m,parentSession:b,defaultConfig:{apiKey:s.apiKey??t.apiKey??"",systemPrompt:s.systemPrompt??t.systemPrompt},defaultSubagentModel:wt(),childProviderFactory:S,childSkillExecutorFactory:eo(s.model)}),R=new fe({parentSession:b,defaultModel:s.model,defaultSubagentModel:wt()}),x=[...we,"agent","skill"];d=new Q({permissions:{allowedTools:x},subagentExecutor:F,skillExecutor:R});let M=s.systemPrompt||t.systemPrompt,_=t.autoRouting?.telegram??!1,B=typeof M=="string"?_t(M,_):M,K=new Z({...s.apiKey!==void 0?{apiKey:s.apiKey}:{},model:s.model,...B!==void 0?{systemPrompt:B}:{},maxTurns:100,...c!==void 0?{maxOutputTokens:c}:{},provider:d,hookRegistry:Mt()});return h=K,K}let u=s.systemPrompt||t.systemPrompt,p=t.autoRouting?.telegram??!1,f=typeof u=="string"?_t(u,p):u;return new Z({...s.apiKey!==void 0?{apiKey:s.apiKey}:{},model:s.model,...f!==void 0?{systemPrompt:f}:{},maxTurns:100,...c!==void 0?{maxOutputTokens:c}:{},hookRegistry:Mt()})}});try{o.start(),console.log("\u2705 Bot started successfully!"),console.log(`
1265
+ \u{1F4DD} Slash commands (Agent SDK):`),console.log(" /start - Welcome and command list"),console.log(" /help - Show command list"),console.log(" /clear - Clear conversation history"),console.log(" /compact - Compact history (summarize older messages)"),console.log(" /model - Switch model (opus/sonnet/haiku/gpt-5.4/...)"),console.log(`
1266
+ \u{1F4AC} Send any message to chat with the agent.`),console.log(`
1267
+ \u23F9\uFE0F Press Ctrl+C to stop the bot.`);let s=setInterval(()=>{let a=o.getStats();console.log(`
1268
+ \u{1F4CA} Stats: ${a.activeSessions} active sessions, ${a.totalChats} total chats`)},3e5),i=async()=>{console.log(`
1269
+
1270
+ \u{1F6D1} Shutting down bot...`),clearInterval(s),await o.stop(),console.log("\u2705 Bot stopped."),process.exit(0)};process.on("SIGINT",i),process.on("SIGTERM",i)}catch(s){console.error("\u274C Failed to start bot:",s),process.exit(1)}}Ka().catch(t=>{console.error("\u274C Unhandled error:",t),process.exit(1)});