agent-afk 3.18.0 → 3.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +259 -259
- package/dist/index.mjs +10 -10
- package/dist/telegram.mjs +31 -31
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -923,7 +923,7 @@ Don't refuse the flow; just clarify where the wizard runs.
|
|
|
923
923
|
Be terse and operational. The user is doing one-time setup; they want it done, not narrated. Confirm each step in one line, don't over-explain. Use \`\u2713\` for success, \`\u2717\` for failure, and code fences for any command they should run.
|
|
924
924
|
`}};function $(t){let e=Mr[t];if(!e){let n=Object.keys(Mr).sort(),r=n.length>0?"Available: "+n.join(", "):"";throw new Error("Unknown skill: "+t+". "+r)}return e}var gt=new Map;function J(t){gt.set(t.name,t)}function Ae(t){let e=gt.get(t);if(e)return e;let n=Array.from(gt.keys()).sort(),r=n.length>0?`
|
|
925
925
|
Available skills: ${n.join(", ")}`:"";throw new Error(`Skill not found: ${t}${r}`)}function ht(){return Array.from(gt.keys()).sort()}var ze=class{nodes=new Map;traceWriter;constructor(e){this.traceWriter=e}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}childrenOf(e){let n=this.nodes.get(e);return n?Array.from(n.children):[]}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 c={parentId:e,childId:n,reason:s.controller.signal.reason};for(let a of i.listeners)try{a(c)}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,r="user_signal"){let o=this.nodes.get(e);if(!o||o.controller.signal.aborted)return;let s=[],i=[...o.children],c=new Set;for(;i.length;){let a=i.shift();if(c.has(a))continue;c.add(a);let l=this.nodes.get(a);if(l){l.cascading=!0,s.push(a);for(let d of l.children)i.push(d)}}hr(this.traceWriter,{origin:r,cascadedTo:s,...n!==void 0?{reason:wa(n)}:{}}),o.controller.abort(n);for(let a of s){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)}}};function wa(t){if(typeof t=="string")return t;if(t instanceof Error)return t.message;try{return JSON.stringify(t)}catch{return String(t)}}var Ve=0,yt=5e3;async function Je(t,e,n={}){if(!Number.isFinite(e)||e<=0)return t;let r,o=new Promise((s,i)=>{r=setTimeout(()=>{let c=n.label?` (${n.label})`:"",a=new fe(`Operation timed out after ${e}ms${c}`,e);n.controller&&!n.controller.signal.aborted&&n.controller.abort(a),i(a)},e)});try{return await Promise.race([t,o])}finally{r!==void 0&&clearTimeout(r)}}var bt=3e4;var Ye=class extends Error{constructor(n,r){super(`hook handler timed out after ${r}ms during ${n}`);this.hookEvent=n;this.timeoutMs=r;this.name="HookHandlerTimeoutError"}hookEvent;timeoutMs;code="HOOK_HANDLER_TIMEOUT"};async function ge(t,e,n,r){if(!t)return;if(r.kind==="blocked"){await De(t,{hookEvent:e,decision:"block",...r.err.reason!==void 0?{reason:r.err.reason}:{},...e==="PreToolUse"&&n.toolName!==void 0?{blockedTool:n.toolName}:{}});return}let o=r.decision;await De(t,{hookEvent:e,decision:o.decision,...o.reason!==void 0?{reason:o.reason}:{},...o.injectContext!==void 0?{injectedContextBytes:Buffer.byteLength(o.injectContext,"utf8")}:{}})}async function Or(t,e,n={}){if(t)try{let r=await t.dispatch(e,n.signal);await ge(n.traceWriter,"SubagentStart",{},{kind:"decision",decision:r})}catch(r){throw r instanceof K&&await ge(n.traceWriter,"SubagentStart",{},{kind:"blocked",err:r}),r}}function ka(t,e,n){return new Promise((r,o)=>{let s=!1,i=setTimeout(()=>{s||(s=!0,o(new Ye(n,e)))},e);i.unref(),t.then(c=>{s||(s=!0,clearTimeout(i),r(c))},c=>{s||(s=!0,clearTimeout(i),o(c))})})}async function Dr(t,e,n={}){if(!t)return{};try{let r=await ka(t.dispatch(e,n.signal,bt),bt,"SubagentStop");return await ge(n.traceWriter,"SubagentStop",{},{kind:"decision",decision:r}),r}catch(r){return r instanceof Ye?(console.warn(`[afk] SubagentStop hook timed out after ${bt}ms (subagentId=${e.subagentId}): ${r.message}`),n.onError?.(r),{}):(r instanceof K&&await ge(n.traceWriter,"SubagentStop",{},{kind:"blocked",err:r}),r instanceof K||r instanceof te?(I(`SubagentStop hook swallowed ${r.name}: ${r.message}`),n.onError?.(r),{}):(I(`SubagentStop hook unexpected error: ${String(r)}`),n.onError?.(r instanceof Error?r:new Error(String(r))),{}))}}async function pn(t,e,n={}){if(t)try{let r=await t.dispatch(e,n.signal);await ge(n.traceWriter,"PreToolUse",{toolName:e.toolName},{kind:"decision",decision:r})}catch(r){throw r instanceof K&&await ge(n.traceWriter,"PreToolUse",{toolName:e.toolName},{kind:"blocked",err:r}),r}}async function Fr(t,e,n={}){if(t)try{let r=await t.dispatch(e,n.signal);await ge(n.traceWriter,"PostToolUse",{toolName:e.toolName},{kind:"decision",decision:r})}catch(r){if(r instanceof K&&await ge(n.traceWriter,"PostToolUse",{toolName:e.toolName},{kind:"blocked",err:r}),r instanceof K||r instanceof te){I(`PostToolUse hook swallowed ${r.name}: ${r.message}`),n.onError?.(r);return}I(`PostToolUse hook unexpected error: ${String(r)}`),n.onError?.(r instanceof Error?r:new Error(String(r)))}}import{mkdir as xa,writeFile as Ra}from"fs/promises";import{dirname as Pa,join as Ia}from"path";import{join as H,dirname as va,isAbsolute as Sa}from"path";import{homedir as Ea}from"os";import{fileURLToPath as Ta}from"url";function X(){let t=S.AFK_HOME;if(t!==void 0&&t!==""){if(!Sa(t)||t==="/")throw new Error(`AFK_HOME must be an absolute path that is not /, got: ${t}`);return t}return H(Ea(),".afk")}function xe(){return H(X(),"agent-framework")}function wt(){return H(xe(),"forge-telemetry.jsonl")}function Fe(){return H(xe(),"briefs")}function kt(){return H(xe(),"ceiling-ledger")}function vt(){return H(X(),"skills")}function Le(){return H(X(),"plugins")}function _a(){return H(process.cwd(),".afk")}function fn(){return H(_a(),"plugins")}function St(){return H(Le(),".index.json")}function mn(){return H(Aa(),"schedules.json")}function gn(){let t=Ta(import.meta.url),e=va(t);return H(e,"bundled-plugins")}function Aa(){return H(X(),"config")}function Et(){return H(X(),"state")}function Lr(){return H(Et(),"sessions")}function Tt(){return H(Et(),"memory")}function Ne(){return H(Et(),"session-grants.jsonl")}function Nr(){return H(X(),"farms")}function Ur(t){return H(Nr(),t)}function $r(t="default"){return H(Et(),"daemon",`agent-afk@${t}`)}function Ca(){return Ia(xe(),"routing-decisions.jsonl")}async function _t(t){if(!(S.VITEST||S.NODE_ENV==="test"))try{let e=Ca();await xa(Pa(e),{recursive:!0});let r={ts:new Date().toISOString().split(".")[0]+"Z",surface:"afk"};for(let[s,i]of Object.entries(t))i!==void 0&&(r[s]=i);let o=JSON.stringify(r)+`
|
|
926
|
-
`;await Ra(e,o,{flag:"a"})}catch{}}import{AsyncLocalStorage as Ma}from"node:async_hooks";var Hr=new Ma;function jr(t,e){return Hr.run(t,e)}function Re(){return Hr.getStore()}function hn(t){let e=Oa(t);return e!==void 0?e:Da(t)}function Oa(t){let e=/```(?:json)?\s*([\s\S]*?)```/gi,n,r;for(;(r=e.exec(t))!==null;)n=r[1];if(n)return Br(n.trim())}function Da(t){for(let e=t.length-1;e>=0;e--){if(t[e]!=="}")continue;let n=Fa(t,e);if(n===-1)continue;let r=t.slice(n,e+1),o=Br(r);if(o!==void 0)return o}}function Fa(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 Br(t){try{return JSON.parse(t)}catch{return}}function yn(){return{toolCalls:[],toolResults:[],thinkingPresent:!1,turnCount:0}}function Wr(t,e,n,r,o){if(!r)return{id:t,status:e,message:n,trace:o};let s=hn(n.content),i=r.safeParse(s);return i.success?{id:t,status:e,message:n,output:i.data,trace:o}:{id:t,status:"failed",message:n,error:new Error(`structured output did not match schema: ${i.error.message}`,{cause:i.error}),schemaError:i.error,trace:o}}function Kr(t,e,n,r){let o=n instanceof Error?n:new Error(String(n));return{id:t,status:e,error:o,trace:r}}function U(t){return`${t.status}${t.error?`: ${t.error.message}`:""}`}var At=class{constructor(e,n,r,o,s,i,c,a,l,d,u,p,h,f){this.id=e;this.session=n;this.controller=r;this.abortGraph=o;this.outputSchema=s;this.timeoutMs=i;this.hookRegistry=c;this.onTerminal=a;this.parentInputStreamRef=l;this.parentAbortSignal=d;this.agentType=u;this.traceWriter=f;this.progressSink=p,this.parentId=h}id;session;controller;abortGraph;outputSchema;timeoutMs;hookRegistry;onTerminal;parentInputStreamRef;parentAbortSignal;agentType;traceWriter;currentStatus="idle";inFlight=null;lastMessage;lastDurationMs;latestTerminalStatus;stopDispatched=!1;progressSink;parentId;currentTrace=yn();lastStreamedContent="";get status(){return this.currentStatus}async run(e,n){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 r=Date.now(),o=Je(this.streamToFinalMessage(e,n),this.timeoutMs,{controller:this.controller,label:this.id});this.inFlight=o;try{let s=await o;return this.lastMessage=s.content,this.lastDurationMs=Date.now()-r,this.currentStatus="succeeded",this.latestTerminalStatus="succeeded",Te(this.traceWriter,{transition:"succeeded",subagentId:this.id,durationMs:this.lastDurationMs,turnCount:this.currentTrace.turnCount,outputBytes:Buffer.byteLength(this.lastMessage,"utf8")}),this.onTerminal(),s}catch(s){throw this.lastDurationMs=Date.now()-r,this.currentStatus!=="cancelled"&&(this.controller.signal.aborted?(Te(this.traceWriter,{transition:"cancelled",subagentId:this.id,source:"cascade"}),this.currentStatus="cancelled",this.latestTerminalStatus="cancelled"):(Te(this.traceWriter,{transition:"failed",subagentId:this.id,errorClass:s instanceof Error?s.constructor.name:"Unknown",errorMessage:s instanceof Error?s.message:String(s),partialOutputBytes:Buffer.byteLength(this.lastStreamedContent,"utf8")}),this.currentStatus="failed",this.latestTerminalStatus="failed")),this.onTerminal(),s}finally{this.inFlight=null}}async streamToFinalMessage(e,n){let r,o;this.lastStreamedContent="",this.currentTrace=yn();let s=n??this.progressSink??Re(),i={subagentId:this.id,...this.parentId!==void 0&&{parentId:this.parentId},...this.agentType!==void 0&&{agentType:this.agentType}};for await(let c of this.session.sendMessageStream(e)){if(s&&s(c,i),c.type==="chunk"){let a=c.chunk;a.type==="content"?this.lastStreamedContent+=a.content:a.type==="tool_use_detail"?this.currentTrace.toolCalls.push({id:a.toolUseId,name:a.toolName,inputBytes:Buffer.byteLength(a.toolInput,"utf8")}):a.type==="tool_result"?this.currentTrace.toolResults.push({toolUseId:a.toolUseId,isError:a.isError,truncated:a.truncated,sizeBytes:a.sizeBytes}):a.type==="thinking"&&(this.currentTrace.thinkingPresent=!0)}if(c.type==="message")r=c.message,this.currentTrace.turnCount++;else if(c.type==="error"){o=c.error;break}else if(c.type==="done"){if(typeof c.metadata?.usage=="object"&&c.metadata.usage!==null){let a=c.metadata.usage;this.currentTrace.usage={inputTokens:typeof a.input_tokens=="number"?a.input_tokens:void 0,outputTokens:typeof a.output_tokens=="number"?a.output_tokens:void 0,cacheReadTokens:typeof a.cache_read_input_tokens=="number"?a.cache_read_input_tokens:void 0,cacheCreationTokens:typeof a.cache_creation_input_tokens=="number"?a.cache_creation_input_tokens:void 0}}break}}if(o)throw o;if(r)return r;if(this.lastStreamedContent.length>0)return{role:"assistant",content:this.lastStreamedContent,timestamp:new Date};throw new Error(`Subagent ${this.id} produced no terminal message`)}async runToResult(e,n){try{let r=await this.run(e,n);return Wr(this.id,this.currentStatus,r,this.outputSchema,this.currentTrace)}catch(r){let o=Kr(this.id,this.currentStatus,r,this.currentTrace);return this.lastStreamedContent.length>0&&(o.partialOutput=this.lastStreamedContent),o}}runInBackground(e,n,r){let o;if(r){let s=this.progressSink??Re();o=(i,c)=>{r(i),s?.(i,c)}}this.runToResult(e,o).then(s=>{n?.(s)}).catch(s=>{I("runInBackground: unexpected rejection after runToResult",s),console.error("Subagent runInBackground failed unexpectedly:",s)})}async cancel(){if(this.currentStatus==="cancelled"||this.stopDispatched)return;let e=this.latestTerminalStatus??"cancelled";this.currentStatus="cancelled",Te(this.traceWriter,{transition:"cancelled",subagentId:this.id,source:"explicit"});try{this.abortGraph.abort(this.id,"cancelled")}catch{}try{this.inFlight&&await this.session.interrupt()}catch{}try{await this.session.close()}finally{await this.dispatchStopAndRelease(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 Dr(this.hookRegistry,{event:"SubagentStop",subagentId:this.id,status:e,lastMessage:this.lastMessage,agentType:this.agentType,durationMs:this.lastDurationMs,trace:this.currentTrace},this.traceWriter?{traceWriter:this.traceWriter}:{});if(n.injectContext&&this.parentInputStreamRef)if(this.parentAbortSignal?.aborted)I(`Skipping SubagentStop injectContext for ${this.id}: parent is aborted`);else try{this.parentInputStreamRef.pushUserMessage(n.injectContext)}catch(r){I(`Failed to inject context from SubagentStop handler: ${String(r)}`)}this.onTerminal()}};var La=async(t,e)=>({action:"decline"}),C=class{active=new Map;parentCanUseTool;hookRegistry;progressSink;parentApiKey;parentBaseUrl;parentCwd;abortGraph;rootId;rootController;counter=0;constructor(e={}){if(this.parentCanUseTool=e.canUseTool,this.hookRegistry=e.hookRegistry,this.progressSink=e.progressSink,this.parentApiKey=e.apiKey,this.parentBaseUrl=e.baseUrl,this.parentCwd=e.cwd,this.abortGraph=new ze(e.traceWriter),this.rootId=`manager-root-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,this.rootController=new AbortController,this.abortGraph.register(this.rootId,this.rootController),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,n="user_signal"){this.abortGraph.abort(this.rootId,e,n)}async forkSubagent(e){let n=`${e.idPrefix??"subagent"}-${Date.now()}-${++this.counter}`,r=e.parent.sessionId,o=e.config.hookRegistry??this.hookRegistry;o&&await Or(o,{event:"SubagentStart",subagentId:n,parentSessionId:e.parent.sessionId},{signal:this.rootController.signal,...e.config.traceWriter?{traceWriter:e.config.traceWriter}:{}});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,apiKey:e.config.apiKey||this.parentApiKey,baseUrl:e.config.baseUrl??this.parentBaseUrl,...e.config.cwd===void 0&&this.parentCwd!==void 0?{cwd:this.parentCwd}:{},hookRegistry:e.config.hookRegistry??this.hookRegistry,permissionBubbler:e.config.permissionBubbler??(this.parentCanUseTool!==void 0&&e.config.canUseTool===void 0?{canUseTool:this.parentCanUseTool}:void 0),...e.denyElicitations===!0?{onElicitation:La}:{}},c;try{c=new Pe(i)}catch(y){throw this.abortGraph.dispose(n),y}let a=e.parent.getInputStreamRef?.(),l=e.parent.abortSignal,d=this.progressSink??Re(),u=e.agentType?.trim()||void 0,p=e.parentId?.trim()||void 0,h=new At(n,c,s,this.abortGraph,e.outputSchema,e.config.timeoutMs??Ve,o,()=>{this.active.delete(n),this.abortGraph.dispose(n)},a,l,u??e.idPrefix,d,p??e.parent.sessionId,e.config.traceWriter);this.active.set(n,h);let f=typeof e.config.model=="string"?e.config.model:JSON.stringify(e.config.model);return Te(e.config.traceWriter,{transition:"started",subagentId:n,parentId:e.parent.sessionId??this.rootId,model:f,...i.tools?.allowedTools?{allowedTools:[...i.tools.allowedTools]}:{}}),await _t({event:"subagent.dispatched",subagent_id:n,id_prefix:e.idPrefix,model:f,parent_session_id:e.parent.sessionId}),h}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 xt(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((c,a)=>a)),i=t.map((c,a)=>c.handle.runToResult(c.prompt).then(l=>{if(o[a]=l,s.delete(a),n&&l.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(c=>c.handle.teardown())),o}import{fileURLToPath as Na}from"node:url";import{dirname as Ua}from"node:path";var $a=Na(import.meta.url),dg=Ua($a),Y={name:"research-agent",systemPrompt:`---
|
|
926
|
+
`;await Ra(e,o,{flag:"a"})}catch{}}import{AsyncLocalStorage as Ma}from"node:async_hooks";var Hr=new Ma;function jr(t,e){return Hr.run(t,e)}function Re(){return Hr.getStore()}function hn(t){let e=Oa(t);return e!==void 0?e:Da(t)}function Oa(t){let e=/```(?:json)?\s*([\s\S]*?)```/gi,n,r;for(;(r=e.exec(t))!==null;)n=r[1];if(n)return Br(n.trim())}function Da(t){for(let e=t.length-1;e>=0;e--){if(t[e]!=="}")continue;let n=Fa(t,e);if(n===-1)continue;let r=t.slice(n,e+1),o=Br(r);if(o!==void 0)return o}}function Fa(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 Br(t){try{return JSON.parse(t)}catch{return}}function yn(){return{toolCalls:[],toolResults:[],thinkingPresent:!1,turnCount:0}}function Wr(t,e,n,r,o){if(!r)return{id:t,status:e,message:n,trace:o};let s=hn(n.content),i=r.safeParse(s);return i.success?{id:t,status:e,message:n,output:i.data,trace:o}:{id:t,status:"failed",message:n,error:new Error(`structured output did not match schema: ${i.error.message}`,{cause:i.error}),schemaError:i.error,trace:o}}function Kr(t,e,n,r){let o=n instanceof Error?n:new Error(String(n));return{id:t,status:e,error:o,trace:r}}function U(t){return`${t.status}${t.error?`: ${t.error.message}`:""}`}var At=class{constructor(e,n,r,o,s,i,c,a,l,d,u,p,h,f){this.id=e;this.session=n;this.controller=r;this.abortGraph=o;this.outputSchema=s;this.timeoutMs=i;this.hookRegistry=c;this.onTerminal=a;this.parentInputStreamRef=l;this.parentAbortSignal=d;this.agentType=u;this.traceWriter=f;this.progressSink=p,this.parentId=h}id;session;controller;abortGraph;outputSchema;timeoutMs;hookRegistry;onTerminal;parentInputStreamRef;parentAbortSignal;agentType;traceWriter;currentStatus="idle";inFlight=null;lastMessage;lastDurationMs;latestTerminalStatus;stopDispatched=!1;progressSink;parentId;currentTrace=yn();lastStreamedContent="";get status(){return this.currentStatus}async run(e,n){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 r=Date.now(),o=Je(this.streamToFinalMessage(e,n),this.timeoutMs,{controller:this.controller,label:this.id});this.inFlight=o;try{let s=await o;return this.lastMessage=s.content,this.lastDurationMs=Date.now()-r,this.currentStatus="succeeded",this.latestTerminalStatus="succeeded",Te(this.traceWriter,{transition:"succeeded",subagentId:this.id,durationMs:this.lastDurationMs,turnCount:this.currentTrace.turnCount,outputBytes:Buffer.byteLength(this.lastMessage,"utf8")}),this.onTerminal(),s}catch(s){throw this.lastDurationMs=Date.now()-r,this.currentStatus!=="cancelled"&&(this.controller.signal.aborted?(Te(this.traceWriter,{transition:"cancelled",subagentId:this.id,source:"cascade"}),this.currentStatus="cancelled",this.latestTerminalStatus="cancelled"):(Te(this.traceWriter,{transition:"failed",subagentId:this.id,errorClass:s instanceof Error?s.constructor.name:"Unknown",errorMessage:s instanceof Error?s.message:String(s),partialOutputBytes:Buffer.byteLength(this.lastStreamedContent,"utf8")}),this.currentStatus="failed",this.latestTerminalStatus="failed")),this.onTerminal(),s}finally{this.inFlight=null}}async streamToFinalMessage(e,n){let r,o;this.lastStreamedContent="",this.currentTrace=yn();let s=n??this.progressSink??Re(),i={subagentId:this.id,...this.parentId!==void 0&&{parentId:this.parentId},...this.agentType!==void 0&&{agentType:this.agentType}};for await(let c of this.session.sendMessageStream(e)){if(s&&s(c,i),c.type==="chunk"){let a=c.chunk;a.type==="content"?this.lastStreamedContent+=a.content:a.type==="tool_use_detail"?this.currentTrace.toolCalls.push({id:a.toolUseId,name:a.toolName,inputBytes:Buffer.byteLength(a.toolInput,"utf8")}):a.type==="tool_result"?this.currentTrace.toolResults.push({toolUseId:a.toolUseId,isError:a.isError,truncated:a.truncated,sizeBytes:a.sizeBytes}):a.type==="thinking"&&(this.currentTrace.thinkingPresent=!0)}if(c.type==="message")r=c.message,this.currentTrace.turnCount++;else if(c.type==="error"){o=c.error;break}else if(c.type==="done"){if(typeof c.metadata?.usage=="object"&&c.metadata.usage!==null){let a=c.metadata.usage;this.currentTrace.usage={inputTokens:typeof a.input_tokens=="number"?a.input_tokens:void 0,outputTokens:typeof a.output_tokens=="number"?a.output_tokens:void 0,cacheReadTokens:typeof a.cache_read_input_tokens=="number"?a.cache_read_input_tokens:void 0,cacheCreationTokens:typeof a.cache_creation_input_tokens=="number"?a.cache_creation_input_tokens:void 0}}break}}if(o)throw o;if(r)return r;if(this.lastStreamedContent.length>0)return{role:"assistant",content:this.lastStreamedContent,timestamp:new Date};throw new Error(`Subagent ${this.id} produced no terminal message`)}async runToResult(e,n){try{let r=await this.run(e,n);return Wr(this.id,this.currentStatus,r,this.outputSchema,this.currentTrace)}catch(r){let o=Kr(this.id,this.currentStatus,r,this.currentTrace);return this.lastStreamedContent.length>0&&(o.partialOutput=this.lastStreamedContent),o}}runInBackground(e,n,r){let o;if(r){let s=this.progressSink??Re();o=(i,c)=>{r(i),s?.(i,c)}}this.runToResult(e,o).then(s=>{n?.(s)}).catch(s=>{I("runInBackground: unexpected rejection after runToResult",s),console.error("Subagent runInBackground failed unexpectedly:",s)})}async cancel(){if(this.currentStatus==="cancelled"||this.stopDispatched)return;let e=this.latestTerminalStatus??"cancelled";this.currentStatus="cancelled",Te(this.traceWriter,{transition:"cancelled",subagentId:this.id,source:"explicit"});try{this.abortGraph.abort(this.id,"cancelled")}catch{}try{this.inFlight&&await this.session.interrupt()}catch{}try{await this.session.close()}finally{await this.dispatchStopAndRelease(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 Dr(this.hookRegistry,{event:"SubagentStop",subagentId:this.id,status:e,lastMessage:this.lastMessage,agentType:this.agentType,durationMs:this.lastDurationMs,trace:this.currentTrace},this.traceWriter?{traceWriter:this.traceWriter}:{});if(n.injectContext&&this.parentInputStreamRef)if(this.parentAbortSignal?.aborted)I(`Skipping SubagentStop injectContext for ${this.id}: parent is aborted`);else try{this.parentInputStreamRef.pushUserMessage(n.injectContext)}catch(r){I(`Failed to inject context from SubagentStop handler: ${String(r)}`)}this.onTerminal()}};var La=async(t,e)=>({action:"decline"}),C=class{active=new Map;parentCanUseTool;hookRegistry;progressSink;parentApiKey;parentBaseUrl;parentCwd;abortGraph;rootId;rootController;counter=0;constructor(e={}){if(this.parentCanUseTool=e.canUseTool,this.hookRegistry=e.hookRegistry,this.progressSink=e.progressSink,this.parentApiKey=e.apiKey,this.parentBaseUrl=e.baseUrl,this.parentCwd=e.cwd,this.abortGraph=new ze(e.traceWriter),this.rootId=`manager-root-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,this.rootController=new AbortController,this.abortGraph.register(this.rootId,this.rootController),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,n="user_signal"){this.abortGraph.abort(this.rootId,e,n)}async forkSubagent(e){let n=`${e.idPrefix??"subagent"}-${Date.now()}-${++this.counter}`,r=e.parent.sessionId,o=e.config.hookRegistry??this.hookRegistry;o&&await Or(o,{event:"SubagentStart",subagentId:n,parentSessionId:e.parent.sessionId},{signal:this.rootController.signal,...e.config.traceWriter?{traceWriter:e.config.traceWriter}:{}});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,apiKey:e.config.apiKey||this.parentApiKey,baseUrl:e.config.baseUrl??this.parentBaseUrl,...e.config.cwd===void 0&&this.parentCwd!==void 0?{cwd:this.parentCwd}:{},hookRegistry:e.config.hookRegistry??this.hookRegistry,permissionBubbler:e.config.permissionBubbler??(this.parentCanUseTool!==void 0&&e.config.canUseTool===void 0?{canUseTool:this.parentCanUseTool}:void 0),...e.denyElicitations===!0?{onElicitation:La}:{}},c;try{c=new Pe(i)}catch(y){throw this.abortGraph.dispose(n),y}let a=e.parent.getInputStreamRef?.(),l=e.parent.abortSignal,d=this.progressSink??Re(),u=e.agentType?.trim()||void 0,p=e.parentId?.trim()||void 0,h=new At(n,c,s,this.abortGraph,e.outputSchema,e.config.timeoutMs??Ve,o,()=>{this.active.delete(n),this.abortGraph.dispose(n)},a,l,u??e.idPrefix,d,p??e.parent.sessionId,e.config.traceWriter);this.active.set(n,h);let f=typeof e.config.model=="string"?e.config.model:JSON.stringify(e.config.model);return Te(e.config.traceWriter,{transition:"started",subagentId:n,parentId:e.parent.sessionId??this.rootId,model:f,...i.tools?.allowedTools?{allowedTools:[...i.tools.allowedTools]}:{}}),await _t({event:"subagent.dispatched",subagent_id:n,id_prefix:e.idPrefix,model:f,parent_session_id:e.parent.sessionId}),h}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 xt(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((c,a)=>a)),i=t.map((c,a)=>c.handle.runToResult(c.prompt).then(l=>{if(o[a]=l,s.delete(a),n&&l.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(c=>c.handle.teardown())),o}import{fileURLToPath as Na}from"node:url";import{dirname as Ua}from"node:path";var $a=Na(import.meta.url),ug=Ua($a),Y={name:"research-agent",systemPrompt:`---
|
|
927
927
|
name: research-agent
|
|
928
928
|
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.
|
|
929
929
|
model: sonnet
|
|
@@ -976,7 +976,7 @@ Unless the dispatcher specifies a different schema, return:
|
|
|
976
976
|
**\`boundary_flag\` is required.** If nothing applies, emit \`"none"\` \u2014 do not omit the field. Treat missing as \`"none"\` is acceptable on the orchestrator side, but emit the field explicitly so downstream synthesizers and validators do not see \`null\`.
|
|
977
977
|
|
|
978
978
|
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\`.
|
|
979
|
-
`,sourcePath:"agent-framework-private/agents/research-agent.md",allowedTools:["Read","Grep","Glob","WebFetch","WebSearch"],description:"Read-only sub-agent for research, validation, verification, and codebase inspection. Mechanically locked to Read, Grep, Glob, WebFetch, WebSearch \u2014 cannot Edit, Write, Bash, commit, or push. Delegates git queries to `git-investigator`. Use when the dispatched task is findings-only."};import{existsSync as he,readdirSync as za,readFileSync as Va}from"fs";import{join as ae}from"path";import{existsSync as bn,readFileSync as Ba,readdirSync as Wa,statSync as Ka}from"fs";import{join as Qe,resolve as qr}from"path";import{existsSync as Ha,mkdirSync as
|
|
979
|
+
`,sourcePath:"agent-framework-private/agents/research-agent.md",allowedTools:["Read","Grep","Glob","WebFetch","WebSearch"],description:"Read-only sub-agent for research, validation, verification, and codebase inspection. Mechanically locked to Read, Grep, Glob, WebFetch, WebSearch \u2014 cannot Edit, Write, Bash, commit, or push. Delegates git queries to `git-investigator`. Use when the dispatched task is findings-only."};import{existsSync as he,readdirSync as za,readFileSync as Va}from"fs";import{join as ae}from"path";import{existsSync as bn,readFileSync as Ba,readdirSync as Wa,statSync as Ka}from"fs";import{join as Qe,resolve as qr}from"path";import{existsSync as Ha,mkdirSync as mg,readFileSync as ja,renameSync as gg,writeFileSync as hg,unlinkSync as yg}from"fs";function Gr(t=St()){if(!Ha(t))return Rt();try{let e=ja(t,"utf8"),n=JSON.parse(e);if(!n||typeof n!="object")return Rt();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 Rt()}catch{return Rt()}}function Rt(){return{version:2,plugins:{},marketplaces:{}}}var Ga=5,zr="cache",Xe;function ie(t=Le()){Xe||(Xe=new Map);let e=Xe.get(t);if(e)return[...e];if(!bn(t))return Xe.set(t,[]),[];let n=t===Le()?St():Qe(t,".index.json"),r=Gr(n),o=[];return Vr(t,t,0,o,new Set,r.plugins),Xe.set(t,o),[...o]}function Vr(t,e,n,r,o,s){if(n>Ga||o.has(e))return;if(o.add(e),bn(Qe(e,".claude-plugin","plugin.json"))){let c=wn(t,e);if(c===null){r.push({type:"local",path:e});return}if(c.layout==="cache"){let l=s[c.key];if(!l||l.enabled===!1)return;r.push({type:"local",path:e});return}let a=s[c.key];if(a&&a.enabled===!1)return;r.push({type:"local",path:e});return}let i;try{i=Wa(e)}catch{return}for(let c of i){if(c.startsWith("."))continue;let a=Qe(e,c),l;try{l=Ka(a)}catch{continue}l.isDirectory()&&Vr(t,a,n+1,r,o,s)}}function wn(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]===zr&&r.length>=3){let s=r[1];if(s){let i=Qe(t,zr,s),a=qa(i,e)??r[2];if(a)return{layout:"cache",key:`${s}:${a}`}}}let o=r[0];return o?{layout:"flat",key:o}:null}function qa(t,e){let n=Qe(t,".claude-plugin","marketplace.json");if(!bn(n))return null;let r;try{r=JSON.parse(Ba(n,"utf8"))}catch{return null}if(!r||typeof r!="object")return null;let o=r.plugins;if(!Array.isArray(o))return null;let s=qr(e);for(let i of o){if(!i||typeof i!="object")continue;let c=i;if(!(typeof c.name!="string"||typeof c.source!="string")&&!(!c.source.startsWith("./")&&!c.source.startsWith("../"))&&qr(t,c.source)===s)return c.name}return null}var Jr=["command","agent"];function Yr(t=X()){let e=[],n=ae(t,"skills");if(he(n))for(let r of Pt(n)){let o=ae(n,r,"SKILL.md");he(o)&&e.push({path:o,type:"skill",source:"user"})}for(let r of Jr){let o=ae(t,`${r}s`);if(he(o))for(let s of Pt(o))s.endsWith(".md")&&e.push({path:ae(o,s),type:r,source:"user"})}return e}function Xr(t=Le()){if(!he(t))return[];let e=[],n=ie(t);for(let r of n){let s=wn(t,r.path)?.key,i=ae(r.path,"skills");if(he(i))for(let c of Pt(i)){let a=ae(i,c,"SKILL.md");if(!he(a))continue;let l={path:a,type:"skill",source:"plugin"};s&&(l.plugin_key=s),e.push(l)}for(let c of Jr){let a=ae(r.path,`${c}s`);if(he(a))for(let l of Pt(a)){if(!l.endsWith(".md"))continue;let d={path:ae(a,l),type:c,source:"plugin"};s&&(d.plugin_key=s),e.push(d)}}}return e}function Qr(t=ae(X(),"settings.json")){if(!he(t))return[];try{let e=Va(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 c=0;c<i.length;c++)o.push({event:s,index:c,raw:i[c]});return o}catch{return[]}}function Pt(t){try{return za(t).filter(e=>!e.startsWith("."))}catch{return[]}}var no=L.object({path:L.string(),type:L.enum(["skill","command","agent","hook"]),source:L.enum(["user","plugin"]),plugin_key:L.string().optional(),verdict:L.enum(["correct","misfit","outlier"]),recommended_type:L.string(),rationale:L.string(),confidence:L.enum(["high","med","low"])}),to=L.record(L.string(),L.record(L.string(),L.number())),Hg=L.object({inventory:L.object({user:to,plugin:to}),misfits:L.array(no),briefs_written:L.number(),total_artifacts:L.number()}),Ja=L.object({writeBriefs:L.boolean().optional(),scope:L.enum(["user","plugin","all"]).optional()}),Ya=["skill","command","agent"],ro=["skill","command","agent","hook"];function Xa(t){return{runUserDiscovery:t!=="plugin",runPluginDiscovery:t!=="user",runHookInspector:t!=="plugin"}}function Qa(t){let e=()=>{let s={};for(let i of ro)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 Za(t){return t.verdict==="misfit"&&t.confidence==="high"&&t.source==="user"}function ec(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(`
|
|
980
980
|
`)}function tc(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(`
|
|
981
981
|
`);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(`
|
|
982
982
|
`)}function nc(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 rc(t,e,n){let r=n?.apiKey,o=n?.callId,s=typeof t=="object"&&t!==null?t:{},i=Ja.parse(s),c=i.writeBriefs??!0,a=i.scope??"all",l=Xa(a);if(!e?.sessionId)throw new Error("audit-fit requires a parent session with sessionId");let d=e.sessionId,u=$("audit-fit"),p={skill:u["01-skill-inspector.md"],command:u["02-command-inspector.md"],agent:u["03-agent-inspector.md"],hook:u["04-hook-inspector.md"]};for(let E of ro)if(!p[E])throw new Error(`audit-fit skill missing inspector prompt for ${E}`);let h=l.runUserDiscovery?Yr():[],f=l.runPluginDiscovery?Xr():[],y={skill:[],command:[],agent:[]};for(let E of[...h,...f])y[E.type].push(E);let w=new C({apiKey:r}),T=()=>async E=>Y.allowedTools.includes(E)?{behavior:"allow"}:{behavior:"deny",message:`Tool ${E} not allowed for audit-fit inspectors. Allowed tools: ${Y.allowedTools.join(", ")}`},k=[];for(let E of Ya){let x=y[E];if(x.length===0)continue;let M=p[E];M&&k.push({type:E,prompt:`${M}
|
|
@@ -1008,7 +1008,7 @@ ${x.rationale}
|
|
|
1008
1008
|
---
|
|
1009
1009
|
Generated by audit-fit on ${new Date().toISOString().split(".")[0]}Z
|
|
1010
1010
|
`;await eo(D,W),v++}}let R=xe();await Zr(R,{recursive:!0});let A=E=>{let x=0;for(let M of Object.values(E))for(let D of Object.values(M))x+=D;return x},O=E=>{let x=m.user[E]??{},M=m.plugin[E]??{},D=W=>Object.values(W).reduce((z,V)=>z+V,0);return D(x)+D(M)},P={timestamp:new Date().toISOString(),surface:"afk",scope:a,total_artifacts:g.length,misfits_count:b.length,briefs_written:v,by_source:{user:A(m.user),plugin:A(m.plugin)},by_type:{skill:O("skill"),command:O("command"),agent:O("agent"),hook:O("hook")}},B=kn(R,"audit-fit-telemetry.jsonl");return await eo(B,JSON.stringify(P)+`
|
|
1011
|
-
`),{inventory:m,misfits:b,briefs_written:v,total_artifacts:g.length}}var oc={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:rc,argumentHint:"[--write-briefs]",whenToUse:"When the user wants ~/.afk artifacts (skills, commands, agents, hooks) audited for correct type categorization.",flags:["--write-briefs"]};J(oc);import{z as _}from"zod";import{execFile as cc}from"node:child_process";import{promisify as lc}from"node:util";import{tmpdir as dc}from"node:os";import{join as so}from"node:path";function oo(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 sc}from"node:url";import{dirname as ic}from"node:path";var ac=sc(import.meta.url),
|
|
1011
|
+
`),{inventory:m,misfits:b,briefs_written:v,total_artifacts:g.length}}var oc={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:rc,argumentHint:"[--write-briefs]",whenToUse:"When the user wants ~/.afk artifacts (skills, commands, agents, hooks) audited for correct type categorization.",flags:["--write-briefs"]};J(oc);import{z as _}from"zod";import{execFile as cc}from"node:child_process";import{promisify as lc}from"node:util";import{tmpdir as dc}from"node:os";import{join as so}from"node:path";function oo(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 sc}from"node:url";import{dirname as ic}from"node:path";var ac=sc(import.meta.url),qg=ic(ac),vn={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 Sn(t){let e={description:t.description,prompt:t.systemPrompt};return t.allowedTools&&(e.tools=[...t.allowedTools]),t.model&&(e.model=t.model),e}var It=lc(cc),co=_.object({id:_.string(),claim:_.string(),confidence:_.number().min(0).max(1),evidence_sources:_.array(_.string()),location:_.string().optional(),proposed_fix:_.string().optional(),coverage_gaps:_.array(_.string()).nullish().transform(t=>t??void 0),boundary_flag:_.string().nullish().transform(t=>t??void 0)}),uc=_.object({hypothesis_id:_.string(),claim:_.string(),verdict:_.enum(["VERIFIED","REFUTED","INCONCLUSIVE"]),evidence:_.string(),gate_reason:_.string()}),lo=_.object({hypothesis_id:_.string(),reproducer_passed:_.boolean(),regressions:_.array(_.string()),confidence:_.number().min(0).max(1),verification_log:_.string()}),pc=_.enum(["crash","regression","logic-error","flaky","environment","unknown"]),fc=_.object({failure_type:pc,error_signature:_.string(),affected_area:_.string()}),mc=_.enum(["clear_winner","multiple_plausible","dissent","all_inconclusive","no_hypotheses"]),lh=_.object({reproducer:_.string().optional(),triage:fc.optional(),hypotheses:_.array(co),premise_verifications:_.array(uc).optional(),winner:_.object({hypothesis_id:_.string(),verification_log:_.string(),proposed_fix:_.string()}).optional(),verification_results:_.array(lo).optional(),outcome:mc.optional(),recommended_next_skill:_.enum(["spec"]).optional()});async function gc(t,e){let n=t.map(a=>({hypothesis:a,decision:oo(a)})).filter(a=>a.decision.verify);if(n.length===0)return{premise_verifications:[],hypotheses_to_test:t};let r=[],o;try{r=await e(n.map(a=>a.hypothesis.claim))}catch(a){o=a instanceof Error?a.message:String(a)}let s=n.map((a,l)=>{let d=r[l];return o!==void 0?{hypothesis_id:a.hypothesis.id,claim:a.hypothesis.claim,verdict:"INCONCLUSIVE",evidence:`shadow-verify dispatch failed: ${o}`,gate_reason:a.decision.reason}:d?{hypothesis_id:a.hypothesis.id,claim:a.hypothesis.claim,verdict:d.verdict,evidence:d.evidence,gate_reason:a.decision.reason}:{hypothesis_id:a.hypothesis.id,claim:a.hypothesis.claim,verdict:"INCONCLUSIVE",evidence:"no verifier result for this claim",gate_reason:a.decision.reason}}),i=new Set(s.filter(a=>a.verdict==="REFUTED").map(a=>a.hypothesis_id)),c=i.size===0?t:t.filter(a=>!i.has(a.id));return{premise_verifications:s,hypotheses_to_test:c}}async function hc(t,e,n){let r=n?.apiKey,o=(()=>{if(typeof t=="string")return{failure:t,repoPath:process.cwd(),context:"",maxHypotheses:4};if(typeof t=="object"&&t!==null){let F=t;if(typeof F.failure=="string")return{failure:F.failure,repoPath:F.repoPath||process.cwd(),context:F.context||"",maxHypotheses:Math.min(F.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 s=e.sessionId,i=$("diagnose"),c=i["system.md"],a=i["research.md"],l=i["hypothesis.md"],d=i["verify.md"];if(!c||!a||!l||!d)throw new Error("diagnose skill missing required prompts (system.md, research.md, hypothesis.md, verify.md)");let u=new C({apiKey:r}),p=kc(o.context),h=yc(o.failure,o.context),f=`Triage:
|
|
1012
1012
|
failure_type: ${h.failure_type}
|
|
1013
1013
|
error_signature: ${h.error_signature}
|
|
1014
1014
|
affected_area: ${h.affected_area}`,w=`${Y.systemPrompt}
|
|
@@ -1055,7 +1055,7 @@ Location: ${t.location||"unknown"}
|
|
|
1055
1055
|
Proposed fix: ${t.proposed_fix||"unknown"}
|
|
1056
1056
|
Reproducer: ${e}
|
|
1057
1057
|
|
|
1058
|
-
Working directory (isolated): ${c}`,d=await a.runToResult(l);return d.status!=="succeeded"||!d.output?{hypothesis_id:t.id,reproducer_passed:!1,regressions:[],confidence:0,verification_log:`Verification failed: ${U(d)}`}:d.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 It("git",["worktree","remove","--force",c],{cwd:n})}catch{}}}function Ec(){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.`}:Y.allowedTools.includes(e)?{behavior:"allow"}:{behavior:"deny",message:`Tool ${e} not allowed. Allowed tools: ${Y.allowedTools.join(", ")}`}}var Tc={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:hc,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."};J(Tc);import{z as re}from"zod";import{execFile as Bc}from"child_process";import{promisify as Wc}from"util";import{mkdir as ko,writeFile as vo,readFile as Kc}from"fs/promises";import{existsSync as Mt}from"fs";import{dirname as So,join as ce}from"path";import{fileURLToPath as Gc}from"url";import{fileURLToPath as _c}from"node:url";import{dirname as Ac}from"node:path";var xc=_c(import.meta.url),
|
|
1058
|
+
Working directory (isolated): ${c}`,d=await a.runToResult(l);return d.status!=="succeeded"||!d.output?{hypothesis_id:t.id,reproducer_passed:!1,regressions:[],confidence:0,verification_log:`Verification failed: ${U(d)}`}:d.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 It("git",["worktree","remove","--force",c],{cwd:n})}catch{}}}function Ec(){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.`}:Y.allowedTools.includes(e)?{behavior:"allow"}:{behavior:"deny",message:`Tool ${e} not allowed. Allowed tools: ${Y.allowedTools.join(", ")}`}}var Tc={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:hc,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."};J(Tc);import{z as re}from"zod";import{execFile as Bc}from"child_process";import{promisify as Wc}from"util";import{mkdir as ko,writeFile as vo,readFile as Kc}from"fs/promises";import{existsSync as Mt}from"fs";import{dirname as So,join as ce}from"path";import{fileURLToPath as Gc}from"url";import{fileURLToPath as _c}from"node:url";import{dirname as Ac}from"node:path";var xc=_c(import.meta.url),mh=Ac(xc),En={name:"qualify",systemPrompt:`---
|
|
1059
1059
|
name: qualify
|
|
1060
1060
|
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.
|
|
1061
1061
|
model: sonnet
|
|
@@ -1291,7 +1291,7 @@ If the append fails (permissions, disk full, unwritable path), do not retry and
|
|
|
1291
1291
|
- 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).
|
|
1292
1292
|
|
|
1293
1293
|
Be skeptical. Protect the plugin from fluff. Stage 2 catches patterns that are strong when they work and catastrophic when they don't.
|
|
1294
|
-
`,sourcePath:"agent-framework-local/agents/qualify.md"};import{fileURLToPath as Rc}from"node:url";import{dirname as Pc}from"node:path";var Ic=Rc(import.meta.url),
|
|
1294
|
+
`,sourcePath:"agent-framework-local/agents/qualify.md"};import{fileURLToPath as Rc}from"node:url";import{dirname as Pc}from"node:path";var Ic=Rc(import.meta.url),wh=Pc(Ic);import{mkdir as uo,writeFile as po}from"fs/promises";import{dirname as Cc,join as Mc}from"path";async function Q(t){let e=wt();await uo(Cc(e),{recursive:!0});let n=new Date().toISOString().split(".")[0]+"Z",r={timestamp:n,surface:"afk",...t},o=JSON.stringify(r)+`
|
|
1295
1295
|
`;return await po(e,o,{flag:"a"}),n}async function fo(){let t=kt(),e=Mc(t,"forge-thaw-history.jsonl");await uo(t,{recursive:!0});let r={timestamp:new Date().toISOString().split(".")[0]+"Z",surface:"afk",event:"forge.thaw_override",thaw_triggered:!0},o=JSON.stringify(r)+`
|
|
1296
1296
|
`;await po(e,o,{flag:"a"})}import{readFile as mo,readdir as Oc,writeFile as Dc,mkdir as Fc,unlink as Lc}from"fs/promises";import{join as Ct}from"path";import{existsSync as Nc}from"fs";async function go(t){let e=Ct(Fe(),t+".md"),n=await mo(e,"utf-8");return{id:t,content:n}}async function ho(){let t=Fe();return Nc(t)?(await Oc(t,{withFileTypes:!0})).filter(r=>r.isFile()&&r.name.endsWith(".md")).map(r=>r.name.slice(0,-3)):[]}async function Tn(t,e){let n=Fe(),r=Ct(n,t+".md"),o=Ct(n,e),s=Ct(o,t+".md");await Fc(o,{recursive:!0});let i=await mo(r,"utf-8");await Dc(s,i,"utf-8"),await Lc(r)}var Uc=/^(APPROVE|SALVAGE|REJECT)\b/,$c=/^(?:\w+\s+)*verdict(?:\s+\w+)*\s*[:\-—]\s*(APPROVE|SALVAGE|REJECT)\b/i,Hc=/\b(?:verdict|decision)\b/i;function bo(t){return t.toUpperCase()}function yo(t,e){for(let n=t.length-1;n>=0;n--){let r=t[n];if(!r)continue;let o=r.match(e);if(o&&o[1])return{index:n,verdict:bo(o[1])}}return null}function jc(t){let e=/\b(APPROVE|SALVAGE|REJECT)\b/g;for(let n=t.length-1;n>=0;n--){let r=t[n];if(!r||!Hc.test(r))continue;let o=Array.from(r.matchAll(e));if(o.length===1){let s=o[0]?.[1];if(s)return{index:n,verdict:bo(s)}}}return null}function wo(t){let e=t.split(`
|
|
1297
1297
|
`).map(a=>a.trim()).filter(a=>a.length>0),n=e.map(a=>a.replace(/\*\*/g,"")),r=yo(n,Uc)??yo(n,$c)??jc(n);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.slice(r.index+1).join(`
|
|
@@ -1299,7 +1299,7 @@ Be skeptical. Protect the plugin from fluff. Stage 2 catches patterns that are s
|
|
|
1299
1299
|
- ${e.join(`
|
|
1300
1300
|
- `)}`)}function Vc(){let t=So(Gc(import.meta.url));return zc(t)}function Jc(t){return ce(t,"..","..","..","plugins","awa-private")}function Yc(){return kt()}function Xc(t){let e=t.split(`
|
|
1301
1301
|
`),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 Qc(t){let e=Yc(),n=ce(e,"qualifications.jsonl");await ko(e,{recursive:!0});let o=new Date().toISOString().split(".")[0]+"Z",i=JSON.stringify({timestamp:o,surface:"afk",refers_to_run_id:t,source:"forge-gate-check-ts"})+`
|
|
1302
|
-
`;return await vo(n,i,{flag:"a"}),o}async function Zc(){let t;try{t=Vc()}catch(a){throw new Error(`Failed to resolve eval-harness runner.py: ${a instanceof Error?a.message:String(a)}`)}let e=Jc(t),n="",r="",o=0;try{let a=await qc("python3",[t,"--plugin-root",e],{timeout:6e4});n=a.stdout||"",r=a.stderr||"",o=0}catch(a){let l=a;if(n=l.stdout||"",r=l.stderr||"",o=typeof l.code=="number"?l.code:1,l.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"?Xc(n):void 0,c;if(s==="OPEN"){let a=new Date().toISOString().split(".")[0]+"Z";c=await Qc(a)}return{gate_status:s,exit_code:o,stdout:n,stderr:r||void 0,tasks_failed:i,ledger_entry_ref:c}}var el=re.object({iteration:re.number().int().positive(),verdict:re.enum(["APPROVE","SALVAGE","REJECT"]),score:re.number().optional(),feedback:re.string()}),
|
|
1302
|
+
`;return await vo(n,i,{flag:"a"}),o}async function Zc(){let t;try{t=Vc()}catch(a){throw new Error(`Failed to resolve eval-harness runner.py: ${a instanceof Error?a.message:String(a)}`)}let e=Jc(t),n="",r="",o=0;try{let a=await qc("python3",[t,"--plugin-root",e],{timeout:6e4});n=a.stdout||"",r=a.stderr||"",o=0}catch(a){let l=a;if(n=l.stdout||"",r=l.stderr||"",o=typeof l.code=="number"?l.code:1,l.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"?Xc(n):void 0,c;if(s==="OPEN"){let a=new Date().toISOString().split(".")[0]+"Z";c=await Qc(a)}return{gate_status:s,exit_code:o,stdout:n,stderr:r||void 0,tasks_failed:i,ledger_entry_ref:c}}var el=re.object({iteration:re.number().int().positive(),verdict:re.enum(["APPROVE","SALVAGE","REJECT"]),score:re.number().optional(),feedback:re.string()}),ty=re.object({status:re.enum(["APPROVED","REJECTED","GATE_CLOSED","MAX_ITERATIONS"]),skill_path:re.string().optional(),qualify_verdicts:re.array(el),brief_id:re.string().optional(),telemetry_ref:re.string()}),tl=new Set(["unknown","unnamed","skill","new-skill","tbd","placeholder","<name>",""]);function nl(t){if(!t.startsWith(`---
|
|
1303
1303
|
`))return{ok:!1,reason:"frontmatter_missing",message:"SKILL.md does not start with a YAML frontmatter fence (---)",skillNameAttempted:null};let e=t.split(`
|
|
1304
1304
|
`),n=-1;for(let a=1;a<Math.min(e.length,41);a++)if(e[a]==="---"){n=a;break}if(n===-1)return{ok:!1,reason:"frontmatter_missing",message:'SKILL.md frontmatter closing "---" not found within first 40 lines',skillNameAttempted:null};let o=e.slice(1,n).join(`
|
|
1305
1305
|
`);if(!o.match(/^name:/m)||!o.match(/^description:/m))return{ok:!1,reason:"frontmatter_missing",message:'SKILL.md frontmatter is missing required "name:" or "description:" key',skillNameAttempted:null};let c=(o.match(/^name:[ \t]*([^\n]*)/m)?.[1]??"").trim().replace(/^["']|["']$/g,"");return c?tl.has(c)?{ok:!1,reason:"sentinel_name",message:`SKILL.md "name:" resolved to sentinel/placeholder value: "${c}"`,skillNameAttempted:c}:{ok:!0,skillName:c}:{ok:!1,reason:"name_unparseable",message:'SKILL.md frontmatter "name:" key is present but value is empty after trim',skillNameAttempted:null}}function rl(t,e){if(e.registeredSkills.includes(t))return{ok:!1,reason:"name_collision",message:`skill name "${t}" is already registered in this session (built-in, plugin, or user-scope). Delete or rename the existing skill before forging a replacement.`,skillNameAttempted:t};let n=ce(e.skillsDir,t);return Mt(n)?{ok:!1,reason:"name_collision",message:`target directory already exists on disk: ${n}. Forge would silently overwrite or shadow it. Remove the directory first if you intend to replace the skill.`,skillNameAttempted:t}:null}async function ol(t,e,n){let r=n?.apiKey,o=n?.callId,s=typeof t=="string"?{brief:t}:typeof t=="object"&&t!==null?t:{},i=s.brief,c=s.forceThaw??!1,a=s.maxIterations??3,l="",d=[],u="REJECTED",p,h;try{let f=await Zc();if(f.gate_status==="CLOSED"&&!c)return l=await Q({event:"forge.gate_check",gate_status:"CLOSED"}),{status:"GATE_CLOSED",qualify_verdicts:[],telemetry_ref:l};c&&f.gate_status==="CLOSED"&&(await fo(),l=await Q({event:"forge.thaw_override",gate_status:"CLOSED"})),l=await Q({event:"forge.gate_check",gate_status:"OPEN"});let y="",w=!1;if(i)y=i,w=!0;else{let A=await ho();if(A.length>0){let O=A[0],P=await go(O);y=P.content,h=P.id,w=!0}else{if(!e?.sessionId)throw new Error("forge requires parent session for gap discovery");let P=$("forge")["gap-discovery.md"];if(!P)throw new Error("forge skill missing gap-discovery.md prompt");let x=await(await new C({apiKey:r}).forkSubagent({parent:{sessionId:e.sessionId},config:{model:"sonnet",systemPrompt:P},idPrefix:"forge-gap-discovery",...o?{parentId:o}:{}})).runToResult("Identify the most impactful skill gap.");if(x.status!=="succeeded")throw new Error(`gap discovery failed: ${U(x)}`);if(y=x.message?.content||"",!y)throw new Error("gap discovery returned no concept")}}if(l=await Q({event:"forge.brief_loaded",used_brief:w,brief_id:h||null}),!e?.sessionId)throw new Error("forge requires parent session for skill generation");let T=$("forge"),k=T["generate.md"],g=T["system.md"];if(!k)throw new Error("forge skill missing generate.md prompt");if(!g)throw new Error("forge skill missing system.md prompt");let v=await(await new C({apiKey:r}).forkSubagent({parent:{sessionId:e.sessionId},config:{model:"sonnet",systemPrompt:g},idPrefix:"forge-generate",...o?{parentId:o}:{}})).runToResult(`${k}
|
|
@@ -1463,7 +1463,7 @@ ${s}`}}}return{...t,systemPrompt:r}}import vu from"openai";function rt(t,e){let
|
|
|
1463
1463
|
--
|
|
1464
1464
|
${d.content}`,isError:!0}),i.push({call:l,result:d}),yield{type:"tool.output",toolUseId:l.id,content:d.content,...d.isError===!0?{isError:!0}:{},sessionId:this.initSessionId}}}this.priorTurns.push(Rs(e.assistantText,r));for(let c of Ps(i))this.priorTurns.push(c)}async interrupt(){let e=this.abortController;if(e&&!e.signal.aborted){e.abort("interrupted");return}this.pendingAbortReason="interrupted"}async setModel(e){e!==void 0&&(this.currentModel=e)}async setPermissionMode(e){this.currentPermissionMode=Cs(e)}async supportedCommands(){try{return it().map(n=>{let r={name:n.name,description:n.description};return n.argumentHint&&(r.argumentHint=n.argumentHint),r})}catch{return[]}}async supportedModels(){return[{value:"gpt-4o",displayName:"GPT-4o",description:"OpenAI flagship multimodal"},{value:"gpt-4o-mini",displayName:"GPT-4o mini",description:"Fast/cheap GPT-4o"},{value:"gpt-4.1",displayName:"GPT-4.1",description:"Long-context GPT-4"},{value:"gpt-4.1-mini",displayName:"GPT-4.1 mini",description:"Fast 4.1 variant"},{value:"o1",displayName:"o1",description:"Reasoning model"},{value:"o1-mini",displayName:"o1 mini",description:"Fast reasoning"},{value:"o3-mini",displayName:"o3 mini",description:"Newer reasoning, faster"}]}async supportedAgents(){return[]}async getContextUsage(){let e=this.lastUsage,n=ot(this.currentModel),r;if(e&&n>0){let o=st(e);r=Math.min(100,Math.max(0,o/n*100))}return{tools:[],agents:[],isAutoCompactEnabled:!1,apiUsage:this.lastUsage,...r!==void 0?{percentage:r}:{},maxTokens:n}}async mcpServerStatus(){return this.opts.mcpManager?this.opts.mcpManager.getServerStates().map(e=>({name:e.serverName,status:e.status})):[]}async accountInfo(){return{authSource:this.opts.auth.source}}async rewindFiles(e,n){return{canRewind:!1,error:`${jn} provider does not support file checkpoint rewind yet.`}}close(){this.closed=!0;let e=this.abortController;e&&!e.signal.aborted?e.abort("closed"):this.pendingAbortReason="closed",this.closeResolve?.(),I(`\u{1F7E2} ${jn}: closed`)}};function Tu(t){let e={apiKey:t.apiKey};return t.baseURL!==void 0&&(e.baseURL=t.baseURL),new vu(e)}function _u(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(`
|
|
1465
1465
|
`)[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:""}function Ms(t,e,n={}){let r=$n(t.apiKey),o=t.resume??`openai-pending-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,s=typeof t.model=="string"?t.model:"gpt-4o-mini",i={auth:r,model:s,synthesizedSessionId:o,promptStream:e,config:t};return n.baseURL!==void 0&&(i.baseURL=n.baseURL),n.toolDispatcher!==void 0&&(i.toolDispatcher=n.toolDispatcher),n.mcpManager!==void 0&&(i.mcpManager=n.mcpManager),new Bt(i)}var Pu="openai-compatible",ue=class{name=Pu;providerOpts;memoryStore;schemas;_sharedReadRoots;_sharedWriteRoots;_initialResolveBase;constructor(e={}){this.providerOpts=e,this.memoryStore=e.memoryStore??new de;let n=[...oe];e.subagentExecutor&&n.push(ye),e.skillExecutor&&n.push(be),e.composeExecutor&&n.push(we),n.push(...ke),this.schemas=n}query(e){let n=e.config,r=n.permissionMode??"default";this.ensureSharedRoots(n.cwd),n.readRoots&&this._sharedReadRoots&&this._sharedReadRoots.length<=1&&(this._sharedReadRoots.length=0,this._sharedReadRoots.push(...n.readRoots)),n.writeRoots&&this._sharedWriteRoots&&this._sharedWriteRoots.length<=1&&(this._sharedWriteRoots.length=0,this._sharedWriteRoots.push(...n.writeRoots));let o=this.providerOpts.tools??this.buildDispatcher(r,{...n.cwd!==void 0?{cwd:n.cwd}:{},...this._sharedReadRoots!==void 0?{readRoots:this._sharedReadRoots}:{},...this._sharedWriteRoots!==void 0?{writeRoots:this._sharedWriteRoots}:{},...n.sessionId!==void 0?{sessionId:n.sessionId}:{},...n.traceWriter!==void 0?{traceWriter:n.traceWriter}:{}}),s={};return this.providerOpts.baseURL!==void 0&&(s.baseURL=this.providerOpts.baseURL),s.toolDispatcher=o,this.providerOpts.mcpManager!==void 0&&(s.mcpManager=this.providerOpts.mcpManager),Ms(n,e.prompt,s)}buildDispatcher(e,n){let r=$e(e,n.cwd),o=et(this.memoryStore,void 0,this.providerOpts.surface??"cli");for(let[c,a]of o)r.set(c,a);let s=this.providerOpts.mcpManager?this.providerOpts.mcpManager.getMcpTools():[];if(this.providerOpts.mcpManager)for(let[c,a]of this.providerOpts.mcpManager.getMcpHandlers())r.set(c,a);let i={handlers:r,schemas:[...this.schemas,...s]};return this.providerOpts.hookRegistry!==void 0&&(i.hookRegistry=this.providerOpts.hookRegistry),this.providerOpts.permissions!==void 0&&(i.permissions=this.providerOpts.permissions),this.providerOpts.subagentExecutor!==void 0&&(i.subagentExecutor=this.providerOpts.subagentExecutor),this.providerOpts.skillExecutor!==void 0&&(i.skillExecutor=this.providerOpts.skillExecutor),this.providerOpts.composeExecutor!==void 0&&(i.composeExecutor=this.providerOpts.composeExecutor),n.cwd!==void 0&&(i.cwd=n.cwd),n.readRoots!==void 0&&(i.readRoots=n.readRoots),n.writeRoots!==void 0&&(i.writeRoots=n.writeRoots),n.sessionId!==void 0&&(i.sessionId=n.sessionId),n.traceWriter!==void 0&&(i.traceWriter=n.traceWriter),new le(i)}ensureSharedRoots(e){if(!this._sharedReadRoots){let n=e?[e]:[];this._sharedReadRoots=n.slice(),this._sharedWriteRoots=n.slice(),e&&!this._initialResolveBase&&(this._initialResolveBase=e)}}addReadRoot(e,n="slash",r){this.ensureSharedRoots();let o=Bn.resolve(e);this._sharedReadRoots.includes(o)||this._sharedReadRoots.push(o),this.appendProviderAuditLog({action:"grant-read",path:o,source:n,sessionId:r})}addWriteRoot(e,n="slash",r){this.ensureSharedRoots();let o=Bn.resolve(e);this._sharedReadRoots.includes(o)||this._sharedReadRoots.push(o),this._sharedWriteRoots.includes(o)||this._sharedWriteRoots.push(o),this.appendProviderAuditLog({action:"grant-write",path:o,source:n,sessionId:r})}revokeRoot(e,n="slash",r){if(!this._sharedReadRoots)return;let o=Bn.resolve(e);if(this._initialResolveBase&&o===this._initialResolveBase)return;let s=this._sharedReadRoots.indexOf(o);if(s!==-1&&this._sharedReadRoots.splice(s,1),this._sharedWriteRoots){let i=this._sharedWriteRoots.indexOf(o);i!==-1&&this._sharedWriteRoots.splice(i,1)}this.appendProviderAuditLog({action:"revoke",path:o,source:n,sessionId:r})}getGrants(){return{resolveBase:this._initialResolveBase,readRoots:this._sharedReadRoots?.slice()??[],writeRoots:this._sharedWriteRoots?.slice()??[]}}appendProviderAuditLog(e){try{let n=Ne();xu(Ru(n),{recursive:!0});let r=JSON.stringify({timestamp:new Date().toISOString(),sessionId:e.sessionId??null,action:e.action,path:e.path,source:e.source});Au(n,r+`
|
|
1466
|
-
`)}catch{}}close(){this.memoryStore.close()}},Wn=new ue;import{config as
|
|
1466
|
+
`)}catch{}}close(){this.memoryStore.close()}},Wn=new ue;import{config as Vw}from"dotenv";var Wt={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 Os(t){return t in Wt}function Ds(t){let e=Wt[t];if(!e)throw new Error(`Invalid model: ${t}`);return e}function at(t){if(t!==void 0)return typeof t=="string"&&Os(t)?Ds(t):t}import{execFile as Iu}from"node:child_process";import{promisify as Cu}from"node:util";var Hw=Cu(Iu);function Fs(){return S.ANTHROPIC_API_KEY||S.CLAUDE_CODE_OAUTH_TOKEN||ne()}function q(){return Fs()}async function Ls(t,e,n,r){let s=$("mint")["spec.md"];if(!s)throw new Error("mint skill missing spec.md prompt");let a=await(await new C(n!==void 0?{cwd:n}:{}).forkSubagent({parent:{sessionId:e},config:{model:"sonnet",systemPrompt:s,apiKey:q()},idPrefix:"mint-spec",...r?{parentId:r}:{}})).runToResult(`Create a detailed specification for: ${t}`);if(a.status!=="succeeded"||!a.message)throw new Error(`spec phase failed: ${U(a)}`);return a.message.content}async function Ns(t,e,n,r){let s=$("mint")["research.md"];if(!s)throw new Error("mint skill missing research.md prompt");let a=await(await new C(n!==void 0?{cwd:n}:{}).forkSubagent({parent:{sessionId:e},config:{model:"sonnet",systemPrompt:s,apiKey:q()},idPrefix:"mint-research",...r?{parentId:r}:{}})).runToResult(`Gather context and research for this specification:
|
|
1467
1467
|
|
|
1468
1468
|
${t}`);if(a.status!=="succeeded"||!a.message)throw new Error(`research phase failed: ${U(a)}`);return a.message.content}async function Us(t,e,n,r,o){let i=$("mint")["plan.md"];if(!i)throw new Error("mint skill missing plan.md prompt");let a=await new C(r!==void 0?{cwd:r}:{}).forkSubagent({parent:{sessionId:n},config:{model:"sonnet",systemPrompt:i,apiKey:q()},idPrefix:"mint-plan",...o?{parentId:o}:{}}),l=`Specification:
|
|
1469
1469
|
${t}
|
|
@@ -1579,7 +1579,7 @@ Save reusable multi-step workflows the user teaches you or that you discover wor
|
|
|
1579
1579
|
- Working directory: ${P}`,...m.slice(2)].join(`
|
|
1580
1580
|
|
|
1581
1581
|
`),x=this.buildDispatcher(h,{cwd:P,readRoots:this._sharedReadRoots,writeRoots:this._sharedWriteRoots,...n.env!==void 0?{env:n.env}:{},sessionId:n.sessionId,traceWriter:n.traceWriter});return{userSystem:E,dispatcher:x}},O=Qp(n.effort,u);return new zt({client:a,authMode:r?"api-key":s,promptStream:e.prompt,toolDispatcher:f,...v!==void 0?{sessionId:v}:{},...R!==void 0?{initialMessages:R}:{},model:u,...n.permissionMode!==void 0?{permissionMode:n.permissionMode}:{},maxTokens:p,tools:y,userSystem:g,systemPrefix:l,tokenRefresher:b,...n.thinking!==void 0?{thinking:Xp(n.thinking,p,u)}:{},...O!==void 0?{effort:O}:{},...r?{baseUrl:n.baseUrl}:{},...n.traceWriter?{traceWriter:n.traceWriter}:{},...n.autoResumeOnUsageLimit!==void 0?{autoResumeOnUsageLimit:n.autoResumeOnUsageLimit}:{},...A!==void 0?{cwdDependentsFactory:A}:{},...this.mcpManager!==void 0?{mcpManager:this.mcpManager}:{},...ki(n.autoCompact)!==void 0?{autoCompactThreshold:ki(n.autoCompact)}:{}})}};function zp(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}var Vp=.9;function ki(t){if(t===void 0||t===!1)return;if(t===!0)return Vp;let e=t.threshold;if(!(typeof e!="number"||!Number.isFinite(e)||e<=0||e>=1))return e}function Jp(t,e){let n=t.maxOutputTokens;return typeof n=="number"&&Number.isFinite(n)&&n>0?Math.floor(n):bs(e)}function Yp(t){if(!t||t.length===0)return;let e=[];for(let n of t)n.user.length>0&&e.push({role:"user",content:n.user}),n.assistant.length>0&&e.push({role:"assistant",content:n.assistant});return e.length>0?e:void 0}function Xp(t,e,n){switch(t.type){case"adaptive":return{type:"adaptive",display:"summarized"};case"disabled":return{type:"disabled"};case"enabled":{if(typeof n=="string"&&qp(n))return{type:"adaptive",display:"summarized"};let r=t.budgetTokens!==void 0&&Number.isFinite(t.budgetTokens)?Math.min(t.budgetTokens,e-1):e-1;return{type:"enabled",budget_tokens:Math.max(r,1024),display:"summarized"}}}}function Qp(t,e){if(t!==void 0)return t;let n=e.toLowerCase();if(/(claude-)?(opus|sonnet)-4-[67]/.test(n))return"max"}var Zp=new Ce;var ef=new Set([...Object.keys(Wt),"auto"]);function Ie(t){if(!t)return"anthropic-direct";let e=t.trim().toLowerCase();return!e||ef.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"||e.includes("/")?"openai-compatible":"anthropic-direct"}function Vt(t){switch(Ie(t)){case"openai-compatible":case"openai-codex":return new ue;default:return new Ce}}async function Jt(t,e,n){if(!t)return;if(n.kind==="blocked"){await De(t,{hookEvent:e,decision:"block",...n.err.reason!==void 0?{reason:n.err.reason}:{}});return}let r=n.decision;await De(t,{hookEvent:e,decision:r.decision,...r.reason!==void 0?{reason:r.reason}:{},...r.injectContext!==void 0?{injectedContextBytes:Buffer.byteLength(r.injectContext,"utf8")}:{}})}async function vi(t,e,n={}){if(t)try{let r=await t.dispatch(e,n.signal);await Jt(n.traceWriter,"SessionStart",{kind:"decision",decision:r})}catch(r){throw r instanceof K&&await Jt(n.traceWriter,"SessionStart",{kind:"blocked",err:r}),r}}async function Si(t,e,n={}){if(t)try{let r=await t.dispatch(e,n.signal);await Jt(n.traceWriter,"SessionEnd",{kind:"decision",decision:r})}catch(r){if(r instanceof K&&await Jt(n.traceWriter,"SessionEnd",{kind:"blocked",err:r}),r instanceof K||r instanceof te){I(`SessionEnd hook swallowed ${r.name}: ${r.message}`),n.onError?.(r);return}I(`SessionEnd hook unexpected error: ${String(r)}`),n.onError?.(r instanceof Error?r:new Error(String(r)))}}var Yt=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 Ei(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 Ti(t,e){let n=t.permissionMode??"default",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}}var Xt=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}};function _i(t){try{let e=JSON.parse(t);if(!Array.isArray(e))return null;let n=e.length;if(n===0)return"no results";let r=0,o=0;for(let c of e)if(c&&typeof c=="object"){let a=c.type;a==="fact"?r++:a==="procedure"&&o++}let s=`${n} result${n===1?"":"s"}`;if(r+o!==n)return s;let i=[];return r>0&&i.push(`${r} fact${r===1?"":"s"}`),o>0&&i.push(`${o} procedure${o===1?"":"s"}`),i.length===0?s:`${s} (${i.join(", ")})`}catch{return null}}function Ai(t){try{let e=JSON.parse(t);if(!e||typeof e!="object")return null;let n=e;if(n.target==="hot"&&n.saved===!0)return"hot memory saved";if(n.target==="fact"){if(n.action==="remove")return n.removed===!0?"fact removed":"fact not found";if(n.action==="set"&&typeof n.id=="number")return`fact #${n.id} set`;if(n.action==="supersede"&&typeof n.id=="number"&&typeof n.supersedes=="number")return`fact #${n.id} supersedes #${n.supersedes}`}return null}catch{return null}}function xi(t){try{let e=JSON.parse(t);if(!e||typeof e!="object")return null;let n=e;return typeof n.name=="string"&&n.written===!0?`wrote procedure '${n.name}'`:null}catch{return null}}function tr(t){let e=t.trim();if(e.length===0)return null;let n=e[0];if(n!=="{"&&n!=="[")return null;let r=e[e.length-1];if(n==="{"&&r!=="}"||n==="["&&r!=="]")return null;let o;try{o=JSON.parse(e)}catch{return null}return Array.isArray(o)?Ri(tf(o)):o!==null&&typeof o=="object"?Ri(nf(o)):null}function tf(t){return t.length===0?"[empty array]":t.length===1?"[1 item]":`[${t.length} items]`}function nf(t){let e=Object.keys(t);if(e.length===0)return"{empty object}";let n=e.slice(0,4),r=e.length>4?", \u2026":"";return`{${n.join(", ")}${r}}`}function Ri(t){return t.length<=80?t:t.slice(0,79)+"\u2026"}var rf=new Map([["memory_search",_i],["memory_update",Ai],["procedure_write",xi],["bash",tr],["Bash",tr]]);function of(t){return t.replace(/\x1b\[[0-?]*[ -/]*[@-~]/g,"").replace(/\x1b[@-_]/g,"").replace(/[\x00-\x1f\x7f]/g," ").trim()}function Pi(t,e){if(!t)return null;let n=rf.get(t);if(!n)return null;try{let r=n(e);if(r===null)return null;let o=of(r);return o.length>0?o:null}catch{return null}}function sf(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),c=i;o==="KB"?c=i*1024:o==="MB"?c=i*1024*1024:o==="GB"&&(c=i*1024*1024*1024);let a=r;return i%1===0&&(a=String(Math.floor(i))),a+=o,{sizeLabel:a,sizeBytes:Math.round(c),absolutePath:s.trim()}}function af(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 cf(t){let e=Buffer.byteLength(t,"utf8"),n=af(e),r=t.split(`
|
|
1582
|
-
`);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 lf(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 df(t){let e=t.isError===!0?null:Pi(t.toolName,t.content),n=e!==null?{display:e}:{},r=sf(t.content);if(r)return{type:"chunk",chunk:{type:"tool_result",toolUseId:t.toolUseId,content:`Output persisted (${r.sizeLabel}) \u2192 ${r.absolutePath}`,isError:t.isError===!0,persistedPath:r.absolutePath,sizeBytes:r.sizeBytes,sizeLabel:r.sizeLabel,...n}};let{content:o,truncated:s,lineCount:i,sizeBytes:c,sizeLabel:a}=cf(t.content);return{type:"chunk",chunk:{type:"tool_result",toolUseId:t.toolUseId,content:o,isError:t.isError===!0,sizeBytes:c,sizeLabel:a,...s&&{truncated:s},...i!==void 0&&{lineCount:i},...n}}}function nr(t,e){switch(t.type){case"session.init":{let n=t.info;return e.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}:{}})),e.updateSessionIdentity(n.sessionId),e.resolveInitialization(),null}case"session.status":return e.setSessionMetadata(n=>({...n,sessionId:t.sessionId,...t.permissionMode!==void 0?{permissionMode:t.permissionMode}:{permissionMode:n.permissionMode},...t.status!==void 0?{status:t.status}:{}})),null;case"delta.text":return{type:"chunk",chunk:{type:"content",content:t.text,metadata:{eventType:"delta",deltaType:"text_delta"}}};case"delta.reasoning":return{type:"chunk",chunk:{type:"thinking",content:t.text,metadata:{eventType:"delta",deltaType:"thinking_delta"}}};case"assistant.message":if(t.sessionId&&e.updateSessionIdentity(t.sessionId),t.text){let n={role:"assistant",content:t.text,timestamp:new Date};return e.conversationHistory.push(n),{type:"message",message:n}}return null;case"tool.use.start":return{type:"chunk",chunk:{type:"tool_use_detail",toolUseId:t.toolUseId,toolName:t.toolName,toolInput:t.toolInput}};case"tool.use":return{type:"chunk",chunk:{type:"tool_use",content:t.summary,metadata:{eventType:"tool_use_summary",precedingToolUseIds:t.toolUseIds}}};case"tool.output":return df(t);case"tool.diff":return{type:"chunk",chunk:{type:"tool_diff",toolUseId:t.toolUseId,diff:t.diff}};case"progress":return{type:"progress",progress:{taskId:t.progress.taskId,description:t.progress.description,...t.progress.summary!==void 0?{summary:t.progress.summary}:{},...t.progress.lastToolName!==void 0?{lastToolName:t.progress.lastToolName}:{},totalTokens:t.progress.totalTokens,toolUses:t.progress.toolUses,durationMs:t.progress.durationMs}};case"suggestion":return{type:"suggestion",suggestion:t.suggestion};case"turn.completed":{let n=lf(t.usage,t.sessionId??e.getSessionMetadata().sessionId);e.setLastResponseMetadata(n);for(let r=e.conversationHistory.length-1;r>=0;r--){let o=e.conversationHistory[r];if(o?.role==="assistant"){o.metadata=n;break}}if(e.maxBudgetUsd!==void 0&&e.abortBudget!==void 0&&typeof n.totalCostUsd=="number"&&(e._runningCostUsd=(e._runningCostUsd??0)+n.totalCostUsd,e._runningCostUsd>=e.maxBudgetUsd)){gr(e.traceWriter,{kind:"monetary",runningCostUsd:e._runningCostUsd,maxBudgetUsd:e.maxBudgetUsd,lastTurnCostUsd:n.totalCostUsd});let r=new Oe(e._runningCostUsd,e.maxBudgetUsd);return e.abortBudget(r.message),{type:"error",error:r}}return{type:"done",metadata:n}}case"error":return{type:"error",error:t.error};case"paused":return{type:"paused",reason:t.reason,...t.resetsAt!==void 0?{resetsAt:t.resetsAt}:{},...t.accountId!==void 0?{accountId:t.accountId}:{}};case"resumed":return{type:"resumed",hotSwapped:t.hotSwapped,...t.accountId!==void 0?{accountId:t.accountId}:{}};default:return null}}var Pe=class{config;currentState="idle";providerQuery;providerIterator;conversationHistory=[];turnCount=0;lastResponseMetadata=null;initPromise=null;inputStream;abortController;hookRegistry;sessionEndDispatched=!1;stateManager;sessionRunningCostUsd=0;sessionRunningTokens={input:0,output:0,cacheRead:0,cacheCreation:0};lastStopReason;constructor(e){this.config=e,this.abortController=new AbortController,this.hookRegistry=e.hookRegistry,Ei(e.abortSignal,this.abortController,()=>{this.onAbort()}),this.initSdkLifecycle()}initSdkLifecycle(){let e=at(this.config.model)??this.config.model,{sessionIdentity:n,metadata:r}=Ti(this.config,e);this.stateManager=new Xt(n,r),this.inputStream=new Yt(()=>this.sessionId);let o=this.config.provider??Vt(e);I(`\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.sessionRunningCostUsd=0,this.sessionRunningTokens={input:0,output:0,cacheRead:0,cacheCreation:0},this.lastStopReason=void 0,this.sessionEndDispatched=!1,this.currentState="idle";let s=this.providerQuery;this.providerIterator=s[Symbol.asyncIterator](),this.initPromise=this.pullInitialization()}async pullInitialization(){try{for(await vi(this.hookRegistry,{event:"SessionStart",sessionId:this.sessionId},{signal:this.abortController.signal,...this.config.traceWriter?{traceWriter:this.config.traceWriter}:{}});;){let e=await this.providerIterator.next();if(e.done){this.stateManager.resolveInitializationIfNeeded();return}let n=e.value,r=nr(n,this.buildTransformDeps());if(n.type==="session.init"||r&&r.type==="error")return}}catch(e){let n=e instanceof Error?e:new Error(String(e));this.stateManager.isInitializationSettled()||this.stateManager.rejectInitializationOnce(n),await this.dispatchSessionEndOnce("error").catch(()=>{})}}buildTransformDeps(){return{conversationHistory:this.conversationHistory,getSessionMetadata:()=>this.stateManager.getSessionMetadata(),setSessionMetadata:e=>this.stateManager.setSessionMetadata(e),updateSessionIdentity:e=>this.stateManager.updateSessionIdentity(e),resolveInitialization:()=>this.stateManager.resolveInitializationOnce(),setLastResponseMetadata:e=>{this.lastResponseMetadata=e,typeof e.totalCostUsd=="number"&&Number.isFinite(e.totalCostUsd)&&(this.sessionRunningCostUsd+=e.totalCostUsd);let n=e.usage;if(n&&typeof n=="object"){let r=n,o=(s,i)=>{let c=r[s];typeof c=="number"&&Number.isFinite(c)&&(this.sessionRunningTokens[i]+=c)};o("input_tokens","input"),o("output_tokens","output"),o("cache_read_input_tokens","cacheRead"),o("cache_creation_input_tokens","cacheCreation")}typeof e.stopReason=="string"&&(this.lastStopReason=e.stopReason)},maxBudgetUsd:this.config.maxBudgetUsd,abortBudget:e=>{this.abortController.signal.aborted||this.abortController.abort(e)},...this.config.traceWriter?{traceWriter:this.config.traceWriter}:{}}}get state(){return this.currentState}get sessionId(){return this.stateManager.getSessionId()}get cwd(){return this.config.cwd}get abortSignal(){return this.abortController.signal}async sendMessage(e,n={}){this.assertCanSend();let r=this.config.timeoutMs??Ve,o=async()=>{let s=null,i="";this.currentState=n.stream?"streaming":"processing";for await(let c of this.sendMessageStreamInternal(e)){if(c.type==="chunk"&&c.chunk.type==="content"&&(i+=c.chunk.content),c.type==="message"&&c.message.role==="assistant"&&(s=c.message),c.type==="error")throw c.error;if(c.type==="done"){if(s)return{...s,metadata:c.metadata};if(i)return{role:"assistant",content:i,metadata:c.metadata,timestamp:new Date}}}if(s)return s;if(i)return{role:"assistant",content:i,timestamp:new Date};throw new Error("No assistant response received")};try{return await Je(o(),r,{controller:this.abortController,label:this.sessionId??"session"})}finally{this.currentState==="processing"&&(this.currentState="idle")}}async*sendMessageStream(e){this.assertCanSend(),this.currentState="streaming";try{yield*this.sendMessageStreamInternal(e)}finally{this.currentState==="streaming"&&(this.currentState="idle")}}async*sendMessageStreamInternal(e){this.initPromise&&await this.initPromise;let r={role:"user",content:typeof e=="string"?e:this.summarizeContentBlocks(e),timestamp:new Date};this.conversationHistory.push(r),this.inputStream.pushUserMessage(e);let o=this.buildTransformDeps();try{for(;;){let s=await this.providerIterator.next();if(s.done)break;let i=s.value,c=nr(i,o);if(c&&(c.type==="done"&&this.turnCount++,yield c,c.type==="done"||c.type==="error"))break}}finally{this.currentState==="streaming"&&(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 te("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{}await this.providerIterator.return?.(),this.initPromise&&await Promise.race([this.initPromise,new Promise(e=>setTimeout(e,yt))]).catch(()=>{}),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=at(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}))}setCwd(e){this.config={...this.config,cwd:e},this.providerQuery.setCwd?.(e)}async reauth(){return await this.providerQuery.reauth?.()??null}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(){throw new Error("getOutputStream() is not supported \u2014 use sendMessageStream() instead")}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{await this.providerQuery.close()}catch{}if(await this.providerIterator.return?.(),this.initPromise)try{await Promise.race([this.initPromise,new Promise(e=>setTimeout(e,yt))])}catch{}await this.dispatchSessionEndOnce("close")}}async dispatchSessionEndOnce(e){this.sessionEndDispatched||(this.sessionEndDispatched=!0,await this.emitClosure(e).catch(()=>{}),await this.sealTraceWriter(e).catch(()=>{}),await Si(this.hookRegistry,{event:"SessionEnd",sessionId:this.sessionId,reason:e},this.config.traceWriter?{traceWriter:this.config.traceWriter}:{}))}async emitClosure(e){let n=this.config.traceWriter;if(!n)return;let r=this.deriveClosureReason(e),o={};this.sessionRunningTokens.input>0&&(o.input=this.sessionRunningTokens.input),this.sessionRunningTokens.output>0&&(o.output=this.sessionRunningTokens.output),this.sessionRunningTokens.cacheRead>0&&(o.cacheRead=this.sessionRunningTokens.cacheRead),this.sessionRunningTokens.cacheCreation>0&&(o.cacheCreation=this.sessionRunningTokens.cacheCreation),await br(n,{reason:r,finalTurnCount:this.turnCount,finalCostUsd:this.sessionRunningCostUsd,finalTokens:o,...this.lastStopReason!==void 0?{lastStopReason:this.lastStopReason}:{}})}deriveClosureReason(e){if(e==="error")return"abort";let n=this.abortController.signal;if(n.aborted&&n.reason!=="closed"){let r=n.reason;if(r instanceof Oe)return"budget_exceeded";if(r instanceof fe)return"timeout";if(typeof r=="string"){if(r.startsWith("Budget "))return"budget_exceeded";if(r.includes("timed out"))return"timeout"}return"abort"}return"model_end_turn"}async sealTraceWriter(e){let n=this.config.traceWriter;if(!n)return;let r=this.deriveSealStatus(e);await n.seal({status:r,finalCostUsd:this.sessionRunningCostUsd,finalTurnCount:this.turnCount,closedAt:new Date().toISOString()})}deriveSealStatus(e){if(e==="error")return"failed";let n=this.abortController.signal;return n.aborted&&n.reason!=="closed"?"cancelled":"succeeded"}assertCanSend(){if(this.currentState==="closed")throw new Error("Cannot send message: session is closed");if(this.abortController.signal.aborted)throw new te("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`)}};function uf(t){let e=new Map,n=t.defaultMode??"ask";if(t.tools)for(let[r,o]of Object.entries(t.tools))typeof o=="string"?e.set(r,{mode:o}):e.set(r,{mode:o.mode,reason:o.reason});if(t.list)for(let r of t.list)e.set(r.tool,{mode:r.mode,reason:r.reason});return{defaultMode:n,byTool:e}}function pf(t){return t.behavior==="allow"?{behavior:"allow"}:{behavior:"deny",message:t.reason??"Tool denied by permission rules"}}function Ii(t){let{defaultMode:e,byTool:n}=uf(t.rules);return async(r,o)=>{let s={toolName:r,input:o},i=n.get(r),c=i?.mode??e,a=i?.reason,l;return c==="ask"&&t.onAsk?l=await t.onAsk(s):c==="deny"?l={behavior:"deny",reason:a}:l={behavior:"allow"},t.onDecision?.(s,l),pf(l)}}import{Telegraf as Qf}from"telegraf";import{promises as ct}from"fs";import{join as Ci}from"path";var Be=class{sessions=new Map;pendingSessions=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,botCwd:e.botCwd,createSession:e.createSession}}getSessionIfExists(e){return this.sessions.get(e)}async getSession(e){let n=this.sessions.get(e);if(n)return this._touchActivity(e),n;let r=this.pendingSessions.get(e);if(r)try{return await r}finally{this._touchActivity(e)}let o=this.sessionData.get(e)??{chatId:e,model:this.options.defaultModel,createdAt:new Date().toISOString(),lastActivity:new Date().toISOString()},s=(async()=>{let i={model:o.model,apiKey:this.options.apiKey};this.options.settingSources?.length&&(i.settingSources=this.options.settingSources),this.options.thinking!==void 0&&(i.thinking=this.options.thinking),this.options.effort!==void 0&&(i.effort=this.options.effort);let c=o.cwd??this.options.botCwd;c!==void 0&&c.length>0&&(i.cwd=c);let a=await this.options.createSession(Nn(i));return this.sessions.set(e,a),this.sessionData.set(e,o),a})();this.pendingSessions.set(e,s);try{let i=await s;return this._touchActivity(e),i}finally{this.pendingSessions.delete(e)}}_touchActivity(e){let n=this.sessionData.get(e);n&&(n.lastActivity=new Date().toISOString())}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 setCwd(e,n){let r=this.sessions.get(e);r&&(await r.close(),this.sessions.delete(e));let o=this.sessionData.get(e);o?(o.cwd=n,o.lastActivity=new Date().toISOString()):(o={chatId:e,model:this.options.defaultModel,createdAt:new Date().toISOString(),lastActivity:new Date().toISOString(),cwd:n},this.sessionData.set(e,o))}getCwd(e){return this.sessionData.get(e)?.cwd??this.options.botCwd}async loadSessions(){try{await ct.mkdir(this.options.dataDir,{recursive:!0});let e=await ct.readdir(this.options.dataDir);for(let n of e)if(n.endsWith(".json")){let r=Ci(this.options.dataDir,n),o=await ct.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 ct.mkdir(this.options.dataDir,{recursive:!0});for(let[e,n]of this.sessionData.entries()){let r=Ci(this.options.dataDir,`${e}.json`);await ct.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 lt(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(`
|
|
1582
|
+
`);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 lf(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 df(t){let e=t.isError===!0?null:Pi(t.toolName,t.content),n=e!==null?{display:e}:{},r=sf(t.content);if(r)return{type:"chunk",chunk:{type:"tool_result",toolUseId:t.toolUseId,content:`Output persisted (${r.sizeLabel}) \u2192 ${r.absolutePath}`,isError:t.isError===!0,persistedPath:r.absolutePath,sizeBytes:r.sizeBytes,sizeLabel:r.sizeLabel,...n}};let{content:o,truncated:s,lineCount:i,sizeBytes:c,sizeLabel:a}=cf(t.content);return{type:"chunk",chunk:{type:"tool_result",toolUseId:t.toolUseId,content:o,isError:t.isError===!0,sizeBytes:c,sizeLabel:a,...s&&{truncated:s},...i!==void 0&&{lineCount:i},...n}}}function nr(t,e){switch(t.type){case"session.init":{let n=t.info;return e.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}:{}})),e.updateSessionIdentity(n.sessionId),e.resolveInitialization(),null}case"session.status":return e.setSessionMetadata(n=>({...n,sessionId:t.sessionId,...t.permissionMode!==void 0?{permissionMode:t.permissionMode}:{permissionMode:n.permissionMode},...t.status!==void 0?{status:t.status}:{}})),null;case"delta.text":return{type:"chunk",chunk:{type:"content",content:t.text,metadata:{eventType:"delta",deltaType:"text_delta"}}};case"delta.reasoning":return{type:"chunk",chunk:{type:"thinking",content:t.text,metadata:{eventType:"delta",deltaType:"thinking_delta"}}};case"assistant.message":if(t.sessionId&&e.updateSessionIdentity(t.sessionId),t.text){let n={role:"assistant",content:t.text,timestamp:new Date};return e.conversationHistory.push(n),{type:"message",message:n}}return null;case"tool.use.start":return{type:"chunk",chunk:{type:"tool_use_detail",toolUseId:t.toolUseId,toolName:t.toolName,toolInput:t.toolInput}};case"tool.use":return{type:"chunk",chunk:{type:"tool_use",content:t.summary,metadata:{eventType:"tool_use_summary",precedingToolUseIds:t.toolUseIds}}};case"tool.output":return df(t);case"tool.diff":return{type:"chunk",chunk:{type:"tool_diff",toolUseId:t.toolUseId,diff:t.diff}};case"progress":return{type:"progress",progress:{taskId:t.progress.taskId,description:t.progress.description,...t.progress.summary!==void 0?{summary:t.progress.summary}:{},...t.progress.lastToolName!==void 0?{lastToolName:t.progress.lastToolName}:{},totalTokens:t.progress.totalTokens,toolUses:t.progress.toolUses,durationMs:t.progress.durationMs}};case"suggestion":return{type:"suggestion",suggestion:t.suggestion};case"turn.completed":{let n=lf(t.usage,t.sessionId??e.getSessionMetadata().sessionId);e.setLastResponseMetadata(n);for(let r=e.conversationHistory.length-1;r>=0;r--){let o=e.conversationHistory[r];if(o?.role==="assistant"){o.metadata=n;break}}if(e.maxBudgetUsd!==void 0&&e.abortBudget!==void 0&&typeof n.totalCostUsd=="number"&&(e._runningCostUsd=(e._runningCostUsd??0)+n.totalCostUsd,e._runningCostUsd>=e.maxBudgetUsd)){gr(e.traceWriter,{kind:"monetary",runningCostUsd:e._runningCostUsd,maxBudgetUsd:e.maxBudgetUsd,lastTurnCostUsd:n.totalCostUsd});let r=new Oe(e._runningCostUsd,e.maxBudgetUsd);return e.abortBudget(r.message),{type:"error",error:r}}return{type:"done",metadata:n}}case"error":return{type:"error",error:t.error};case"paused":return{type:"paused",reason:t.reason,...t.resetsAt!==void 0?{resetsAt:t.resetsAt}:{},...t.accountId!==void 0?{accountId:t.accountId}:{}};case"resumed":return{type:"resumed",hotSwapped:t.hotSwapped,...t.accountId!==void 0?{accountId:t.accountId}:{}};default:return null}}var Pe=class{config;currentState="idle";providerQuery;providerIterator;conversationHistory=[];turnCount=0;lastResponseMetadata=null;initPromise=null;inputStream;abortController;hookRegistry;sessionEndDispatched=!1;stateManager;sessionRunningCostUsd=0;sessionRunningTokens={input:0,output:0,cacheRead:0,cacheCreation:0};lastStopReason;constructor(e){this.config=e,this.abortController=new AbortController,this.hookRegistry=e.hookRegistry,Ei(e.abortSignal,this.abortController,()=>{this.onAbort()}),this.initSdkLifecycle()}initSdkLifecycle(){let e=at(this.config.model)??this.config.model,{sessionIdentity:n,metadata:r}=Ti(this.config,e);this.stateManager=new Xt(n,r),this.inputStream=new Yt(()=>this.sessionId);let o=this.config.provider??Vt(e);I(`\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.sessionRunningCostUsd=0,this.sessionRunningTokens={input:0,output:0,cacheRead:0,cacheCreation:0},this.lastStopReason=void 0,this.sessionEndDispatched=!1,this.currentState="idle";let s=this.providerQuery;this.providerIterator=s[Symbol.asyncIterator](),this.initPromise=this.pullInitialization()}async pullInitialization(){try{for(await vi(this.hookRegistry,{event:"SessionStart",sessionId:this.sessionId},{signal:this.abortController.signal,...this.config.traceWriter?{traceWriter:this.config.traceWriter}:{}});;){let e=await this.providerIterator.next();if(e.done){this.stateManager.resolveInitializationIfNeeded();return}let n=e.value,r=nr(n,this.buildTransformDeps());if(n.type==="session.init"||r&&r.type==="error")return}}catch(e){let n=e instanceof Error?e:new Error(String(e));this.stateManager.isInitializationSettled()||this.stateManager.rejectInitializationOnce(n),await this.dispatchSessionEndOnce("error").catch(()=>{})}}buildTransformDeps(){return{conversationHistory:this.conversationHistory,getSessionMetadata:()=>this.stateManager.getSessionMetadata(),setSessionMetadata:e=>this.stateManager.setSessionMetadata(e),updateSessionIdentity:e=>this.stateManager.updateSessionIdentity(e),resolveInitialization:()=>this.stateManager.resolveInitializationOnce(),setLastResponseMetadata:e=>{this.lastResponseMetadata=e,typeof e.totalCostUsd=="number"&&Number.isFinite(e.totalCostUsd)&&(this.sessionRunningCostUsd+=e.totalCostUsd);let n=e.usage;if(n&&typeof n=="object"){let r=n,o=(s,i)=>{let c=r[s];typeof c=="number"&&Number.isFinite(c)&&(this.sessionRunningTokens[i]+=c)};o("input_tokens","input"),o("output_tokens","output"),o("cache_read_input_tokens","cacheRead"),o("cache_creation_input_tokens","cacheCreation")}typeof e.stopReason=="string"&&(this.lastStopReason=e.stopReason)},maxBudgetUsd:this.config.maxBudgetUsd,abortBudget:e=>{this.abortController.signal.aborted||this.abortController.abort(e)},...this.config.traceWriter?{traceWriter:this.config.traceWriter}:{}}}get state(){return this.currentState}get sessionId(){return this.stateManager.getSessionId()}get cwd(){return this.config.cwd}get abortSignal(){return this.abortController.signal}async sendMessage(e,n={}){this.assertCanSend();let r=this.config.timeoutMs??Ve,o=async()=>{let s=null,i="";this.currentState=n.stream?"streaming":"processing";for await(let c of this.sendMessageStreamInternal(e)){if(c.type==="chunk"&&c.chunk.type==="content"&&(i+=c.chunk.content),c.type==="message"&&c.message.role==="assistant"&&(s=c.message),c.type==="error")throw c.error;if(c.type==="done"){if(s)return{...s,metadata:c.metadata};if(i)return{role:"assistant",content:i,metadata:c.metadata,timestamp:new Date}}}if(s)return s;if(i)return{role:"assistant",content:i,timestamp:new Date};throw new Error("No assistant response received")};try{return await Je(o(),r,{controller:this.abortController,label:this.sessionId??"session"})}finally{this.currentState==="processing"&&(this.currentState="idle")}}async*sendMessageStream(e){this.assertCanSend(),this.currentState="streaming";try{yield*this.sendMessageStreamInternal(e)}finally{this.currentState==="streaming"&&(this.currentState="idle")}}async*sendMessageStreamInternal(e){this.initPromise&&await this.initPromise;let r={role:"user",content:typeof e=="string"?e:this.summarizeContentBlocks(e),timestamp:new Date};this.conversationHistory.push(r),this.inputStream.pushUserMessage(e);let o=this.buildTransformDeps();try{for(;;){let s=await this.providerIterator.next();if(s.done)break;let i=s.value,c=nr(i,o);if(c&&(c.type==="done"&&this.turnCount++,yield c,c.type==="done"||c.type==="error"))break}}finally{this.currentState==="streaming"&&(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 te("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{}await this.providerIterator.return?.(),this.initPromise&&await Promise.race([this.initPromise,new Promise(e=>setTimeout(e,yt))]).catch(()=>{}),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=at(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}))}setCwd(e){this.config={...this.config,cwd:e},this.providerQuery.setCwd?.(e)}async reauth(){return await this.providerQuery.reauth?.()??null}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(){throw new Error("getOutputStream() is not supported \u2014 use sendMessageStream() instead")}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{await this.providerQuery.close()}catch{}if(await this.providerIterator.return?.(),this.initPromise)try{await Promise.race([this.initPromise,new Promise(e=>setTimeout(e,yt))])}catch{}await this.dispatchSessionEndOnce("close")}}async dispatchSessionEndOnce(e){this.sessionEndDispatched||(this.sessionEndDispatched=!0,await this.emitClosure(e).catch(()=>{}),await this.sealTraceWriter(e).catch(()=>{}),await Si(this.hookRegistry,{event:"SessionEnd",sessionId:this.sessionId,reason:e},this.config.traceWriter?{traceWriter:this.config.traceWriter}:{}))}async emitClosure(e){let n=this.config.traceWriter;if(!n)return;let r=this.deriveClosureReason(e),o={};this.sessionRunningTokens.input>0&&(o.input=this.sessionRunningTokens.input),this.sessionRunningTokens.output>0&&(o.output=this.sessionRunningTokens.output),this.sessionRunningTokens.cacheRead>0&&(o.cacheRead=this.sessionRunningTokens.cacheRead),this.sessionRunningTokens.cacheCreation>0&&(o.cacheCreation=this.sessionRunningTokens.cacheCreation),await br(n,{reason:r,finalTurnCount:this.turnCount,finalCostUsd:this.sessionRunningCostUsd,finalTokens:o,...this.lastStopReason!==void 0?{lastStopReason:this.lastStopReason}:{}})}deriveClosureReason(e){if(e==="error")return"abort";let n=this.abortController.signal;if(n.aborted&&n.reason!=="closed"){let r=n.reason;if(r instanceof Oe)return"budget_exceeded";if(r instanceof fe)return"timeout";if(typeof r=="string"){if(r.startsWith("Budget "))return"budget_exceeded";if(r.includes("timed out"))return"timeout"}return"abort"}return"model_end_turn"}async sealTraceWriter(e){let n=this.config.traceWriter;if(!n)return;let r=this.deriveSealStatus(e);await n.seal({status:r,finalCostUsd:this.sessionRunningCostUsd,finalTurnCount:this.turnCount,closedAt:new Date().toISOString()})}deriveSealStatus(e){if(e==="error")return"failed";let n=this.abortController.signal;return n.aborted&&n.reason!=="closed"?"cancelled":"succeeded"}assertCanSend(){if(this.currentState==="closed")throw new Error("Cannot send message: session is closed");if(this.abortController.signal.aborted)throw new te("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`)}};function uf(t){let e=new Map,n=t.defaultMode??"ask";if(t.tools)for(let[r,o]of Object.entries(t.tools))typeof o=="string"?e.set(r,{mode:o}):e.set(r,{mode:o.mode,reason:o.reason});if(t.list)for(let r of t.list)e.set(r.tool,{mode:r.mode,reason:r.reason});return{defaultMode:n,byTool:e}}function pf(t){return t.behavior==="allow"?{behavior:"allow"}:{behavior:"deny",message:t.reason??"Tool denied by permission rules"}}function Ii(t){let{defaultMode:e,byTool:n}=uf(t.rules);return async(r,o)=>{let s={toolName:r,input:o},i=n.get(r),c=i?.mode??e,a=i?.reason,l;return c==="ask"&&t.onAsk?l=await t.onAsk(s):c==="deny"?l={behavior:"deny",reason:a}:l={behavior:"allow"},t.onDecision?.(s,l),pf(l)}}import{Telegraf as Zf}from"telegraf";import{promises as ct}from"fs";import{join as Ci}from"path";var Be=class{sessions=new Map;pendingSessions=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,botCwd:e.botCwd,createSession:e.createSession}}getSessionIfExists(e){return this.sessions.get(e)}async getSession(e){let n=this.sessions.get(e);if(n)return this._touchActivity(e),n;let r=this.pendingSessions.get(e);if(r)try{return await r}finally{this._touchActivity(e)}let o=this.sessionData.get(e)??{chatId:e,model:this.options.defaultModel,createdAt:new Date().toISOString(),lastActivity:new Date().toISOString()},s=(async()=>{let i={model:o.model,apiKey:this.options.apiKey};this.options.settingSources?.length&&(i.settingSources=this.options.settingSources),this.options.thinking!==void 0&&(i.thinking=this.options.thinking),this.options.effort!==void 0&&(i.effort=this.options.effort);let c=o.cwd??this.options.botCwd;c!==void 0&&c.length>0&&(i.cwd=c);let a=await this.options.createSession(Nn(i));return this.sessions.set(e,a),this.sessionData.set(e,o),a})();this.pendingSessions.set(e,s);try{let i=await s;return this._touchActivity(e),i}finally{this.pendingSessions.delete(e)}}_touchActivity(e){let n=this.sessionData.get(e);n&&(n.lastActivity=new Date().toISOString())}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 setCwd(e,n){let r=this.sessions.get(e);r&&(await r.close(),this.sessions.delete(e));let o=this.sessionData.get(e);o?(o.cwd=n,o.lastActivity=new Date().toISOString()):(o={chatId:e,model:this.options.defaultModel,createdAt:new Date().toISOString(),lastActivity:new Date().toISOString(),cwd:n},this.sessionData.set(e,o))}getCwd(e){return this.sessionData.get(e)?.cwd??this.options.botCwd}async loadSessions(){try{await ct.mkdir(this.options.dataDir,{recursive:!0});let e=await ct.readdir(this.options.dataDir);for(let n of e)if(n.endsWith(".json")){let r=Ci(this.options.dataDir,n),o=await ct.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 ct.mkdir(this.options.dataDir,{recursive:!0});for(let[e,n]of this.sessionData.entries()){let r=Ci(this.options.dataDir,`${e}.json`);await ct.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 lt(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(`
|
|
1583
1583
|
`,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 c=i[i.length-1];if(c){let a=r.lastIndexOf(c,e);a>e-200&&a>0&&(o=a+2)}}else{let c=r.lastIndexOf(" ",e);c>e-100&&c>0&&(o=c+1)}}n.push(r.slice(0,o).trim()),r=r.slice(o).trim()}return n}function Qt(t){t=t.replace(/[\x02\x03]/g,"");let e=t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"),n=[];e=e.replace(/^ {0,3}```([\w]*)\n([\s\S]*?)```/gm,(o,s,i)=>{let c=n.length;return n.push(`<pre>${i}</pre>`),`FENCED${c}`});let r=[];return e=e.replace(/`([^`]+)`/g,(o,s)=>{let i=r.length;return r.push(`<code>${s}</code>`),`CODE${i}`}),e=e.replace(/\*\*([^*]+)\*\*/g,"<b>$1</b>"),e=e.replace(/__([^_]+)__/g,"<b>$1</b>"),e=e.replace(/\*([^*]+)\*/g,"<i>$1</i>"),e=e.replace(/(^|[^\w])_([^_\n]+?)_(?!\w)/gm,"$1<i>$2</i>"),e=e.replace(/~~([^~]+)~~/g,"<s>$1</s>"),e=e.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(o,s,i)=>'<a href="'+i.replace(/"/g,""")+'">'+s+"</a>"),e=e.replace(/^#{1,6}\s+/gm,""),e=e.replace(/\x02CODE(\d+)\x03/g,(o,s)=>r[Number(s)]??o),e=e.replace(/\x02FENCED(\d+)\x03/g,(o,s)=>n[Number(s)]??o),e}function N(t){return`\u274C Error: ${t instanceof Error?t.message:t}`}function Zt(){return"\u26A0\uFE0F An internal error occurred. Please try again."}var Mi=[{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"},{cmd:"/cd [path]",desc:"Show or change the session working directory"}];function Oi(t){let e=["\u{1F4CB} Bot commands (aligned with agent-afk CLI):","",...Mi.map(n=>` ${n.cmd}
|
|
1584
1584
|
${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(`
|
|
1585
1585
|
`)}function rr(){return`\u{1F44B} Welcome to Agent AFK Bot!
|
|
@@ -1599,7 +1599,7 @@ Usage: /cd <path>`}function Fi(t){return`\u{1F4C2} cwd set to: ${t}
|
|
|
1599
1599
|
Next message starts a fresh session in this directory.`}function sr(t){if(!t)return"\u{1F4E6} Conversation compacted (older messages summarized).";let e=t.tokensSavedEstimate!==void 0&&t.tokensSavedEstimate>0?` (~${mf(t.tokensSavedEstimate)} input tokens saved)`:"";return`\u{1F4E6} Compacted ${t.before} \u2192 ${t.after} messages${e}.`}function ir(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 mf(t){return t>=1e3?`${Math.round(t/100)/10}k`:String(t)}async function ar(t){await t.reply(rr())}async function cr(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,c)=>setTimeout(()=>c(new Error("timeout")),2e3))]);let s=o.getSessionMetadata();s.slashCommands?.length&&(r=s.slashCommands)}catch{}await t.reply(Oi(r))}import{promises as gf}from"fs";import{homedir as Li}from"os";import{isAbsolute as hf,resolve as lr}from"path";async function dr(t,e,n,r){let o=t.chat?.id;if(!o){await t.reply(N("Could not identify chat"));return}try{await e.resetSession(o),n.delete(o),await t.reply(dt())}catch(s){r("Clear error:",s),await t.reply(N(s))}}async function Ni(t,e,n){let r=t.chat?.id;if(!r){await t.reply(N("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(sr({before:s.messagesBefore,after:s.messagesAfter,...s.tokensSavedEstimate!==void 0?{tokensSavedEstimate:s.tokensSavedEstimate}:{}})):await t.reply(ir(s.reason??"unknown"))}catch(o){n("Compact error:",o),await t.reply(N(o))}}async function ur(t,e,n){let r=t.chat?.id;if(!r){await t.reply(N("Could not identify chat"));return}let s=t.message.text.split(/\s+/).slice(1);if(s.length===0){let u=e.getModel(r);await t.reply(`Current model: ${u.toUpperCase()}
|
|
1600
1600
|
|
|
1601
1601
|
Usage: /model [opus|opus_1m|sonnet|sonnet_1m|haiku] or org/model HF id`);return}let i=s[0];if(!i){await t.reply(N("Please specify a model: opus, opus_1m, sonnet, sonnet_1m, haiku, or an org/model id"));return}let c=["opus","opus_1m","sonnet","sonnet_1m","haiku"],a=i.toLowerCase(),l=c.includes(a),d=Ie(a)==="openai-compatible";if(!l&&!d){await t.reply(N(`Invalid model: ${i}
|
|
1602
|
-
Aliases: ${c.join(", ")}, or org/model HF id`));return}try{await e.switchModel(r,a),await t.reply(or(a))}catch(u){n("Model switch error:",u),await t.reply(N(u))}}function yf(t,e){let n=t.trim();return n==="~"?Li():n.startsWith("~/")?lr(Li(),n.slice(2)):hf(n)?lr(n):lr(e,n)}async function Ui(t,e,n){let r=t.chat?.id;if(!r){await t.reply(N("Could not identify chat"));return}let s=t.message.text.split(/\s+/).slice(1).filter(l=>l.length>0);if(s.length===0){let l=e.getCwd(r);await t.reply(Di(l));return}let i=s[0];if(!i){await t.reply(N("Please specify a directory path"));return}let c=e.getCwd(r)??process.cwd(),a=yf(i,c);try{if(!(await gf.stat(a)).isDirectory()){await t.reply(N(`Not a directory: ${a}`));return}}catch(l){let d=l.code;d==="ENOENT"?await t.reply(N(`Directory does not exist: ${a}`)):d==="EACCES"?await t.reply(N(`Permission denied: ${a}`)):(n("cwd stat error:",l),await t.reply(N(l)));return}try{await e.setCwd(r,a),await t.reply(Fi(a))}catch(l){n("Cwd switch error:",l),await t.reply(N(l))}}import{execFile as Ff,spawn as Lf}from"node:child_process";import{promisify as Nf}from"node:util";import{execFile as bf}from"node:child_process";import{randomBytes as wf}from"node:crypto";import{promises as en}from"node:fs";import{join as tn}from"node:path";import{promisify as kf}from"node:util";var
|
|
1602
|
+
Aliases: ${c.join(", ")}, or org/model HF id`));return}try{await e.switchModel(r,a),await t.reply(or(a))}catch(u){n("Model switch error:",u),await t.reply(N(u))}}function yf(t,e){let n=t.trim();return n==="~"?Li():n.startsWith("~/")?lr(Li(),n.slice(2)):hf(n)?lr(n):lr(e,n)}async function Ui(t,e,n){let r=t.chat?.id;if(!r){await t.reply(N("Could not identify chat"));return}let s=t.message.text.split(/\s+/).slice(1).filter(l=>l.length>0);if(s.length===0){let l=e.getCwd(r);await t.reply(Di(l));return}let i=s[0];if(!i){await t.reply(N("Please specify a directory path"));return}let c=e.getCwd(r)??process.cwd(),a=yf(i,c);try{if(!(await gf.stat(a)).isDirectory()){await t.reply(N(`Not a directory: ${a}`));return}}catch(l){let d=l.code;d==="ENOENT"?await t.reply(N(`Directory does not exist: ${a}`)):d==="EACCES"?await t.reply(N(`Permission denied: ${a}`)):(n("cwd stat error:",l),await t.reply(N(l)));return}try{await e.setCwd(r,a),await t.reply(Fi(a))}catch(l){n("Cwd switch error:",l),await t.reply(N(l))}}import{execFile as Ff,spawn as Lf}from"node:child_process";import{promisify as Nf}from"node:util";import{execFile as bf}from"node:child_process";import{randomBytes as wf}from"node:crypto";import{promises as en}from"node:fs";import{join as tn}from"node:path";import{promisify as kf}from"node:util";var zT=kf(bf);var Se=class extends Error{cause;code;constructor(e,n,r){super(e),this.name="WorktreeError",this.cause=n,this.code=r}};function vf(t,e=40){return t.toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,e).replace(/-+$/g,"")||"task"}function Sf(){return wf(4).toString("hex").slice(0,4)}function Ef(t){let e=n=>String(n).padStart(2,"0");return`${t.getUTCFullYear()}${e(t.getUTCMonth()+1)}${e(t.getUTCDate())}T${e(t.getUTCHours())}${e(t.getUTCMinutes())}${e(t.getUTCSeconds())}`}function $i(t,e={}){let n=(e.now??(()=>new Date))(),r=(e.randomSuffix??Sf)();return`${Ef(n)}-${vf(t,32)}-${r}`}function Tf(t){let e=t;return e.respawnedAt===void 0&&(e.respawnedAt=void 0),e.respawnedAs===void 0&&(e.respawnedAs=void 0),e.prUrl===void 0&&(e.prUrl=void 0),e.prCreatedAt===void 0&&(e.prCreatedAt=void 0),e}async function We(t){let e=tn(Ur(t),"farm.json");try{let n=await en.readFile(e,"utf8"),r=JSON.parse(n);if(r.schemaVersion!==1&&r.schemaVersion!==2&&r.schemaVersion!==3)throw new Se(`unsupported farm manifest schema: ${r.schemaVersion} (expected 1, 2, or 3)`,void 0,"unsupported-schema");return Tf(r)}catch(n){if(n.code==="ENOENT")return null;throw n instanceof Se?n:new Se(`failed to load farm manifest ${e}`,n,"invalid")}}async function Hi(t,e){let n=await We(t);if(!n)throw new Se(`farm not found: ${t}`);return n.human_decision=e,n.decidedAt=new Date().toISOString(),n.schemaVersion=3,await en.writeFile(tn(n.farmDir,"farm.json"),JSON.stringify(n,null,2)+`
|
|
1603
1603
|
`,"utf8"),n}async function ji(t,e){let n=await We(t);if(!n)throw new Se(`farm not found: ${t}`);return n.respawnedAt=new Date().toISOString(),n.respawnedAs=e,n.schemaVersion=3,await en.writeFile(tn(n.farmDir,"farm.json"),JSON.stringify(n,null,2)+`
|
|
1604
1604
|
`,"utf8"),n}async function Bi(t,e){let n=await We(t);if(!n)throw new Se(`farm not found: ${t}`);return n.prUrl=e,n.prCreatedAt=new Date().toISOString(),n.schemaVersion=3,await en.writeFile(tn(n.farmDir,"farm.json"),JSON.stringify(n,null,2)+`
|
|
1605
1605
|
`,"utf8"),n}import{execFile as _f}from"node:child_process";import{promisify as Af}from"node:util";var xf=Af(_f),Rf=2e4,pt=class extends Error{kind;exitCode;stderr;constructor(e,n,r,o){super(e),this.name="GhError",this.kind=n,this.exitCode=r,this.stderr=o}},nn=null,ut=null;function Pf(t,e,n){return n===!0?"timeout":e==="ENOENT"?"not-found":/already exists/i.test(t)?"already-exists":/authentication|please log in|HTTP 40[13]|bad credentials|token|scope/i.test(t)?"unauthed":/ETIMEDOUT|ECONNRESET|ECONNREFUSED/i.test(t+(e??""))?"network":"unknown"}function Wi(t,e){return xf(t,e,{timeout:Rf,killSignal:"SIGTERM"}).then(n=>({stdout:n.stdout,stderr:n.stderr}))}async function Ki(t={}){let e=(t._now??(()=>Date.now()))(),n=t.ttlMs??6e4,r=t.execFn??Wi,o=t.log??(()=>{});return nn&&nn.expiresAt>e?(o("[gh] checkGhReady cache hit"),nn.result):(o("[gh] checkGhReady cache miss \u2014 probing"),ut||(ut=(async()=>{try{await r("gh",["--version"])}catch(c){let a=c;return a.killed?{ok:!1,hint:"`gh` timed out \u2014 check connectivity"}:a.code==="ENOENT"?{ok:!1,hint:"`gh` CLI not found \u2014 install with: brew install gh"}:{ok:!1,hint:"`gh --version` failed unexpectedly \u2014 check gh installation"}}try{await r("gh",["auth","status"])}catch(c){let a=c;return a.killed||/ETIMEDOUT|ECONNRESET|ENOTFOUND/i.test(String(a.code??""))?{ok:!1,hint:"check network \u2014 cannot reach GitHub"}:{ok:!1,hint:"`gh` is not authenticated \u2014 run: gh auth login"}}let i={ok:!0};return n>0&&(nn={result:i,expiresAt:e+n}),i})().finally(()=>{ut=null}),ut))}async function Gi(t,e){let n=e??Wi,r=["pr","create","--base",t.base,"--head",t.head,"--title",t.title,"--body",t.body];try{let{stdout:o}=await n("gh",r);return o.trim()}catch(o){let s=o,i=s.stderr??"",c=s.code,a=s.exitCode??1,l=Pf(i,c,s.killed);throw new pt(`gh pr create failed (${l}): ${i.trim()}`,l,a,i)}}function qi(t,e){let n;try{n=e?._store??new de}catch(r){return{skipped:!0,reason:r instanceof Error?r.message:String(r)}}try{let r={type:"farm-decision",taskSlug:t.taskSlug,decision:t.decision,decidedAt:t.decidedAt,via:t.via};return{factId:n.storeFact({category:"decision",content:JSON.stringify(r),source_surface:"afk"})}}catch(r){return{skipped:!0,reason:r instanceof Error?r.message:String(r)}}}import{promises as If}from"node:fs";import{join as Cf}from"node:path";function Ji(t){let e=t.filter(r=>r.score!==null),n=t.filter(r=>r.score===null).map(r=>r.index).sort((r,o)=>r-o);return e.sort((r,o)=>{let s=r.score,i=o.score,c=zi(s),a=zi(i);if(c!==a)return a-c;let l=Vi(s.lint_ok),d=Vi(i.lint_ok);return l!==d?d-l:s.loc_delta!==i.loc_delta?s.loc_delta-i.loc_delta:r.index-o.index}),[...e.map(r=>r.index),...n]}function zi(t){let e=t.pass+t.fail;return e===0?0:t.pass/e}function Vi(t){return t===!0?2:t===!1?1:0}async function rn(t,e={}){if(t.branches.length===0)throw new Error(`resolveWinnerBranch: farm ${t.taskSlug} has no branches`);let n=e.loadScore??Mf,r=await Promise.all(t.branches.map(async i=>({index:i.index,score:await n(t.farmDir,i.index)}))),o=Ji(r),s=new Map(t.branches.map(i=>[i.index,i]));for(let i of o){let c=r.find(a=>a.index===i)?.score;if(c&&c.pass>0&&c.fail===0){let a=s.get(i);if(a)return{branch:a,source:"winner"}}}for(let i of o)if(r.find(a=>a.index===i)?.score){let a=s.get(i);if(a)return{branch:a,source:"top-scored"}}return{branch:t.branches[0],source:"fallback-first-branch"}}async function Mf(t,e){let n=Cf(t,"scores",`branch-${e}.json`);try{let r=await If.readFile(n,"utf8");return JSON.parse(r)}catch(r){return r.code==="ENOENT",null}}var on="afk:f:";var Of=new Set(["p","d","r","x"]),Df=/^[a-z0-9T][a-z0-9T-]{0,62}$/;function Yi(t){if(!t||!t.startsWith(on)||Buffer.byteLength(t,"utf8")>64)return null;let e=t.slice(on.length),n=e.indexOf(":");if(n<1)return null;let r=e.slice(0,n),o=e.slice(n+1);return!Of.has(r)||!Df.test(o)?null:{action:r,taskSlug:o}}var Uf=Nf(Ff),pr=new Map;async function Qi(t,e={}){let n=e.log??(()=>{}),r=$f(t),o=Yi(r);if(!o){await j(t,"Unknown action",n);return}if(t.chat?.id===void 0){await j(t,"No chat context",n);return}let s=e.loadFarm??We,i;try{i=await s(o.taskSlug)}catch(c){n("[farm-callback] loadFarm failed:",c),await j(t,"Farm load failed",n);return}if(!i){await j(t,"Farm not found (already GC\u2019d?)",n);return}try{await Hf(o.action,t,i,e,n)}catch(c){n("[farm-callback] dispatch error:",c),await j(t,"Internal error",n)}}function $f(t){return t.callbackQuery?.data}async function j(t,e,n){try{await t.answerCbQuery(e)}catch(r){n("[farm-callback] answerCbQuery failed:",r)}}async function Hf(t,e,n,r,o){switch(t){case"x":return Kf(e,n,r,o);case"d":return Gf(e,n,r,o);case"p":return Xi(`p:${n.taskSlug}`,e,n,r,o,jf);case"r":return Xi(`r:${n.taskSlug}`,e,n,r,o,Wf)}}async function Xi(t,e,n,r,o,s){let i=pr.get(t);if(i){o(`[farm-callback] ${t} \u2014 second tap, awaiting in-flight lock`);try{await i}catch{}let a=r.loadFarm??We,l;try{l=await a(n.taskSlug)}catch{await j(e,"Farm load failed",o);return}if(!l){await j(e,"Farm not found",o);return}return s(e,l,r,o)}let c=s(e,n,r,o);return pr.set(t,c),c.finally(()=>{pr.delete(t)}),c}async function jf(t,e,n,r){if(e.prUrl){await j(t,`PR already open: ${e.prUrl}`,r);return}await j(t,"Opening PR\u2026",r);let o=n.checkGhReady??Ki,s;try{s=await o()}catch(y){r("[farm-callback] checkGhReady threw:",y);try{await t.reply("gh readiness check failed \u2014 see daemon logs")}catch{}return}if(!s.ok){try{await t.reply(s.hint)}catch{}return}let i=n.resolveWinnerBranch??rn,c;try{c=await i(e)}catch(y){r("[farm-callback] resolveWinnerBranch failed:",y);try{await t.reply("Winner lookup failed")}catch{}return}let a=c.branch.branch,l=e.baseBranch??"main",d=`Auto PR: ${e.taskName}`,u=`Auto-generated by afk farm ${e.taskSlug} | winner: ${a} | created: ${new Date().toISOString()}`,p=n.createPr??Gi,h;try{h=await p({base:l,head:a,title:d,body:u})}catch(y){if(y instanceof pt){let w={"not-found":"gh CLI not found \u2014 install with: brew install gh","already-exists":"PR already exists for this branch",unauthed:"gh is not authenticated \u2014 run: gh auth login",network:"Network error \u2014 check gh connectivity",timeout:"gh timed out \u2014 check connectivity",unknown:"gh pr create failed \u2014 see daemon logs"};try{await t.reply(w[y.kind])}catch{}return}r("[farm-callback] createPr failed:",y);try{await t.reply("gh pr create failed \u2014 see daemon logs")}catch{}return}let f=n.recordPrCreated??Bi;try{await f(e.taskSlug,h)}catch(y){r("[farm-callback] recordPrCreated failed:",y)}try{await t.reply(`PR opened \u2713
|
|
@@ -1633,4 +1633,4 @@ No reset time available. I'll resume automatically if you log in with a differen
|
|
|
1633
1633
|
|
|
1634
1634
|
Resets at ${c.toLocaleTimeString(void 0,{hour:"numeric",minute:"2-digit",hour12:!0})} (in ~${O} min).
|
|
1635
1635
|
|
|
1636
|
-
I'll auto-resume when the limit resets \u2014 no need to retype.`;l=!0,u(E,!0).finally(()=>{l=!1})}},Jf));continue}if(m.type==="resumed"){a!==null&&(clearInterval(a),a=null),c=null;let b=m.hotSwapped&&m.accountId?`\u25B6 **Resumed on ${m.accountId}**`:"\u25B6 **Resumed**";await u(b,!0);continue}if(m.type==="done"){a!==null&&(clearInterval(a),a=null),o.trim()&&await u(o,!0);break}if(m.type==="error")throw a!==null&&(clearInterval(a),a=null),m.error}})}finally{await Promise.resolve(h.return?.(void 0)).catch(()=>{})}if(o&&s){let g=lt(Qt(o));if(g.length>1)for(let m=1;m<g.length;m++){let b=g[m];b&&await t.reply(b,{parse_mode:"HTML"})}}await Promise.resolve(h.return?.(void 0)).catch(g=>{r?.("iter.return error (session cleanup):",g)})}catch(p){throw r?.("Streaming error:",p),p}}async function mr(t,e,n,r,o){if(!r.has(e))try{await Promise.race([n.waitForInitialization(),new Promise((c,a)=>setTimeout(()=>a(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)"},{command:"cd",description:"Show or change session working directory"}];if(s.slashCommands?.length)for(let c of s.slashCommands){let a=c.replace(/^\//,"");i.push({command:a,description:`SDK command: ${a}`})}if(s.skills?.length)for(let c of s.skills)i.push({command:c,description:`Run ${c} 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)}}function Xf(t){return t.length<3?null:t.length>=4&&t[0]===137&&t[1]===80&&t[2]===78&&t[3]===71?"image/png":t[0]===71&&t[1]===73&&t[2]===70?"image/gif":t.length>=12&&t[0]===82&&t[1]===73&&t[2]===70&&t[3]===70&&t[8]===87&&t[9]===69&&t[10]===66&&t[11]===80?"image/webp":t[0]===255&&t[1]===216&&t[2]===255?"image/jpeg":null}var sn=class t{static MAX_QUEUE_DEPTH=5;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 handlePhoto(e){let n=e.chat?.id,r=e.message,o=r?.photo;if(!n||!o?.length){this.log(`Photo handling: missing chatId or photo array for chat ${n??"(unknown)"}`);return}this.log(`\u{1F4F7} Photo from chat ID: ${n}`);let s=o[o.length-1];if(!s){this.log(`Photo handling: empty photo array for chat ${n}`);return}let i=5*1024*1024;if(s.file_size!=null&&s.file_size>i){this.log(`Photo handling: oversized file (${s.file_size} bytes) rejected for chat ${n}`),await e.reply("\u274C Image is too large (max 5 MB). Please send a smaller photo.");return}let c=r?.caption;try{let a=await this.sessionManager.getSession(n);if(mr(this.bot,n,a,this.registeredCommandChats,this.log).catch(m=>this.log("Failed to register chat commands:",m)),a.state!=="idle"&&(this.messageQueues.get(n)?.length??0)>=t.MAX_QUEUE_DEPTH){await e.reply("\u23F3 Queue full. Please wait for your messages to be processed.");return}let l=await e.telegram.getFileLink(s.file_id),d=l instanceof URL?l:new URL(String(l));if(d.protocol!=="https:"||d.hostname!=="api.telegram.org"||d.port!==""&&d.port!=="443"){this.log(`Photo handling: unexpected file URL (protocol=${d.protocol} hostname=${d.hostname}) rejected for chat ${n}`),await e.reply("\u274C Couldn't download the image. Please try resending.");return}let u=await globalThis.fetch(d.href,{signal:AbortSignal.timeout(15e3),redirect:"error"});if(!u.ok){this.log(`Photo handling: fetch failed with status ${u.status} for chat ${n}`),await e.reply("\u274C Couldn't download the image. Please try resending.");return}let p=await u.arrayBuffer();if(p.byteLength>i){this.log(`Photo handling: downloaded file (${p.byteLength} bytes) exceeds limit for chat ${n}`),await e.reply("\u274C Image is too large (max 5 MB). Please send a smaller photo.");return}let h=Buffer.from(p),f=h.toString("base64"),y=["image/jpeg","image/png","image/gif","image/webp"],w=u.headers.get("content-type")??"",T=(w.split(";")[0]?.trim()??"").toLowerCase(),k;if(y.includes(T))k=T;else{let m=Xf(h);if(m!==null)this.log(`Photo: sniffed ${m} (Content-Type was "${w}") for chat ${n}`),k=m;else{this.log(`Photo: unrecognised image format for chat ${n} (Content-Type: "${w}")`),await e.reply("\u274C Unsupported image format. Please send a JPEG, PNG, GIF, or WebP.");return}}let g=[];if(c!=null&&g.push({type:"text",text:`[User caption]: ${[...c].slice(0,1024).join("")}`}),g.push({type:"image",source:{type:"base64",media_type:k,data:f}}),a.state!=="idle"){this.enqueuePhoto(n,e,g)&&await e.reply("Message queued.");return}await this.processOne(n,e,g)}catch(a){let d=(a instanceof Error?a.message:String(a)).replace(/\/bot[^/]+\//g,"/bot[REDACTED]/");this.log("Photo handling error:",d),Ke(a)?await e.reply("\u23F3 Rate limit reached. Please wait a moment and try again."):Ge(a)?await e.reply("\u274C Couldn't download the image. Please try resending."):await e.reply(Zt())}}async handle(e){let n=e.chat?.id,r=e.message.text;if(!(!n||!r)&&(this.log(`\u{1F4EC} Message from chat ID: ${n}`),!r.startsWith("/")))try{let o=await this.sessionManager.getSession(n);if(mr(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){this.log("Message handling error:",o),Ke(o)?await e.reply("\u23F3 Rate limit reached. Please wait a moment and try again."):Ge(o)?await e.reply("\u{1F310} Network error. Please check your connection and try again."):await e.reply(Zt())}}async processClearDirect(e,n){try{await this.sessionManager.resetSession(e),this.registeredCommandChats.delete(e),await n.reply(dt())}catch(r){this.log("Clear error:",r),await n.reply(N(r))}}enqueueMessage(e,n,r){let o=this.messageQueues.get(e);return o||(o=[],this.messageQueues.set(e,o)),o.length>=t.MAX_QUEUE_DEPTH?(n.reply("\u23F3 Queue full. Please wait for your messages to be processed.").catch(()=>{}),!1):(o.push({type:"message",ctx:n,text:r}),!0)}enqueuePhoto(e,n,r){let o=this.messageQueues.get(e);return o||(o=[],this.messageQueues.set(e,o)),o.length>=t.MAX_QUEUE_DEPTH?(n.reply("\u23F3 Queue full. Please wait for your messages to be processed.").catch(()=>{}),!1):(o.push({type:"photo",ctx:n,content:r}),!0)}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){let o=!1;try{let s=await this.sessionManager.getSession(e);await n.sendChatAction("typing").catch(()=>{}),await fr(n,s,r,this.log)}catch(s){if(this.log("Message handling error:",s),(s?.message??"").includes("session is busy")){(typeof r=="string"?this.enqueueMessage(e,n,r):this.enqueuePhoto(e,n,r))&&await n.reply("Message queued."),o=!0;return}Ke(s)?await n.reply("\u23F3 Rate limit reached. Please wait a moment and try again."):Ge(s)?await n.reply("\u{1F310} Network error. Please check your connection and try again."):await n.reply(Zt())}finally{o||this.drainQueue(e).catch(s=>this.log("Drain error:",s))}}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):r.type==="photo"?await this.processOne(e,r.ctx,r.content):await this.processClearDirect(e,r.ctx)}};var an=class{bot;sessionManager;options;running=!1;registeredCommandChats=new Set;messageHandler;constructor(e){this.options=e,this.bot=new Qf(e.botToken),this.sessionManager=new Be(e),this.messageHandler=new sn(this.bot,this.sessionManager,this.registeredCommandChats,this.log.bind(this)),this.setupHandlers()}setupHandlers(){this.bot.use(Cn(this.options.allowedChatIds,this.log.bind(this))),this.bot.command("start",n=>ar(n)),this.bot.command("help",n=>cr(n,this.sessionManager)),this.bot.command("clear",async n=>{let r=n.chat?.id;if(!r){await n.reply(N("Could not identify chat"));return}(await this.sessionManager.getSession(r)).state!=="idle"?(this.messageHandler.enqueueClear(r,n),await n.reply("Clear queued.")):await dr(n,this.sessionManager,this.registeredCommandChats,this.log.bind(this))}),this.bot.command("compact",n=>Ni(n,this.sessionManager,this.log.bind(this))),this.bot.command("model",n=>ur(n,this.sessionManager,this.log.bind(this))),this.bot.command(["cd","cwd"],n=>Ui(n,this.sessionManager,this.log.bind(this))),this.bot.on("text",n=>this.messageHandler.handle(n)),this.bot.on("photo",n=>this.messageHandler.handlePhoto(n));let e=new RegExp(`^${Zf(on)}`);this.bot.action(e,n=>Qi(n,{log:this.log.bind(this)})),this.bot.catch((n,r)=>{this.log("Bot error:",n),r.reply(N("An unexpected error occurred. Please try again.")).catch(o=>this.log("Failed to send error message:",o))})}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 ar(e)}async handleHelp(e){return cr(e,this.sessionManager)}async handleClear(e){let n=e.chat?.id;if(!n){await e.reply(N("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 dr(e,this.sessionManager,this.registeredCommandChats,this.log.bind(this))}async handleMessage(e){return this.messageHandler.handle(e)}async handlePhoto(e){return this.messageHandler.handlePhoto(e)}async handleModelSwitch(e){return ur(e,this.sessionManager,this.log.bind(this))}log(...e){this.options.verbose&&console.log("[TelegramBot]",...e)}};function Zf(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}export{Pe as AgentSession,ue as OpenAICompatibleProvider,Be as SessionManager,C as SubagentManager,an as TelegramBot,Ii as createCanUseToolHook,Wn as openaiCompatibleProvider,Ie as providerForModel,Vt as resolveProvider};
|
|
1636
|
+
I'll auto-resume when the limit resets \u2014 no need to retype.`;l=!0,u(E,!0).finally(()=>{l=!1})}},Jf));continue}if(m.type==="resumed"){a!==null&&(clearInterval(a),a=null),c=null;let b=m.hotSwapped&&m.accountId?`\u25B6 **Resumed on ${m.accountId}**`:"\u25B6 **Resumed**";await u(b,!0);continue}if(m.type==="done"){a!==null&&(clearInterval(a),a=null),o.trim()&&await u(o,!0);break}if(m.type==="error")throw a!==null&&(clearInterval(a),a=null),m.error}})}finally{await Promise.resolve(h.return?.(void 0)).catch(()=>{})}if(o&&s){let g=lt(Qt(o));if(g.length>1)for(let m=1;m<g.length;m++){let b=g[m];b&&await t.reply(b,{parse_mode:"HTML"})}}await Promise.resolve(h.return?.(void 0)).catch(g=>{r?.("iter.return error (session cleanup):",g)})}catch(p){throw r?.("Streaming error:",p),p}}async function mr(t,e,n,r,o){if(!r.has(e))try{await Promise.race([n.waitForInitialization(),new Promise((c,a)=>setTimeout(()=>a(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)"},{command:"cd",description:"Show or change session working directory"}];if(s.slashCommands?.length)for(let c of s.slashCommands){let a=c.replace(/^\//,"");i.push({command:a,description:`SDK command: ${a}`})}if(s.skills?.length)for(let c of s.skills)i.push({command:c,description:`Run ${c} 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)}}function Xf(t){return t.length<3?null:t.length>=4&&t[0]===137&&t[1]===80&&t[2]===78&&t[3]===71?"image/png":t[0]===71&&t[1]===73&&t[2]===70?"image/gif":t.length>=12&&t[0]===82&&t[1]===73&&t[2]===70&&t[3]===70&&t[8]===87&&t[9]===69&&t[10]===66&&t[11]===80?"image/webp":t[0]===255&&t[1]===216&&t[2]===255?"image/jpeg":null}async function Qf(t,e){let n=t.headers.get("content-length");if(n!=null){let c=Number(n);if(Number.isFinite(c)&&c>e)return{status:"too-large",bytesRead:c}}let r=t.body;if(!r)return{status:"missing-body"};let o=r.getReader(),s=[],i=0;try{for(;;){let{done:c,value:a}=await o.read();if(c)break;if(i+=a.byteLength,i>e)return await o.cancel().catch(()=>{}),{status:"too-large",bytesRead:i};s.push(Buffer.from(a))}}finally{o.releaseLock()}return{status:"ok",bytes:Buffer.concat(s,i)}}var sn=class t{static MAX_QUEUE_DEPTH=5;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 handlePhoto(e){let n=e.chat?.id,r=e.message,o=r?.photo;if(!n||!o?.length){this.log(`Photo handling: missing chatId or photo array for chat ${n??"(unknown)"}`);return}this.log(`\u{1F4F7} Photo from chat ID: ${n}`);let s=o[o.length-1];if(!s){this.log(`Photo handling: empty photo array for chat ${n}`);return}let i=5*1024*1024;if(s.file_size!=null&&s.file_size>i){this.log(`Photo handling: oversized file (${s.file_size} bytes) rejected for chat ${n}`),await e.reply("\u274C Image is too large (max 5 MB). Please send a smaller photo.");return}let c=r?.caption;try{let a=await this.sessionManager.getSession(n);if(mr(this.bot,n,a,this.registeredCommandChats,this.log).catch(m=>this.log("Failed to register chat commands:",m)),a.state!=="idle"&&(this.messageQueues.get(n)?.length??0)>=t.MAX_QUEUE_DEPTH){await e.reply("\u23F3 Queue full. Please wait for your messages to be processed.");return}let l=await e.telegram.getFileLink(s.file_id),d=l instanceof URL?l:new URL(String(l));if(d.protocol!=="https:"||d.hostname!=="api.telegram.org"||d.port!==""&&d.port!=="443"){this.log(`Photo handling: unexpected file URL (protocol=${d.protocol} hostname=${d.hostname}) rejected for chat ${n}`),await e.reply("\u274C Couldn't download the image. Please try resending.");return}let u=await globalThis.fetch(d.href,{signal:AbortSignal.timeout(15e3),redirect:"error"});if(!u.ok){this.log(`Photo handling: fetch failed with status ${u.status} for chat ${n}`),await e.reply("\u274C Couldn't download the image. Please try resending.");return}let p=await Qf(u,i);if(p.status==="too-large"){this.log(`Photo handling: downloaded file (${p.bytesRead} bytes) exceeds limit for chat ${n}`),await e.reply("\u274C Image is too large (max 5 MB). Please send a smaller photo.");return}if(p.status==="missing-body"){this.log(`Photo handling: fetch response had no body for chat ${n}`),await e.reply("\u274C Couldn't download the image. Please try resending.");return}let h=p.bytes,f=h.toString("base64"),y=["image/jpeg","image/png","image/gif","image/webp"],w=u.headers.get("content-type")??"",T=(w.split(";")[0]?.trim()??"").toLowerCase(),k;if(y.includes(T))k=T;else{let m=Xf(h);if(m!==null)this.log(`Photo: sniffed ${m} (Content-Type was "${w}") for chat ${n}`),k=m;else{this.log(`Photo: unrecognised image format for chat ${n} (Content-Type: "${w}")`),await e.reply("\u274C Unsupported image format. Please send a JPEG, PNG, GIF, or WebP.");return}}let g=[];if(c!=null&&g.push({type:"text",text:`[User caption]: ${[...c].slice(0,1024).join("")}`}),g.push({type:"image",source:{type:"base64",media_type:k,data:f}}),a.state!=="idle"){this.enqueuePhoto(n,e,g)&&await e.reply("Message queued.");return}await this.processOne(n,e,g)}catch(a){let d=(a instanceof Error?a.message:String(a)).replace(/\/bot[^/]+\//g,"/bot[REDACTED]/");this.log("Photo handling error:",d),Ke(a)?await e.reply("\u23F3 Rate limit reached. Please wait a moment and try again."):Ge(a)?await e.reply("\u274C Couldn't download the image. Please try resending."):await e.reply(Zt())}}async handle(e){let n=e.chat?.id,r=e.message.text;if(!(!n||!r)&&(this.log(`\u{1F4EC} Message from chat ID: ${n}`),!r.startsWith("/")))try{let o=await this.sessionManager.getSession(n);if(mr(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){this.log("Message handling error:",o),Ke(o)?await e.reply("\u23F3 Rate limit reached. Please wait a moment and try again."):Ge(o)?await e.reply("\u{1F310} Network error. Please check your connection and try again."):await e.reply(Zt())}}async processClearDirect(e,n){try{await this.sessionManager.resetSession(e),this.registeredCommandChats.delete(e),await n.reply(dt())}catch(r){this.log("Clear error:",r),await n.reply(N(r))}}enqueueMessage(e,n,r){let o=this.messageQueues.get(e);return o||(o=[],this.messageQueues.set(e,o)),o.length>=t.MAX_QUEUE_DEPTH?(n.reply("\u23F3 Queue full. Please wait for your messages to be processed.").catch(()=>{}),!1):(o.push({type:"message",ctx:n,text:r}),!0)}enqueuePhoto(e,n,r){let o=this.messageQueues.get(e);return o||(o=[],this.messageQueues.set(e,o)),o.length>=t.MAX_QUEUE_DEPTH?(n.reply("\u23F3 Queue full. Please wait for your messages to be processed.").catch(()=>{}),!1):(o.push({type:"photo",ctx:n,content:r}),!0)}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){let o=!1;try{let s=await this.sessionManager.getSession(e);await n.sendChatAction("typing").catch(()=>{}),await fr(n,s,r,this.log)}catch(s){if(this.log("Message handling error:",s),(s?.message??"").includes("session is busy")){(typeof r=="string"?this.enqueueMessage(e,n,r):this.enqueuePhoto(e,n,r))&&await n.reply("Message queued."),o=!0;return}Ke(s)?await n.reply("\u23F3 Rate limit reached. Please wait a moment and try again."):Ge(s)?await n.reply("\u{1F310} Network error. Please check your connection and try again."):await n.reply(Zt())}finally{o||this.drainQueue(e).catch(s=>this.log("Drain error:",s))}}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):r.type==="photo"?await this.processOne(e,r.ctx,r.content):await this.processClearDirect(e,r.ctx)}};var an=class{bot;sessionManager;options;running=!1;registeredCommandChats=new Set;messageHandler;constructor(e){this.options=e,this.bot=new Zf(e.botToken),this.sessionManager=new Be(e),this.messageHandler=new sn(this.bot,this.sessionManager,this.registeredCommandChats,this.log.bind(this)),this.setupHandlers()}setupHandlers(){this.bot.use(Cn(this.options.allowedChatIds,this.log.bind(this))),this.bot.command("start",n=>ar(n)),this.bot.command("help",n=>cr(n,this.sessionManager)),this.bot.command("clear",async n=>{let r=n.chat?.id;if(!r){await n.reply(N("Could not identify chat"));return}(await this.sessionManager.getSession(r)).state!=="idle"?(this.messageHandler.enqueueClear(r,n),await n.reply("Clear queued.")):await dr(n,this.sessionManager,this.registeredCommandChats,this.log.bind(this))}),this.bot.command("compact",n=>Ni(n,this.sessionManager,this.log.bind(this))),this.bot.command("model",n=>ur(n,this.sessionManager,this.log.bind(this))),this.bot.command(["cd","cwd"],n=>Ui(n,this.sessionManager,this.log.bind(this))),this.bot.on("text",n=>this.messageHandler.handle(n)),this.bot.on("photo",n=>this.messageHandler.handlePhoto(n));let e=new RegExp(`^${em(on)}`);this.bot.action(e,n=>Qi(n,{log:this.log.bind(this)})),this.bot.catch((n,r)=>{this.log("Bot error:",n),r.reply(N("An unexpected error occurred. Please try again.")).catch(o=>this.log("Failed to send error message:",o))})}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 ar(e)}async handleHelp(e){return cr(e,this.sessionManager)}async handleClear(e){let n=e.chat?.id;if(!n){await e.reply(N("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 dr(e,this.sessionManager,this.registeredCommandChats,this.log.bind(this))}async handleMessage(e){return this.messageHandler.handle(e)}async handlePhoto(e){return this.messageHandler.handlePhoto(e)}async handleModelSwitch(e){return ur(e,this.sessionManager,this.log.bind(this))}log(...e){this.options.verbose&&console.log("[TelegramBot]",...e)}};function em(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}export{Pe as AgentSession,ue as OpenAICompatibleProvider,Be as SessionManager,C as SubagentManager,an as TelegramBot,Ii as createCanUseToolHook,Wn as openaiCompatibleProvider,Ie as providerForModel,Vt as resolveProvider};
|