agentix-cli 0.17.0 → 0.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/README.md +75 -27
- package/dist/agent-57MG4LBM.js +2 -0
- package/dist/audit-JU3HWISB.js +3 -0
- package/dist/audit-JU3HWISB.js.map +1 -0
- package/dist/{board-dashboard-CXIVJKDP.js → board-dashboard-HXDOYGIG.js} +2237 -69
- package/dist/board-dashboard-HXDOYGIG.js.map +1 -0
- package/dist/chunk-23AUU4S2.js +102 -0
- package/dist/chunk-23AUU4S2.js.map +1 -0
- package/dist/{chunk-EKTPCSN4.js → chunk-4ITQP3XL.js} +2 -2
- package/dist/chunk-4MREHZP5.js +111 -0
- package/dist/chunk-4MREHZP5.js.map +1 -0
- package/dist/chunk-4YCH6IZV.js +2 -0
- package/dist/chunk-53NRX2NA.js +2 -0
- package/dist/chunk-53NRX2NA.js.map +1 -0
- package/dist/chunk-6B74TO2J.js +743 -0
- package/dist/chunk-6B74TO2J.js.map +1 -0
- package/dist/chunk-7P5QRX5W.js +108 -0
- package/dist/chunk-7P5QRX5W.js.map +1 -0
- package/dist/chunk-A6BKSZQA.js +3 -0
- package/dist/chunk-A6BKSZQA.js.map +1 -0
- package/dist/{chunk-6PPIFDOQ.js → chunk-CNNLREHD.js} +67 -22
- package/dist/{chunk-6PPIFDOQ.js.map → chunk-CNNLREHD.js.map} +1 -1
- package/dist/chunk-DJEZ2HVU.js +5 -0
- package/dist/chunk-DJEZ2HVU.js.map +1 -0
- package/dist/chunk-DLVOHCTA.js +5 -0
- package/dist/{chunk-MBEQASP3.js.map → chunk-DLVOHCTA.js.map} +1 -1
- package/dist/chunk-E4ZZILAK.js +15 -0
- package/dist/chunk-E4ZZILAK.js.map +1 -0
- package/dist/{chunk-63UYRJIC.js → chunk-IKBHHTIT.js} +2 -2
- package/dist/chunk-JGXE2YNV.js +46 -0
- package/dist/chunk-JGXE2YNV.js.map +1 -0
- package/dist/chunk-JTJIPNXY.js +2 -0
- package/dist/chunk-JTJIPNXY.js.map +1 -0
- package/dist/chunk-MBOLXKA2.js +6 -0
- package/dist/chunk-MBOLXKA2.js.map +1 -0
- package/dist/{inbox-L5ZZ623Y.js → chunk-MTRWXRFF.js} +69 -4
- package/dist/chunk-MTRWXRFF.js.map +1 -0
- package/dist/{processes-XF5CV4LK.js → chunk-NOF4HSGK.js} +3 -3
- package/dist/{processes-XF5CV4LK.js.map → chunk-NOF4HSGK.js.map} +1 -1
- package/dist/chunk-QW2OYR3N.js +7 -0
- package/dist/chunk-QW2OYR3N.js.map +1 -0
- package/dist/chunk-SR3X25TN.js +3 -0
- package/dist/chunk-SR3X25TN.js.map +1 -0
- package/dist/chunk-SV3I4CI7.js +440 -0
- package/dist/chunk-SV3I4CI7.js.map +1 -0
- package/dist/{chunk-TT2Q7YMZ.js → chunk-TC3BSUP7.js} +6 -6
- package/dist/{chunk-TT2Q7YMZ.js.map → chunk-TC3BSUP7.js.map} +1 -1
- package/dist/chunk-VJUTQAPJ.js +2 -0
- package/dist/chunk-VJUTQAPJ.js.map +1 -0
- package/dist/chunk-VWTBHLMX.js +1 -0
- package/dist/chunk-WFHIIVLL.js +719 -0
- package/dist/chunk-WFHIIVLL.js.map +1 -0
- package/dist/chunk-WPPUOTY6.js +6 -0
- package/dist/chunk-WPPUOTY6.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/{compaction-X46EQEPS.js → compaction-BTUJJ3LJ.js} +4 -4
- package/dist/config-QXWKEQON.js +2 -0
- package/dist/config-mutator-53XGR2NT.js +2 -0
- package/dist/conflict-detector-D7VIYPDI.js +2 -0
- package/dist/conflict-detector-D7VIYPDI.js.map +1 -0
- package/dist/{context-planner-G2J7FNNU.js → context-planner-I7ID7XF3.js} +3 -3
- package/dist/debug-N3B5NVJU.js +2 -0
- package/dist/discover-XJXQXXIO.js +4 -0
- package/dist/discover-XJXQXXIO.js.map +1 -0
- package/dist/doctor-SEOUFHSL.js +2 -0
- package/dist/{editor-chat-R54E65W5.js → editor-chat-RVLCKKB7.js} +2 -2
- package/dist/heal-YEQYWX2L.js +2 -0
- package/dist/inbox-BIN2S5XN.js +2 -0
- package/dist/index.d.ts +1292 -122
- package/dist/index.js +8 -8
- package/dist/index.js.map +1 -1
- package/dist/{ingest-whatsapp-NS4OWDOU.js → ingest-whatsapp-LZE62INA.js} +2 -2
- package/dist/loader-5CA3O5GM.js +2 -0
- package/dist/loader-6IHUCPVO.js +2 -0
- package/dist/memory-extract-KRCHD3OP.js +2 -0
- package/dist/migrate-v2-QO7SLKIM.js +4 -0
- package/dist/migrate-v2-QO7SLKIM.js.map +1 -0
- package/dist/processes-RJ6RDP32.js +2 -0
- package/dist/program-SASDC2GV.js +2 -0
- package/dist/providers-WVCMIW67.js +2 -0
- package/dist/query-HZYYRCLU.js +2 -0
- package/dist/recipes-EPLE2SNT.js +2 -0
- package/dist/registry-HM4ELSXS.js +2 -0
- package/dist/rotation-memo-GMTZPMNE.js +13 -0
- package/dist/rotation-memo-GMTZPMNE.js.map +1 -0
- package/dist/scheduler-XVFIK4XH.js +2 -0
- package/dist/{slack-PSQLVTGB.js → slack-6P7ZJ32Y.js} +2 -2
- package/dist/store-BAPDZHXE.js +2 -0
- package/dist/{subagent-2SJHSSJS.js → subagent-WV7QKQ3L.js} +2 -2
- package/dist/{task-store-NM7VKNLE.js → task-store-RHISEU6V.js} +2 -2
- package/dist/task-store-RHISEU6V.js.map +1 -0
- package/dist/{telegram-W4SLFMNY.js → telegram-PIYDRM46.js} +2 -2
- package/dist/timers-5LPZN55J.js +2 -0
- package/dist/timers-5LPZN55J.js.map +1 -0
- package/dist/types-VECTMYTO.js +2 -0
- package/dist/types-VECTMYTO.js.map +1 -0
- package/dist/types-ZRLHHCGB.js +2 -0
- package/dist/types-ZRLHHCGB.js.map +1 -0
- package/dist/web/activity-graph.global.js +654 -0
- package/dist/web/activity-graph.global.js.map +1 -0
- package/dist/web/workflow-editor.global.js +35 -12
- package/dist/web/workflow-editor.global.js.map +1 -1
- package/dist/{whatsapp-DCHRBRVV.js → whatsapp-PFRDMUMT.js} +2 -2
- package/dist/{whatsapp-state-6D6FHHD2.js → whatsapp-state-XMTCSRXU.js} +2 -2
- package/dist/wiki-53W5NLZV.js +2 -0
- package/dist/wiki-53W5NLZV.js.map +1 -0
- package/dist/workspace-setup-FPGN5VNY.js +2 -0
- package/dist/workspace-setup-FPGN5VNY.js.map +1 -0
- package/package.json +13 -2
- package/dist/agent-4AOMVXRJ.js +0 -2
- package/dist/board-dashboard-CXIVJKDP.js.map +0 -1
- package/dist/chunk-34NG7UDX.js +0 -11
- package/dist/chunk-34NG7UDX.js.map +0 -1
- package/dist/chunk-4HP6UC2X.js +0 -13
- package/dist/chunk-4HP6UC2X.js.map +0 -1
- package/dist/chunk-5WNGHDFC.js +0 -164
- package/dist/chunk-5WNGHDFC.js.map +0 -1
- package/dist/chunk-ABCHHNG6.js +0 -625
- package/dist/chunk-ABCHHNG6.js.map +0 -1
- package/dist/chunk-FIOB3MEX.js +0 -2
- package/dist/chunk-HCFSHGK4.js +0 -46
- package/dist/chunk-HCFSHGK4.js.map +0 -1
- package/dist/chunk-HHJGKD5B.js +0 -71
- package/dist/chunk-HHJGKD5B.js.map +0 -1
- package/dist/chunk-LEIYC3BF.js +0 -104
- package/dist/chunk-LEIYC3BF.js.map +0 -1
- package/dist/chunk-MBEQASP3.js +0 -5
- package/dist/chunk-MCJUAE6V.js +0 -6
- package/dist/chunk-MCJUAE6V.js.map +0 -1
- package/dist/chunk-SRHLXZRF.js +0 -7
- package/dist/chunk-SRHLXZRF.js.map +0 -1
- package/dist/chunk-WZEYII2S.js +0 -6
- package/dist/chunk-WZEYII2S.js.map +0 -1
- package/dist/chunk-XDJSYQST.js +0 -6
- package/dist/chunk-XDJSYQST.js.map +0 -1
- package/dist/chunk-YPOELN6Z.js +0 -798
- package/dist/chunk-YPOELN6Z.js.map +0 -1
- package/dist/config-KCYHMKCT.js +0 -2
- package/dist/config-mutator-QP4GLBOE.js +0 -2
- package/dist/debug-3MEUO2P2.js +0 -2
- package/dist/heal-JDXUPRET.js +0 -2
- package/dist/inbox-L5ZZ623Y.js.map +0 -1
- package/dist/loader-PTCXLJEX.js +0 -2
- package/dist/memory-extract-WH4FZ456.js +0 -2
- package/dist/program-FFWEILAS.js +0 -2
- package/dist/providers-AKQ4HTB4.js +0 -2
- package/dist/query-PKGYE5HR.js +0 -2
- package/dist/registry-IFMDJWQ7.js +0 -2
- package/dist/scheduler-63D5KFO7.js +0 -2
- package/dist/store-5MJOO74U.js +0 -2
- package/dist/timers-PCB4ZIBD.js +0 -2
- package/dist/types-C7IFH42Z.js +0 -2
- package/dist/types-OIFU3KSQ.js +0 -2
- package/dist/usage-dashboard-AXPXB2KP.js +0 -803
- package/dist/usage-dashboard-AXPXB2KP.js.map +0 -1
- package/dist/wiki-UDPYFJBL.js +0 -2
- package/dist/workspace-setup-C4VB3QZV.js +0 -2
- /package/dist/{agent-4AOMVXRJ.js.map → agent-57MG4LBM.js.map} +0 -0
- /package/dist/{chunk-EKTPCSN4.js.map → chunk-4ITQP3XL.js.map} +0 -0
- /package/dist/{chunk-FIOB3MEX.js.map → chunk-4YCH6IZV.js.map} +0 -0
- /package/dist/{chunk-63UYRJIC.js.map → chunk-IKBHHTIT.js.map} +0 -0
- /package/dist/{config-KCYHMKCT.js.map → chunk-VWTBHLMX.js.map} +0 -0
- /package/dist/{compaction-X46EQEPS.js.map → compaction-BTUJJ3LJ.js.map} +0 -0
- /package/dist/{config-mutator-QP4GLBOE.js.map → config-QXWKEQON.js.map} +0 -0
- /package/dist/{debug-3MEUO2P2.js.map → config-mutator-53XGR2NT.js.map} +0 -0
- /package/dist/{context-planner-G2J7FNNU.js.map → context-planner-I7ID7XF3.js.map} +0 -0
- /package/dist/{heal-JDXUPRET.js.map → debug-N3B5NVJU.js.map} +0 -0
- /package/dist/{loader-PTCXLJEX.js.map → doctor-SEOUFHSL.js.map} +0 -0
- /package/dist/{editor-chat-R54E65W5.js.map → editor-chat-RVLCKKB7.js.map} +0 -0
- /package/dist/{memory-extract-WH4FZ456.js.map → heal-YEQYWX2L.js.map} +0 -0
- /package/dist/{program-FFWEILAS.js.map → inbox-BIN2S5XN.js.map} +0 -0
- /package/dist/{ingest-whatsapp-NS4OWDOU.js.map → ingest-whatsapp-LZE62INA.js.map} +0 -0
- /package/dist/{providers-AKQ4HTB4.js.map → loader-5CA3O5GM.js.map} +0 -0
- /package/dist/{query-PKGYE5HR.js.map → loader-6IHUCPVO.js.map} +0 -0
- /package/dist/{registry-IFMDJWQ7.js.map → memory-extract-KRCHD3OP.js.map} +0 -0
- /package/dist/{scheduler-63D5KFO7.js.map → processes-RJ6RDP32.js.map} +0 -0
- /package/dist/{store-5MJOO74U.js.map → program-SASDC2GV.js.map} +0 -0
- /package/dist/{task-store-NM7VKNLE.js.map → providers-WVCMIW67.js.map} +0 -0
- /package/dist/{timers-PCB4ZIBD.js.map → query-HZYYRCLU.js.map} +0 -0
- /package/dist/{types-C7IFH42Z.js.map → recipes-EPLE2SNT.js.map} +0 -0
- /package/dist/{types-OIFU3KSQ.js.map → registry-HM4ELSXS.js.map} +0 -0
- /package/dist/{wiki-UDPYFJBL.js.map → scheduler-XVFIK4XH.js.map} +0 -0
- /package/dist/{slack-PSQLVTGB.js.map → slack-6P7ZJ32Y.js.map} +0 -0
- /package/dist/{workspace-setup-C4VB3QZV.js.map → store-BAPDZHXE.js.map} +0 -0
- /package/dist/{subagent-2SJHSSJS.js.map → subagent-WV7QKQ3L.js.map} +0 -0
- /package/dist/{telegram-W4SLFMNY.js.map → telegram-PIYDRM46.js.map} +0 -0
- /package/dist/{whatsapp-DCHRBRVV.js.map → whatsapp-PFRDMUMT.js.map} +0 -0
- /package/dist/{whatsapp-state-6D6FHHD2.js.map → whatsapp-state-XMTCSRXU.js.map} +0 -0
package/dist/chunk-FIOB3MEX.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
var e=Object.defineProperty;var g=Object.getOwnPropertyDescriptor;var h=Object.getOwnPropertyNames;var i=Object.prototype.hasOwnProperty;var j=(a,b,c)=>b in a?e(a,b,{enumerable:!0,configurable:!0,writable:!0,value:c}):a[b]=c;var l=(a=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(a,{get:(b,c)=>(typeof require<"u"?require:b)[c]}):a)(function(a){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+a+'" is not supported')});var m=(a,b)=>()=>(a&&(b=a(a=0)),b);var n=(a,b)=>{for(var c in b)e(a,c,{get:b[c],enumerable:!0})},k=(a,b,c,f)=>{if(b&&typeof b=="object"||typeof b=="function")for(let d of h(b))!i.call(a,d)&&d!==c&&e(a,d,{get:()=>b[d],enumerable:!(f=g(b,d))||f.enumerable});return a};var o=a=>k(e({},"__esModule",{value:!0}),a);var p=(a,b,c)=>(j(a,typeof b!="symbol"?b+"":b,c),c);export{l as a,m as b,n as c,o as d,p as e};
|
|
2
|
-
//# sourceMappingURL=chunk-FIOB3MEX.js.map
|
package/dist/chunk-HCFSHGK4.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import{existsSync as Y,readFileSync as X,writeFileSync as te,mkdirSync as ne}from"fs";import P from"path";import Q from"os";import U from"chalk";import j from"prompts";import q from"chalk";var C={error(...r){console.log(q.red(...r))},warn(...r){console.log(q.yellow(...r))},info(...r){console.log(q.cyan(...r))},success(...r){console.log(q.green(...r))},break(){console.log("")}};var H=P.join(Q.homedir(),".agentx"),J=P.join(H,"auth.json");function R(){if(!Y(J))return null;try{let r=JSON.parse(X(J,"utf8"));return r.provider&&r.authType&&r.token&&r.model?r:null}catch{return null}}function oe(r){Y(H)||ne(H,{recursive:!0}),te(J,JSON.stringify(r,null,2),"utf8")}function N(r){if(r?.trim()){let y=r.startsWith("sk-ant-oat")?"oauth":"api-key";return{token:r.trim(),authType:y}}let e=process.env.ANTHROPIC_OAUTH_TOKEN;if(e?.trim())return{token:e.trim(),authType:"oauth"};let t=process.env.CLAUDE_CODE_OAUTH_TOKEN;if(t?.trim())return{token:t.trim(),authType:"oauth"};let n=process.env.ANTHROPIC_API_KEY;if(n?.trim())return{token:n.trim(),authType:"api-key"};let o=R();if(o)return{token:o.token,authType:o.authType};let s=Q.homedir(),u=[P.join(s,".openclaw","agents","main","agent","auth-profiles.json"),P.join(s,".openclaw","auth-profiles.json"),P.join(s,".openclaw","credentials","oauth.json"),P.join(s,".claude","oauth.json"),P.join(s,".config","claude","oauth.json"),P.join(s,".config","anthropic","oauth.json")];for(let y of u){let g=re(y);if(g)return{token:g,authType:"oauth"}}return null}function re(r){if(!Y(r))return"";try{let e=JSON.parse(X(r,"utf8"));if(e.profiles){let t="";for(let[n,o]of Object.entries(e.profiles))if(n.startsWith("anthropic")){if(o.type==="oauth"&&o.access){if(o.expires&&Date.now()>o.expires)continue;return o.access}o.type==="token"&&o.token&&(t=o.token)}if(t)return t}return e.anthropic?.access?e.anthropic.access:e.anthropic?.token?e.anthropic.token:""}catch{return""}}var B=[{id:"claude-sonnet-4-20250514",label:"anthropic/claude-sonnet-4",hint:"Claude Sonnet 4 \xB7 ctx 200k \xB7 recommended"},{id:"claude-opus-4-20250514",label:"anthropic/claude-opus-4-5",hint:"Claude Opus 4.5 \xB7 ctx 200k \xB7 reasoning"},{id:"claude-haiku-4-20250514",label:"anthropic/claude-haiku-4",hint:"Claude Haiku 4 \xB7 ctx 200k \xB7 fast"}];async function se(){let r=process.env.ANTHROPIC_API_KEY;if(r?.trim()){let n=r.slice(0,10)+"..."+r.slice(-4),{useExisting:o}=await j({type:"confirm",name:"useExisting",message:`Use existing ANTHROPIC_API_KEY (env, ${n})?`,initial:!0});if(o)return{token:r.trim(),authType:"api-key"}}let e=R();if(e?.authType==="api-key"&&e.token){let n=e.token.slice(0,10)+"..."+e.token.slice(-4),{useExisting:o}=await j({type:"confirm",name:"useExisting",message:`Use stored API key (${n})?`,initial:!0});if(o)return{token:e.token,authType:"api-key"}}let{apiKey:t}=await j({type:"password",name:"apiKey",message:"Enter Anthropic API key",validate:n=>n.startsWith("sk-ant-api")?n.length<40?"API key seems too short":!0:"API key must start with sk-ant-api"});return t?{token:t,authType:"api-key"}:null}async function ie(){C.break();let r=46,e="Run `claude setup-token` in your terminal.",t="Then paste the generated token below.";console.log(` ${U.cyan("Anthropic setup-token")} ${"\u2500".repeat(r-21-1)}\u256E`),console.log(` ${" ".repeat(r)}\u2502`),console.log(` ${e}${" ".repeat(r-e.length)}\u2502`),console.log(` ${t}${" ".repeat(r-t.length)}\u2502`),console.log(` ${" ".repeat(r)}\u2502`),console.log(` ${"\u2500".repeat(r)}\u256F`),C.break();let{token:n}=await j({type:"password",name:"token",message:"Paste Anthropic setup-token",validate:s=>s.trim()?s.length<40?"Token seems too short":!0:"Token is required"});if(!n)return null;let{tokenName:o}=await j({type:"text",name:"tokenName",message:"Token name (blank = default)"});return{token:n,authType:"oauth"}}async function ae(){for(;;){let{provider:r}=await j({type:"select",name:"provider",message:"Model/auth provider",choices:[{title:"Anthropic",value:"anthropic",description:"setup-token + API key"}]});if(r===void 0)return null;let{method:e}=await j({type:"select",name:"method",message:"Anthropic auth method",choices:[{title:"Anthropic token (paste setup-token)",value:"setup-token",description:"run `claude setup-token` elsewhere, then paste the token here"},{title:"Anthropic API key",value:"api-key"},{title:U.dim("Back"),value:"back"}]});if(e===void 0)return null;if(e!=="back")return e==="api-key"?se():e==="setup-token"?ie():null}}async function le(){let r=R(),e=B.map(n=>({title:n.label,value:n.id,description:n.hint+(r?.model===n.id?" \xB7 current":"")}));if(r?.model){let n=B.find(s=>s.id===r.model),o=n?n.label:r.model;e.unshift({title:`Keep current (${o})`,value:r.model,description:"no change"})}let{modelId:t}=await j({type:"select",name:"modelId",message:"Default model",choices:e});return t||null}async function ce(){let r=await ae();if(!r)return null;let e=await le();if(!e)return null;let t={provider:r.authType==="oauth"?"claude-code":"claude",authType:r.authType,token:r.token,model:e};return oe(t),C.break(),C.success("Configuration saved to ~/.agentx/auth.json"),console.log(` Provider: ${U.bold("anthropic")} (${t.authType})`),console.log(` Model: ${U.bold(B.find(n=>n.id===t.model)?.label||t.model)}`),t}async function _e(r){return N(r)?!0:(C.warn("No AI credentials configured."),C.break(),await ce()!==null)}var L=[{name:"create_files",description:"Create one or more files as output. Use this when you need to generate code, documents, configs, or any file-based output.",input_schema:{type:"object",properties:{files:{type:"array",items:{type:"object",properties:{path:{type:"string",description:"Relative file path from project root (e.g., src/components/Button.tsx)"},content:{type:"string",description:"The full content of the file"},language:{type:"string",description:"Programming language or file type"},description:{type:"string",description:"Brief description of what this file does"}},required:["path","content"]}},summary:{type:"string",description:"Brief summary of all generated files"}},required:["files"]},permission:"file-write"},{name:"ask_user",description:"Ask the user a clarifying question when you need more information to proceed. Use this when the request is ambiguous or you need to confirm important decisions.",input_schema:{type:"object",properties:{question:{type:"string",description:"The question to ask the user"},options:{type:"array",items:{type:"string"},description:"Optional list of choices for the user"}},required:["question"]},permission:"none"},{name:"read_file",description:"Read the contents of a file. Use this to inspect existing code, understand patterns, check implementations, or gather context before generating code.",input_schema:{type:"object",properties:{path:{type:"string",description:"Relative file path from project root"},max_lines:{type:"number",description:"Maximum number of lines to read. Defaults to 500. Use for large files."}},required:["path"]},permission:"file-read"},{name:"search_files",description:"Search for files matching a pattern and optionally search their content with a regex. Use this to find relevant code, understand project structure, or locate specific patterns.",input_schema:{type:"object",properties:{pattern:{type:"string",description:"Glob pattern to match files (e.g., 'src/**/*.ts', '*.json')"},content_regex:{type:"string",description:"Optional regex to search within matched files. Returns matching lines."},max_results:{type:"number",description:"Maximum number of results to return. Default: 50."}},required:["pattern"]},permission:"none"},{name:"list_directory",description:"List files and directories at a given path. Use this to explore project structure.",input_schema:{type:"object",properties:{path:{type:"string",description:"Relative directory path from project root. Defaults to '.' (root)."},recursive:{type:"boolean",description:"List recursively. Default: false."},max_depth:{type:"number",description:"Maximum depth for recursive listing. Default: 3."}}},permission:"none"},{name:"run_command",description:"Execute a shell command. Use this to run build tools, test commands, linters, or inspect the environment. Commands run in the project root directory.",input_schema:{type:"object",properties:{command:{type:"string",description:"The shell command to execute"},timeout:{type:"number",description:"Timeout in milliseconds. Default: 30000 (30 seconds)."}},required:["command"]},permission:"command"},{name:"edit_file",description:"Apply search-and-replace edits to an existing file. Use this for targeted modifications to existing code rather than rewriting entire files.",input_schema:{type:"object",properties:{path:{type:"string",description:"Relative file path from project root"},edits:{type:"array",items:{type:"object",properties:{old_text:{type:"string",description:"The exact text to find in the file"},new_text:{type:"string",description:"The replacement text"}},required:["old_text","new_text"]},description:"List of search/replace pairs to apply in order"}},required:["path","edits"]},permission:"file-write"},{name:"spawn_agent",description:"Spawn a sub-agent to handle a task in the background. The sub-agent runs in its own session and returns results. Use this for parallel research, long-running tasks, or delegating work to a specialized agent.",input_schema:{type:"object",properties:{agent_id:{type:"string",description:"The ID of the agent to spawn (must be a registered agent)"},prompt:{type:"string",description:"The task description for the sub-agent"},timeout_seconds:{type:"number",description:"Maximum time to wait for completion in seconds. Default: 300 (5 minutes)."}},required:["agent_id","prompt"]},permission:"none"}];function pe(r){return(r?L.filter(t=>r.includes(t.name)):L).map(({name:t,description:n,input_schema:o})=>({name:t,description:n,input_schema:o}))}function I(){return pe(["create_files","ask_user"])}function xe(){let r=L.filter(t=>t.name!=="create_files"&&t.name!=="ask_user");if(r.length===0)return"";let e=["# Available Capabilities","In addition to generating files, you have the following capabilities:",""];for(let t of r)e.push(`## ${t.name}`),e.push(t.description),e.push("");return e.join(`
|
|
2
|
-
`)}var Ae=L.map(r=>r.name);var V="claude-sonnet-4-20250514",W=8192,M=class{name="claude";apiKey;authType="api-key";constructor(e){if(this.apiKey=e||process.env.ANTHROPIC_API_KEY||"",!this.apiKey){let t=N();t&&(this.apiKey=t.token,this.authType=t.authType)}if(!this.apiKey)throw new Error("Anthropic API key required. Run `agentx model` to configure, set ANTHROPIC_API_KEY, or pass --api-key.")}async generate(e,t){let n=t?.model||V,o=t?.maxTokens||W,s=e.find(c=>c.role==="system"),u=e.filter(c=>c.role!=="system").map(c=>({role:c.role,content:c.content})),y={model:n,max_tokens:o,messages:u,tools:I()};s&&(y.system=s.content),t?.temperature!==void 0&&(y.temperature=t.temperature);let g=await this.callApi(y);return this.parseResponse(g)}async generateRaw(e,t,n,o){let s=o?.model||V,u=o?.maxTokens||W,y={model:s,max_tokens:u,system:t,messages:e,tools:n};o?.temperature!==void 0&&(y.temperature=o.temperature);let g=await this.callApi(y);return{content:g.content.map(d=>d.type==="text"?{type:"text",text:d.text||""}:d.type==="tool_use"?{type:"tool_use",id:d.id||"",name:d.name||"",input:d.input||{}}:{type:"text",text:""}),stop_reason:g.stop_reason,usage:g.usage}}async*stream(e,t){let n=t?.model||V,o=t?.maxTokens||W,s=e.find(f=>f.role==="system"),u=e.filter(f=>f.role!=="system").map(f=>({role:f.role,content:f.content})),y={model:n,max_tokens:o,messages:u,stream:!0,tools:I()};s&&(y.system=s.content);let g=this.buildHeaders(),c=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:g,body:JSON.stringify(y)});if(!c.ok){let f=await c.text();yield{type:"error",error:`Anthropic API error (${c.status}): ${f}`};return}let d=c.body?.getReader();if(!d){yield{type:"error",error:"No response body"};return}let m=new TextDecoder,l="",_=[],v="",w,A=0,i=null,k=f=>{let O=(f||"").trim();if(!O||O.includes("```"))return;let T=O.replace(/\r\n/g,`
|
|
3
|
-
`).split(`
|
|
4
|
-
`),x=T.slice(Math.max(0,T.length-20)),p=x.join(`
|
|
5
|
-
`);if(/\b(plan|proposal)\b/i.test(p)&&/(ready for your review|review (the )?plan|requesting plan approval|awaiting approval|waiting for (your )?approval|approve (the )?plan|approval to proceed)/i.test(p))return`The provider is requesting plan approval.
|
|
6
|
-
Reply with:
|
|
7
|
-
- approve
|
|
8
|
-
- revise: <what to change>
|
|
9
|
-
- cancel`;let h=b=>/^(question|clarification|clarify|i need|need more|before i proceed|to proceed|please (confirm|clarify)|which|what|where|when|how|do you)/i.test(b.trim()),D=-1;for(let b=x.length-1;b>=0;b--){let E=x[b].trim();if(E&&(h(E)||E.includes("?"))){D=b;break}}if(D===-1)return;let S=[];for(let b=D;b<x.length&&S.length<8;b++){let E=x[b],K=E.trim();if(S.length>0&&!K||S.length>0&&!/^(options?:|[-*]\s|\d+[\).]\s)/i.test(K)&&!K.includes("?"))break;S.push(E.trimEnd())}let $=S.join(`
|
|
10
|
-
`).trim();if(!($.length<5))return $.length>800?$.slice(0,800).trimEnd():$};try{for(;;){let{done:f,value:O}=await d.read();if(f)break;l+=m.decode(O,{stream:!0});let T=l.split(`
|
|
11
|
-
`);l=T.pop()||"";for(let x of T){if(!x.startsWith("data: "))continue;let p=x.slice(6).trim();if(p!=="[DONE]")try{let a=JSON.parse(p);if(a.type==="content_block_start"&&a.content_block?.type==="tool_use"){if(i){yield{type:"tool_use_end",name:i.name};try{let h=JSON.parse(i.json||"{}");i.name==="create_files"&&h&&(Array.isArray(h.files)&&_.push(...h.files),typeof h.summary=="string"&&h.summary.trim()&&(v+=`
|
|
12
|
-
${h.summary}`)),i.name==="ask_user"&&h&&typeof h.question=="string"&&h.question.trim()&&(w=h.question,Array.isArray(h.options)&&h.options.length&&(w+=`
|
|
13
|
-
Options: ${h.options.join(", ")}`))}catch{}finally{i=null}}i={name:a.content_block.name,id:a.content_block.id,json:""},yield{type:"tool_use_start",name:a.content_block.name,id:a.content_block.id}}if(a.type==="content_block_delta"&&(a.delta?.type==="text_delta"&&(v+=a.delta.text,yield{type:"text_delta",text:a.delta.text}),a.delta?.type==="input_json_delta"&&(i&&(i.json+=a.delta.partial_json||""),yield{type:"tool_use_delta",json:a.delta.partial_json})),a.type==="content_block_stop"&&i){yield{type:"tool_use_end",name:i.name};try{let h=JSON.parse(i.json||"{}");i.name==="create_files"&&h&&(Array.isArray(h.files)&&_.push(...h.files),typeof h.summary=="string"&&h.summary.trim()&&(v+=`
|
|
14
|
-
${h.summary}`)),i.name==="ask_user"&&h&&typeof h.question=="string"&&h.question.trim()&&(w=h.question,Array.isArray(h.options)&&h.options.length&&(w+=`
|
|
15
|
-
Options: ${h.options.join(", ")}`))}catch{}finally{i=null}}a.type==="message_delta"&&a.usage&&(A=(a.usage.input_tokens||0)+(a.usage.output_tokens||0)),a.type}catch{}}}}finally{d.releaseLock()}if(i){yield{type:"tool_use_end",name:i.name};try{let f=JSON.parse(i.json||"{}");i.name==="create_files"&&f&&(Array.isArray(f.files)&&_.push(...f.files),typeof f.summary=="string"&&f.summary.trim()&&(v+=`
|
|
16
|
-
${f.summary}`)),i.name==="ask_user"&&f&&typeof f.question=="string"&&f.question.trim()&&(w=f.question,Array.isArray(f.options)&&f.options.length&&(w+=`
|
|
17
|
-
Options: ${f.options.join(", ")}`))}catch{}i=null}!w&&_.length===0&&(w=k(v)),yield{type:"done",result:{content:v,files:_,followUp:w,tokensUsed:A}}}buildHeaders(){let e={"Content-Type":"application/json","anthropic-version":"2023-06-01"};return this.authType==="oauth"?(e.Authorization=`Bearer ${this.apiKey}`,e["anthropic-beta"]="claude-code-20250219,oauth-2025-04-20",e["user-agent"]="claude-cli/2.1.2 (external, cli)",e["x-app"]="cli",e["anthropic-dangerous-direct-browser-access"]="true"):e["x-api-key"]=this.apiKey,e}async callApi(e){let t=this.buildHeaders(),n=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:t,body:JSON.stringify(e)});if(!n.ok){let o=await n.text();throw new Error(`Anthropic API error (${n.status}): ${o}`)}return await n.json()}parseResponse(e){let t=[],n="",o;for(let s of e.content)if(s.type==="text"&&(n+=s.text||""),s.type==="tool_use"){if(s.name==="create_files"&&s.input){let u=s.input;t.push(...u.files||[]),u.summary&&(n+=`
|
|
18
|
-
${u.summary}`)}if(s.name==="ask_user"&&s.input){let u=s.input;o=u.question,u.options?.length&&(o+=`
|
|
19
|
-
Options: ${u.options.join(", ")}`)}}return{content:n,files:t,followUp:o,tokensUsed:e.usage.input_tokens+e.usage.output_tokens}}};import{execa as Z}from"execa";var F="claude-sonnet-4-20250514",z=8192,ee={"claude-sonnet-4-20250514":"sonnet","claude-opus-4-20250514":"opus","claude-haiku-4-20250514":"haiku"},G=class{name="claude-code";credential;constructor(){let e=R();if(e){this.credential={type:e.authType,token:e.token};return}let t=N();if(!t)throw new Error(`No Claude credentials found.
|
|
20
|
-
Options:
|
|
21
|
-
1. Run \`agentx model\` to configure credentials
|
|
22
|
-
2. Set ANTHROPIC_API_KEY environment variable
|
|
23
|
-
3. Set ANTHROPIC_OAUTH_TOKEN environment variable`);this.credential={type:t.authType,token:t.token}}async generate(e,t){return this.credential.type==="oauth"?this.generateViaCli(e,t):this.generateViaApi(e,t)}async generateRaw(e,t,n,o){if(this.credential.type==="oauth")throw new Error("generateRaw() not available for OAuth/CLI mode");let s=o?.model||F,u=o?.maxTokens||z,y={model:s,max_tokens:u,system:t,messages:e,tools:n};o?.temperature!==void 0&&(y.temperature=o.temperature);let g={"Content-Type":"application/json","anthropic-version":"2023-06-01","x-api-key":this.credential.token},c=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:g,body:JSON.stringify(y)});if(!c.ok){let l=await c.text();throw new Error(`Anthropic API error (${c.status}): ${l}`)}let d=await c.json();return{content:d.content.map(l=>l.type==="text"?{type:"text",text:l.text||""}:l.type==="tool_use"?{type:"tool_use",id:l.id||"",name:l.name||"",input:l.input||{}}:{type:"text",text:""}),stop_reason:d.stop_reason,usage:d.usage}}get supportsAgenticLoop(){return this.credential.type==="api-key"}async generateViaCli(e,t){let n=t?.model||R()?.model||F,o=ee[n]||n,s=e.find(l=>l.role==="system"),y=e.filter(l=>l.role==="user").map(l=>l.content).join(`
|
|
24
|
-
|
|
25
|
-
`),g=["-p","--output-format","json","--model",o,"--dangerously-skip-permissions"];s&&g.push("--append-system-prompt",s.content),g.push(y);let c={...process.env};delete c.ANTHROPIC_API_KEY,delete c.ANTHROPIC_API_KEY_OLD;let d=await Z("claude",g,{env:c,extendEnv:!1,reject:!1,timeout:3e5,stdin:"ignore"});if(d.exitCode!==0){let l=d.stderr||d.stdout||"Claude CLI failed";throw new Error(`Claude CLI error: ${l}`)}let m=d.stdout.trim();try{let l=JSON.parse(m);if(l.is_error&&l.result)throw new Error(l.result)}catch(l){if(l.message&&!l.message.includes("JSON"))throw l}return this.parseCliOutput(m)}async generateViaApi(e,t){let n=t?.model||F,o=t?.maxTokens||z,s=e.find(m=>m.role==="system"),u=e.filter(m=>m.role!=="system").map(m=>({role:m.role,content:m.content})),y={model:n,max_tokens:o,messages:u,tools:I()};s&&(y.system=s.content),t?.temperature!==void 0&&(y.temperature=t.temperature);let g={"Content-Type":"application/json","anthropic-version":"2023-06-01","x-api-key":this.credential.token},c=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:g,body:JSON.stringify(y)});if(!c.ok){let m=await c.text();throw new Error(`Anthropic API error (${c.status}): ${m}`)}let d=await c.json();return this.parseApiResponse(d)}async*stream(e,t){this.credential.type==="oauth"?yield*this.streamViaCli(e,t):yield*this.streamViaApi(e,t)}async*streamViaCli(e,t){let n=t?.model||R()?.model||F,o=ee[n]||n,s=e.find(i=>i.role==="system"),y=e.filter(i=>i.role==="user").map(i=>i.content).join(`
|
|
26
|
-
|
|
27
|
-
`),g=["-p","--output-format","stream-json","--model",o,"--dangerously-skip-permissions"];s&&g.push("--append-system-prompt",s.content),g.push(y);let c={...process.env};delete c.ANTHROPIC_API_KEY,delete c.ANTHROPIC_API_KEY_OLD;let d=Z("claude",g,{env:c,extendEnv:!1,reject:!1,timeout:3e5,stdin:"ignore"}),m="",l="",_;if(d.stderr&&d.stderr.on("data",i=>{l+=Buffer.isBuffer(i)?i.toString("utf8"):String(i)}),d.stdout){let i=new TextDecoder,k=d.stdout;for await(let f of k){let T=(typeof f=="string"?f:i.decode(f,{stream:!0})).split(`
|
|
28
|
-
`).filter(Boolean);for(let x of T)try{let p=JSON.parse(x);if(p.type==="error"){_=String(p.error||p.message||"Claude CLI error");continue}if(p.is_error&&(p.result||p.message)){_=String(p.result||p.message);continue}p.type==="assistant"&&p.message?(m+=p.message,yield{type:"text_delta",text:p.message}):p.type==="result"&&(m=p.result||m)}catch{m+=x,yield{type:"text_delta",text:x}}}}let v=await d;if(v.exitCode!==0&&!_&&(_=(l||v.stderr||v.stdout||"Claude CLI failed").toString().trim()),_){yield{type:"error",error:`Claude CLI error: ${_}`};return}let w=this.extractFilesFromText(m),A=w.length===0?this.inferFollowUpFromText(m):void 0;yield{type:"done",result:{content:m,files:w,followUp:A,tokensUsed:0}}}async*streamViaApi(e,t){let n=t?.model||F,o=t?.maxTokens||z,s=e.find(k=>k.role==="system"),u=e.filter(k=>k.role!=="system").map(k=>({role:k.role,content:k.content})),y={model:n,max_tokens:o,messages:u,tools:I(),stream:!0};s&&(y.system=s.content);let g={"Content-Type":"application/json","anthropic-version":"2023-06-01","x-api-key":this.credential.token},c=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:g,body:JSON.stringify(y)});if(!c.ok){let k=await c.text();yield{type:"error",error:`Anthropic API error (${c.status}): ${k}`};return}let d=c.body?.getReader();if(!d){yield{type:"error",error:"No response body"};return}let m=new TextDecoder,l="",_="",v=0,w=[],A,i=null;try{for(;;){let{done:k,value:f}=await d.read();if(k)break;l+=m.decode(f,{stream:!0});let O=l.split(`
|
|
29
|
-
`);l=O.pop()||"";for(let T of O){if(!T.startsWith("data: "))continue;let x=T.slice(6).trim();if(x!=="[DONE]")try{let p=JSON.parse(x);if(p.type==="content_block_start"&&p.content_block?.type==="tool_use"){if(i){yield{type:"tool_use_end",name:i.name};try{let a=JSON.parse(i.json||"{}");i.name==="create_files"&&a&&(Array.isArray(a.files)&&w.push(...a.files),typeof a.summary=="string"&&a.summary.trim()&&(_+=`
|
|
30
|
-
${a.summary}`)),i.name==="ask_user"&&a&&typeof a.question=="string"&&a.question.trim()&&(A=a.question,Array.isArray(a.options)&&a.options.length&&(A+=`
|
|
31
|
-
Options: ${a.options.join(", ")}`))}catch{}finally{i=null}}i={name:p.content_block.name,id:p.content_block.id,json:""},yield{type:"tool_use_start",name:i.name,id:i.id}}if(p.type==="content_block_delta"&&p.delta?.type==="text_delta"&&(_+=p.delta.text,yield{type:"text_delta",text:p.delta.text}),p.type==="content_block_delta"&&p.delta?.type==="input_json_delta"&&(i&&(i.json+=p.delta.partial_json||""),yield{type:"tool_use_delta",json:p.delta.partial_json}),p.type==="content_block_stop"&&i){yield{type:"tool_use_end",name:i.name};try{let a=JSON.parse(i.json||"{}");i.name==="create_files"&&a&&(Array.isArray(a.files)&&w.push(...a.files),typeof a.summary=="string"&&a.summary.trim()&&(_+=`
|
|
32
|
-
${a.summary}`)),i.name==="ask_user"&&a&&typeof a.question=="string"&&a.question.trim()&&(A=a.question,Array.isArray(a.options)&&a.options.length&&(A+=`
|
|
33
|
-
Options: ${a.options.join(", ")}`))}catch{}finally{i=null}}p.type==="message_delta"&&p.usage&&(v=(p.usage.input_tokens||0)+(p.usage.output_tokens||0))}catch{}}}}finally{d.releaseLock()}if(i){yield{type:"tool_use_end",name:i.name};try{let k=JSON.parse(i.json||"{}");i.name==="create_files"&&k&&(Array.isArray(k.files)&&w.push(...k.files),typeof k.summary=="string"&&k.summary.trim()&&(_+=`
|
|
34
|
-
${k.summary}`)),i.name==="ask_user"&&k&&typeof k.question=="string"&&k.question.trim()&&(A=k.question,Array.isArray(k.options)&&k.options.length&&(A+=`
|
|
35
|
-
Options: ${k.options.join(", ")}`))}catch{}i=null}w.length===0&&w.push(...this.extractFilesFromText(_)),!A&&w.length===0&&(A=this.inferFollowUpFromText(_)),yield{type:"done",result:{content:_,files:w,followUp:A,tokensUsed:v}}}parseCliOutput(e){let t;try{t=JSON.parse(e)}catch{let u=this.inferFollowUpFromText(e.trim());return{content:e.trim(),files:[],followUp:u,tokensUsed:0}}let n=t.result||t.text||t.content||"",o=this.extractFilesFromText(n),s=o.length===0?this.inferFollowUpFromText(n):void 0;return{content:n,files:o,followUp:s,tokensUsed:t.usage?(t.usage.input_tokens||0)+(t.usage.output_tokens||0):0}}extractFilesFromText(e){let t=[],n=/```[\w]*\s*([\w/._-]+\.\w+)\n([\s\S]*?)```/g,o;for(;(o=n.exec(e))!==null;){let s=o[1],u=o[2];s&&u&&t.push({path:s,content:u.trimEnd()})}return t}inferFollowUpFromText(e){let t=(e||"").trim();if(!t||t.includes("```"))return;let n=t.replace(/\r\n/g,`
|
|
36
|
-
`).split(`
|
|
37
|
-
`),o=n.slice(Math.max(0,n.length-20)),s=o.join(`
|
|
38
|
-
`);if(/\b(plan|proposal)\b/i.test(s)&&/(ready for your review|review (the )?plan|requesting plan approval|awaiting approval|waiting for (your )?approval|approve (the )?plan|approval to proceed)/i.test(s))return`The provider is requesting plan approval.
|
|
39
|
-
Reply with:
|
|
40
|
-
- approve
|
|
41
|
-
- revise: <what to change>
|
|
42
|
-
- cancel`;let y=m=>/^(question|clarification|clarify|i need|need more|before i proceed|to proceed|please (confirm|clarify)|which|what|where|when|how|do you)/i.test(m.trim()),g=-1;for(let m=o.length-1;m>=0;m--){let l=o[m].trim();if(l&&(y(l)||l.includes("?"))){g=m;break}}if(g===-1)return;let c=[];for(let m=g;m<o.length&&c.length<8;m++){let l=o[m],_=l.trim();if(c.length>0&&!_||c.length>0&&!/^(options?:|[-*]\s|\d+[\).]\s)/i.test(_)&&!_.includes("?"))break;c.push(l.trimEnd())}let d=c.join(`
|
|
43
|
-
`).trim();if(!(d.length<5))return d.length>800?d.slice(0,800).trimEnd():d}parseApiResponse(e){let t=[],n="",o;for(let s of e.content)if(s.type==="text"&&(n+=s.text||""),s.type==="tool_use"){if(s.name==="create_files"&&s.input){let u=s.input;t.push(...u.files||[]),u.summary&&(n+=`
|
|
44
|
-
${u.summary}`)}if(s.name==="ask_user"&&s.input){let u=s.input;o=u.question,u.options?.length&&(o+=`
|
|
45
|
-
Options: ${u.options.join(", ")}`)}}return{content:n,files:t,followUp:o,tokensUsed:e.usage.input_tokens+e.usage.output_tokens}}};function Ne(r="claude-code",e){let t=r;if(r==="claude-code"&&!e){let n=R();n&&(t=n.provider)}switch(t){case"claude-code":return new G;case"claude":return new M(e);case"openai":throw new Error("OpenAI provider coming soon. Set provider to 'claude-code' or contribute at github.com/anis-marrouchi/agentx");case"ollama":throw new Error("Ollama provider coming soon. Set provider to 'claude-code' or contribute at github.com/anis-marrouchi/agentx");default:throw new Error(`Unknown provider: ${t}. Supported: claude-code, claude`)}}export{C as a,R as b,oe as c,N as d,ce as e,_e as f,pe as g,I as h,xe as i,Ae as j,M as k,G as l,Ne as m};
|
|
46
|
-
//# sourceMappingURL=chunk-HCFSHGK4.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/auth-store.ts","../src/utils/logger.ts","../src/agent/tools/definitions.ts","../src/agent/providers/claude.ts","../src/agent/providers/claude-code.ts","../src/agent/providers/index.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync, mkdirSync } from \"fs\"\nimport path from \"path\"\nimport os from \"os\"\nimport chalk from \"chalk\"\nimport prompts from \"prompts\"\nimport { logger } from \"@/utils/logger\"\n\n// --- Auth config stored at ~/.agentx/auth.json ---\n\nexport interface AuthConfig {\n provider: \"claude\" | \"claude-code\"\n authType: \"api-key\" | \"oauth\"\n token: string\n model: string\n}\n\nconst AUTH_DIR = path.join(os.homedir(), \".agentx\")\nconst AUTH_FILE = path.join(AUTH_DIR, \"auth.json\")\n\nexport function loadAuthConfig(): AuthConfig | null {\n if (!existsSync(AUTH_FILE)) return null\n try {\n const data = JSON.parse(readFileSync(AUTH_FILE, \"utf8\"))\n if (data.provider && data.authType && data.token && data.model) {\n return data as AuthConfig\n }\n return null\n } catch {\n return null\n }\n}\n\nexport function saveAuthConfig(config: AuthConfig): void {\n if (!existsSync(AUTH_DIR)) {\n mkdirSync(AUTH_DIR, { recursive: true })\n }\n writeFileSync(AUTH_FILE, JSON.stringify(config, null, 2), \"utf8\")\n}\n\n/**\n * Resolve a token for the Anthropic API.\n * Priority: (1) explicit token, (2) env vars, (3) ~/.agentx/auth.json, (4) OpenClaw auth stores\n */\nexport function resolveToken(explicitKey?: string): {\n token: string\n authType: \"api-key\" | \"oauth\"\n} | null {\n // 1. Explicit CLI flag\n if (explicitKey?.trim()) {\n const type = explicitKey.startsWith(\"sk-ant-oat\") ? \"oauth\" : \"api-key\"\n return { token: explicitKey.trim(), authType: type }\n }\n\n // 2. Environment variables\n const envOAuth = process.env.ANTHROPIC_OAUTH_TOKEN\n if (envOAuth?.trim()) {\n return { token: envOAuth.trim(), authType: \"oauth\" }\n }\n\n // Claude Code's native env var (sk-ant-oat01-...). Same OAuth token format\n // as ANTHROPIC_OAUTH_TOKEN but Claude Code sets it under its own name, so\n // without this fallback the SDK providers fail to resolve even though the\n // `claude` CLI in the same shell works fine. Enables the context planner\n // to use the fast SDK path instead of cold-spawning a subprocess.\n const envClaudeCodeOAuth = process.env.CLAUDE_CODE_OAUTH_TOKEN\n if (envClaudeCodeOAuth?.trim()) {\n return { token: envClaudeCodeOAuth.trim(), authType: \"oauth\" }\n }\n\n const envApiKey = process.env.ANTHROPIC_API_KEY\n if (envApiKey?.trim()) {\n return { token: envApiKey.trim(), authType: \"api-key\" }\n }\n\n // 3. Stored config\n const stored = loadAuthConfig()\n if (stored) {\n return { token: stored.token, authType: stored.authType }\n }\n\n // 4. OpenClaw auth-profiles store (legacy fallback)\n const homeDir = os.homedir()\n const storePaths = [\n path.join(homeDir, \".openclaw\", \"agents\", \"main\", \"agent\", \"auth-profiles.json\"),\n path.join(homeDir, \".openclaw\", \"auth-profiles.json\"),\n path.join(homeDir, \".openclaw\", \"credentials\", \"oauth.json\"),\n path.join(homeDir, \".claude\", \"oauth.json\"),\n path.join(homeDir, \".config\", \"claude\", \"oauth.json\"),\n path.join(homeDir, \".config\", \"anthropic\", \"oauth.json\"),\n ]\n\n for (const p of storePaths) {\n const t = readTokenFromAuthProfiles(p)\n if (t) {\n return { token: t, authType: \"oauth\" }\n }\n }\n\n return null\n}\n\n/**\n * Read an Anthropic OAuth/token credential from an auth-profiles or oauth JSON file.\n */\nfunction readTokenFromAuthProfiles(filePath: string): string {\n if (!existsSync(filePath)) return \"\"\n\n try {\n const data = JSON.parse(readFileSync(filePath, \"utf8\"))\n\n // Modern auth-profiles format: { profiles: { \"anthropic:xxx\": { type, access/token } } }\n if (data.profiles) {\n let fallbackToken = \"\"\n for (const [id, cred] of Object.entries(data.profiles) as [string, any][]) {\n if (!id.startsWith(\"anthropic\")) continue\n if (cred.type === \"oauth\" && cred.access) {\n if (cred.expires && Date.now() > cred.expires) {\n continue\n }\n return cred.access\n }\n if (cred.type === \"token\" && cred.token) {\n fallbackToken = cred.token\n }\n }\n if (fallbackToken) return fallbackToken\n }\n\n // Legacy oauth.json format: { anthropic: { access: \"...\" } }\n if (data.anthropic?.access) return data.anthropic.access\n if (data.anthropic?.token) return data.anthropic.token\n\n return \"\"\n } catch {\n return \"\"\n }\n}\n\n// --- Model setup & credentials ---\n\nconst ANTHROPIC_MODELS = [\n { id: \"claude-sonnet-4-20250514\", label: \"anthropic/claude-sonnet-4\", hint: \"Claude Sonnet 4 · ctx 200k · recommended\" },\n { id: \"claude-opus-4-20250514\", label: \"anthropic/claude-opus-4-5\", hint: \"Claude Opus 4.5 · ctx 200k · reasoning\" },\n { id: \"claude-haiku-4-20250514\", label: \"anthropic/claude-haiku-4\", hint: \"Claude Haiku 4 · ctx 200k · fast\" },\n]\n\nasync function handleApiKey(): Promise<{ token: string; authType: \"api-key\" } | null> {\n const envKey = process.env.ANTHROPIC_API_KEY\n if (envKey?.trim()) {\n const preview = envKey.slice(0, 10) + \"...\" + envKey.slice(-4)\n const { useExisting } = await prompts({\n type: \"confirm\",\n name: \"useExisting\",\n message: `Use existing ANTHROPIC_API_KEY (env, ${preview})?`,\n initial: true,\n })\n\n if (useExisting) {\n return { token: envKey.trim(), authType: \"api-key\" }\n }\n }\n\n const stored = loadAuthConfig()\n if (stored?.authType === \"api-key\" && stored.token) {\n const preview = stored.token.slice(0, 10) + \"...\" + stored.token.slice(-4)\n const { useExisting } = await prompts({\n type: \"confirm\",\n name: \"useExisting\",\n message: `Use stored API key (${preview})?`,\n initial: true,\n })\n\n if (useExisting) {\n return { token: stored.token, authType: \"api-key\" }\n }\n }\n\n const { apiKey } = await prompts({\n type: \"password\",\n name: \"apiKey\",\n message: \"Enter Anthropic API key\",\n validate: (v: string) => {\n if (!v.startsWith(\"sk-ant-api\")) return \"API key must start with sk-ant-api\"\n if (v.length < 40) return \"API key seems too short\"\n return true\n },\n })\n\n if (!apiKey) return null\n return { token: apiKey, authType: \"api-key\" }\n}\n\nasync function handleSetupToken(): Promise<{ token: string; authType: \"oauth\" } | null> {\n logger.break()\n const boxWidth = 46\n const line1 = \"Run `claude setup-token` in your terminal.\"\n const line2 = \"Then paste the generated token below.\"\n console.log(` ${chalk.cyan(\"Anthropic setup-token\")} ${\"─\".repeat(boxWidth - \"Anthropic setup-token\".length - 1)}╮`)\n console.log(` ${\" \".repeat(boxWidth)}│`)\n console.log(` ${line1}${\" \".repeat(boxWidth - line1.length)}│`)\n console.log(` ${line2}${\" \".repeat(boxWidth - line2.length)}│`)\n console.log(` ${\" \".repeat(boxWidth)}│`)\n console.log(` ${\"─\".repeat(boxWidth)}╯`)\n logger.break()\n\n const { token } = await prompts({\n type: \"password\",\n name: \"token\",\n message: \"Paste Anthropic setup-token\",\n validate: (v: string) => {\n if (!v.trim()) return \"Token is required\"\n if (v.length < 40) return \"Token seems too short\"\n return true\n },\n })\n\n if (!token) return null\n\n const { tokenName } = await prompts({\n type: \"text\",\n name: \"tokenName\",\n message: \"Token name (blank = default)\",\n })\n\n return { token, authType: \"oauth\" }\n}\n\ntype AuthResult = { token: string; authType: \"api-key\" | \"oauth\" } | null\n\nasync function selectAuthMethod(): Promise<AuthResult> {\n while (true) {\n const { provider } = await prompts({\n type: \"select\",\n name: \"provider\",\n message: \"Model/auth provider\",\n choices: [\n { title: \"Anthropic\", value: \"anthropic\", description: \"setup-token + API key\" },\n ],\n })\n\n if (provider === undefined) return null\n\n const { method } = await prompts({\n type: \"select\",\n name: \"method\",\n message: \"Anthropic auth method\",\n choices: [\n { title: \"Anthropic token (paste setup-token)\", value: \"setup-token\", description: \"run `claude setup-token` elsewhere, then paste the token here\" },\n { title: \"Anthropic API key\", value: \"api-key\" },\n { title: chalk.dim(\"Back\"), value: \"back\" },\n ],\n })\n\n if (method === undefined) return null\n if (method === \"back\") continue\n\n if (method === \"api-key\") return handleApiKey()\n if (method === \"setup-token\") return handleSetupToken()\n\n return null\n }\n}\n\nasync function selectModel(): Promise<string | null> {\n const stored = loadAuthConfig()\n\n const choices = ANTHROPIC_MODELS.map((m) => ({\n title: m.label,\n value: m.id,\n description: m.hint + (stored?.model === m.id ? \" · current\" : \"\"),\n }))\n\n if (stored?.model) {\n const current = ANTHROPIC_MODELS.find((m) => m.id === stored.model)\n const label = current ? current.label : stored.model\n choices.unshift({\n title: `Keep current (${label})`,\n value: stored.model,\n description: \"no change\",\n })\n }\n\n const { modelId } = await prompts({\n type: \"select\",\n name: \"modelId\",\n message: \"Default model\",\n choices,\n })\n\n return modelId || null\n}\n\n/**\n * Reusable interactive setup flow. Returns the saved config, or null if the user cancelled.\n */\nexport async function runModelSetup(): Promise<AuthConfig | null> {\n const auth = await selectAuthMethod()\n if (!auth) return null\n\n const modelId = await selectModel()\n if (!modelId) return null\n\n const config: AuthConfig = {\n provider: auth.authType === \"oauth\" ? \"claude-code\" : \"claude\",\n authType: auth.authType,\n token: auth.token,\n model: modelId,\n }\n\n saveAuthConfig(config)\n\n logger.break()\n logger.success(\"Configuration saved to ~/.agentx/auth.json\")\n console.log(` Provider: ${chalk.bold(\"anthropic\")} (${config.authType})`)\n console.log(` Model: ${chalk.bold(ANTHROPIC_MODELS.find((m) => m.id === config.model)?.label || config.model)}`)\n\n return config\n}\n\n/**\n * Ensure credentials are available. If not, auto-prompt the interactive setup.\n * Returns true if credentials are ready, false if user cancelled.\n */\nexport async function ensureCredentials(explicitKey?: string): Promise<boolean> {\n const resolved = resolveToken(explicitKey)\n if (resolved) return true\n\n logger.warn(\"No AI credentials configured.\")\n logger.break()\n\n const result = await runModelSetup()\n return result !== null\n}\n","import chalk from \"chalk\"\n\nexport const logger = {\n error(...args: unknown[]) {\n console.log(chalk.red(...args))\n },\n warn(...args: unknown[]) {\n console.log(chalk.yellow(...args))\n },\n info(...args: unknown[]) {\n console.log(chalk.cyan(...args))\n },\n success(...args: unknown[]) {\n console.log(chalk.green(...args))\n },\n break() {\n console.log(\"\")\n },\n}\n","// --- Agent tool definitions in Anthropic tool_use format ---\n\nexport interface ToolDefinition {\n name: string\n description: string\n input_schema: Record<string, unknown>\n permission?: \"file-read\" | \"file-write\" | \"command\" | \"none\"\n}\n\nconst TOOL_DEFINITIONS: ToolDefinition[] = [\n {\n name: \"create_files\",\n description:\n \"Create one or more files as output. Use this when you need to generate code, documents, configs, or any file-based output.\",\n input_schema: {\n type: \"object\",\n properties: {\n files: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n path: {\n type: \"string\",\n description:\n \"Relative file path from project root (e.g., src/components/Button.tsx)\",\n },\n content: {\n type: \"string\",\n description: \"The full content of the file\",\n },\n language: {\n type: \"string\",\n description: \"Programming language or file type\",\n },\n description: {\n type: \"string\",\n description: \"Brief description of what this file does\",\n },\n },\n required: [\"path\", \"content\"],\n },\n },\n summary: {\n type: \"string\",\n description: \"Brief summary of all generated files\",\n },\n },\n required: [\"files\"],\n },\n permission: \"file-write\",\n },\n {\n name: \"ask_user\",\n description:\n \"Ask the user a clarifying question when you need more information to proceed. Use this when the request is ambiguous or you need to confirm important decisions.\",\n input_schema: {\n type: \"object\",\n properties: {\n question: {\n type: \"string\",\n description: \"The question to ask the user\",\n },\n options: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Optional list of choices for the user\",\n },\n },\n required: [\"question\"],\n },\n permission: \"none\",\n },\n {\n name: \"read_file\",\n description:\n \"Read the contents of a file. Use this to inspect existing code, understand patterns, check implementations, or gather context before generating code.\",\n input_schema: {\n type: \"object\",\n properties: {\n path: {\n type: \"string\",\n description: \"Relative file path from project root\",\n },\n max_lines: {\n type: \"number\",\n description:\n \"Maximum number of lines to read. Defaults to 500. Use for large files.\",\n },\n },\n required: [\"path\"],\n },\n permission: \"file-read\",\n },\n {\n name: \"search_files\",\n description:\n \"Search for files matching a pattern and optionally search their content with a regex. Use this to find relevant code, understand project structure, or locate specific patterns.\",\n input_schema: {\n type: \"object\",\n properties: {\n pattern: {\n type: \"string\",\n description:\n \"Glob pattern to match files (e.g., 'src/**/*.ts', '*.json')\",\n },\n content_regex: {\n type: \"string\",\n description:\n \"Optional regex to search within matched files. Returns matching lines.\",\n },\n max_results: {\n type: \"number\",\n description: \"Maximum number of results to return. Default: 50.\",\n },\n },\n required: [\"pattern\"],\n },\n permission: \"none\",\n },\n {\n name: \"list_directory\",\n description:\n \"List files and directories at a given path. Use this to explore project structure.\",\n input_schema: {\n type: \"object\",\n properties: {\n path: {\n type: \"string\",\n description:\n \"Relative directory path from project root. Defaults to '.' (root).\",\n },\n recursive: {\n type: \"boolean\",\n description: \"List recursively. Default: false.\",\n },\n max_depth: {\n type: \"number\",\n description: \"Maximum depth for recursive listing. Default: 3.\",\n },\n },\n },\n permission: \"none\",\n },\n {\n name: \"run_command\",\n description:\n \"Execute a shell command. Use this to run build tools, test commands, linters, or inspect the environment. Commands run in the project root directory.\",\n input_schema: {\n type: \"object\",\n properties: {\n command: {\n type: \"string\",\n description: \"The shell command to execute\",\n },\n timeout: {\n type: \"number\",\n description:\n \"Timeout in milliseconds. Default: 30000 (30 seconds).\",\n },\n },\n required: [\"command\"],\n },\n permission: \"command\",\n },\n {\n name: \"edit_file\",\n description:\n \"Apply search-and-replace edits to an existing file. Use this for targeted modifications to existing code rather than rewriting entire files.\",\n input_schema: {\n type: \"object\",\n properties: {\n path: {\n type: \"string\",\n description: \"Relative file path from project root\",\n },\n edits: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n old_text: {\n type: \"string\",\n description: \"The exact text to find in the file\",\n },\n new_text: {\n type: \"string\",\n description: \"The replacement text\",\n },\n },\n required: [\"old_text\", \"new_text\"],\n },\n description: \"List of search/replace pairs to apply in order\",\n },\n },\n required: [\"path\", \"edits\"],\n },\n permission: \"file-write\",\n },\n {\n name: \"spawn_agent\",\n description:\n \"Spawn a sub-agent to handle a task in the background. The sub-agent runs in its own session and returns results. Use this for parallel research, long-running tasks, or delegating work to a specialized agent.\",\n input_schema: {\n type: \"object\",\n properties: {\n agent_id: {\n type: \"string\",\n description: \"The ID of the agent to spawn (must be a registered agent)\",\n },\n prompt: {\n type: \"string\",\n description: \"The task description for the sub-agent\",\n },\n timeout_seconds: {\n type: \"number\",\n description: \"Maximum time to wait for completion in seconds. Default: 300 (5 minutes).\",\n },\n },\n required: [\"agent_id\", \"prompt\"],\n },\n permission: \"none\",\n },\n]\n\n/**\n * Get all tool definitions in Anthropic API format (for generateRaw()).\n * Optionally filter by enabled tool names.\n */\nexport function getAnthropicTools(enabledTools?: string[]): Array<{\n name: string\n description: string\n input_schema: Record<string, unknown>\n}> {\n const defs = enabledTools\n ? TOOL_DEFINITIONS.filter((t) => enabledTools.includes(t.name))\n : TOOL_DEFINITIONS\n\n return defs.map(({ name, description, input_schema }) => ({\n name,\n description,\n input_schema,\n }))\n}\n\n/**\n * Get the legacy tools (create_files + ask_user) for backward compatibility.\n */\nexport function getLegacyTools(): Array<{\n name: string\n description: string\n input_schema: Record<string, unknown>\n}> {\n return getAnthropicTools([\"create_files\", \"ask_user\"])\n}\n\n/**\n * Format tool descriptions for inclusion in a system prompt.\n * Used when the `claude` CLI binary handles its own tools —\n * we describe our additional tools as text so the binary's built-in\n * capabilities (read, write, bash) handle them natively.\n */\nexport function formatToolsForSystemPrompt(): string {\n const agenticTools = TOOL_DEFINITIONS.filter(\n (t) => t.name !== \"create_files\" && t.name !== \"ask_user\"\n )\n\n if (agenticTools.length === 0) return \"\"\n\n const lines = [\n \"# Available Capabilities\",\n \"In addition to generating files, you have the following capabilities:\",\n \"\",\n ]\n\n for (const tool of agenticTools) {\n lines.push(`## ${tool.name}`)\n lines.push(tool.description)\n lines.push(\"\")\n }\n\n return lines.join(\"\\n\")\n}\n\nexport const ALL_TOOL_NAMES = TOOL_DEFINITIONS.map((t) => t.name)\n","import type {\n AgentProvider,\n GenerationMessage,\n GenerationResult,\n GeneratedFile,\n ProviderOptions,\n StreamEvent,\n AnthropicMessage,\n RawGenerationResult,\n ContentBlock,\n} from \"./types\"\nimport { resolveToken } from \"@/utils/auth-store\"\nimport { getLegacyTools } from \"../tools/definitions\"\n\n// --- Claude provider (default) using Anthropic SDK ---\n\nconst DEFAULT_MODEL = \"claude-sonnet-4-20250514\"\nconst DEFAULT_MAX_TOKENS = 8192\n\ninterface AnthropicResponse {\n id: string\n content: Array<{\n type: \"text\" | \"tool_use\" | \"tool_result\"\n text?: string\n id?: string\n name?: string\n input?: Record<string, unknown>\n tool_use_id?: string\n content?: string\n }>\n model: string\n stop_reason: string\n usage: { input_tokens: number; output_tokens: number }\n}\n\nexport class ClaudeProvider implements AgentProvider {\n name = \"claude\"\n private apiKey: string\n private authType: \"api-key\" | \"oauth\" = \"api-key\"\n\n constructor(apiKey?: string) {\n this.apiKey = apiKey || process.env.ANTHROPIC_API_KEY || \"\"\n if (!this.apiKey) {\n // Fallback to auth store\n const resolved = resolveToken()\n if (resolved) {\n this.apiKey = resolved.token\n this.authType = resolved.authType\n }\n }\n if (!this.apiKey) {\n throw new Error(\n \"Anthropic API key required. Run `agentx model` to configure, set ANTHROPIC_API_KEY, or pass --api-key.\"\n )\n }\n }\n\n async generate(\n messages: GenerationMessage[],\n options?: ProviderOptions\n ): Promise<GenerationResult> {\n const model = options?.model || DEFAULT_MODEL\n const maxTokens = options?.maxTokens || DEFAULT_MAX_TOKENS\n\n // Extract system message\n const systemMsg = messages.find((m) => m.role === \"system\")\n const conversationMsgs = messages\n .filter((m) => m.role !== \"system\")\n .map((m) => ({\n role: m.role as \"user\" | \"assistant\",\n content: m.content,\n }))\n\n const body: Record<string, unknown> = {\n model,\n max_tokens: maxTokens,\n messages: conversationMsgs,\n tools: getLegacyTools(),\n }\n\n if (systemMsg) {\n body.system = systemMsg.content\n }\n\n if (options?.temperature !== undefined) {\n body.temperature = options.temperature\n }\n\n const response = await this.callApi(body)\n\n return this.parseResponse(response)\n }\n\n async generateRaw(\n messages: AnthropicMessage[],\n systemPrompt: string,\n tools: Array<{ name: string; description: string; input_schema: Record<string, unknown> }>,\n options?: ProviderOptions\n ): Promise<RawGenerationResult> {\n const model = options?.model || DEFAULT_MODEL\n const maxTokens = options?.maxTokens || DEFAULT_MAX_TOKENS\n\n const body: Record<string, unknown> = {\n model,\n max_tokens: maxTokens,\n system: systemPrompt,\n messages,\n tools,\n }\n\n if (options?.temperature !== undefined) {\n body.temperature = options.temperature\n }\n\n const response = await this.callApi(body)\n\n // Map response content blocks to our ContentBlock type\n const content: ContentBlock[] = response.content.map((block) => {\n if (block.type === \"text\") {\n return { type: \"text\" as const, text: block.text || \"\" }\n }\n if (block.type === \"tool_use\") {\n return {\n type: \"tool_use\" as const,\n id: block.id || \"\",\n name: block.name || \"\",\n input: block.input || {},\n }\n }\n return { type: \"text\" as const, text: \"\" }\n })\n\n return {\n content,\n stop_reason: response.stop_reason as RawGenerationResult[\"stop_reason\"],\n usage: response.usage,\n }\n }\n\n async *stream(\n messages: GenerationMessage[],\n options?: ProviderOptions\n ): AsyncIterable<StreamEvent> {\n const model = options?.model || DEFAULT_MODEL\n const maxTokens = options?.maxTokens || DEFAULT_MAX_TOKENS\n\n const systemMsg = messages.find((m) => m.role === \"system\")\n const conversationMsgs = messages\n .filter((m) => m.role !== \"system\")\n .map((m) => ({\n role: m.role as \"user\" | \"assistant\",\n content: m.content,\n }))\n\n const body: Record<string, unknown> = {\n model,\n max_tokens: maxTokens,\n messages: conversationMsgs,\n stream: true,\n tools: getLegacyTools(),\n }\n\n if (systemMsg) {\n body.system = systemMsg.content\n }\n\n const headers = this.buildHeaders()\n\n const res = await fetch(\"https://api.anthropic.com/v1/messages\", {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n })\n\n if (!res.ok) {\n const errorText = await res.text()\n yield { type: \"error\", error: `Anthropic API error (${res.status}): ${errorText}` }\n return\n }\n\n const reader = res.body?.getReader()\n if (!reader) {\n yield { type: \"error\", error: \"No response body\" }\n return\n }\n\n const decoder = new TextDecoder()\n let buffer = \"\"\n const files: GeneratedFile[] = []\n let content = \"\"\n let followUp: string | undefined\n let tokensUsed = 0\n let activeTool: { name: string; id: string; json: string } | null = null\n\n const inferFollowUpFromText = (text: string): string | undefined => {\n const cleaned = (text || \"\").trim()\n if (!cleaned) return undefined\n if (cleaned.includes(\"```\")) return undefined\n\n const lines = cleaned.replace(/\\r\\n/g, \"\\n\").split(\"\\n\")\n const tail = lines.slice(Math.max(0, lines.length - 20))\n const tailText = tail.join(\"\\n\")\n\n const looksLikePlanApproval =\n /\\b(plan|proposal)\\b/i.test(tailText) &&\n /(ready for your review|review (the )?plan|requesting plan approval|awaiting approval|waiting for (your )?approval|approve (the )?plan|approval to proceed)/i.test(\n tailText\n )\n\n if (looksLikePlanApproval) {\n return (\n \"The provider is requesting plan approval.\\n\" +\n \"Reply with:\\n\" +\n \"- approve\\n\" +\n \"- revise: <what to change>\\n\" +\n \"- cancel\"\n )\n }\n\n const isIntro = (l: string) =>\n /^(question|clarification|clarify|i need|need more|before i proceed|to proceed|please (confirm|clarify)|which|what|where|when|how|do you)/i.test(\n l.trim()\n )\n\n let startIdx = -1\n for (let i = tail.length - 1; i >= 0; i--) {\n const l = tail[i].trim()\n if (!l) continue\n if (isIntro(l) || l.includes(\"?\")) {\n startIdx = i\n break\n }\n }\n if (startIdx === -1) return undefined\n\n const out: string[] = []\n for (let i = startIdx; i < tail.length && out.length < 8; i++) {\n const l = tail[i]\n const t = l.trim()\n if (out.length > 0 && !t) break\n if (\n out.length > 0 &&\n !/^(options?:|[-*]\\s|\\d+[\\).]\\s)/i.test(t) &&\n !t.includes(\"?\")\n ) {\n break\n }\n out.push(l.trimEnd())\n }\n\n const candidate = out.join(\"\\n\").trim()\n if (candidate.length < 5) return undefined\n if (candidate.length > 800) return candidate.slice(0, 800).trimEnd()\n return candidate\n }\n\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n buffer += decoder.decode(value, { stream: true })\n const lines = buffer.split(\"\\n\")\n buffer = lines.pop() || \"\"\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) continue\n const data = line.slice(6).trim()\n if (data === \"[DONE]\") continue\n\n try {\n const event = JSON.parse(data)\n\n if (event.type === \"content_block_start\") {\n if (event.content_block?.type === \"tool_use\") {\n // Finalize any previous tool block if the stream didn't send a stop.\n if (activeTool) {\n yield { type: \"tool_use_end\", name: activeTool.name }\n try {\n const input = JSON.parse(activeTool.json || \"{}\") as any\n if (activeTool.name === \"create_files\" && input) {\n if (Array.isArray(input.files)) {\n files.push(...(input.files as GeneratedFile[]))\n }\n if (typeof input.summary === \"string\" && input.summary.trim()) {\n content += `\\n${input.summary}`\n }\n }\n if (activeTool.name === \"ask_user\" && input) {\n if (typeof input.question === \"string\" && input.question.trim()) {\n followUp = input.question\n if (Array.isArray(input.options) && input.options.length) {\n followUp += `\\nOptions: ${input.options.join(\", \")}`\n }\n }\n }\n } catch {\n // Ignore invalid tool JSON\n } finally {\n activeTool = null\n }\n }\n\n activeTool = {\n name: event.content_block.name,\n id: event.content_block.id,\n json: \"\",\n }\n yield {\n type: \"tool_use_start\",\n name: event.content_block.name,\n id: event.content_block.id,\n }\n }\n }\n\n if (event.type === \"content_block_delta\") {\n if (event.delta?.type === \"text_delta\") {\n content += event.delta.text\n yield { type: \"text_delta\", text: event.delta.text }\n }\n if (event.delta?.type === \"input_json_delta\") {\n if (activeTool) activeTool.json += event.delta.partial_json || \"\"\n yield { type: \"tool_use_delta\", json: event.delta.partial_json }\n }\n }\n\n if (event.type === \"content_block_stop\") {\n // Tool use blocks are complete\n if (activeTool) {\n // Manually inline finalize to avoid generator gymnastics.\n yield { type: \"tool_use_end\", name: activeTool.name }\n try {\n const input = JSON.parse(activeTool.json || \"{}\") as any\n if (activeTool.name === \"create_files\" && input) {\n if (Array.isArray(input.files)) {\n files.push(...(input.files as GeneratedFile[]))\n }\n if (typeof input.summary === \"string\" && input.summary.trim()) {\n content += `\\n${input.summary}`\n }\n }\n if (activeTool.name === \"ask_user\" && input) {\n if (typeof input.question === \"string\" && input.question.trim()) {\n followUp = input.question\n if (Array.isArray(input.options) && input.options.length) {\n followUp += `\\nOptions: ${input.options.join(\", \")}`\n }\n }\n }\n } catch {\n // Ignore invalid tool JSON\n } finally {\n activeTool = null\n }\n }\n }\n\n if (event.type === \"message_delta\") {\n if (event.usage) {\n tokensUsed = (event.usage.input_tokens || 0) + (event.usage.output_tokens || 0)\n }\n }\n\n if (event.type === \"message_stop\") {\n // Message complete\n }\n } catch {\n // Skip unparseable lines\n }\n }\n }\n } finally {\n reader.releaseLock()\n }\n\n // Flush any trailing tool input.\n if (activeTool) {\n yield { type: \"tool_use_end\", name: activeTool.name }\n try {\n const input = JSON.parse(activeTool.json || \"{}\") as any\n if (activeTool.name === \"create_files\" && input) {\n if (Array.isArray(input.files)) {\n files.push(...(input.files as GeneratedFile[]))\n }\n if (typeof input.summary === \"string\" && input.summary.trim()) {\n content += `\\n${input.summary}`\n }\n }\n if (activeTool.name === \"ask_user\" && input) {\n if (typeof input.question === \"string\" && input.question.trim()) {\n followUp = input.question\n if (Array.isArray(input.options) && input.options.length) {\n followUp += `\\nOptions: ${input.options.join(\", \")}`\n }\n }\n }\n } catch {\n // Ignore\n }\n activeTool = null\n }\n\n if (!followUp && files.length === 0) {\n followUp = inferFollowUpFromText(content)\n }\n\n yield {\n type: \"done\",\n result: { content, files, followUp, tokensUsed },\n }\n }\n\n private buildHeaders(): Record<string, string> {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"anthropic-version\": \"2023-06-01\",\n }\n\n if (this.authType === \"oauth\") {\n headers[\"Authorization\"] = `Bearer ${this.apiKey}`\n headers[\"anthropic-beta\"] = \"claude-code-20250219,oauth-2025-04-20\"\n headers[\"user-agent\"] = \"claude-cli/2.1.2 (external, cli)\"\n headers[\"x-app\"] = \"cli\"\n headers[\"anthropic-dangerous-direct-browser-access\"] = \"true\"\n } else {\n headers[\"x-api-key\"] = this.apiKey\n }\n\n return headers\n }\n\n private async callApi(body: Record<string, unknown>): Promise<AnthropicResponse> {\n const headers = this.buildHeaders()\n\n const res = await fetch(\"https://api.anthropic.com/v1/messages\", {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n })\n\n if (!res.ok) {\n const errorText = await res.text()\n throw new Error(`Anthropic API error (${res.status}): ${errorText}`)\n }\n\n return (await res.json()) as AnthropicResponse\n }\n\n private parseResponse(response: AnthropicResponse): GenerationResult {\n const files: GeneratedFile[] = []\n let content = \"\"\n let followUp: string | undefined\n\n for (const block of response.content) {\n if (block.type === \"text\") {\n content += block.text || \"\"\n }\n\n if (block.type === \"tool_use\") {\n if (block.name === \"create_files\" && block.input) {\n const input = block.input as {\n files: GeneratedFile[]\n summary?: string\n }\n files.push(...(input.files || []))\n if (input.summary) {\n content += `\\n${input.summary}`\n }\n }\n\n if (block.name === \"ask_user\" && block.input) {\n const input = block.input as { question: string; options?: string[] }\n followUp = input.question\n if (input.options?.length) {\n followUp += `\\nOptions: ${input.options.join(\", \")}`\n }\n }\n }\n }\n\n return {\n content,\n files,\n followUp,\n tokensUsed: response.usage.input_tokens + response.usage.output_tokens,\n }\n }\n}\n","import type {\n AgentProvider,\n GenerationMessage,\n GenerationResult,\n GeneratedFile,\n ProviderOptions,\n StreamEvent,\n AnthropicMessage,\n RawGenerationResult,\n ContentBlock,\n} from \"./types\"\nimport { resolveToken, loadAuthConfig } from \"@/utils/auth-store\"\nimport { execa } from \"execa\"\nimport { getLegacyTools } from \"../tools/definitions\"\n\n// --- Claude Code provider: uses Claude CLI (subscription) or direct API (API key) ---\n\nconst DEFAULT_MODEL = \"claude-sonnet-4-20250514\"\nconst DEFAULT_MAX_TOKENS = 8192\n\n// Model ID → claude CLI alias\nconst CLI_MODEL_ALIASES: Record<string, string> = {\n \"claude-sonnet-4-20250514\": \"sonnet\",\n \"claude-opus-4-20250514\": \"opus\",\n \"claude-haiku-4-20250514\": \"haiku\",\n}\n\ntype AuthCredential = { type: \"oauth\"; token: string } | { type: \"api-key\"; token: string }\n\ninterface AnthropicResponse {\n id: string\n content: Array<{\n type: \"text\" | \"tool_use\" | \"tool_result\"\n text?: string\n id?: string\n name?: string\n input?: Record<string, unknown>\n }>\n model: string\n stop_reason: string\n usage: { input_tokens: number; output_tokens: number }\n}\n\nexport class ClaudeCodeProvider implements AgentProvider {\n name = \"claude-code\"\n private credential: AuthCredential\n\n constructor() {\n // Stored config takes priority — if user ran `agentx model` and chose OAuth,\n // we use that regardless of ANTHROPIC_API_KEY env var (same as OpenClaw's clearEnv).\n const stored = loadAuthConfig()\n if (stored) {\n this.credential = { type: stored.authType, token: stored.token }\n return\n }\n\n const resolved = resolveToken()\n if (!resolved) {\n throw new Error(\n \"No Claude credentials found.\\n\" +\n \"Options:\\n\" +\n \" 1. Run `agentx model` to configure credentials\\n\" +\n \" 2. Set ANTHROPIC_API_KEY environment variable\\n\" +\n \" 3. Set ANTHROPIC_OAUTH_TOKEN environment variable\"\n )\n }\n this.credential = { type: resolved.authType, token: resolved.token }\n }\n\n async generate(\n messages: GenerationMessage[],\n options?: ProviderOptions\n ): Promise<GenerationResult> {\n // OAuth tokens → use claude CLI (subscription billing)\n // API keys → call API directly\n if (this.credential.type === \"oauth\") {\n return this.generateViaCli(messages, options)\n }\n return this.generateViaApi(messages, options)\n }\n\n /**\n * generateRaw() for the agentic tool_result loop.\n * Only available for API key auth — the CLI binary has its own agent loop.\n */\n async generateRaw(\n messages: AnthropicMessage[],\n systemPrompt: string,\n tools: Array<{ name: string; description: string; input_schema: Record<string, unknown> }>,\n options?: ProviderOptions\n ): Promise<RawGenerationResult> {\n // OAuth path: not supported — the claude CLI has its own built-in tools\n if (this.credential.type === \"oauth\") {\n throw new Error(\"generateRaw() not available for OAuth/CLI mode\")\n }\n\n const model = options?.model || DEFAULT_MODEL\n const maxTokens = options?.maxTokens || DEFAULT_MAX_TOKENS\n\n const body: Record<string, unknown> = {\n model,\n max_tokens: maxTokens,\n system: systemPrompt,\n messages,\n tools,\n }\n\n if (options?.temperature !== undefined) {\n body.temperature = options.temperature\n }\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"anthropic-version\": \"2023-06-01\",\n \"x-api-key\": this.credential.token,\n }\n\n const res = await fetch(\"https://api.anthropic.com/v1/messages\", {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n })\n\n if (!res.ok) {\n const errorText = await res.text()\n throw new Error(`Anthropic API error (${res.status}): ${errorText}`)\n }\n\n const response = (await res.json()) as AnthropicResponse\n\n const content: ContentBlock[] = response.content.map((block) => {\n if (block.type === \"text\") {\n return { type: \"text\" as const, text: block.text || \"\" }\n }\n if (block.type === \"tool_use\") {\n return {\n type: \"tool_use\" as const,\n id: block.id || \"\",\n name: block.name || \"\",\n input: block.input || {},\n }\n }\n return { type: \"text\" as const, text: \"\" }\n })\n\n return {\n content,\n stop_reason: response.stop_reason as RawGenerationResult[\"stop_reason\"],\n usage: response.usage,\n }\n }\n\n /**\n * Returns true if this provider can use the agentic tool loop.\n * Only available for API key auth (CLI mode falls back to legacy loop).\n */\n get supportsAgenticLoop(): boolean {\n return this.credential.type === \"api-key\"\n }\n\n /**\n * Generate via the `claude` CLI binary.\n * This is how subscription billing works — the CLI handles auth internally.\n */\n private async generateViaCli(\n messages: GenerationMessage[],\n options?: ProviderOptions\n ): Promise<GenerationResult> {\n const model = options?.model || loadAuthConfig()?.model || DEFAULT_MODEL\n const cliModel = CLI_MODEL_ALIASES[model] || model\n\n const systemMsg = messages.find((m) => m.role === \"system\")\n const userMsgs = messages.filter((m) => m.role === \"user\")\n const prompt = userMsgs.map((m) => m.content).join(\"\\n\\n\")\n\n const args = [\n \"-p\",\n \"--output-format\", \"json\",\n \"--model\", cliModel,\n \"--dangerously-skip-permissions\",\n ]\n\n if (systemMsg) {\n args.push(\"--append-system-prompt\", systemMsg.content)\n }\n\n // Prompt goes as the last positional argument\n args.push(prompt)\n\n // Clear ANTHROPIC_API_KEY to force CLI to use subscription auth\n const env = { ...process.env }\n delete env.ANTHROPIC_API_KEY\n delete env.ANTHROPIC_API_KEY_OLD\n\n const result = await execa(\"claude\", args, {\n env,\n extendEnv: false,\n reject: false,\n timeout: 300_000,\n stdin: \"ignore\",\n })\n\n if (result.exitCode !== 0) {\n const err = result.stderr || result.stdout || \"Claude CLI failed\"\n throw new Error(`Claude CLI error: ${err}`)\n }\n\n // Claude CLI may return success exit code but with is_error in JSON\n const output = result.stdout.trim()\n try {\n const json = JSON.parse(output)\n if (json.is_error && json.result) {\n throw new Error(json.result)\n }\n } catch (e: any) {\n if (e.message && !e.message.includes(\"JSON\")) throw e\n // Not JSON — that's fine, parseCliOutput will handle it\n }\n\n return this.parseCliOutput(output)\n }\n\n /**\n * Generate via direct Anthropic API call (for API key auth).\n */\n private async generateViaApi(\n messages: GenerationMessage[],\n options?: ProviderOptions\n ): Promise<GenerationResult> {\n const model = options?.model || DEFAULT_MODEL\n const maxTokens = options?.maxTokens || DEFAULT_MAX_TOKENS\n\n const systemMsg = messages.find((m) => m.role === \"system\")\n const conversationMsgs = messages\n .filter((m) => m.role !== \"system\")\n .map((m) => ({\n role: m.role as \"user\" | \"assistant\",\n content: m.content,\n }))\n\n const body: Record<string, unknown> = {\n model,\n max_tokens: maxTokens,\n messages: conversationMsgs,\n tools: getLegacyTools(),\n }\n\n if (systemMsg) {\n body.system = systemMsg.content\n }\n\n if (options?.temperature !== undefined) {\n body.temperature = options.temperature\n }\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"anthropic-version\": \"2023-06-01\",\n \"x-api-key\": this.credential.token,\n }\n\n const res = await fetch(\"https://api.anthropic.com/v1/messages\", {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n })\n\n if (!res.ok) {\n const errorText = await res.text()\n throw new Error(`Anthropic API error (${res.status}): ${errorText}`)\n }\n\n const response = (await res.json()) as AnthropicResponse\n return this.parseApiResponse(response)\n }\n\n /**\n * Stream responses. For OAuth, uses CLI with --output-format stream-json.\n * For API keys, uses SSE streaming.\n */\n async *stream(\n messages: GenerationMessage[],\n options?: ProviderOptions\n ): AsyncIterable<StreamEvent> {\n if (this.credential.type === \"oauth\") {\n // CLI streaming via --output-format stream-json\n yield* this.streamViaCli(messages, options)\n } else {\n // API streaming via SSE (same as ClaudeProvider.stream)\n yield* this.streamViaApi(messages, options)\n }\n }\n\n private async *streamViaCli(\n messages: GenerationMessage[],\n options?: ProviderOptions\n ): AsyncIterable<StreamEvent> {\n const model = options?.model || loadAuthConfig()?.model || DEFAULT_MODEL\n const cliModel = CLI_MODEL_ALIASES[model] || model\n\n const systemMsg = messages.find((m) => m.role === \"system\")\n const userMsgs = messages.filter((m) => m.role === \"user\")\n const prompt = userMsgs.map((m) => m.content).join(\"\\n\\n\")\n\n const args = [\n \"-p\",\n \"--output-format\", \"stream-json\",\n \"--model\", cliModel,\n \"--dangerously-skip-permissions\",\n ]\n\n if (systemMsg) {\n args.push(\"--append-system-prompt\", systemMsg.content)\n }\n\n args.push(prompt)\n\n const env = { ...process.env }\n delete env.ANTHROPIC_API_KEY\n delete env.ANTHROPIC_API_KEY_OLD\n\n const child = execa(\"claude\", args, {\n env,\n extendEnv: false,\n reject: false,\n timeout: 300_000,\n stdin: \"ignore\",\n })\n\n let fullContent = \"\"\n let stderr = \"\"\n let fatalError: string | undefined\n\n if (child.stderr) {\n child.stderr.on(\"data\", (chunk: any) => {\n stderr += Buffer.isBuffer(chunk) ? chunk.toString(\"utf8\") : String(chunk)\n })\n }\n\n if (child.stdout) {\n const decoder = new TextDecoder()\n const readable = child.stdout as unknown as AsyncIterable<Uint8Array>\n\n for await (const chunk of readable) {\n const text = typeof chunk === \"string\" ? chunk : decoder.decode(chunk, { stream: true })\n // Stream JSON format: each line is a JSON object\n const lines = text.split(\"\\n\").filter(Boolean)\n for (const line of lines) {\n try {\n const event = JSON.parse(line)\n // Some claude stream-json builds emit error events.\n if (event.type === \"error\") {\n fatalError = String(event.error || event.message || \"Claude CLI error\")\n continue\n }\n if (event.is_error && (event.result || event.message)) {\n fatalError = String(event.result || event.message)\n continue\n }\n if (event.type === \"assistant\" && event.message) {\n fullContent += event.message\n yield { type: \"text_delta\", text: event.message }\n } else if (event.type === \"result\") {\n fullContent = event.result || fullContent\n }\n } catch {\n // Not JSON, treat as raw text\n fullContent += line\n yield { type: \"text_delta\", text: line }\n }\n }\n }\n }\n\n const res = await child\n if (res.exitCode !== 0 && !fatalError) {\n fatalError = (stderr || res.stderr || res.stdout || \"Claude CLI failed\").toString().trim()\n }\n\n if (fatalError) {\n yield { type: \"error\", error: `Claude CLI error: ${fatalError}` }\n return\n }\n\n const files = this.extractFilesFromText(fullContent)\n const followUp =\n files.length === 0 ? this.inferFollowUpFromText(fullContent) : undefined\n yield {\n type: \"done\",\n result: { content: fullContent, files, followUp, tokensUsed: 0 },\n }\n }\n\n private async *streamViaApi(\n messages: GenerationMessage[],\n options?: ProviderOptions\n ): AsyncIterable<StreamEvent> {\n const model = options?.model || DEFAULT_MODEL\n const maxTokens = options?.maxTokens || DEFAULT_MAX_TOKENS\n\n const systemMsg = messages.find((m) => m.role === \"system\")\n const conversationMsgs = messages\n .filter((m) => m.role !== \"system\")\n .map((m) => ({ role: m.role as \"user\" | \"assistant\", content: m.content }))\n\n const body: Record<string, unknown> = {\n model,\n max_tokens: maxTokens,\n messages: conversationMsgs,\n tools: getLegacyTools(),\n stream: true,\n }\n\n if (systemMsg) body.system = systemMsg.content\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"anthropic-version\": \"2023-06-01\",\n \"x-api-key\": this.credential.token,\n }\n\n const res = await fetch(\"https://api.anthropic.com/v1/messages\", {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n })\n\n if (!res.ok) {\n const errorText = await res.text()\n yield { type: \"error\", error: `Anthropic API error (${res.status}): ${errorText}` }\n return\n }\n\n const reader = res.body?.getReader()\n if (!reader) {\n yield { type: \"error\", error: \"No response body\" }\n return\n }\n\n const decoder = new TextDecoder()\n let buffer = \"\"\n let content = \"\"\n let tokensUsed = 0\n const files: GeneratedFile[] = []\n let followUp: string | undefined\n let activeTool: { name: string; id: string; json: string } | null = null\n\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n buffer += decoder.decode(value, { stream: true })\n const lines = buffer.split(\"\\n\")\n buffer = lines.pop() || \"\"\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) continue\n const data = line.slice(6).trim()\n if (data === \"[DONE]\") continue\n\n try {\n const event = JSON.parse(data)\n if (event.type === \"content_block_start\") {\n if (event.content_block?.type === \"tool_use\") {\n // Finalize any previous tool block if the stream didn't send a stop.\n if (activeTool) {\n yield { type: \"tool_use_end\", name: activeTool.name }\n try {\n const input = JSON.parse(activeTool.json || \"{}\") as any\n if (activeTool.name === \"create_files\" && input) {\n if (Array.isArray(input.files)) {\n files.push(...(input.files as GeneratedFile[]))\n }\n if (typeof input.summary === \"string\" && input.summary.trim()) {\n content += `\\n${input.summary}`\n }\n }\n if (activeTool.name === \"ask_user\" && input) {\n if (typeof input.question === \"string\" && input.question.trim()) {\n followUp = input.question\n if (Array.isArray(input.options) && input.options.length) {\n followUp += `\\nOptions: ${input.options.join(\", \")}`\n }\n }\n }\n } catch {\n // Ignore invalid tool JSON\n } finally {\n activeTool = null\n }\n }\n\n activeTool = {\n name: event.content_block.name,\n id: event.content_block.id,\n json: \"\",\n }\n yield { type: \"tool_use_start\", name: activeTool.name, id: activeTool.id }\n }\n }\n\n if (event.type === \"content_block_delta\" && event.delta?.type === \"text_delta\") {\n content += event.delta.text\n yield { type: \"text_delta\", text: event.delta.text }\n }\n if (event.type === \"content_block_delta\" && event.delta?.type === \"input_json_delta\") {\n if (activeTool) activeTool.json += event.delta.partial_json || \"\"\n yield { type: \"tool_use_delta\", json: event.delta.partial_json }\n }\n if (event.type === \"content_block_stop\") {\n if (activeTool) {\n yield { type: \"tool_use_end\", name: activeTool.name }\n try {\n const input = JSON.parse(activeTool.json || \"{}\") as any\n if (activeTool.name === \"create_files\" && input) {\n if (Array.isArray(input.files)) {\n files.push(...(input.files as GeneratedFile[]))\n }\n if (typeof input.summary === \"string\" && input.summary.trim()) {\n content += `\\n${input.summary}`\n }\n }\n if (activeTool.name === \"ask_user\" && input) {\n if (typeof input.question === \"string\" && input.question.trim()) {\n followUp = input.question\n if (Array.isArray(input.options) && input.options.length) {\n followUp += `\\nOptions: ${input.options.join(\", \")}`\n }\n }\n }\n } catch {\n // Ignore invalid tool JSON\n } finally {\n activeTool = null\n }\n }\n }\n if (event.type === \"message_delta\" && event.usage) {\n tokensUsed = (event.usage.input_tokens || 0) + (event.usage.output_tokens || 0)\n }\n } catch {\n // Skip\n }\n }\n }\n } finally {\n reader.releaseLock()\n }\n\n // Flush any trailing tool input.\n if (activeTool) {\n yield { type: \"tool_use_end\", name: activeTool.name }\n try {\n const input = JSON.parse(activeTool.json || \"{}\") as any\n if (activeTool.name === \"create_files\" && input) {\n if (Array.isArray(input.files)) {\n files.push(...(input.files as GeneratedFile[]))\n }\n if (typeof input.summary === \"string\" && input.summary.trim()) {\n content += `\\n${input.summary}`\n }\n }\n if (activeTool.name === \"ask_user\" && input) {\n if (typeof input.question === \"string\" && input.question.trim()) {\n followUp = input.question\n if (Array.isArray(input.options) && input.options.length) {\n followUp += `\\nOptions: ${input.options.join(\", \")}`\n }\n }\n }\n } catch {\n // Ignore\n }\n activeTool = null\n }\n\n // If the model didn't use tools (or we couldn't parse them), fall back to fenced-code extraction.\n if (files.length === 0) {\n files.push(...this.extractFilesFromText(content))\n }\n if (!followUp && files.length === 0) {\n followUp = this.inferFollowUpFromText(content)\n }\n yield {\n type: \"done\",\n result: { content, files, followUp, tokensUsed },\n }\n }\n\n /**\n * Parse JSON output from the `claude` CLI.\n */\n private parseCliOutput(stdout: string): GenerationResult {\n let parsed: any\n try {\n parsed = JSON.parse(stdout)\n } catch {\n // CLI returned plain text\n const inferred = this.inferFollowUpFromText(stdout.trim())\n return {\n content: stdout.trim(),\n files: [],\n followUp: inferred,\n tokensUsed: 0,\n }\n }\n\n // Claude CLI JSON format: { result: \"...\", session_id: \"...\", ... }\n const text = parsed.result || parsed.text || parsed.content || \"\"\n\n // Extract files from the text if it contains code blocks with file paths\n const files = this.extractFilesFromText(text)\n const followUp = files.length === 0 ? this.inferFollowUpFromText(text) : undefined\n\n return {\n content: text,\n files,\n followUp,\n tokensUsed: parsed.usage\n ? (parsed.usage.input_tokens || 0) + (parsed.usage.output_tokens || 0)\n : 0,\n }\n }\n\n /**\n * Extract file blocks from CLI text output.\n * Looks for patterns like: ```path/to/file.ts ... ```\n */\n private extractFilesFromText(text: string): GeneratedFile[] {\n const files: GeneratedFile[] = []\n // Match fenced code blocks with a file path hint on the opening line\n const pattern = /```[\\w]*\\s*([\\w/._-]+\\.\\w+)\\n([\\s\\S]*?)```/g\n let match: RegExpExecArray | null\n while ((match = pattern.exec(text)) !== null) {\n const filePath = match[1]\n const content = match[2]\n if (filePath && content) {\n files.push({ path: filePath, content: content.trimEnd() })\n }\n }\n return files\n }\n\n /**\n * Claude CLI (OAuth/subscription) doesn't always emit structured ask_user tool blocks.\n * When it's obviously asking for clarification, infer a follow-up question from the tail.\n */\n private inferFollowUpFromText(text: string): string | undefined {\n const cleaned = (text || \"\").trim()\n if (!cleaned) return undefined\n\n // If it looks like it produced file blocks, don't treat it as a follow-up.\n if (cleaned.includes(\"```\")) return undefined\n\n const lines = cleaned.replace(/\\r\\n/g, \"\\n\").split(\"\\n\")\n const tail = lines.slice(Math.max(0, lines.length - 20))\n\n const tailText = tail.join(\"\\n\")\n const looksLikePlanApproval =\n /\\b(plan|proposal)\\b/i.test(tailText) &&\n /(ready for your review|review (the )?plan|requesting plan approval|awaiting approval|waiting for (your )?approval|approve (the )?plan|approval to proceed)/i.test(\n tailText\n )\n\n if (looksLikePlanApproval) {\n return (\n \"The provider is requesting plan approval.\\n\" +\n \"Reply with:\\n\" +\n \"- approve\\n\" +\n \"- revise: <what to change>\\n\" +\n \"- cancel\"\n )\n }\n\n const isIntro = (l: string) =>\n /^(question|clarification|clarify|i need|need more|before i proceed|to proceed|please (confirm|clarify)|which|what|where|when|how|do you)/i.test(\n l.trim()\n )\n\n // Find the last strong candidate line.\n let startIdx = -1\n for (let i = tail.length - 1; i >= 0; i--) {\n const l = tail[i].trim()\n if (!l) continue\n if (isIntro(l) || l.includes(\"?\")) {\n startIdx = i\n break\n }\n }\n if (startIdx === -1) return undefined\n\n // Collect the question + a small option/list block that follows it.\n const out: string[] = []\n for (let i = startIdx; i < tail.length && out.length < 8; i++) {\n const l = tail[i]\n const t = l.trim()\n if (out.length > 0 && !t) break\n\n if (\n out.length > 0 &&\n !/^(options?:|[-*]\\s|\\d+[\\).]\\s)/i.test(t) &&\n !t.includes(\"?\")\n ) {\n break\n }\n\n out.push(l.trimEnd())\n }\n\n const candidate = out.join(\"\\n\").trim()\n if (candidate.length < 5) return undefined\n if (candidate.length > 800) return candidate.slice(0, 800).trimEnd()\n return candidate\n }\n\n /**\n * Parse Anthropic API response (tool-use format).\n */\n private parseApiResponse(response: AnthropicResponse): GenerationResult {\n const files: GeneratedFile[] = []\n let content = \"\"\n let followUp: string | undefined\n\n for (const block of response.content) {\n if (block.type === \"text\") {\n content += block.text || \"\"\n }\n\n if (block.type === \"tool_use\") {\n if (block.name === \"create_files\" && block.input) {\n const input = block.input as {\n files: GeneratedFile[]\n summary?: string\n }\n files.push(...(input.files || []))\n if (input.summary) {\n content += `\\n${input.summary}`\n }\n }\n\n if (block.name === \"ask_user\" && block.input) {\n const input = block.input as { question: string; options?: string[] }\n followUp = input.question\n if (input.options?.length) {\n followUp += `\\nOptions: ${input.options.join(\", \")}`\n }\n }\n }\n }\n\n return {\n content,\n files,\n followUp,\n tokensUsed: response.usage.input_tokens + response.usage.output_tokens,\n }\n }\n}\n","import type { AgentProvider } from \"./types\"\nimport { ClaudeProvider } from \"./claude\"\nimport { ClaudeCodeProvider } from \"./claude-code\"\nimport { loadAuthConfig } from \"@/utils/auth-store\"\n\nexport type ProviderName = \"claude-code\" | \"claude\" | \"openai\" | \"ollama\" | \"custom\"\n\nexport function createProvider(\n name: ProviderName = \"claude-code\",\n apiKey?: string\n): AgentProvider {\n // Auto-detect provider from stored config when using the default\n let resolvedName = name\n if (name === \"claude-code\" && !apiKey) {\n const stored = loadAuthConfig()\n if (stored) {\n resolvedName = stored.provider\n }\n }\n\n switch (resolvedName) {\n case \"claude-code\":\n return new ClaudeCodeProvider()\n case \"claude\":\n return new ClaudeProvider(apiKey)\n case \"openai\":\n throw new Error(\n \"OpenAI provider coming soon. Set provider to 'claude-code' or contribute at github.com/anis-marrouchi/agentx\"\n )\n case \"ollama\":\n throw new Error(\n \"Ollama provider coming soon. Set provider to 'claude-code' or contribute at github.com/anis-marrouchi/agentx\"\n )\n default:\n throw new Error(`Unknown provider: ${resolvedName}. Supported: claude-code, claude`)\n }\n}\n\nexport { ClaudeProvider } from \"./claude\"\nexport { ClaudeCodeProvider } from \"./claude-code\"\nexport type {\n AgentProvider,\n GenerationMessage,\n GenerationResult,\n GeneratedFile,\n ProviderOptions,\n StreamEvent,\n AnthropicMessage,\n ContentBlock,\n RawGenerationResult,\n} from \"./types\"\n"],"mappings":"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d,EACA,CACE,KAAM,WACN,YACE,mKACF,aAAc,CACZ,KAAM,SACN,WAAY,CACV,SAAU,CACR,KAAM,SACN,YAAa,8BACf,EACA,QAAS,CACP,KAAM,QACN,MAAO,CAAE,KAAM,QAAS,EACxB,YAAa,uCACf,CACF,EACA,SAAU,CAAC,UAAU,CACvB,EACA,WAAY,MACd,EACA,CACE,KAAM,YACN,YACE,wJACF,aAAc,CACZ,KAAM,SACN,WAAY,CACV,KAAM,CACJ,KAAM,SACN,YAAa,sCACf,EACA,UAAW,CACT,KAAM,SACN,YACE,wEACJ,CACF,EACA,SAAU,CAAC,MAAM,CACnB,EACA,WAAY,WACd,EACA,CACE,KAAM,eACN,YACE,mLACF,aAAc,CACZ,KAAM,SACN,WAAY,CACV,QAAS,CACP,KAAM,SACN,YACE,6DACJ,EACA,cAAe,CACb,KAAM,SACN,YACE,wEACJ,EACA,YAAa,CACX,KAAM,SACN,YAAa,mDACf,CACF,EACA,SAAU,CAAC,SAAS,CACtB,EACA,WAAY,MACd,EACA,CACE,KAAM,iBACN,YACE,qFACF,aAAc,CACZ,KAAM,SACN,WAAY,CACV,KAAM,CACJ,KAAM,SACN,YACE,oEACJ,EACA,UAAW,CACT,KAAM,UACN,YAAa,mCACf,EACA,UAAW,CACT,KAAM,SACN,YAAa,kDACf,CACF,CACF,EACA,WAAY,MACd,EACA,CACE,KAAM,cACN,YACE,wJACF,aAAc,CACZ,KAAM,SACN,WAAY,CACV,QAAS,CACP,KAAM,SACN,YAAa,8BACf,EACA,QAAS,CACP,KAAM,SACN,YACE,uDACJ,CACF,EACA,SAAU,CAAC,SAAS,CACtB,EACA,WAAY,SACd,EACA,CACE,KAAM,YACN,YACE,+IACF,aAAc,CACZ,KAAM,SACN,WAAY,CACV,KAAM,CACJ,KAAM,SACN,YAAa,sCACf,EACA,MAAO,CACL,KAAM,QACN,MAAO,CACL,KAAM,SACN,WAAY,CACV,SAAU,CACR,KAAM,SACN,YAAa,oCACf,EACA,SAAU,CACR,KAAM,SACN,YAAa,sBACf,CACF,EACA,SAAU,CAAC,WAAY,UAAU,CACnC,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","names":["existsSync","readFileSync","writeFileSync","mkdirSync","path","os","chalk","prompts","chalk","logger","args","AUTH_DIR","path","os","AUTH_FILE","loadAuthConfig","existsSync","data","readFileSync","saveAuthConfig","config","mkdirSync","writeFileSync","resolveToken","explicitKey","type","envOAuth","envClaudeCodeOAuth","envApiKey","stored","homeDir","storePaths","p","t","readTokenFromAuthProfiles","filePath","fallbackToken","id","cred","ANTHROPIC_MODELS","handleApiKey","envKey","preview","useExisting","prompts","apiKey","v","handleSetupToken","logger","boxWidth","line1","line2","chalk","token","tokenName","selectAuthMethod","provider","method","selectModel","choices","m","current","label","modelId","runModelSetup","auth","ensureCredentials","TOOL_DEFINITIONS","getAnthropicTools","enabledTools","name","description","input_schema","getLegacyTools","formatToolsForSystemPrompt","agenticTools","lines","tool","ALL_TOOL_NAMES","t","DEFAULT_MODEL","DEFAULT_MAX_TOKENS","ClaudeProvider","apiKey","resolved","resolveToken","messages","options","model","maxTokens","systemMsg","m","conversationMsgs","body","getLegacyTools","response","systemPrompt","tools","block","headers","res","errorText","reader","decoder","buffer","files","content","followUp","tokensUsed","activeTool","inferFollowUpFromText","text","cleaned","lines","tail","tailText","isIntro","l","startIdx","i","out","t","candidate","done","value","line","data","event","input","execa","DEFAULT_MODEL","DEFAULT_MAX_TOKENS","CLI_MODEL_ALIASES","ClaudeCodeProvider","stored","loadAuthConfig","resolved","resolveToken","messages","options","systemPrompt","tools","model","maxTokens","body","headers","res","errorText","response","block","cliModel","systemMsg","m","prompt","args","env","result","execa","err","output","json","e","conversationMsgs","getLegacyTools","child","fullContent","stderr","fatalError","chunk","decoder","readable","lines","line","event","files","followUp","reader","buffer","content","tokensUsed","activeTool","done","value","data","input","stdout","parsed","inferred","text","pattern","match","filePath","cleaned","tail","tailText","isIntro","l","startIdx","i","out","t","candidate","createProvider","name","apiKey","resolvedName","stored","loadAuthConfig","ClaudeCodeProvider","ClaudeProvider"]}
|
package/dist/chunk-HHJGKD5B.js
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import{a as fe}from"./chunk-5F3J55LG.js";import{a as pe}from"./chunk-34NG7UDX.js";import{a as ye,b as be,d as xe}from"./chunk-WJXU5F4Z.js";import{b as me}from"./chunk-LEIYC3BF.js";import{b as ge,c as he}from"./chunk-WZEYII2S.js";import{a as de}from"./chunk-63UYRJIC.js";import{c as W,d as B}from"./chunk-QOYAX2FT.js";import{execa as nt}from"execa";import{execFile as st}from"child_process";function H(i){let e=(i||"").trim();if(!e)return{message:"Unknown error from the model.",kind:"unknown",retryable:!1};if(/timed out after/i.test(e))return{message:e.slice(0,300),kind:"timeout",retryable:!0,raw:e};if(/not logged in|please run \/login/i.test(e))return{kind:"auth",retryable:!0,message:"The agent's Claude Code session is logged out.",fix:"Usually a transient OAuth refresh race under concurrent load \u2014 retry in a moment. If it persists, run `/login` in the agent's workspace.",raw:e};let t=e.match(/\{.*\}\s*$/s)||e.match(/\{[\s\S]*\}/),n;if(t)try{n=JSON.parse(t[0])}catch{}let s=n?.error||n,r=typeof s?.type=="string"?s.type:void 0,o=typeof s?.message=="string"?s.message:void 0,c=e.match(/API Error:\s*(\d{3})/i),a=c?parseInt(c[1],10):void 0;return o&&/out of extra usage/i.test(o)?{kind:"overage_disabled",retryable:!0,message:"Claude Max-plan overage is unavailable (disabled or depleted at the org level).",fix:"Enable overage / extra usage at https://claude.ai/settings/usage (this is the subscription account's toggle \u2014 not Anthropic API billing). Warm sessions can still succeed via prompt cache; cold dispatches will keep failing until overage is re-enabled.",raw:e}:o&&/out of (extra )?usage|out of credit|credit(s)? exhausted|insufficient credit/i.test(o)?{kind:"out_of_credits",retryable:!1,message:"The agent is out of Anthropic credits.",fix:"Top up at https://console.anthropic.com/settings/billing (or claude.ai/settings/usage for Max subscribers), then retry.",raw:e}:o&&/context|prompt is too long|too many tokens|maximum context length/i.test(o)?{kind:"context_too_large",retryable:!1,message:"The conversation has grown past what the model can hold.",fix:"Clear session history or switch the agent to a bigger context model.",raw:e}:r==="authentication_error"||o&&/authentication|invalid.*api.*key|no api key|not authenticated/i.test(o)?{kind:"auth",retryable:!1,message:"Authentication failed talking to Anthropic.",fix:"Check ANTHROPIC_API_KEY in .env (or the Claude Code login for claude-code tier agents).",raw:e}:r==="permission_error"||a===403?{kind:"permission",retryable:!1,message:o||"The API key doesn't have permission for this request.",raw:e}:r==="rate_limit_error"||a===429?{kind:"rate_limit",retryable:!0,message:"Anthropic's API rate-limited this request.",fix:"AgentX will retry automatically. If it recurs, lower the agent's concurrency or spread scheduled jobs.",raw:e}:r==="overloaded_error"||a===529||a===503?{kind:"overloaded",retryable:!0,message:"Anthropic's API is temporarily overloaded.",fix:"AgentX will retry in a moment.",raw:e}:r==="invalid_request_error"||a===400?{kind:"invalid_request",retryable:!1,message:o||"The model rejected the request as invalid.",raw:e}:a&&a>=500?{kind:"upstream_api",retryable:!0,message:o||`Anthropic API error (HTTP ${a}).`,fix:"Transient \u2014 retry. Check https://status.anthropic.com if it persists.",raw:e}:{kind:"unknown",retryable:!1,message:e.replace(/\s+/g," ").slice(0,220),raw:e}}function N(i){return i.fix?`${i.message} \u2014 ${i.fix}`:i.message}function V(i,e,t){let n=[];if(e.context&&!t){let s=e.context,r=["","[Environment]"],o=s.channel==="gitlab"||s.channel?.startsWith("webhook:"),c=s.channel==="telegram";if(s.channel&&r.push(`Channel: ${s.channel}`),s.group&&r.push(`Group: ${s.group}`),s.sender&&r.push(`Message from: ${s.sender}`),s.myHandle&&r.push(`Your handle on this channel: ${s.myHandle}`),o&&(r.push(""),r.push("[IMPORTANT: You are responding to a GitLab comment/event]"),r.push("- Keep it short \u2014 3-5 lines for the main message. Humans scan, not read"),r.push("- Lead with the result or action, not a narration of what you plan to do"),r.push("- Use <details><summary>Details</summary>\\n\\ncontent\\n</details> for verbose output (logs, full commands, step-by-step)"),r.push("- Do NOT mention Telegram handles \u2014 they don't work on GitLab"),r.push("- Do NOT try to delegate to other agents \u2014 reply directly"),r.push("- Reference issues with #IID and MRs with !IID")),c&&s.peers?.length){r.push(""),r.push("[Team \u2014 other agents you can mention to delegate or collaborate]");for(let a of s.peers){let l=a.handle?` (mention: ${a.handle})`:"",h=a.role?` \u2014 ${a.role}`:"";r.push(`\u2022 ${a.name}${l}${h}`)}r.push(""),r.push("To involve another agent, mention their handle in your response and they will automatically see it and reply.")}n.push(r.join(`
|
|
2
|
-
`))}return e.context?.replyToText&&(n.push(""),n.push(`[Replying to]: ${e.context.replyToText}`)),e.context?.mediaPath&&(n.push(""),n.push(`[Attached file: ${e.context.mediaPath}]`),n.push(`[File type: ${e.context.mediaType||"unknown"}]`),e.context.mediaType?.startsWith("image/")?n.push("Please read/view this image file and describe or respond to it."):e.context.mediaType?.startsWith("audio/")?n.push("Please transcribe this audio file and respond to its content."):e.context.mediaType?.startsWith("video/")?n.push("A video file is attached. Describe what you can determine about it."):n.push("Please read this file and respond based on its content.")),t&&(n.push(""),n.push(t)),n.push(""),n.push(e.message),n.join(`
|
|
3
|
-
`)}function we(i,e,t,n,s,r){let o=["-p",e,"--output-format",t?"stream-json":"json"];t&&o.push("--verbose"),n&&o.push("--resume",n);let c=s||i.model;return c&&o.push("--model",c),i.permissionMode==="bypassPermissions"&&o.push("--dangerously-skip-permissions"),r&&r.trim().length>0&&o.push("--append-system-prompt",r),o}function rt(i){try{let e=JSON.parse(i);if(e&&e.is_error&&typeof e.result=="string")return e.result;if(e&&e.error&&typeof e.error=="string")return e.error}catch{}return null}function it(i){try{let e=JSON.parse(i),t=e.usage?{inputTokens:e.usage.input_tokens||0,outputTokens:e.usage.output_tokens||0,cacheReadTokens:e.usage.cache_read_input_tokens||0,cacheCreateTokens:e.usage.cache_creation_input_tokens||0}:void 0,n=typeof e.model=="string"&&e.model||typeof e.message?.model=="string"&&e.message.model||void 0;return{text:e.result||e.content||"",sessionId:e.session_id,usage:t,billedModel:n}}catch{return{text:i}}}async function ot(i,e,t,n){let s=Date.now(),r=V(i,e,t),o=we(i,r,!1,n,e.model,e.systemPromptAppend);try{let c=Math.max(6e4,(i.maxExecutionMinutes??20)*6e4),{stdout:a,stderr:l,exitCode:h}=await new Promise((p,b)=>{st("claude",o,{cwd:i.workspace,timeout:c,maxBuffer:10485760,env:{...process.env,HOME:process.env.HOME||"/home/"+(process.env.USER||"user")}},($,I,k)=>{p({stdout:I||"",stderr:k||"",exitCode:$?$.code??1:0})}).stdin?.end()});if(!a&&h!==0){let p;return h===143?p=`Claude Code timed out after ${Math.round(c/6e4)}m (SIGTERM). Bump agent.maxExecutionMinutes for "${i.name||"this agent"}" if tasks need longer.`:p=l?.trim()||`Claude Code exited with code ${h}`,{content:"",error:N(H(p)),duration:Date.now()-s}}let g=rt(a);if(g)return{content:"",error:N(H(g)),duration:Date.now()-s};let m=it(a);return{content:m.text,duration:Date.now()-s,claudeSessionId:m.sessionId,usage:m.usage,billedModel:m.billedModel}}catch(c){return console.error(`[runtime] execFile threw: ${c.message}`),{content:"",error:c.message||"Claude Code failed",duration:Date.now()-s}}}async function at(i,e,t,n,s,r){let o=Date.now(),c=V(i,e,n),a=we(i,c,!0,s,e.model,e.systemPromptAppend),l="",h,g,m,p;try{let b=Math.max(6e4,(i.maxExecutionMinutes??20)*6e4),w=nt("claude",a,{cwd:i.workspace,timeout:b,reject:!1,env:process.env,buffer:!1,stdin:"ignore"});if(w.stdout){let I="";w.stdout.on("data",k=>{I+=k.toString();let C=I.split(`
|
|
4
|
-
`);I=C.pop()||"";for(let D of C)if(D.trim())try{let f=JSON.parse(D);if(r)try{r(f)}catch{}if(f.type==="assistant"&&f.message?.content){for(let x of f.message.content)if(x.type==="text"&&x.text){let R=x.text.slice(l.length);R&&(l=x.text,t(R,l))}}if(f.type==="content_block_delta"&&f.delta?.text&&(l+=f.delta.text,t(f.delta.text,l)),f.type==="result"&&f.result){if(f.is_error&&typeof f.result=="string")p=f.result;else{let x=(typeof f.result=="string",f.result);if(typeof x=="string"&&x.length>l.length){let R=x.slice(l.length);l=x,R&&t(R,l)}}f.usage&&(g={inputTokens:f.usage.input_tokens||0,outputTokens:f.usage.output_tokens||0,cacheReadTokens:f.usage.cache_read_input_tokens||0,cacheCreateTokens:f.usage.cache_creation_input_tokens||0}),typeof f.model=="string"&&(h=f.model),typeof f.session_id=="string"&&(m=f.session_id)}f.type==="system"&&f.subtype==="init"&&(typeof f.model=="string"&&(h=f.model),typeof f.session_id=="string"&&(m=f.session_id))}catch{D.trim()&&!D.startsWith("{")&&(l+=D+`
|
|
5
|
-
`,t(D+`
|
|
6
|
-
`,l))}})}let $=await w;if(!l&&$.stdout&&(l=typeof $.stdout=="string"?$.stdout:""),$.exitCode!==0&&!l){let I=typeof $.stderr=="string"?$.stderr:"",k=$,C;return k.timedOut?C=`Claude Code timed out after ${Math.round(b/6e4)}m. Bump agent.maxExecutionMinutes for "${i.name||"this agent"}" if tasks need longer.`:k.signal?C=I.trim()||`Claude Code killed by signal ${k.signal}`:C=I.trim()||`Claude Code exited with code ${k.exitCode??"unknown"}`,{content:"",error:N(H(C)),duration:Date.now()-o}}return p?{content:"",error:N(H(p)),duration:Date.now()-o,usage:g,billedModel:h,claudeSessionId:m}:{content:l,duration:Date.now()-o,usage:g,billedModel:h,claudeSessionId:m}}catch(b){return{content:l||"",error:N(H(b.message)),duration:Date.now()-o,usage:g,billedModel:h,claudeSessionId:m}}}async function ct(i,e,t,n){let s=Date.now();try{let r=await import("@anthropic-ai/claude-agent-sdk"),{query:o}=r,c=V(i,e,n),a="",l=o({prompt:c,options:{model:e.model||i.model,cwd:i.workspace,permissionMode:"bypassPermissions"}});for await(let h of l)h.type==="result"&&h.subtype==="success"&&(a=h.result||"");return{content:a,duration:Date.now()-s}}catch(r){return{content:"",error:`SDK error: ${r.message}`,duration:Date.now()-s}}}async function ut(i,e,t,n){let s=Date.now();try{let{generate:r}=await import("./agent-4AOMVXRJ.js"),o=i.provider||"claude-code",c=n?`${n}
|
|
7
|
-
|
|
8
|
-
${e.message}`:e.message,a=await r({task:c,cwd:i.workspace,provider:o,model:e.model||i.model,apiKey:t,overwrite:!0,interactive:!1,context7:!1});return{content:a.content||"Done.",tokensUsed:a.tokensUsed,duration:Date.now()-s}}catch(r){return{content:"",error:`Orchestrator error: ${r.message}`,duration:Date.now()-s}}}async function Se(i,e,t,n,s,r,o){switch(i.tier){case"claude-code":return n?at(i,e,n,s,r,o):ot(i,e,s,r);case"sdk":{let c=i.provider||"claude",a=t[c]?.apiKey;return a?ct(i,e,a,s):{content:"",error:`No API key for provider "${c}". Configure providers.${c}.apiKey`}}case"orchestrator":{let c=i.provider||"claude-code",a=t[c]?.apiKey;return ut(i,e,a,s)}default:return{content:"",error:`Unknown tier: ${i.tier}`}}}import{readFileSync as Te,writeFileSync as lt,mkdirSync as dt,existsSync as ve,readdirSync as gt}from"fs";import{resolve as ee}from"path";var ht=12e3,$e=30,mt=45,pt=15,ft=18e4,yt="[Compacted conversation summary",bt=[/\bearlier\b/i,/\bbefore\b/i,/\bjust said\b/i,/\btold (?:me|you|us|him|her|them)\b/i,/\bmention(?:ed|ing)?\b/i,/\bask(?:ed)? (?:me|you|him|her|them|about)\b/i,/\bping(?:ed)?\b/i,/\bdm\b/i,/\bdirect message\b/i,/\bother (?:chat|group|conversation|thread)\b/i,/\bthat (?:chat|group|conversation|thread)\b/i,/\bsame (?:issue|thread|conversation)\b/i,/\bcontinuing\b/i,/@\w{2,}_?(?:bot|agent)\b/i,/قلت/,/قال(?:لك|لي|له|لها|لنا)?/,/قبل/,/الحين/,/الثاني/,/المجموعة/];function xt(i){return i?bt.some(e=>e.test(i)):!1}function Ie(i,e,t,n){if(i.length===0)return!1;let s=i[i.length-1];return s.role===e&&(s.name??"")===t&&s.content===n}function wt(i){let e=i.slice(11,16),t=e.slice(0,2),n=parseInt(e.slice(3,5),10);if(Number.isNaN(n))return e;let s=Math.floor(n/15)*15;return`${t}:${s.toString().padStart(2,"0")}`}var q=class{sessionsDir;cache=new Map;staleMinutes;maxTurnsPerSession;tierTwoThresholdTokens;constructor(e=process.cwd(),t={}){this.sessionsDir=ee(e,".agentx/sessions"),ve(this.sessionsDir)||dt(this.sessionsDir,{recursive:!0}),this.staleMinutes=Math.max(1,t.staleMinutes??mt),this.maxTurnsPerSession=Math.max(2,t.maxTurnsPerSession??pt),this.tierTwoThresholdTokens=Math.max(5e4,t.tierTwoThresholdTokens??ft)}sessionKey(e,t,n){let s=new Date().toISOString().slice(0,10);return`${e}:${t}:${n}:${s}`}sessionFile(e){let t=e.replace(/[^a-zA-Z0-9_:-]/g,"_");return ee(this.sessionsDir,`${t}.json`)}getSession(e,t,n){let s=this.sessionKey(e,t,n);if(this.cache.has(s))return this.cache.get(s);let r=this.sessionFile(s);if(ve(r))try{let a=JSON.parse(Te(r,"utf-8"));return this.cache.set(s,a),a}catch{}let o=new Date().toISOString().slice(0,10),c={id:s,agentId:e,channel:t,chatId:n,day:o,messages:[],createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()};return this.cache.set(s,c),this.save(c),c}addUserMessage(e,t,n,s,r){let o=this.getSession(e,t,n);Ie(o.messages,"user",s,r)||(o.messages.push({role:"user",name:s,content:r,timestamp:new Date().toISOString()}),this.trim(o),o.updatedAt=new Date().toISOString(),this.save(o))}addAgentMessage(e,t,n,s){let r=this.getSession(e,t,n);Ie(r.messages,"agent",e,s)||(r.messages.push({role:"agent",name:e,content:s,timestamp:new Date().toISOString()}),this.trim(r),r.updatedAt=new Date().toISOString(),this.save(r))}getClaudeSessionId(e,t,n){return this.getSession(e,t,n).claudeSessionId}setClaudeSessionId(e,t,n,s){let r=this.getSession(e,t,n);r.claudeSessionId=s,r.updatedAt=new Date().toISOString(),this.save(r)}buildHistoryContext(e,t,n){let s=this.getSession(e,t,n);if(s.messages.length===0)return"";let r=[`[Conversation history for today (${s.day})]`],o="";for(let c of s.messages){let a=wt(c.timestamp);a!==o&&(r.push(`\u2014 ${a} \u2014`),o=a);let l=c.name||(c.role==="user"?"User":"Agent");r.push(`${l}: ${c.content}`)}return r.push("[End of history \u2014 respond to the latest message above]"),r.push(""),r.join(`
|
|
9
|
-
`)}isSessionStale(e,t,n){let s=this.getSession(e,t,n);return s.claudeSessionId?Date.now()-new Date(s.updatedAt).getTime()>this.staleMinutes*60*1e3:!1}getCrossSessionSummary(e,t,n,s){if(s!==void 0&&s!==""&&!xt(s))return"";let r=new Date().toISOString().slice(0,10),o=this.sessionKey(e,t,n);try{let c=gt(this.sessionsDir).filter(l=>l.startsWith(e.replace(/[^a-zA-Z0-9_:-]/g,"_"))&&l.includes(r)&&l.endsWith(".json")),a=[];for(let l of c)try{let h=JSON.parse(Te(ee(this.sessionsDir,l),"utf-8"));if(h.id===o||h.messages.length===0)continue;let g=h.messages.slice(-4),p=!h.chatId.startsWith("-")&&/^\d+$/.test(h.chatId)?"DM":h.chatId,b=g.map(w=>` [${w.timestamp.slice(11,16)}] ${w.name||w.role}: ${w.content.slice(0,200)}`);a.push(`From ${p} (${h.channel}):
|
|
10
|
-
${b.join(`
|
|
11
|
-
`)}`)}catch{}return a.length===0?"":["[Cross-chat context \u2014 recent activity from your other conversations today]",...a,"[End cross-chat context \u2014 the user in THIS chat may be referring to actions from above]",""].join(`
|
|
12
|
-
`)}catch{return""}}async compactIfNeeded(e,t,n,s){let r=this.getSession(e,t,n),{needsCompaction:o,compactSession:c,applyCompaction:a}=await import("./compaction-X46EQEPS.js");if(!o(r.messages))return{compacted:!1};let l=await c(r.messages,e,s);return l.compactedCount===0?{compacted:!1}:(r.messages=a(r.messages,l),r.updatedAt=new Date().toISOString(),this.save(r),{compacted:!0,qualityScore:l.qualityScore,lostEntities:l.lostEntities,drift:l.drift})}hasCompaction(e,t,n){let s=this.getSession(e,t,n);return s.messages.length>0&&s.messages[0].content.startsWith(yt)}clearClaudeSessionId(e,t,n){let s=this.getSession(e,t,n);delete s.claudeSessionId,delete s.turnCount,delete s.lastTurnInputTokens,s.updatedAt=new Date().toISOString(),this.save(s)}shouldRotateByTurns(e,t,n){let s=this.getSession(e,t,n);return s.claudeSessionId?(s.turnCount??0)>=this.maxTurnsPerSession:!1}shouldRotateByTierTwo(e,t,n){let s=this.getSession(e,t,n);return s.claudeSessionId?(s.lastTurnInputTokens??0)>=this.tierTwoThresholdTokens:!1}recordTurnUsage(e,t,n,s){let r=this.getSession(e,t,n);r.turnCount=(r.turnCount??0)+1,r.lastTurnInputTokens=(s.inputTokens||0)+(s.cacheReadTokens||0)+(s.cacheCreateTokens||0),r.updatedAt=new Date().toISOString(),this.save(r)}getTurnCount(e,t,n){return this.getSession(e,t,n).turnCount??0}getLastTurnInputTokens(e,t,n){return this.getSession(e,t,n).lastTurnInputTokens??0}getMaxTurnsPerSession(){return this.maxTurnsPerSession}getTierTwoThresholdTokens(){return this.tierTwoThresholdTokens}trim(e){e.messages.length>$e&&(e.messages=e.messages.slice(-$e));let t=e.messages.reduce((n,s)=>n+s.content.length,0);for(;t>ht&&e.messages.length>2;){let n=e.messages.shift();t-=n.content.length}}save(e){try{let t=this.sessionFile(e.id);lt(t,JSON.stringify(e,null,2))}catch{}}};var K=class{windows=new Map;maxPerMinute;maxPerHour;constructor(e=10,t=100){this.maxPerMinute=e,this.maxPerHour=t}check(e){let t=Date.now(),n=this.windows.get(e)||[],s=t-36e5,r=n.filter(a=>a>s),o=t-6e4,c=r.filter(a=>a>o);if(c.length>=this.maxPerMinute){let a=c[0],l=Math.max(50,a+6e4-t);return{allowed:!1,reason:`Rate limit: ${c.length}/${this.maxPerMinute} per minute`,waitMs:l}}if(r.length>=this.maxPerHour){let a=r[0],l=Math.max(1e3,a+36e5-t);return{allowed:!1,reason:`Rate limit: ${r.length}/${this.maxPerHour} per hour`,waitMs:l}}return r.push(t),this.windows.set(e,r),{allowed:!0}}async acquire(e,t={}){let n=t.maxWaitMs??3e5,s=Date.now()+n,r=!0;for(;;){let o=this.check(e);if(o.allowed)return{ok:!0};if(Date.now()>=s)return{ok:!1,reason:`${o.reason} (waited ${Math.round(n/1e3)}s, giving up)`};r&&(r=!1,t.onWait?.(o.reason,o.waitMs));let c=s-Date.now(),a=Math.min(o.waitMs??1e3,c,5e3);await new Promise(l=>setTimeout(l,a))}}usage(e){let t=Date.now(),n=this.windows.get(e)||[];return{lastMinute:n.filter(s=>s>t-6e4).length,lastHour:n.filter(s=>s>t-36e5).length}}};var St={totalBudget:6e3,layerBudgets:{channel:200,scope:200,landscape:800,identity:200,bootstrap:500,intent:200,artifacts:500,memory:600,history:1200,"cross-chat":800,wiki:1e3}},ke=4;function Ce(i,e=St){let t=Tt(i,e);t.sort((o,c)=>o.priority-c.priority);let n=[],s=0,r=e.totalBudget*ke;for(let o of t){if(!o.content)continue;let c=o.maxTokens*ke,a=o.content.length>c?o.content.slice(0,c)+"...":o.content;if(s+a.length>r){let l=r-s;l>100&&n.push(a.slice(0,l)+"...");break}n.push(a),s+=a.length}return n.join(`
|
|
13
|
-
|
|
14
|
-
`)}function Tt(i,e){let t=(o,c)=>e.layerBudgets?.[o]??c,n=[];if(n.push(vt(i,t("channel",200))),n.push($t(i,t("scope",200))),i.landscape&&n.push({name:"landscape",priority:3,maxTokens:t("landscape",350),content:i.landscape,tags:["landscape","world-model"]}),i.systemPrompt&&n.push({name:"identity",priority:4,maxTokens:t("identity",200),content:i.systemPrompt.split(`
|
|
15
|
-
`)[0],tags:["identity",i.agentId]}),i.bootstrapContext&&n.push({name:"bootstrap",priority:4.5,maxTokens:t("bootstrap",500),content:i.bootstrapContext,tags:["bootstrap","identity","personality"]}),i.intent&&i.intent.path.length>0){let o=[`[Intent path: ${i.intent.pathLabel}${i.intent.status==="pending"?" (pending approval)":""}]`],c=i.intent.path[i.intent.path.length-1],a=i.intent.axes?.[c];if(a&&Object.keys(a).length){let l=Object.entries(a).map(([h,g])=>` ${h}: ${g}`).join(`
|
|
16
|
-
`);o.push(l)}i.intent.leaf?.input&&o.push(` input: ${i.intent.leaf.input}`),n.push({name:"intent",priority:5,maxTokens:t("intent",200),content:o.join(`
|
|
17
|
-
`),tags:["intent",...i.intent.path]})}else{let o=It(i.message);o.length&&n.push({name:"intent",priority:5,maxTokens:t("intent",200),content:`[Intent: ${o.join(", ")}]`,tags:o})}let s=[];i.replyToText&&s.push(`[Replying to]: ${i.replyToText.slice(0,300)}`),i.mediaPath&&(s.push(`[Attached file: ${i.mediaPath}]`),s.push(`[File type: ${i.mediaType||"unknown"}]`),i.mediaType?.startsWith("image/")?s.push("Please view this image and respond to it."):i.mediaType?.startsWith("audio/")&&s.push("Please transcribe this audio and respond.")),i.issueMR&&s.push(`[${i.issueMR.type} #${i.issueMR.iid}: ${i.issueMR.title}]`),s.length&&n.push({name:"artifacts",priority:6,maxTokens:t("artifacts",500),content:s.join(`
|
|
18
|
-
`),tags:["artifacts",...i.mediaType?["media"]:[]]}),i.skillInjection&&n.push({name:"skills",priority:6.2,maxTokens:t("skills",2e3),content:i.skillInjection,tags:["skills","auto-inject"]}),i.patternContext&&n.push({name:"patterns",priority:6.3,maxTokens:t("patterns",400),content:i.patternContext,tags:["patterns","behavioral","self-improving"]}),i.memoryContext&&n.push({name:"memory",priority:6.5,maxTokens:t("memory",600),content:i.memoryContext,tags:["memory","persistent"]});let r=i.groupHistory||i.sessionHistory;if(r&&n.push({name:"history",priority:7,maxTokens:t("history",1200),content:r,tags:["history","conversation"]}),i.crossChatContext&&n.push({name:"cross-chat",priority:7,maxTokens:t("cross-chat",800),content:i.crossChatContext,tags:["history","cross-chat"]}),i.handoverNote){let o=[`[Handover] You are taking over this conversation from ${i.handoverNote.fromAgent}.`];i.handoverNote.summary&&o.push(`Operator summary: ${i.handoverNote.summary}`),o.push(`Handover time: ${i.handoverNote.at}`),n.push({name:"handover",priority:7.5,maxTokens:t("handover",400),content:o.join(`
|
|
19
|
-
`),tags:["handover",i.handoverNote.fromAgent]})}return i.wikiContext&&n.push({name:"wiki",priority:8,maxTokens:t("wiki",1e3),content:i.wikiContext,tags:["wiki","knowledge"]}),n}function vt(i,e){let t=[`Channel: ${i.channel}`],n=[],s=[i.channel];switch(i.channel){case"telegram":i.agentHandle&&t.push(`Your handle: ${i.agentHandle}`),t.push(`From: ${i.sender}`),i.senderId&&t.push(`Telegram user ID: ${i.senderId}`),i.senderUsername&&t.push(`Username: @${i.senderUsername}`),n.push("Format responses using Telegram-compatible markdown"),n.push("Be brief \u2014 2-4 sentences max for the main point. Humans scan, not read"),n.push("Lead with the action or answer, skip preamble");break;case"whatsapp":t.push(`From: ${i.sender}`),n.push("Be brief \u2014 2-3 sentences max. WhatsApp is mobile-first"),n.push("No rich formatting \u2014 plain text only"),n.push("Lead with the action or answer, skip preamble");break;case"gitlab":t.push(`From: ${i.sender}`),n.push("Reply as a short, actionable GitLab comment \u2014 3-5 lines for the main message"),n.push("Do NOT mention Telegram handles \u2014 they don't work on GitLab"),n.push("Do NOT delegate to other agents"),n.push("Reference issues with #IID and merge requests with !IID"),n.push("Put verbose details (logs, full commands, step-by-step) inside collapsible sections: <details><summary>Title</summary>\\n\\ncontent\\n</details>"),n.push("Never narrate what you are about to do \u2014 just do it and report the result"),s.push("code-review");break;case"discord":t.push(`From: ${i.sender}`),n.push("Use Discord markdown for formatting"),n.push("Be brief \u2014 2-4 sentences for the main point");break;default:i.channel.startsWith("webhook:")&&(n.push("This is an automated event \u2014 respond with actionable steps"),s.push("webhook","automated"))}return n.length&&(t.push(""),t.push("[Rules]"),t.push(...n.map(r=>`- ${r}`))),{name:"channel",priority:1,maxTokens:e,content:t.join(`
|
|
20
|
-
`),tags:s,rules:n}}function $t(i,e){let t=[],n=[];if(i.channelScope==="group"&&i.groupName?(t.push(`Group: ${i.groupName}`),n.push("group",i.groupName)):i.channelScope==="project"&&i.projectPath?(t.push(`Project: ${i.projectPath}`),n.push("project",i.projectPath)):i.channelScope==="personal"&&(t.push("Direct message"),n.push("dm")),i.channelMeta){let s=i.channelMeta;if(s.agents?.length&&(t.push(`[Verified bots in this chat: ${s.agents.map(r=>r.handle||r.name||r.id).join(", ")}]`),t.push("Only mention these agents as group members \u2014 do NOT assume others are present.")),s.project&&t.push(`Project: ${s.project}`),s.issue&&t.push(`${s.issue.type} #${s.issue.iid}${s.issue.title?`: ${s.issue.title}`:""}`),s.facts?.length)for(let r of s.facts)t.push(`\u2022 ${r}`)}return{name:"scope",priority:2,maxTokens:e,content:t.join(`
|
|
21
|
-
`),tags:n}}function It(i){let e=[],t=i.toLowerCase();return/deploy|push|release|ship/.test(t)&&e.push("deployment"),/review|check|look at|approve/.test(t)&&e.push("review"),/fix|bug|broken|error|issue/.test(t)&&e.push("bugfix"),/create|add|build|implement/.test(t)&&e.push("feature"),/test|spec|coverage/.test(t)&&e.push("testing"),/refactor|clean|improve/.test(t)&&e.push("refactor"),/docs|document|readme/.test(t)&&e.push("docs"),/security|vuln|auth|token/.test(t)&&e.push("security"),/perf|slow|optim|fast/.test(t)&&e.push("performance"),/status|update|progress|standup/.test(t)&&e.push("status"),/help|how|what|explain/.test(t)&&e.push("question"),/gitlab|merge|mr|issue|pipeline/.test(t)&&e.push("gitlab"),/seo|analytics|content|marketing/.test(t)&&e.push("marketing"),/infra|server|docker|k8s|devops/.test(t)&&e.push("devops"),e}import{readFileSync as kt,writeFileSync as Ae,appendFileSync as Ct,mkdirSync as At,existsSync as Me}from"fs";import{resolve as te}from"path";var Pe=200,Mt=7,Q=class{memoryDir;constructor(e=process.cwd()){this.memoryDir=te(e,".agentx/memory"),Me(this.memoryDir)||At(this.memoryDir,{recursive:!0})}filePath(e){return te(this.memoryDir,`${e}.jsonl`)}addMemory(e,t){let n={...t,id:`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,6)}`,createdAt:new Date().toISOString()};Ct(this.filePath(e),JSON.stringify(n)+`
|
|
22
|
-
`)}getAll(e){let t=this.filePath(e);if(!Me(t))return[];try{return kt(t,"utf-8").split(`
|
|
23
|
-
`).filter(s=>s.trim()).map(s=>{try{return JSON.parse(s)}catch{return null}}).filter(s=>s!==null)}catch{return[]}}findRelevant(e,t,n=8){let s=this.getAll(t);if(s.length===0)return[];let r=s.map(p=>`${p.keywords.join(" ")} ${p.content}`),o=te(this.memoryDir,`${t}_bm25_cache.json`),c=B(r,o),a=W(e,c),l=new Map(a.map(p=>[p.docIndex,p.score])),g=s.map((p,b)=>{let w=l.get(b)??0;return p.category==="secret"&&(w+=2),p.category==="commitment"&&(w+=1),{memory:p,score:w}}).filter(p=>p.score>0);if(g.length===0)return s.slice(-n);let m=g.sort((p,b)=>b.score-p.score).slice(0,n).map(p=>p.memory);if(m.length>0)try{this.recordAccess(t,m.map(p=>p.id))}catch{}return m}buildContext(e){if(e.length===0)return"";let t=["[Agent Memory \u2014 persistent facts from past conversations]"],n=t[0].length;for(let s of e){let o=!s.source.chatId.startsWith("-")&&/^\d+$/.test(s.source.chatId)?"DM":s.source.chatId,c=`- [${s.category}] ${s.content} (${o}, ${s.source.date})`;if(n+c.length>2400)break;t.push(c),n+=c.length}return t.push("[End Memory]"),t.join(`
|
|
24
|
-
`)}recordAccess(e,t){if(t.length===0)return;let n=this.getAll(e),s=new Set(t),r=!1;for(let o of n)if(s.has(o.id)){o.accessCount=(o.accessCount||0)+1,o.lastAccessed=new Date().toISOString();let c=o.intervalDays||1;o.intervalDays=Math.min(c*2,30),o.nextReview=new Date(Date.now()+o.intervalDays*864e5).toISOString(),r=!0}r&&Ae(this.filePath(e),n.map(o=>JSON.stringify(o)).join(`
|
|
25
|
-
`)+`
|
|
26
|
-
`)}getDueForReview(e,t=5){let n=this.getAll(e),s=Date.now();return n.filter(r=>r.category==="task-state"?!1:r.nextReview?new Date(r.nextReview).getTime()<=s:!0).sort((r,o)=>!r.nextReview&&o.nextReview?-1:r.nextReview&&!o.nextReview?1:r.nextReview&&o.nextReview?new Date(r.nextReview).getTime()-new Date(o.nextReview).getTime():(r.accessCount||0)-(o.accessCount||0)).slice(0,t)}buildRecallContext(e){let t=this.getDueForReview(e,5);if(t.length===0)return"";let n=["[Memory Recall \u2014 facts due for review, verify they are still accurate]"];for(let s of t){let r=Math.round((Date.now()-new Date(s.createdAt).getTime())/864e5);n.push(`- [${s.category}] ${s.content} (${r}d old, accessed ${s.accessCount||0}x)`)}return n.push("[If any fact is outdated, note the correction. Otherwise, acknowledge recall.]"),n.join(`
|
|
27
|
-
`)}hasSimilar(e,t){let n=this.getAll(e),r=t.toLowerCase().split(/\s+/).filter(o=>o.length>3);return n.some(o=>{let c=o.content.toLowerCase();return r.filter(l=>c.includes(l)).length>=r.length*.7})}prune(e){let t=this.getAll(e);if(t.length===0)return;let n=Date.now(),s=Mt*24*60*60*1e3;t=t.filter(o=>o.category==="task-state"&&o.expiresAt?new Date(o.expiresAt).getTime()>n:o.category==="task-state"&&!o.expiresAt?n-new Date(o.createdAt).getTime()<s:!0),t.length>Pe&&(t=t.slice(-Pe));let r=this.filePath(e);Ae(r,t.map(o=>JSON.stringify(o)).join(`
|
|
28
|
-
`)+`
|
|
29
|
-
`)}};var G=class{queues=new Map;defaultMode;constructor(e="collect"){this.defaultMode=e}key(e,t,n){return`${e}:${t}:${n}`}getOrCreate(e,t,n){let s=this.key(e,t,n);return this.queues.has(s)||this.queues.set(s,{mode:this.defaultMode,pending:[],running:!1}),this.queues.get(s)}setMode(e,t,n,s){this.getOrCreate(e,t,n).mode=s}onFlush(e,t,n,s){this.getOrCreate(e,t,n).onFlush=s}isBusy(e,t,n){return this.getOrCreate(e,t,n).running}markRunning(e,t,n){let s=this.getOrCreate(e,t,n);return s.running?!1:(s.running=!0,!0)}enqueue(e,t,n,s){let r=this.getOrCreate(e,t,n);if(!r.running)return null;switch(r.mode){case"drop":return"drop";case"collect":case"followup":return r.pending.push(s),r.mode}}async markDone(e,t,n){let s=this.getOrCreate(e,t,n);if(s.running=!1,s.pending.length===0)return[];let r=[...s.pending];switch(s.pending=[],s.mode){case"collect":{let o={text:r.map(c=>`[${c.sender}, ${new Date(c.timestamp).toISOString().slice(11,16)}]: ${c.text}`).join(`
|
|
30
|
-
`),sender:r[r.length-1].sender,timestamp:Date.now(),channel:r[0].channel,chatId:r[0].chatId,originalContext:r[r.length-1].originalContext};return s.onFlush&&await s.onFlush([o]),[o]}case"followup":return s.onFlush&&await s.onFlush(r),r;case"drop":return[];default:return r}}pendingCount(e,t,n){return this.getOrCreate(e,t,n).pending.length}clear(e,t,n){let s=this.key(e,t,n);this.queues.delete(s)}stats(){return Array.from(this.queues.entries()).map(([e,t])=>({key:e,mode:t.mode,pending:t.pending.length,running:t.running}))}};import{readFileSync as Pt,writeFileSync as De,appendFileSync as Dt,mkdirSync as Rt,existsSync as Re}from"fs";import{resolve as ne}from"path";var _e=50,_t="claude-haiku-4-20250514",Ot=`You are a behavioral pattern extractor. Given a conversation between a user and an AI agent, extract behavioral patterns \u2014 lessons about HOW to approach tasks, not facts about the world.
|
|
31
|
-
|
|
32
|
-
Extract patterns like:
|
|
33
|
-
- "When asked about X, the approach that works is Y"
|
|
34
|
-
- "User prefers Z style of communication"
|
|
35
|
-
- "For deployment tasks, always check A before doing B"
|
|
36
|
-
- "This codebase uses pattern X, so generate code following X"
|
|
37
|
-
|
|
38
|
-
SKIP:
|
|
39
|
-
- Factual information (names, dates, URLs)
|
|
40
|
-
- Routine task completions
|
|
41
|
-
- Greetings or small talk
|
|
42
|
-
|
|
43
|
-
Output a JSON array:
|
|
44
|
-
[{"pattern":"the behavioral lesson","context":"when this applies","confidence":0.5}]
|
|
45
|
-
|
|
46
|
-
If nothing worth extracting, output: []`,J=class{patternsDir;constructor(e=process.cwd()){this.patternsDir=ne(e,".agentx/patterns"),Re(this.patternsDir)||Rt(this.patternsDir,{recursive:!0})}filePath(e){return ne(this.patternsDir,`${e}.jsonl`)}getAll(e){let t=this.filePath(e);if(!Re(t))return[];try{return Pt(t,"utf-8").split(`
|
|
47
|
-
`).filter(n=>n.trim()).map(n=>{try{return JSON.parse(n)}catch{return null}}).filter(n=>n!==null)}catch{return[]}}addPattern(e,t){let n={...t,id:`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,6)}`,accessCount:0,createdAt:new Date().toISOString()};Dt(this.filePath(e),JSON.stringify(n)+`
|
|
48
|
-
`)}findRelevant(e,t,n=5){let s=this.getAll(t);if(s.length===0)return[];let r=s.map(h=>`${h.context} ${h.pattern}`),o=ne(this.patternsDir,`${t}_bm25_cache.json`),c=B(r,o),l=W(e,c).slice(0,n).map(h=>s[h.docIndex]).filter(h=>h.confidence>=.3);return l.length>0&&this.recordAccess(t,l.map(h=>h.id)),l}buildContext(e){if(e.length===0)return"";let t=["[Learned Patterns \u2014 behavioral lessons from past interactions]"];for(let n of e)t.push(`- ${n.pattern} (context: ${n.context}, confidence: ${Math.round(n.confidence*100)}%)`);return t.push("[Apply these patterns when relevant to the current task]"),t.join(`
|
|
49
|
-
`)}hasSimilar(e,t){let n=this.getAll(e),s=t.toLowerCase().split(/\s+/).filter(r=>r.length>3);return n.some(r=>{let o=r.pattern.toLowerCase();return s.filter(a=>o.includes(a)).length>=s.length*.6})}recordAccess(e,t){let n=this.getAll(e),s=new Set(t),r=!1;for(let o of n)s.has(o.id)&&(o.accessCount++,o.lastUsed=new Date().toISOString(),o.confidence=Math.min(1,o.confidence+.05),r=!0);r&&De(this.filePath(e),n.map(o=>JSON.stringify(o)).join(`
|
|
50
|
-
`)+`
|
|
51
|
-
`)}prune(e){let t=this.getAll(e);t.length<=_e||(t.sort((n,s)=>s.confidence*s.accessCount-n.confidence*n.accessCount),t=t.slice(0,_e),De(this.filePath(e),t.map(n=>JSON.stringify(n)).join(`
|
|
52
|
-
`)+`
|
|
53
|
-
`))}};async function Oe(i,e,t,n,s){if(e.length<30&&t.length<100)return;let{createProvider:r}=await import("./providers-AKQ4HTB4.js"),a=(await r("claude").generate([{role:"system",content:Ot},{role:"user",content:`User: ${e.slice(0,500)}
|
|
54
|
-
|
|
55
|
-
Agent: ${t.slice(0,1e3)}`}],{model:_t,maxTokens:512})).content.trim().match(/\[[\s\S]*\]/);if(!a)return;let l=JSON.parse(a[0]);if(!(!Array.isArray(l)||l.length===0)){for(let h of l)s.hasSimilar(i,h.pattern)||s.addPattern(i,{agentId:i,pattern:h.pattern,context:h.context,confidence:h.confidence||.5,source:n});Math.random()<.05&&s.prune(i)}}import{readFileSync as Ht}from"fs";import{homedir as Nt}from"os";import{join as Et}from"path";var L=null,jt=6e4;function Lt(){try{let i=Et(Nt(),".claude.json"),e=Ht(i,"utf8"),t=JSON.parse(e);return t&&typeof t=="object"?t:null}catch{return null}}function Ft(i,e=Date.now()){if(!i)return{available:!0,checkedAt:e,unknown:!0};let t=typeof i.cachedExtraUsageDisabledReason=="string"?i.cachedExtraUsageDisabledReason:void 0;return{available:!(t==="org_level_disabled_until"),reason:t,checkedAt:e}}function Ut(i=!1){let e=Date.now();return!i&&L&&e-L.checkedAt<jt||(L=Ft(Lt(),e)),L}function He(i){let e=Ut();return e.available||i?null:{abort:!0,reason:e.reason||"overage_disabled",message:"Claude Max-plan overage is disabled at the org level and this agent has no warm Claude session to cache against. A cold dispatch would pay a fresh cache-create that spills past the regular allotment, producing 'out of extra usage'. Re-enable overage at claude.ai/settings/usage, OR wait until a peer agent has established a warm session this agent can inherit before retrying.",raw:e}}var Ne={warnRatio:.8},v={...Ne},Wt=5*60*60*1e3,Bt=60*60*1e3,O=[];function Ee(i){v={...Ne,...i||{}}}function je(i){let e=i-Wt,t=0;for(;t<O.length&&O[t]<e;)t++;t>0&&O.splice(0,t)}function Le(i=Date.now()){je(i),O.push(i)}function Fe(i=Date.now()){je(i);let e=i-Bt,t=0;for(let r=O.length-1;r>=0&&O[r]>=e;r--)t++;let n=O.length,s={lastHour:t,last5h:n,maxPerHour:v.maxPerHour,maxPer5h:v.maxPer5h};return v.maxPerHour&&v.maxPerHour>0&&(s.hourlyRatio=t/v.maxPerHour),v.maxPer5h&&v.maxPer5h>0&&(s.fiveHourRatio=n/v.maxPer5h),s}function Ue(i,e=Date.now()){let t=Fe(e);return i?null:v.maxPerHour&&t.lastHour>=v.maxPerHour?{abort:!0,reason:"hourly_cap",message:`Claude-code fleet dispatch-budget hit: ${t.lastHour}/${v.maxPerHour} in the last hour. Cold dispatches are being held back to preserve warm-session headroom. Raise agents.budget.maxPerHour in DaemonConfig if this is a false positive.`,usage:t}:v.maxPer5h&&t.last5h>=v.maxPer5h?{abort:!0,reason:"five_hour_cap",message:`Claude-code fleet dispatch-budget hit: ${t.last5h}/${v.maxPer5h} in the last 5h. Cold dispatches are being held back to preserve warm-session headroom. Raise agents.budget.maxPer5h in DaemonConfig if this is a false positive.`,usage:t}:null}function We(i=Date.now()){let e=Fe(i),t=v.warnRatio??.8;return e.hourlyRatio!==void 0&&e.hourlyRatio>=t&&e.hourlyRatio<1?`claude-code hourly usage ${e.lastHour}/${e.maxPerHour} (${Math.round(e.hourlyRatio*100)}% of cap)`:e.fiveHourRatio!==void 0&&e.fiveHourRatio>=t&&e.fiveHourRatio<1?`claude-code 5h usage ${e.last5h}/${e.maxPer5h} (${Math.round(e.fiveHourRatio*100)}% of cap)`:null}var se=new Map;function Be(i,e,t){return t?`${i}:${e}:${t}`:`${i}:${e}`}function qe(i,e,t,n=Date.now()){let s=se.get(i);s||(s={key:i,samples:0,baseline:e,current:e,peak:e,lastAt:n,ring:[]},se.set(i,s)),s.samples+=1,s.baseline=.2*e+(1-.2)*s.baseline,s.current=e,s.peak=Math.max(s.peak,e),s.lastAt=n,s.ring.push({key:i,timestamp:n,total:e,parts:t}),s.ring.length>100&&s.ring.shift()}function Ke(i){let e=se.get(i);if(!e||e.samples<5)return null;let t=e.baseline*1.5;if(e.current<t)return null;let n=e.current/e.baseline;return`prompt-size drift for ${i}: ${e.current} bytes is ${n.toFixed(2)}x baseline (${Math.round(e.baseline)} bytes over ${e.samples} samples, peak ${e.peak})`}import{existsSync as P,mkdirSync as qt,readdirSync as M,readFileSync as re,rmSync as Kt,writeFileSync as Qt}from"fs";import{resolve as T}from"path";var Je;function Bn(i){Je=i}function qn(){return Je}var Qe=64*1024,Gt=5*60*1e3,E=".agentx/task-history",Jt=30;function ie(i,e=800){return i.length<=e?i:i.slice(0,e)+` \u2026[+${i.length-e} chars]`}function zt(i,e){let t=0;try{t=i.listArticles(e).length}catch{return""}if(t===0)return"";let n=T(i.baseDir,"_index.md");if(!P(n))return"";let s=process.argv[1]||"dist/cli.js",r=i.baseDir.replace(new RegExp(`/agents/${e}(/[^/]+)?$`),"");return["[Institutional Wiki \u2014 cross-agent source of truth]",`A curated wiki with ${t} article${t===1?"":"s"} grouped by type: person, project, place, concept, event, decision, pattern.`,"","The wiki is the canonical source for: who people are (team, clients, agents), past events (incidents, deploys), decisions and their reasoning, documented procedures, patterns.","","BEFORE you grep the workspace, search memory, or answer from your own prior context \u2014 if the question is about who / what happened / what we decided / how we do X, call:",` node ${s} wiki query "the user's question" --dir ${r} --agent ${e}`,"","It walks the catalog + wikilink graph and returns a cited answer. Your workspace memory is local to you; the wiki is shared and authoritative. Prefer the wiki for institutional questions; prefer your workspace for code-level questions.","[End Institutional Wiki]"].join(`
|
|
56
|
-
`)}function Xt(){let i="";return e=>{if(!e||typeof e!="object")return"";let t=e.type;if(t==="system"&&e.subtype==="init"){let n=e.model?` model=${e.model}`:"",s=e.session_id?` session=${e.session_id.slice(0,8)}`:"";return`\xB7 init${n}${s}
|
|
57
|
-
`}if(t==="assistant"&&e.message?.content){let n="";for(let s of e.message.content)if(s.type==="text"&&typeof s.text=="string")s.text.length>i.length&&(n+=s.text.slice(i.length),i=s.text);else if(s.type==="thinking"&&typeof s.thinking=="string")n+=`
|
|
58
|
-
\u{1F4AD} ${ie(s.thinking,600)}
|
|
59
|
-
`;else if(s.type==="tool_use"){let r=s.name||"tool",o=s.input?ie(JSON.stringify(s.input),400):"";n+=`
|
|
60
|
-
\u2192 ${r}(${o})
|
|
61
|
-
`}return n}if(t==="user"&&e.message?.content){let n="";for(let s of e.message.content)if(s.type==="tool_result"){let r=Array.isArray(s.content)?s.content.map(c=>typeof c?.text=="string"?c.text:"").join(""):typeof s.content=="string"?s.content:"",o=s.is_error?"\u2190 [error] ":"\u2190 ";n+=`${o}${ie(r,800)}
|
|
62
|
-
`}return n}return t==="result"?`\xB7 done${e.duration_ms?` (${Math.round(e.duration_ms/1e3)}s)`:""}
|
|
63
|
-
`:""}}var Ge=class{agents=new Map;config;providers={};sessions;wikiHub;memoryStore;patternStore;rateLimiter;tokenTracker;landscape;meshFallback;messageQueue;classifier;graphStore;handoverStore=new fe;activeSouls=new Map;taskOutputs=new Map;lastSummaries=new Map;sparklineCache=new Map;log;constructor(e,t=console.error.bind(console,"[agents]")){if(this.log=t,this.config=e,this.providers=e.providers,this.sessions=new q(process.cwd(),{staleMinutes:e.session.staleMinutes,maxTurnsPerSession:e.session.maxTurnsPerSession,tierTwoThresholdTokens:e.session.tierTwoThresholdTokens}),this.wikiHub=new me(void 0,void 0,"unified"),this.memoryStore=new Q,this.patternStore=new J,this.rateLimiter=new K,this.tokenTracker=new pe,this.messageQueue=new G,Ee({maxPerHour:e.session.maxClaudeCodeDispatchesPerHour,maxPer5h:e.session.maxClaudeCodeDispatchesPer5h}),e.graph?.enabled){this.graphStore=new ge({baseDir:T(process.cwd(),e.graph.baseDir),log:(...s)=>t("[graph]",...s)});let n=e.graph.draftAgent||e.dashboard?.draftAgent;this.classifier=new he({store:this.graphStore,daemonUrl:e.dashboard.daemonUrl,token:e.dashboard.token,draftAgent:n,autoApproveStructure:e.graph.autoApproveStructure,autoApproveConfidence:e.graph.autoApproveConfidence,log:(...s)=>t("[classifier]",...s)})}for(let[n,s]of Object.entries(e.agents))this.agents.set(n,{id:n,def:s,activeTasks:0,totalTasks:0,errors:0,runningTasks:[]})}setLandscape(e){this.landscape=e}setMeshFallback(e){this.meshFallback=e}setProviders(e){this.providers=e}setConfig(e){this.config=e}buildHandoverNote(e,t,n){let s=this.handoverStore.get(t,n);if(!s||s.toAgent!==e)return;let r=this.handoverStore.consumeSummary(t,n);if(!(!r&&s.summaryConsumedAt))return{fromAgent:s.fromAgent,summary:r||s.summary,at:s.createdAt}}getAgent(e){return this.agents.get(e)?.def}findByMention(e,t={}){let n=e.toLowerCase(),s,r=0;for(let[o,c]of this.agents)for(let a of c.def.mentions){if(t.atMentionsOnly&&!a.startsWith("@"))continue;let l=a.toLowerCase();n.includes(l)&&l.length>r&&(s=o,r=l.length)}return s}findAllMentioned(e){let t=e.toLowerCase(),n=[];for(let[s,r]of this.agents)for(let o of r.def.mentions)if(t.includes(o.toLowerCase())){n.push(s);break}return n}getWikiHub(){return this.wikiHub}getGraphStore(){return this.graphStore}buildPeerList(e,t){let n=[];for(let[s,r]of this.agents)s!==e&&n.push({name:r.def.name,handle:this.getChannelHandle(s,t),role:r.def.systemPrompt?.split(`
|
|
64
|
-
`)[0]?.slice(0,80)});return n}getChannelHandle(e,t){let n=this.agents.get(e)?.def;if(n)return t==="telegram"?n.mentions.find(s=>s.startsWith("@")):n.mentions[0]}async execute(e,t){let n=this.agents.get(e.agentId);if(!n){if(this.meshFallback){let u=this.meshFallback.directory().find(d=>d.healthy&&d.skills.some(y=>y.id===e.agentId));if(u){this.log(`[${e.agentId}] not local \u2014 routing to mesh peer "${u.peer}"`);try{let d=typeof e.timeoutMinutes=="number"&&e.timeoutMinutes>0?e.timeoutMinutes*60*1e3:void 0;return{content:await this.meshFallback.sendTask(u.peer,e.message,e.agentId,{timeoutMs:d}),viaMesh:u.peer}}catch(d){return this.log(`[${e.agentId}] mesh fallback to "${u.peer}" failed: ${d?.message??d}`),{content:"",error:`mesh fallback failed: ${d?.message??d}`}}}}return{content:"",error:`Unknown agent: ${e.agentId}`}}let s=e.context?.channel||"api",r=e.context?.chatId||e.context?.group||e.context?.sender||"default";if(n.activeTasks>=n.def.maxConcurrent){let u=n.def.queueMode||"collect",d=this.messageQueue.enqueue(e.agentId,s,r,{text:e.message,sender:e.context?.sender||"User",timestamp:Date.now(),channel:s,chatId:r,originalContext:e.context});if(d==="drop")return this.log(`[${e.agentId}] busy, message dropped (mode: drop)`),{content:"",error:`Agent "${e.agentId}" is busy \u2014 message dropped`};if(d){let y=this.messageQueue.pendingCount(e.agentId,s,r);return this.log(`[${e.agentId}] busy, message queued (mode: ${d}, pending: ${y})`),{content:"",error:`__queued__:${d}:${y}`}}}let o=await this.rateLimiter.acquire(e.agentId,{maxWaitMs:5*6e4,onWait:(u,d)=>{this.log(`[${e.agentId}] ${u} \u2014 queued, resumes in ~${Math.max(1,Math.round(d/1e3))}s`)}});if(!o.ok)return this.log(`[${e.agentId}] ${o.reason}`),{content:"",error:o.reason};n.activeTasks++,n.totalTasks++,n.lastActive=new Date;let c={id:`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,messagePreview:(e.message||"").slice(0,200),channel:e.context?.channel||"api",chatId:e.context?.chatId||e.context?.group,sender:e.context?.sender,startedAt:new Date};n.runningTasks.push(c);let a={agentId:e.agentId,buffer:"",subscribers:new Set,done:!1};this.taskOutputs.set(c.id,a);let l=u=>{if(u){a.buffer+=u,a.buffer.length>Qe&&(a.buffer=a.buffer.slice(a.buffer.length-Qe));for(let d of a.subscribers)try{d(u)}catch{}}},h;if(t){let u=Xt();h=d=>{let y=u(d);y&&l(y)}}this.messageQueue.markRunning(e.agentId,s,r),this.log(`[${e.agentId}] executing task (${n.activeTasks}/${n.def.maxConcurrent})`);let g=e.context?.channel||"api",m=e.context?.chatId||e.context?.group||e.context?.sender||"default",p=e.context?.sender||"User";this.sessions.addUserMessage(e.agentId,g,m,p,e.message);let b;if(this.classifier&&g!=="a2a")try{b=await this.classifier.classify({text:e.message,channel:g,sender:e.context?.sender,agentId:e.agentId})||void 0}catch(u){this.log(`[classifier] classify failed for ${e.agentId}: ${u?.message||u}`)}let w=this.wikiHub.getAgentWiki(e.agentId),$=zt(w,e.agentId),I=this.memoryStore.findRelevant(e.message,e.agentId,8),k=this.memoryStore.buildContext(I),C=this.patternStore.findRelevant(e.message,e.agentId,5),D=this.patternStore.buildContext(C),f="";try{let{loadLocalSkills:u,getAutoInjectSkills:d}=await import("./loader-PTCXLJEX.js"),y=await u(n.def.workspace);f=d(y,e.message)}catch{}let x=n.def.tier==="claude-code"?this.sessions.getClaudeSessionId(e.agentId,g,m):void 0;if(x&&this.sessions.isSessionStale(e.agentId,g,m)&&(this.log(`[${e.agentId}] session stale for ${g}:${m}, starting fresh`),this.sessions.clearClaudeSessionId(e.agentId,g,m),x=void 0),x&&this.sessions.shouldRotateByTierTwo(e.agentId,g,m)){let u=this.sessions.getLastTurnInputTokens(e.agentId,g,m);this.log(`[${e.agentId}] tier-2 rotation for ${g}:${m} (last turn: ${u} input tokens \u2265 ${this.sessions.getTierTwoThresholdTokens()})`),this.sessions.clearClaudeSessionId(e.agentId,g,m),x=void 0}if(x&&this.sessions.shouldRotateByTurns(e.agentId,g,m)){let u=this.sessions.getTurnCount(e.agentId,g,m);this.log(`[${e.agentId}] max-turns rotation for ${g}:${m} (${u} turns \u2265 ${this.sessions.getMaxTurnsPerSession()})`),this.sessions.clearClaudeSessionId(e.agentId,g,m),x=void 0}try{let u=await this.sessions.compactIfNeeded(e.agentId,g,m,this.memoryStore);if(u.compacted){let d=u.qualityScore??"?",y=u.lostEntities?.length??0;if(this.log(`[${e.agentId}] session compacted for ${g}:${m} (quality: ${d}%, ${y} entities lost)`),u.lostEntities?.length&&this.log(`[${e.agentId}] lost entities: ${u.lostEntities.slice(0,5).join(", ")}`),u.drift){let S=u.drift;this.log(`[${e.agentId}] DRIFT DETECTED: score=${S.overallScore} (lexicon=${S.lexiconDecay}, tools=${S.toolShift}, semantic=${S.semanticDrift})`),S.lostWords.length&&this.log(`[${e.agentId}] lost domain words: ${S.lostWords.slice(0,5).join(", ")}`)}}}catch(u){this.log(`[${e.agentId}] compaction failed (non-fatal): ${u.message}`)}let R=x?void 0:this.sessions.buildHistoryContext(e.agentId,g,m),oe=this.sessions.getCrossSessionSummary(e.agentId,g,m,e.message),ze=e.contextStrategy??this.config.session.contextStrategy??"layered",ae,ce;if(ze==="planner"){try{let{planContext:u}=await import("./context-planner-G2J7FNNU.js"),d=await u({agentId:e.agentId,channel:g,chatId:m,message:e.message,sessions:this.sessions,memoryStore:this.memoryStore});d?(ae=d.sessionHistory,k=d.memoryContext,oe=d.crossChatContext,ce=d.debug,this.log(`[${e.agentId}] planner: turns=${d.debug.recentTurns}, mem=${d.debug.memoryIncluded?"yes":"no"}, xchat=${d.debug.crossChatIncluded?"yes":"no"} (${d.debug.planLatencyMs}ms) \u2014 ${d.debug.reasoning??""}`)):this.log(`[${e.agentId}] planner returned null \u2014 falling back to layered`)}catch(u){this.log(`[${e.agentId}] planner failed (non-fatal): ${u.message} \u2014 falling back to layered`)}x&&(this.sessions.clearClaudeSessionId(e.agentId,g,m),x=void 0)}let z=`${e.agentId}:${g}:${m}`,F=xe(e.message);F&&(F==="default"?(this.activeSouls.delete(z),this.log(`[${e.agentId}] Soul reset to default`)):(this.activeSouls.set(z,F),this.log(`[${e.agentId}] Soul switched to: ${F}`)));let Xe=this.activeSouls.get(z),Ye=ye(n.def.workspace,Xe),Ze=be(Ye),X=[n.def.systemPrompt||"",Ze||""].filter(u=>u.trim().length>0).join(`
|
|
65
|
-
|
|
66
|
-
`)||void 0,Ve={channel:g,channelScope:e.context?.group?"group":g==="gitlab"?"project":"personal",groupName:e.context?.group,agentId:e.agentId,agentName:n.def.name,agentHandle:this.getChannelHandle(e.agentId,g),systemPrompt:n.def.systemPrompt,sender:p,senderId:e.context?.senderId,senderUsername:e.context?.senderUsername,landscape:this.landscape?.getForAgent(e.agentId),channelMeta:e.context?.channelMeta,mediaPath:e.context?.mediaPath,mediaType:e.context?.mediaType,replyToText:e.context?.replyToText,patternContext:D||void 0,skillInjection:f||void 0,groupHistory:(e.context?.group,void 0),sessionHistory:ae??R,memoryContext:k||void 0,crossChatContext:oe||void 0,wikiContext:$,handoverNote:this.buildHandoverNote(e.agentId,g,m),intent:b?{path:b.path,pathLabel:b.pathLabel,pathId:b.pathId,axes:b.axes,leaf:b.leaf,status:b.status}:void 0,message:e.message},Y=Ce(Ve),Z=(Y?.length??0)+(X?.length??0)+(e.message?.length??0),U={history:Y?.length??0,sysPrompt:X?.length??0,message:e.message?.length??0},ue=Be(e.agentId,g,m);qe(ue,Z,U);let le=Ke(ue);le&&this.log(`[${e.agentId}] ${le}`),Z>16e3&&this.log(`[${e.agentId}] large context for ${g}:${m}: ${Z} bytes (history=${U.history}, sysPrompt=${U.sysPrompt}, message=${U.message})`);let et={...e,systemPromptAppend:X},_;try{if(n.def.tier==="claude-code"){let d=!!x,S=[He(d),Ue(d)].find(j=>j&&j.abort);if(S){n.errors++,this.log(`[${e.agentId}] skipping cold dispatch \u2014 ${S.reason}`);let j={content:"",error:S.message,duration:0};if(!t){a.buffer=`[error] ${S.message}`;for(let tt of a.subscribers)try{tt(a.buffer)}catch{}}return _=j,j}Le();let A=We();A&&this.log(`[${e.agentId}] ${A}`)}let u=await Se(n.def,et,this.providers,t,Y,x,h);if(_=u,!t&&(u.content||u.error)){let d=u.error?`[error] ${u.error}`:u.content;a.buffer=d;for(let y of a.subscribers)try{y(d)}catch{}}if(u.error)n.errors++,this.log(`[${e.agentId}] error: ${u.error}`);else{if(this.sessions.addAgentMessage(e.agentId,g,m,u.content),u.claudeSessionId&&this.sessions.setClaudeSessionId(e.agentId,g,m,u.claudeSessionId),u.claudeSessionId&&u.usage&&this.sessions.recordTurnUsage(e.agentId,g,m,u.usage),u.usage){let A=(u.usage.inputTokens||0)+(u.usage.cacheReadTokens||0)+(u.usage.cacheCreateTokens||0);A>=this.sessions.getTierTwoThresholdTokens()&&this.log(`[${e.agentId}] TIER-2 HIT on ${g}:${m}: ${A} total input tokens (input=${u.usage.inputTokens}, cacheRead=${u.usage.cacheReadTokens}, cacheCreate=${u.usage.cacheCreateTokens}) \u2014 next turn will rotate`)}if(u.content.length>50){try{let A=`${e.agentId}-${Date.now().toString(36)}`;this.wikiHub.getSharedStore().addEntry({id:A,date:new Date().toISOString().slice(0,10),agentId:e.agentId,source:g,sourceContext:e.context?.group||e.context?.sender,content:`User: ${e.message}
|
|
67
|
-
|
|
68
|
-
Agent: ${u.content}`})}catch{}de(e.agentId,e.message,u.content,{channel:g,chatId:m,sender:p},this.memoryStore).catch(()=>{}),Oe(e.agentId,e.message,u.content,{channel:g,date:new Date().toISOString().slice(0,10)},this.patternStore).catch(()=>{})}let d=u.billedModel||e.model||n.def.model,y=e.context?.channel,S=y&&(e.context?.chatId||e.context?.group||e.context?.sender)?`${y}:${e.context?.chatId||e.context?.group||e.context?.sender}`:void 0;this.tokenTracker.record(e.agentId,u.duration||0,u.usage,e.message.length,u.content.length,!1,d,y,S),this.log(`[${e.agentId}] completed in ${u.duration}ms`+(u.tokensUsed?` (${u.tokensUsed} tokens)`:""))}return u}catch(u){return n.errors++,this.log(`[${e.agentId}] unexpected error: ${u.message}`),_={content:"",error:u.message},_}finally{n.activeTasks--;let u=n.runningTasks.findIndex(d=>d.id===c.id);u!==-1&&n.runningTasks.splice(u,1),a.done=!0,a.endedAt=new Date;for(let d of a.subscribers)try{d(`
|
|
69
|
-
[task finished]
|
|
70
|
-
`)}catch{}a.subscribers.clear(),setTimeout(()=>this.taskOutputs.delete(c.id),Gt).unref?.();try{let d=a.endedAt,y={id:c.id,agentId:e.agentId,channel:c.channel,chatId:c.chatId,sender:c.sender,message:e.message||"",startedAt:c.startedAt.toISOString(),endedAt:d.toISOString(),durationMs:d.getTime()-c.startedAt.getTime(),ok:!_?.error,error:_?.error,responseText:_?.content||"",transcript:a.buffer};this.persistTaskRecord(y);let S=(y.responseText||y.error||"").trim();if(S){let A=S.split(/\r?\n/)[0].slice(0,140);this.lastSummaries.set(e.agentId,{text:A,at:d,ok:y.ok})}}catch(d){this.log(`[${e.agentId}] task history persist failed: ${d?.message}`)}this.messageQueue.markDone(e.agentId,s,r).then(d=>{if(d.length!==0){this.log(`[${e.agentId}] flushing ${d.length} queued message(s)`);for(let y of d)this.execute({message:y.text,agentId:e.agentId,context:y.originalContext||{channel:y.channel,sender:y.sender,chatId:y.chatId}}).catch(S=>{this.log(`[${e.agentId}] queued message failed: ${S.message}`)})}}).catch(d=>{this.log(`[${e.agentId}] queue flush failed: ${d.message}`)})}}list(){return Array.from(this.agents.values()).map(e=>{let t=this.lastSummaries.get(e.id);return{id:e.id,name:e.def.name,tier:e.def.tier,model:e.def.model,workspace:e.def.workspace,active:e.activeTasks,total:e.totalTasks,errors:e.errors,lastActive:e.lastActive,runningTasks:e.runningTasks,lastSummary:t?{text:t.text,at:t.at.toISOString(),ok:t.ok}:void 0,hourlyTasks:this.getHourlySparkline(e.id,24)}})}persistTaskRecord(e){let t=e.endedAt.slice(0,10),n=T(process.cwd(),E,this.safe(e.agentId),t);P(n)||qt(n,{recursive:!0});let s=T(n,`${this.safe(e.id)}.json`);Qt(s,JSON.stringify(e,null,2),"utf-8")}getHourlySparkline(e,t=24){let n=Date.now(),s=this.sparklineCache.get(e);if(s&&n-s.at<6e4&&s.hourly.length===t)return s.hourly;let r=new Array(t).fill(0),o=n-t*36e5,c=T(process.cwd(),E,this.safe(e));if(!P(c))return this.sparklineCache.set(e,{hourly:r,at:n}),r;let a=new Date(n).toISOString().slice(0,10),l=new Date(n-864e5).toISOString().slice(0,10);new Date(n).setUTCHours(0,0,0,0);for(let g of[l,a]){let m=T(c,g);if(P(m))try{for(let p of M(m)){if(!p.endsWith(".json"))continue;let b=p.split("-")[0],w=parseInt(b,10);if(!Number.isFinite(w)||w<o||w>n)continue;let $=Math.floor((n-w)/36e5),I=t-1-$;I>=0&&I<t&&r[I]++}}catch{}}return this.sparklineCache.set(e,{hourly:r,at:n}),r}hydrateLastSummariesFromDisk(){let e=T(process.cwd(),E);if(!P(e))return 0;let t=0;for(let n of M(e)){let s=T(e,n),r;try{r=M(s).filter(o=>/^\d{4}-\d{2}-\d{2}$/.test(o)).sort().reverse()}catch{continue}e:for(let o of r){let c=T(s,o),a;try{a=M(c).filter(l=>l.endsWith(".json")).sort().reverse()}catch{continue}for(let l of a)try{let h=JSON.parse(re(T(c,l),"utf-8")),g=(h.responseText||h.error||"").trim();if(!g)continue;let m=g.split(/\r?\n/)[0].slice(0,140);this.lastSummaries.set(h.agentId,{text:m,at:new Date(h.endedAt),ok:h.ok}),t++;break e}catch{}}}return t}pruneTaskHistory(e=Jt){let t=T(process.cwd(),E);if(!P(t))return 0;let n=Date.now()-e*24*60*60*1e3,s=0;for(let r of M(t)){let o=T(t,r),c;try{c=M(o)}catch{continue}for(let a of c){let l=Date.parse(a+"T00:00:00Z");if(!(Number.isNaN(l)||l>=n))try{Kt(T(o,a),{recursive:!0,force:!0}),s++}catch{}}}return s}listTaskHistory(e,t=50){let n=T(process.cwd(),E,this.safe(e));if(!P(n))return[];let s=M(n).filter(o=>/^\d{4}-\d{2}-\d{2}$/.test(o)).sort().reverse(),r=[];for(let o of s){if(r.length>=t)break;let c=T(n,o),a;try{a=M(c).filter(l=>l.endsWith(".json"))}catch{continue}a.sort().reverse();for(let l of a){if(r.length>=t)break;try{let h=JSON.parse(re(T(c,l),"utf-8")),{transcript:g,responseText:m,...p}=h;r.push(p)}catch{}}}return r}getTaskRecord(e,t){let n=T(process.cwd(),E,this.safe(e));if(!P(n))return null;let s=this.safe(t),r=M(n).filter(o=>/^\d{4}-\d{2}-\d{2}$/.test(o)).sort().reverse();for(let o of r){let c=T(n,o,`${s}.json`);if(P(c))try{return JSON.parse(re(c,"utf-8"))}catch{return null}}return null}safe(e){return e.replace(/[^a-zA-Z0-9_.:-]/g,"_")}subscribeToTaskOutput(e,t){let n=this.taskOutputs.get(e);return n?n.done?{initial:n.buffer,done:!0,unsubscribe:()=>{}}:(n.subscribers.add(t),{initial:n.buffer,done:!1,unsubscribe:()=>{n.subscribers.delete(t)}}):null}getUsage(e=7){return this.tokenTracker.summary(e)}getTodayUsage(){return this.tokenTracker.today()}getTokenTracker(){return this.tokenTracker}};export{ot as a,ct as b,ut as c,Se as d,Bn as e,qn as f,Ge as g};
|
|
71
|
-
//# sourceMappingURL=chunk-HHJGKD5B.js.map
|