agent-afk 1.3.0 → 1.8.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 +1 -1
- package/dist/cli.mjs +294 -168
- package/dist/index.mjs +177 -76
- package/dist/telegram.mjs +187 -86
- package/package.json +10 -6
package/dist/telegram.mjs
CHANGED
|
@@ -1,34 +1,121 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{
|
|
3
|
-
|
|
2
|
+
import{existsSync as Ec,readFileSync as Tc}from"fs";import{Telegraf as Es}from"telegraf";import ns from"better-sqlite3";import{existsSync as we,mkdirSync as dn,readFileSync as Le,writeFileSync as un,readdirSync as rs,appendFileSync as os,unlinkSync as pn,copyFileSync as ss}from"fs";import{join as G,basename as mn,resolve as $e,relative as is}from"path";import{join as M,dirname as Xo}from"path";import{homedir as yt}from"os";import{fileURLToPath as Zo}from"url";function Y(){return process.env.AFK_HOME||M(yt(),".afk")}function ce(){return M(Y(),"agent-framework")}function on(){return M(ce(),"forge-telemetry.jsonl")}function pe(){return M(ce(),"briefs")}function Oe(){return M(ce(),"ceiling-ledger")}function bt(){return M(Y(),"skills")}function me(){return M(Y(),"plugins")}function es(){return M(process.cwd(),".afk")}function wt(){return M(es(),"plugins")}function De(){return M(me(),".index.json")}function vt(){let t=Zo(import.meta.url),e=Xo(t);return M(e,"bundled-plugins")}function sn(){return M(Y(),"config")}function an(){return M(Y(),"state")}function ln(){return M(an(),"sessions")}function Fe(){return M(an(),"memory")}function fe(){return M(sn(),"afk.env")}function kt(){return M(sn(),"afk.config.json")}function cn(){return M(yt(),".afk.env")}function St(){return M(yt(),".afk.config.json")}function ts(){return process.env.AFK_DEBUG==="1"||process.env.DEBUG==="1"}function A(...t){ts()&&console.log(...t)}var fn="HOT.md",as="HOT.md.bak",gn="memory.db",hn="memory-wal.jsonl",Ne="procedures",ls=5250,ve=1,cs=`
|
|
3
|
+
CREATE TABLE IF NOT EXISTS sessions (
|
|
4
|
+
session_id TEXT PRIMARY KEY,
|
|
5
|
+
surface TEXT NOT NULL,
|
|
6
|
+
started_at TEXT NOT NULL,
|
|
7
|
+
ended_at TEXT,
|
|
8
|
+
summary TEXT,
|
|
9
|
+
tools_used TEXT NOT NULL DEFAULT '[]',
|
|
10
|
+
outcome TEXT,
|
|
11
|
+
token_count INTEGER,
|
|
12
|
+
cost_usd REAL
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
CREATE TABLE IF NOT EXISTS facts (
|
|
16
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
17
|
+
session_id TEXT,
|
|
18
|
+
created_at TEXT NOT NULL,
|
|
19
|
+
category TEXT NOT NULL CHECK(category IN ('preference', 'convention', 'decision', 'learning')),
|
|
20
|
+
content TEXT NOT NULL,
|
|
21
|
+
source_surface TEXT NOT NULL DEFAULT 'cli',
|
|
22
|
+
superseded_by INTEGER REFERENCES facts(id),
|
|
23
|
+
confidence REAL NOT NULL DEFAULT 1.0,
|
|
24
|
+
access_count INTEGER NOT NULL DEFAULT 0,
|
|
25
|
+
last_accessed TEXT
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS facts_fts USING fts5(
|
|
29
|
+
content,
|
|
30
|
+
category,
|
|
31
|
+
content=facts,
|
|
32
|
+
content_rowid=id,
|
|
33
|
+
tokenize='porter'
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
CREATE TRIGGER IF NOT EXISTS facts_ai AFTER INSERT ON facts BEGIN
|
|
37
|
+
INSERT INTO facts_fts(rowid, content, category) VALUES (new.id, new.content, new.category);
|
|
38
|
+
END;
|
|
39
|
+
|
|
40
|
+
CREATE TRIGGER IF NOT EXISTS facts_ad AFTER DELETE ON facts BEGIN
|
|
41
|
+
INSERT INTO facts_fts(facts_fts, rowid, content, category) VALUES ('delete', old.id, old.content, old.category);
|
|
42
|
+
END;
|
|
43
|
+
|
|
44
|
+
CREATE TRIGGER IF NOT EXISTS facts_au AFTER UPDATE ON facts BEGIN
|
|
45
|
+
INSERT INTO facts_fts(facts_fts, rowid, content, category) VALUES ('delete', old.id, old.content, old.category);
|
|
46
|
+
INSERT INTO facts_fts(rowid, content, category) VALUES (new.id, new.content, new.category);
|
|
47
|
+
END;
|
|
48
|
+
|
|
49
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_started_at ON sessions(started_at DESC);
|
|
50
|
+
CREATE INDEX IF NOT EXISTS idx_facts_session_id ON facts(session_id);
|
|
51
|
+
`;function vn(t){return Math.ceil(t.length/3.5)}var Q=class{dir;db;constructor(e){this.dir=e??Fe(),dn(this.dir,{recursive:!0}),dn(G(this.dir,Ne),{recursive:!0}),this.db=new ns(G(this.dir,gn)),this.db.pragma("journal_mode = WAL"),this.db.pragma("busy_timeout = 5000");let n=this.db.pragma("user_version",{simple:!0});if(n===0)this.db.exec(cs),this.db.pragma(`user_version = ${ve}`);else if(n!==ve)throw n<ve?(this.db.close(),new Error(`memory.db schema version ${n} is older than the current version ${ve}. Delete ${G(this.dir,gn)} to start fresh (your stored facts will be lost).`)):(this.db.close(),new Error(`memory.db schema version ${n} is newer than this build supports (${ve}). Upgrade agent-afk to a version that understands schema v${n}.`));this.replayWAL()}loadHot(){let e=G(this.dir,fn);if(!we(e))return null;try{return Le(e,"utf-8")}catch{return null}}saveHot(e){if(e.length>ls)throw new Error(`HOT.md exceeds ~1,500 token cap (${vn(e)} estimated tokens, ${e.length} chars). Trim before saving.`);let n=G(this.dir,fn);we(n)&&ss(n,G(this.dir,as)),un(n,e,"utf-8")}storeFact(e){let n=new Date().toISOString();this.appendWAL({type:"fact",timestamp:n,data:{...e,created_at:n}});let o=this.db.prepare(`
|
|
52
|
+
INSERT INTO facts (session_id, created_at, category, content, source_surface)
|
|
53
|
+
VALUES (?, ?, ?, ?, ?)
|
|
54
|
+
`).run(e.session_id??null,n,e.category,e.content,e.source_surface);return Number(o.lastInsertRowid)}supersedeFact(e,n,r){let o=this.db.prepare("SELECT * FROM facts WHERE id = ?").get(e);if(!o)throw new Error(`Fact ${e} not found`);let s=new Date().toISOString(),i=r??o.category;this.appendWAL({type:"fact",timestamp:s,data:{session_id:o.session_id,created_at:s,category:i,content:n,source_surface:o.source_surface}});let l=this.db.prepare(`
|
|
55
|
+
INSERT INTO facts (session_id, created_at, category, content, source_surface, confidence)
|
|
56
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
57
|
+
`).run(o.session_id,s,i,n,o.source_surface,1),c=Number(l.lastInsertRowid);return this.db.prepare("UPDATE facts SET superseded_by = ? WHERE id = ?").run(c,e),this.appendWAL({type:"supersede",timestamp:s,data:{old_fact_id:e,new_fact_id:c}}),c}removeFact(e){return this.db.prepare("DELETE FROM facts WHERE id = ?").run(e).changes>0}getFact(e){return this.db.prepare("SELECT * FROM facts WHERE id = ?").get(e)??null}searchFacts(e,n){let r=n?.limit??10,o=["facts_fts MATCH ?"],s=[e];n?.category&&(o.push("f.category = ?"),s.push(n.category)),n?.since&&(o.push("f.created_at >= ?"),s.push(n.since)),o.push("f.superseded_by IS NULL");let i=`
|
|
58
|
+
SELECT f.*, facts_fts.rank
|
|
59
|
+
FROM facts f
|
|
60
|
+
JOIN facts_fts ON facts_fts.rowid = f.id
|
|
61
|
+
WHERE ${o.join(" AND ")}
|
|
62
|
+
ORDER BY facts_fts.rank
|
|
63
|
+
LIMIT ?
|
|
64
|
+
`;return s.push(r),this.db.prepare(i).all(...s)}startSession(e){let n=new Date().toISOString();this.appendWAL({type:"session_start",timestamp:n,data:{...e,started_at:n}}),this.db.prepare(`
|
|
65
|
+
INSERT OR IGNORE INTO sessions (session_id, surface, started_at)
|
|
66
|
+
VALUES (?, ?, ?)
|
|
67
|
+
`).run(e.session_id,e.surface,n)}endSession(e,n,r,o,s){let i=new Date().toISOString();this.appendWAL({type:"session_end",timestamp:i,data:{session_id:e,summary:n,outcome:r,ended_at:i}}),this.db.prepare(`
|
|
68
|
+
UPDATE sessions
|
|
69
|
+
SET ended_at = ?, summary = ?, outcome = ?, token_count = ?, cost_usd = ?
|
|
70
|
+
WHERE session_id = ?
|
|
71
|
+
`).run(i,n,r,o??null,s??null,e)}getSession(e){return this.db.prepare("SELECT * FROM sessions WHERE session_id = ?").get(e)??null}recentSessions(e=5){return this.db.prepare("SELECT * FROM sessions ORDER BY started_at DESC LIMIT ?").all(e)}writeProcedure(e,n,r){let o=yn(e),s=$e(G(this.dir,Ne)),i=$e(s,`${o}.md`);bn(i,s);let a=["---",`name: ${o}`,`created: ${new Date().toISOString()}`,`source_session: ${r??"unknown"}`,"access_count: 0","---",""].join(`
|
|
72
|
+
`);un(i,a+n,"utf-8")}loadProcedure(e){let n=yn(e),r=$e(G(this.dir,Ne)),o=$e(r,`${n}.md`);if(bn(o,r),!we(o))return null;try{return wn(o,Le(o,"utf-8"))}catch{return null}}searchProcedures(e){let n=G(this.dir,Ne);if(!we(n))return[];let r=e.toLowerCase().split(/\s+/),o=[];for(let s of rs(n)){if(!s.endsWith(".md"))continue;let i=Le(G(n,s),"utf-8"),a=i.toLowerCase();if(r.some(l=>a.includes(l))){let l=wn(s,i);l&&o.push(l)}}return o}search(e,n){let r=[];try{let s=this.searchFacts(e,n);for(let i of s)r.push({type:"fact",content:i.content,category:i.category,created_at:i.created_at,source_session:i.session_id,confidence:i.confidence})}catch{}if(!n?.category){let s=this.searchProcedures(e);for(let i of s)r.push({type:"procedure",content:i.content,created_at:i.created,source_session:i.source_session,confidence:1})}let o=n?.limit??10;return r.slice(0,o)}replayWAL(){let e=G(this.dir,hn);if(!we(e))return 0;let n=0;try{let r=Le(e,"utf-8").trim();if(!r)return pn(e),0;let o=r.split(`
|
|
73
|
+
`);for(let s of o)if(s.trim())try{let i=JSON.parse(s);if(!ms(i)){A("WAL replay: skipping invalid entry:",s.slice(0,200));continue}let a=i;if(a.type==="session_start"){let l=a.data;this.db.prepare(`
|
|
74
|
+
INSERT OR IGNORE INTO sessions (session_id, surface, started_at)
|
|
75
|
+
VALUES (?, ?, ?)
|
|
76
|
+
`).run(l.session_id,l.surface,l.started_at),n++}else if(a.type==="session_end"){let l=a.data;this.db.prepare(`
|
|
77
|
+
UPDATE sessions SET ended_at = ?, summary = ?, outcome = ?
|
|
78
|
+
WHERE session_id = ? AND ended_at IS NULL
|
|
79
|
+
`).run(l.ended_at,l.summary,l.outcome,l.session_id),n++}else if(a.type==="fact"){let l=a.data;this.db.prepare("SELECT id FROM facts WHERE content = ? AND created_at = ?").get(l.content,l.created_at)||(this.db.prepare(`
|
|
80
|
+
INSERT INTO facts (session_id, created_at, category, content, source_surface)
|
|
81
|
+
VALUES (?, ?, ?, ?, ?)
|
|
82
|
+
`).run(l.session_id??null,l.created_at,l.category,l.content,l.source_surface??"cli"),n++)}else if(a.type==="supersede"){let l=a.data,c=l.old_fact_id,d=l.new_fact_id;typeof c=="number"&&typeof d=="number"&&(this.db.prepare("UPDATE facts SET superseded_by = ? WHERE id = ? AND superseded_by IS NULL").run(d,c),n++)}}catch(i){A("WAL replay: skipping malformed line:",String(i))}pn(e)}catch(r){A("WAL file unreadable, skipping recovery:",String(r))}return n}close(){this.db.close()}appendWAL(e){let n=G(this.dir,hn);try{os(n,JSON.stringify(e)+`
|
|
83
|
+
`,"utf-8")}catch(r){A("WAL append failed (non-fatal):",String(r))}}},ds=/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/;function yn(t){if(!t||t.length>100||!ds.test(t))throw new Error(`Invalid procedure name "${t}": must be 1-100 chars, alphanumeric/hyphens/underscores only`);return t}var us=new Set(["fact","session_start","session_end","supersede"]),ps=new Set(["preference","convention","decision","learning"]);function ms(t){if(!t||typeof t!="object")return!1;let e=t;if(typeof e.type!="string"||!us.has(e.type)||typeof e.timestamp!="string"||!e.data||typeof e.data!="object")return!1;if(e.type==="fact"){let n=e.data;if(typeof n.category!="string"||!ps.has(n.category))return!1}return!0}function bn(t,e){let n=is(e,t);if(n.startsWith("..")||n.startsWith("/"))throw new Error("Path traversal detected")}function wn(t,e){let n=e.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);if(!n)return{name:mn(t,".md"),content:e,created:"",source_session:null,access_count:0};let r=n[1]??"",o=n[2]??"",s=c=>c.match(/^name:\s*(.+)$/m)?.[1]?.trim()??mn(t,".md"),i=c=>c.match(/^created:\s*(.+)$/m)?.[1]?.trim()??"",a=c=>c.match(/^source_session:\s*(.+)$/m)?.[1]?.trim()??null,l=c=>{let d=c.match(/^access_count:\s*(\d+)$/m);return d?parseInt(d[1],10):0};return{name:s(r),content:o.trim(),created:i(r),source_session:a(r),access_count:l(r)}}import{existsSync as fs,readFileSync as gs}from"fs";import{join as hs}from"path";function kn(){let t=hs(Fe(),"HOT.md");if(!fs(t))return null;try{let e=gs(t,"utf-8");return e.trim().length>0?e:null}catch{return null}}function xt(t){let e=kn();if(!e)return t;let r=`<cross-session-memory>
|
|
84
|
+
${e.replace(/<\/?cross-session-memory\b[^>]*>/gi,"")}
|
|
85
|
+
</cross-session-memory>`,o=t.systemPrompt;if(typeof o=="string")return{...t,systemPrompt:`${r}
|
|
86
|
+
|
|
87
|
+
${o}`};if(o&&typeof o=="object"&&"type"in o&&o.type==="preset"){let s=o.append??"";return{...t,systemPrompt:{...o,append:`${r}
|
|
88
|
+
|
|
89
|
+
${s}`}}}return{...t,systemPrompt:r}}function Et(t,e="cli"){return n=>{if(n.event!=="SessionEnd")return{};try{let r=n.sessionId;r&&(t.startSession({session_id:r,surface:e}),t.endSession(r,n.reason??"session ended","completed"))}catch{}return{}}}var Sn={name:"memory_search",description:'Search cross-session memory for facts and procedures. Returns results ranked by relevance. Use this to recall information from prior sessions. Supports FTS5 match syntax: AND, OR, NOT, "exact phrase", prefix*',input_schema:{type:"object",properties:{query:{type:"string",description:'Search query (supports FTS5 match syntax: AND, OR, NOT, "exact phrase", prefix*)'},category:{type:"string",enum:["preference","convention","decision","learning"],description:"Optional: filter by fact category"},since:{type:"string",description:"Optional: ISO date \u2014 only return facts created after this date"},limit:{type:"number",description:"Max results (default 10)"}},required:["query"]}},xn={name:"memory_update",description:'Store a fact in cross-session memory or update hot memory. Hot memory (target: "hot") persists in the system prompt across all future sessions. Facts (target: "fact") are stored in the searchable archive.',input_schema:{type:"object",properties:{target:{type:"string",enum:["hot","fact"],description:'"hot" writes to HOT.md (system prompt), "fact" writes to the searchable archive'},action:{type:"string",enum:["set","supersede","remove"],description:"Operation: set (create/overwrite), supersede (replace while keeping history), remove (delete)"},content:{type:"string",description:"The content to store (for set/supersede)"},category:{type:"string",enum:["preference","convention","decision","learning"],description:"Required for fact target"},supersedes:{type:"number",description:"Fact ID being superseded (for supersede action)"},id:{type:"number",description:"Fact ID to remove (for remove action)"}},required:["target","action"]}},En={name:"procedure_write",description:"Write a reusable procedure to memory. Procedures are markdown files describing how to perform recurring tasks. They persist across sessions and are searchable via memory_search.",input_schema:{type:"object",properties:{name:{type:"string",description:"Procedure name (kebab-case, becomes the filename)"},content:{type:"string",description:"Procedure content (markdown)"}},required:["name","content"]}},Tt=[Sn,xn,En];function At(t,e,n){let r=async i=>{try{let a=ys(i),l=t.search(a.query,{category:a.category,since:a.since,limit:a.limit??10});return{content:JSON.stringify(l)}}catch(a){return{content:`memory_search error: ${a instanceof Error?a.message:String(a)}`,isError:!0}}},o=async i=>{try{let a=bs(i);if(a.target==="hot")return a.action!=="set"?{content:'Hot memory only supports action: "set". Use supersede/remove only for facts.',isError:!0}:a.content?(t.saveHot(a.content),{content:JSON.stringify({saved:!0,target:"hot"})}):{content:'content is required for action: "set"',isError:!0};if(a.action==="set"){if(!a.category)return{content:"category is required for fact storage",isError:!0};if(!a.content)return{content:'content is required for action: "set"',isError:!0};let l=t.storeFact({session_id:e,category:a.category,content:a.content,source_surface:n??"cli"});return{content:JSON.stringify({id:l,action:"set",target:"fact"})}}if(a.action==="supersede"){if(!a.supersedes)return{content:'supersedes (fact ID) is required for action: "supersede"',isError:!0};if(!a.content)return{content:'content is required for action: "supersede"',isError:!0};let l=t.supersedeFact(a.supersedes,a.content,a.category??void 0);return{content:JSON.stringify({id:l,action:"supersede",target:"fact",supersedes:a.supersedes})}}if(a.action==="remove"){if(!a.id)return{content:'id (fact ID) is required for action: "remove"',isError:!0};let l=t.removeFact(a.id);return{content:JSON.stringify({removed:l,action:"remove",target:"fact"})}}return{content:`Unknown action: ${a.action}`,isError:!0}}catch(a){return{content:`memory_update error: ${a instanceof Error?a.message:String(a)}`,isError:!0}}},s=async i=>{try{let a=ws(i);return t.writeProcedure(a.name,a.content,e),{content:JSON.stringify({name:a.name,written:!0})}}catch(a){return{content:`procedure_write error: ${a instanceof Error?a.message:String(a)}`,isError:!0}}};return new Map([["memory_search",r],["memory_update",o],["procedure_write",s]])}function ys(t){if(typeof t!="object"||t===null)throw new Error("Input must be an object");let e=t;if(typeof e.query!="string")throw new Error("query (string) is required");let n={query:e.query};if(e.category!==void 0){if(typeof e.category!="string")throw new Error("category must be a string");let r=["preference","convention","decision","learning"];if(!r.includes(e.category))throw new Error(`category must be one of: ${r.join(", ")}`);n.category=e.category}if(e.since!==void 0){if(typeof e.since!="string")throw new Error("since must be a string (ISO date)");n.since=e.since}if(e.limit!==void 0){if(typeof e.limit!="number"||e.limit<=0)throw new Error("limit must be a positive number");n.limit=e.limit}return n}function bs(t){if(typeof t!="object"||t===null)throw new Error("Input must be an object");let e=t,n=["hot","fact"];if(typeof e.target!="string"||!n.includes(e.target))throw new Error(`target must be one of: ${n.join(", ")}`);let r=["set","supersede","remove"];if(typeof e.action!="string"||!r.includes(e.action))throw new Error(`action must be one of: ${r.join(", ")}`);let o={target:e.target,action:e.action};if(e.content!==void 0){if(typeof e.content!="string")throw new Error("content must be a string");o.content=e.content}if(e.category!==void 0){if(typeof e.category!="string")throw new Error("category must be a string");let s=["preference","convention","decision","learning"];if(!s.includes(e.category))throw new Error(`category must be one of: ${s.join(", ")}`);o.category=e.category}if(e.supersedes!==void 0){if(typeof e.supersedes!="number"||e.supersedes<=0)throw new Error("supersedes must be a positive fact ID");o.supersedes=e.supersedes}if(e.id!==void 0){if(typeof e.id!="number"||e.id<=0)throw new Error("id must be a positive fact ID");o.id=e.id}return o}function ws(t){if(typeof t!="object"||t===null)throw new Error("Input must be an object");let e=t;if(typeof e.name!="string")throw new Error("name (string) is required");if(typeof e.content!="string")throw new Error("content (string) is required");return{name:e.name,content:e.content}}import{promises as ke}from"fs";import{join as Tn}from"path";var He=class{sessions=new Map;sessionData=new Map;options;constructor(e){this.options={dataDir:e.dataDir||"./data/telegram-sessions",defaultModel:e.defaultModel||"sonnet",apiKey:e.apiKey,settingSources:e.settingSources,thinking:e.thinking,effort:e.effort,createSession:e.createSession}}getSessionIfExists(e){return this.sessions.get(e)}async getSession(e){let n=this.sessions.get(e);if(!n){let o=this.sessionData.get(e)||{chatId:e,model:this.options.defaultModel,createdAt:new Date().toISOString(),lastActivity:new Date().toISOString()},s={model:o.model,apiKey:this.options.apiKey};this.options.settingSources?.length&&(s.settingSources=this.options.settingSources),this.options.thinking!==void 0&&(s.thinking=this.options.thinking),this.options.effort!==void 0&&(s.effort=this.options.effort),n=await this.options.createSession(xt(s)),this.sessions.set(e,n),this.sessionData.set(e,o)}let r=this.sessionData.get(e);return r&&(r.lastActivity=new Date().toISOString()),n}async resetSession(e){let n=this.sessions.get(e);n&&(await n.close(),this.sessions.delete(e));let r=this.sessionData.get(e);r&&(r.lastActivity=new Date().toISOString())}async switchModel(e,n){let r=this.sessions.get(e);r&&(await r.close(),this.sessions.delete(e));let o=this.sessionData.get(e);o?(o.model=n,o.lastActivity=new Date().toISOString()):(o={chatId:e,model:n,createdAt:new Date().toISOString(),lastActivity:new Date().toISOString()},this.sessionData.set(e,o))}getModel(e){return this.sessionData.get(e)?.model||this.options.defaultModel}async loadSessions(){try{await ke.mkdir(this.options.dataDir,{recursive:!0});let e=await ke.readdir(this.options.dataDir);for(let n of e)if(n.endsWith(".json")){let r=Tn(this.options.dataDir,n),o=await ke.readFile(r,"utf-8"),s=JSON.parse(o);this.sessionData.set(s.chatId,s)}}catch(e){e.code!=="ENOENT"&&console.error("Failed to load sessions:",e)}}async saveSessions(){try{await ke.mkdir(this.options.dataDir,{recursive:!0});for(let[e,n]of this.sessionData.entries()){let r=Tn(this.options.dataDir,`${e}.json`);await ke.writeFile(r,JSON.stringify(n,null,2))}}catch(e){console.error("Failed to save sessions:",e)}}async closeAll(){await this.saveSessions();let e=Array.from(this.sessions.values()).map(n=>n.close().catch(r=>console.error("Error closing session:",r)));await Promise.all(e),this.sessions.clear()}getSessionCount(){return this.sessions.size}getChatCount(){return this.sessionData.size}};function Ue(t,e=4096){if(t.length<=e)return[t];let n=[],r=t;for(;r.length>0;){if(r.length<=e){n.push(r);break}let o=e,s=r.lastIndexOf(`
|
|
90
|
+
`,e);if(s>e-500&&s>0)o=s+1;else{let i=r.slice(0,e).match(/[.!?]\s+(?=[A-Z])/g);if(i&&i.length>0){let a=i[i.length-1];if(a){let l=r.lastIndexOf(a,e);l>e-200&&l>0&&(o=l+2)}}else{let a=r.lastIndexOf(" ",e);a>e-100&&a>0&&(o=a+1)}}n.push(r.slice(0,o).trim()),r=r.slice(o).trim()}return n}function Pt(t){let e=t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");return e=e.replace(/^```[\w]*\n?([\s\S]*?)```/gm,"<pre>$1</pre>"),e=e.replace(/`([^`]+)`/g,"<code>$1</code>"),e=e.replace(/\*\*([^*]+)\*\*/g,"<b>$1</b>"),e=e.replace(/__([^_]+)__/g,"<b>$1</b>"),e=e.replace(/\*([^*]+)\*/g,"<i>$1</i>"),e=e.replace(/_([^_]+)_/g,"<i>$1</i>"),e=e.replace(/~~([^~]+)~~/g,"<s>$1</s>"),e=e.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(n,r,o)=>'<a href="'+o.replace(/&/g,"&").replace(/"/g,""")+'">'+r+"</a>"),e=e.replace(/^#{1,6}\s+/gm,""),e}function D(t){return`\u274C Error: ${t instanceof Error?t.message:t}`}var An=[{cmd:"/start",desc:"Show welcome and this command list"},{cmd:"/help",desc:"Show this command list"},{cmd:"/clear",desc:"Clear conversation history (SDK /clear)"},{cmd:"/compact",desc:"Compact conversation history (summarize older messages)"},{cmd:"/model [opus|sonnet|haiku]",desc:"Switch Claude model"}];function Pn(t){let e=["\u{1F4CB} Bot commands (aligned with agent-afk CLI):","",...An.map(n=>` ${n.cmd}
|
|
4
91
|
${n.desc}`)];return t&&t.length>0&&e.push("","\u{1F4CB} Session commands (from SDK, when using settingSources):","",...t.map(n=>` /${n.replace(/^\//,"")}`)),e.push("","Just send a message to chat with Claude."),e.join(`
|
|
5
|
-
`)}function
|
|
92
|
+
`)}function _n(){return`\u{1F44B} Welcome to Agent AFK Bot!
|
|
6
93
|
|
|
7
94
|
I'm powered by Claude and can help you with various tasks.
|
|
8
95
|
|
|
9
96
|
Available commands:
|
|
10
|
-
${
|
|
97
|
+
${An.map(e=>`${e.cmd} - ${e.desc}`).join(`
|
|
11
98
|
`)}
|
|
12
99
|
|
|
13
|
-
Just send me a message to get started!`}function
|
|
100
|
+
Just send me a message to get started!`}function In(t){return`${{opus:"\u{1F680}",sonnet:"\u26A1",haiku:"\u{1F338}"}[t]||"\u{1F916}"} Switched to Claude ${t.toUpperCase()}`}function je(){return"\u{1F504} Conversation history cleared!"}function Rn(t){if(!t)return"\u{1F4E6} Conversation compacted (older messages summarized).";let e=t.tokensSavedEstimate!==void 0&&t.tokensSavedEstimate>0?` (~${vs(t.tokensSavedEstimate)} input tokens saved)`:"";return`\u{1F4E6} Compacted ${t.before} \u2192 ${t.after} messages${e}.`}function Cn(t){return t==="aborted"?"\u{1F4E6} Compaction cancelled.":t.startsWith("summarization-failed")?`\u26A0\uFE0F Compaction failed: ${t}. History unchanged.`:`\u{1F4E6} Nothing to compact (${t}).`}function vs(t){return t>=1e3?`${Math.round(t/100)/10}k`:String(t)}async function _t(t){await t.reply(_n())}async function It(t,e){let n=t.chat?.id,r,o=n?e.getSessionIfExists(n):void 0;if(o)try{await Promise.race([o.waitForInitialization(),new Promise((i,a)=>setTimeout(()=>a(new Error("timeout")),2e3))]);let s=o.getSessionMetadata();s.slashCommands?.length&&(r=s.slashCommands)}catch{}await t.reply(Pn(r))}async function Rt(t,e,n,r){let o=t.chat?.id;if(!o){await t.reply(D("Could not identify chat"));return}try{await e.resetSession(o),n.delete(o),await t.reply(je())}catch(s){r("Clear error:",s),await t.reply(D(s))}}async function Mn(t,e,n){let r=t.chat?.id;if(!r){await t.reply(D("Could not identify chat"));return}try{let o=await e.getSession(r);await t.sendChatAction("typing").catch(()=>{});let s=await o.compact();s.compacted?await t.reply(Rn({before:s.messagesBefore,after:s.messagesAfter,...s.tokensSavedEstimate!==void 0?{tokensSavedEstimate:s.tokensSavedEstimate}:{}})):await t.reply(Cn(s.reason??"unknown"))}catch(o){n("Compact error:",o),await t.reply(D(o))}}async function Ct(t,e,n){let r=t.chat?.id;if(!r){await t.reply(D("Could not identify chat"));return}let s=t.message.text.split(/\s+/).slice(1);if(s.length===0){let c=e.getModel(r);await t.reply(`Current model: ${c.toUpperCase()}
|
|
14
101
|
|
|
15
|
-
Usage: /model [opus|sonnet|haiku]`);return}let i=s[0];if(!i){await t.reply(
|
|
16
|
-
Valid options: opus, sonnet, haiku`));return}try{await e.switchModel(r,a),await t.reply(
|
|
102
|
+
Usage: /model [opus|sonnet|haiku]`);return}let i=s[0];if(!i){await t.reply(D("Please specify a model: opus, sonnet, or haiku"));return}let a=i.toLowerCase();if(!["opus","sonnet","haiku"].includes(a)){await t.reply(D(`Invalid model: ${i}
|
|
103
|
+
Valid options: opus, sonnet, haiku`));return}try{await e.switchModel(r,a),await t.reply(In(a))}catch(c){n("Model switch error:",c),await t.reply(D(c))}}function Mt(t){let e=t instanceof Error?t.message:String(t);return e.toLowerCase().includes("rate limit")||e.toLowerCase().includes("too many requests")}function Ot(t){let e=t instanceof Error?t.message:String(t);return e.toLowerCase().includes("network")||e.toLowerCase().includes("connect")||e.toLowerCase().includes("timeout")}var ks=300,Ss=9e4,xs=6e4;async function On(t,e,n,r){let o="",s=null,i=0,a=async(l,c=!1)=>{let d=Pt(l||"\u2026"),u=Date.now();if(!s){let m=Ue(d);s=await t.reply(m[0]??"\u2026",{parse_mode:"HTML"});return}if(!c&&u-i<ks&&l.length<100)return;i=u;let p=Ue(d);try{await t.telegram.editMessageText(t.chat?.id,s.message_id,void 0,p[0]??d,{parse_mode:"HTML"})}catch{}};try{let l="sendMessageStream"in e&&typeof e.sendMessageStream=="function"?e.sendMessageStream(n):(async function*(){let m=await e.sendMessage(n,{stream:!1});yield{type:"message",message:m},yield{type:"done",metadata:m.metadata}})();await a("Thinking\u2026");let c=l[Symbol.asyncIterator](),d=!1,u=null,p=()=>{let m=d?xs:Ss;return new Promise((f,h)=>{u=setTimeout(()=>{u=null,h(new Error(d?"Response timed out. Try sending a shorter message or try again.":"Request timed out. The agent may still be starting (first message can take a minute). Try again in a moment."))},m),c.next().then(g=>{u!=null&&(clearTimeout(u),u=null),f(g)},g=>{u!=null&&(clearTimeout(u),u=null),h(g)})})};for(;;){process.env.AFK_TELEGRAM_TRACE&&console.log("[trace] awaiting next event");let m=await p();if(process.env.AFK_TELEGRAM_TRACE&&console.log("[trace] event arrived:",m.done?"DONE":m.value.type),m.done)break;let f=m.value;if(d||(d=!0,console.log("\u{1F4E1} First stream event received:",f.type),r?.("First stream event received:",f.type)),f.type==="chunk"&&f.chunk.type==="content"&&(o+=f.chunk.content,await a(o)),f.type==="message"&&f.message.role==="assistant"&&(o=f.message.content,await a(o)),f.type==="progress"){let{description:h,summary:g,lastToolName:y}=f.progress,b=y?`
|
|
17
104
|
\u25E6 ${h} (${y})`:`
|
|
18
|
-
\u25E6 ${h}`;o+=b,
|
|
19
|
-
${
|
|
105
|
+
\u25E6 ${h}`;o+=b,g&&(o+=`
|
|
106
|
+
${g}`),await a(o)}if(f.type==="suggestion"&&(o+=`
|
|
20
107
|
|
|
21
|
-
\u{1F4A1} ${g.suggestion}`,await a(o)),g.type==="done"){o.trim()&&await a(o,!0);break}if(g.type==="error")throw g.error}if(o&&s){let f=Te(st(o));if(f.length>1)for(let g=1;g<f.length;g++){let h=f[g];h&&await t.reply(h,{parse_mode:"HTML"})}}}catch(l){throw r?.("Streaming error:",l),l}}async function Yt(t,e,n,r,o){if(!r.has(e))try{await Promise.race([n.waitForInitialization(),new Promise((a,l)=>setTimeout(()=>l(new Error("timeout")),5e3))]);let s=n.getSessionMetadata(),i=[{command:"start",description:"Show welcome and command list"},{command:"help",description:"Show this command list"},{command:"clear",description:"Clear conversation history"},{command:"compact",description:"Compact conversation history"},{command:"model",description:"Switch Claude model (opus/sonnet/haiku)"}];if(s.slashCommands?.length)for(let a of s.slashCommands){let l=a.replace(/^\//,"");i.push({command:l,description:`SDK command: ${l}`})}if(s.skills?.length)for(let a of s.skills)i.push({command:a,description:`Run ${a} skill`});await t.telegram.setMyCommands(i,{scope:{type:"chat",chat_id:e}}),r.add(e),o(`Registered ${i.length} commands for chat ${e}`)}catch(s){o(`Could not register dynamic commands for chat ${e}:`,s)}}var Ce=class{sessionManager;messageQueues=new Map;registeredCommandChats;log;bot;constructor(e,n,r,o){this.bot=e,this.sessionManager=n,this.registeredCommandChats=r,this.log=o}async handle(e){let n=e.chat?.id,r=e.message.text;if(!(!n||!r)&&(console.log(`\u{1F4EC} Message from chat ID: ${n}`),!r.startsWith("/")))try{let o=await this.sessionManager.getSession(n);if(Yt(this.bot,n,o,this.registeredCommandChats,this.log).catch(s=>this.log("Failed to register chat commands:",s)),o.state!=="idle"){this.enqueueMessage(n,e,r),await e.reply("Message queued.");return}await this.processOne(n,e,r)}catch(o){console.error("\u274C Message handling error:",o),this.log("Message handling error:",o);let s=o;if((s?.message??"").includes("session is busy")){this.enqueueMessage(n,e,r),await e.reply("Message queued.");return}ut(o)?await e.reply("\u23F3 Rate limit reached. Please wait a moment and try again."):dt(o)?await e.reply("\u{1F310} Network error. Please check your connection and try again."):await e.reply(O(s))}}async processClearDirect(e,n){try{await this.sessionManager.resetSession(e),this.registeredCommandChats.delete(e),await n.reply(Ie())}catch(r){this.log("Clear error:",r),await n.reply(O(r))}}enqueueMessage(e,n,r){let o=this.messageQueues.get(e);o||(o=[],this.messageQueues.set(e,o)),o.push({type:"message",ctx:n,text:r})}enqueueClear(e,n){let r=this.messageQueues.get(e);r||(r=[],this.messageQueues.set(e,r)),r.push({type:"clear",ctx:n})}async processOne(e,n,r){try{let o=await this.sessionManager.getSession(e);await n.sendChatAction("typing").catch(()=>{}),await Wt(n,o,r,this.log)}catch(o){console.error("\u274C Message handling error:",o),this.log("Message handling error:",o);let s=o;ut(o)?await n.reply("\u23F3 Rate limit reached. Please wait a moment and try again."):dt(o)?await n.reply("\u{1F310} Network error. Please check your connection and try again."):await n.reply(O(s))}finally{this.drainQueue(e)}}async drainQueue(e){let n=this.messageQueues.get(e);if(!n?.length)return;let r=n.shift();r.type==="message"?await this.processOne(e,r.ctx,r.text):await this.processClearDirect(e,r.ctx)}};function Jt(t,e=()=>{}){let n=new Set;if(!t)return n;for(let r of t.split(",")){let o=r.trim();if(o){if(!/^-?\d+$/.test(o)){e("[allowlist] Ignoring non-numeric chat ID:",o);continue}n.add(Number(o))}}return n}function Qt(t,e=()=>{}){return async(n,r)=>{let o=n.chat?.id;if(o===void 0||!t.has(o)){e("[allowlist] Rejecting update from chat:",o??"<unknown>");return}await r()}}var _e=class{bot;sessionManager;options;running=!1;registeredCommandChats=new Set;messageHandler;constructor(e){this.options=e,this.bot=new wo(e.botToken),this.sessionManager=new Ae(e),this.messageHandler=new Ce(this.bot,this.sessionManager,this.registeredCommandChats,this.log.bind(this)),this.setupHandlers()}setupHandlers(){this.bot.use(Qt(this.options.allowedChatIds,this.log.bind(this))),this.bot.command("start",e=>it(e)),this.bot.command("help",e=>at(e,this.sessionManager)),this.bot.command("clear",async e=>{let n=e.chat?.id;if(!n){await e.reply(O("Could not identify chat"));return}(await this.sessionManager.getSession(n)).state!=="idle"?(this.messageHandler.enqueueClear(n,e),await e.reply("Clear queued.")):await lt(e,this.sessionManager,this.registeredCommandChats,this.log.bind(this))}),this.bot.command("compact",e=>qt(e,this.sessionManager,this.log.bind(this))),this.bot.command("model",e=>ct(e,this.sessionManager,this.log.bind(this))),this.bot.on("text",e=>this.messageHandler.handle(e)),this.bot.catch((e,n)=>{this.log("Bot error:",e),n.reply(O("An unexpected error occurred. Please try again.")).catch(r=>this.log("Failed to send error message:",r))})}async start(){if(this.running)throw new Error("Bot is already running");this.log("Loading sessions..."),await this.sessionManager.loadSessions(),this.log("Starting bot..."),await this.bot.launch(),this.log("Registering bot commands..."),await this.bot.telegram.setMyCommands([{command:"start",description:"Show welcome and command list"},{command:"help",description:"Show this command list"},{command:"clear",description:"Clear conversation history"},{command:"compact",description:"Compact conversation history"},{command:"model",description:"Switch Claude model (opus/sonnet/haiku)"}]),this.running=!0,this.log("Bot started successfully");let e=async n=>{this.log(`Received ${n}, shutting down...`),await this.stop(),process.exit(0)};process.once("SIGINT",()=>e("SIGINT")),process.once("SIGTERM",()=>e("SIGTERM"))}async stop(){if(this.running){this.log("Stopping bot..."),this.running=!1,this.log("Closing sessions..."),await this.sessionManager.closeAll(),this.log("Stopping bot polling...");try{this.bot.stop()}catch(e){this.log("Error stopping bot (may not have been started):",e)}this.log("Bot stopped")}}getStats(){return{running:this.running,activeSessions:this.sessionManager.getSessionCount(),totalChats:this.sessionManager.getChatCount()}}async handleStart(e){return it(e)}async handleHelp(e){return at(e,this.sessionManager)}async handleClear(e){let n=e.chat?.id;if(!n){await e.reply(O("Could not identify chat"));return}if((await this.sessionManager.getSession(n)).state!=="idle")this.messageHandler.enqueueClear(n,e),await e.reply("Clear queued.");else return lt(e,this.sessionManager,this.registeredCommandChats,this.log.bind(this))}async handleMessage(e){return this.messageHandler.handle(e)}async handleModelSwitch(e){return ct(e,this.sessionManager,this.log.bind(this))}log(...e){this.options.verbose&&console.log("[TelegramBot]",...e)}};function ko(){return process.env.AFK_DEBUG==="1"||process.env.DEBUG==="1"}function A(...t){ko()&&console.log(...t)}var V=class extends Error{constructor(e){super(e),this.name="AbortError"}},Me=class extends Error{constructor(n,r){super(n);this.timeoutMs=r;this.name="TimeoutError"}timeoutMs},K=class extends Error{constructor(n,r,o,s){super(n);this.event=r;this.reason=o;this.name="HookBlockedError",s?.cause!==void 0&&(this.cause=s.cause)}event;reason;cause};var he=class extends Error{constructor(n,r,o){super(o??`${n} provider does not support AgentConfig.${r}.`);this.provider=n;this.field=r;this.name="UnsupportedProviderConfigError"}provider;field};var Re=class{queue=[];waiters=[];closed=!1;error=null;push(e){if(this.closed)throw new Error("Cannot push to closed queue");if(process.env.AFK_CODEX_DEBUG&&console.log("[queue] push:",e.type),A("\u{1F4E6} MessageQueue.push: event type=",e.type,"waiters=",this.waiters.length,"queue size=",this.queue.length),this.waiters.length>0){let n=this.waiters.shift();A("\u{1F4E6} MessageQueue.push: Resolving waiter immediately"),n?.({value:e,done:!1})}else this.queue.push(e),A("\u{1F4E6} MessageQueue.push: Added to queue, new size=",this.queue.length)}complete(){for(this.closed=!0;this.waiters.length>0;)this.waiters.shift()?.({value:void 0,done:!0})}fail(e){this.error=e,this.closed=!0;let n={type:"error",error:e};if(this.waiters.length>0)for(this.waiters.shift()?.({value:n,done:!1});this.waiters.length>0;)this.waiters.shift()?.({value:void 0,done:!0});else this.queue.push(n)}isClosed(){return this.closed}hasError(){return this.error}size(){return this.queue.length}async*[Symbol.asyncIterator](){for(A("\u{1F4E6} MessageQueue: Iterator started");;){if(this.queue.length>0){let n=this.queue.shift();if(A("\u{1F4E6} MessageQueue: Yielding queued event, type=",n?.type),n&&(yield n,n.type==="error")){A("\u{1F4E6} MessageQueue: Stopping after error");return}continue}if(this.closed){A("\u{1F4E6} MessageQueue: Closed and empty, stopping");return}A("\u{1F4E6} MessageQueue: Waiting for next event...");let e=await new Promise(n=>{this.waiters.push(n)});if(A("\u{1F4E6} MessageQueue: Got result, done=",e.done,"type=",e.value?.type),e.done)return;if(yield e.value,e.value.type==="error"){A("\u{1F4E6} MessageQueue: Stopping after error");return}}}};import Wr from"@anthropic-ai/sdk";var So="claude-code-20250219,oauth-2025-04-20",xo="claude-cli/1.0.0 (external, cli)",Po="x-anthropic-billing-header: cc_version=1.0.0.test; cc_entrypoint=cli; cch=00000;";function Xt(t){return t.startsWith("sk-ant-oat01-")?"oauth":"api-key"}function pt(t,e){return e==="oauth"?{authToken:t}:{apiKey:t}}function De(t,e,n){return t!=="oauth"?{}:{"anthropic-beta":So,"x-app":"cli","User-Agent":xo,"X-Claude-Code-Session-Id":e,"x-client-request-id":n}}function Zt(t){return t!=="oauth"?null:[{type:"text",text:Po}]}import{execFileSync as en}from"child_process";import{existsSync as Eo,readFileSync as Ao,writeFileSync as To}from"fs";import{homedir as tn,userInfo as nn}from"os";import{join as rn}from"path";var Io="9d1c250a-e61b-44d9-88ed-5944d1962f5e",Co="https://platform.claude.com/v1/oauth/token",_o=300*1e3;function on(){let t=an();if(t===void 0)return;let e=ln(t);if(e!==void 0){if(e.expiresAt!==void 0&&e.expiresAt<=Date.now()){process.stderr.write("agent-afk: Claude Code OAuth token in keychain is expired. Run `claude login` to refresh.\n");return}return e.accessToken}}async function sn(){let t=an();if(t===void 0)return;let e=ln(t);if(e===void 0)return;if(e.expiresAt!==void 0&&e.expiresAt>Date.now()+_o)return e.accessToken;if(!e.refreshToken){process.stderr.write("agent-afk: OAuth token expired and no refresh token available. Run `claude login` to refresh.\n");return}let n=await Mo(e.refreshToken);if(!n){process.stderr.write("agent-afk: OAuth token refresh failed. Run `claude login` to refresh.\n");return}try{let r={};try{r=JSON.parse(t)}catch{}let o=r.claudeAiOauth??{};r.claudeAiOauth={...o,accessToken:n.accessToken,expiresAt:n.expiresAt,...n.refreshToken!==void 0?{refreshToken:n.refreshToken}:{}},Ro(JSON.stringify(r))}catch{process.stderr.write(`agent-afk: Refreshed OAuth token but failed to write back to credential store.
|
|
22
|
-
`)}return n.accessToken}function
|
|
23
|
-
`)[0];return" "+(s.length>80?s.slice(0,77)+"\u2026":s)}let o=e.query??e.pattern??e.url??e.description;return typeof o=="string"?" "+o:""}async function*
|
|
24
|
-
`),
|
|
108
|
+
\u{1F4A1} ${f.suggestion}`,await a(o)),f.type==="done"){o.trim()&&await a(o,!0);break}if(f.type==="error")throw f.error}if(o&&s){let m=Ue(Pt(o));if(m.length>1)for(let f=1;f<m.length;f++){let h=m[f];h&&await t.reply(h,{parse_mode:"HTML"})}}}catch(l){throw r?.("Streaming error:",l),l}}async function Dn(t,e,n,r,o){if(!r.has(e))try{await Promise.race([n.waitForInitialization(),new Promise((a,l)=>setTimeout(()=>l(new Error("timeout")),5e3))]);let s=n.getSessionMetadata(),i=[{command:"start",description:"Show welcome and command list"},{command:"help",description:"Show this command list"},{command:"clear",description:"Clear conversation history"},{command:"compact",description:"Compact conversation history"},{command:"model",description:"Switch Claude model (opus/sonnet/haiku)"}];if(s.slashCommands?.length)for(let a of s.slashCommands){let l=a.replace(/^\//,"");i.push({command:l,description:`SDK command: ${l}`})}if(s.skills?.length)for(let a of s.skills)i.push({command:a,description:`Run ${a} skill`});await t.telegram.setMyCommands(i,{scope:{type:"chat",chat_id:e}}),r.add(e),o(`Registered ${i.length} commands for chat ${e}`)}catch(s){o(`Could not register dynamic commands for chat ${e}:`,s)}}var Be=class{sessionManager;messageQueues=new Map;registeredCommandChats;log;bot;constructor(e,n,r,o){this.bot=e,this.sessionManager=n,this.registeredCommandChats=r,this.log=o}async handle(e){let n=e.chat?.id,r=e.message.text;if(!(!n||!r)&&(console.log(`\u{1F4EC} Message from chat ID: ${n}`),!r.startsWith("/")))try{let o=await this.sessionManager.getSession(n);if(Dn(this.bot,n,o,this.registeredCommandChats,this.log).catch(s=>this.log("Failed to register chat commands:",s)),o.state!=="idle"){this.enqueueMessage(n,e,r),await e.reply("Message queued.");return}await this.processOne(n,e,r)}catch(o){console.error("\u274C Message handling error:",o),this.log("Message handling error:",o);let s=o;if((s?.message??"").includes("session is busy")){this.enqueueMessage(n,e,r),await e.reply("Message queued.");return}Mt(o)?await e.reply("\u23F3 Rate limit reached. Please wait a moment and try again."):Ot(o)?await e.reply("\u{1F310} Network error. Please check your connection and try again."):await e.reply(D(s))}}async processClearDirect(e,n){try{await this.sessionManager.resetSession(e),this.registeredCommandChats.delete(e),await n.reply(je())}catch(r){this.log("Clear error:",r),await n.reply(D(r))}}enqueueMessage(e,n,r){let o=this.messageQueues.get(e);o||(o=[],this.messageQueues.set(e,o)),o.push({type:"message",ctx:n,text:r})}enqueueClear(e,n){let r=this.messageQueues.get(e);r||(r=[],this.messageQueues.set(e,r)),r.push({type:"clear",ctx:n})}async processOne(e,n,r){try{let o=await this.sessionManager.getSession(e);await n.sendChatAction("typing").catch(()=>{}),await On(n,o,r,this.log)}catch(o){console.error("\u274C Message handling error:",o),this.log("Message handling error:",o);let s=o;Mt(o)?await n.reply("\u23F3 Rate limit reached. Please wait a moment and try again."):Ot(o)?await n.reply("\u{1F310} Network error. Please check your connection and try again."):await n.reply(D(s))}finally{this.drainQueue(e).catch(o=>this.log("Drain error:",o))}}async drainQueue(e){let n=this.messageQueues.get(e);if(!n?.length)return;let r=n.shift();r.type==="message"?await this.processOne(e,r.ctx,r.text):await this.processClearDirect(e,r.ctx)}};function Fn(t,e=()=>{}){let n=new Set;if(!t)return n;for(let r of t.split(",")){let o=r.trim();if(o){if(!/^-?\d+$/.test(o)){e("[allowlist] Ignoring non-numeric chat ID:",o);continue}n.add(Number(o))}}return n}function Ln(t,e=()=>{}){return async(n,r)=>{let o=n.chat?.id;if(o===void 0||!t.has(o)){e("[allowlist] Rejecting update from chat:",o??"<unknown>");return}await r()}}var Ke=class{bot;sessionManager;options;running=!1;registeredCommandChats=new Set;messageHandler;constructor(e){this.options=e,this.bot=new Es(e.botToken),this.sessionManager=new He(e),this.messageHandler=new Be(this.bot,this.sessionManager,this.registeredCommandChats,this.log.bind(this)),this.setupHandlers()}setupHandlers(){this.bot.use(Ln(this.options.allowedChatIds,this.log.bind(this))),this.bot.command("start",e=>_t(e)),this.bot.command("help",e=>It(e,this.sessionManager)),this.bot.command("clear",async e=>{let n=e.chat?.id;if(!n){await e.reply(D("Could not identify chat"));return}(await this.sessionManager.getSession(n)).state!=="idle"?(this.messageHandler.enqueueClear(n,e),await e.reply("Clear queued.")):await Rt(e,this.sessionManager,this.registeredCommandChats,this.log.bind(this))}),this.bot.command("compact",e=>Mn(e,this.sessionManager,this.log.bind(this))),this.bot.command("model",e=>Ct(e,this.sessionManager,this.log.bind(this))),this.bot.on("text",e=>this.messageHandler.handle(e)),this.bot.catch((e,n)=>{this.log("Bot error:",e),n.reply(D("An unexpected error occurred. Please try again.")).catch(r=>this.log("Failed to send error message:",r))})}async start(){if(this.running)throw new Error("Bot is already running");this.log("Loading sessions..."),await this.sessionManager.loadSessions(),this.log("Starting bot..."),await this.bot.launch(),this.log("Registering bot commands..."),await this.bot.telegram.setMyCommands([{command:"start",description:"Show welcome and command list"},{command:"help",description:"Show this command list"},{command:"clear",description:"Clear conversation history"},{command:"compact",description:"Compact conversation history"},{command:"model",description:"Switch Claude model (opus/sonnet/haiku)"}]),this.running=!0,this.log("Bot started successfully");let e=async n=>{this.log(`Received ${n}, shutting down...`),await this.stop(),process.exit(0)};process.once("SIGINT",()=>e("SIGINT")),process.once("SIGTERM",()=>e("SIGTERM"))}async stop(){if(this.running){this.log("Stopping bot..."),this.running=!1,this.log("Closing sessions..."),await this.sessionManager.closeAll(),this.log("Stopping bot polling...");try{this.bot.stop()}catch(e){this.log("Error stopping bot (may not have been started):",e)}this.log("Bot stopped")}}getStats(){return{running:this.running,activeSessions:this.sessionManager.getSessionCount(),totalChats:this.sessionManager.getChatCount()}}async handleStart(e){return _t(e)}async handleHelp(e){return It(e,this.sessionManager)}async handleClear(e){let n=e.chat?.id;if(!n){await e.reply(D("Could not identify chat"));return}if((await this.sessionManager.getSession(n)).state!=="idle")this.messageHandler.enqueueClear(n,e),await e.reply("Clear queued.");else return Rt(e,this.sessionManager,this.registeredCommandChats,this.log.bind(this))}async handleMessage(e){return this.messageHandler.handle(e)}async handleModelSwitch(e){return Ct(e,this.sessionManager,this.log.bind(this))}log(...e){this.options.verbose&&console.log("[TelegramBot]",...e)}};import Ld from"chalk";import Cd from"chalk";var Ts="https://api.telegram.org";async function $n(t){try{let e=await fetch(`${Ts}/bot${t}/getMe`);if(!e.ok)return null;let n=await e.json();return!n.ok||!n.result?.id||!n.result?.first_name?null:{id:n.result.id,...n.result.username!==void 0?{username:n.result.username}:{},firstName:n.result.first_name}}catch{return null}}var q=class extends Error{constructor(e){super(e),this.name="AbortError"}},Ge=class extends Error{constructor(n,r){super(n);this.timeoutMs=r;this.name="TimeoutError"}timeoutMs},W=class extends Error{constructor(n,r,o,s){super(n);this.event=r;this.reason=o;this.name="HookBlockedError",s?.cause!==void 0&&(this.cause=s.cause)}event;reason;cause};var Se=class extends Error{constructor(n,r,o){super(o??`${n} provider does not support AgentConfig.${r}.`);this.provider=n;this.field=r;this.name="UnsupportedProviderConfigError"}provider;field};var We=class{queue=[];waiters=[];closed=!1;error=null;push(e){if(this.closed)throw new Error("Cannot push to closed queue");if(process.env.AFK_CODEX_DEBUG&&console.log("[queue] push:",e.type),A("\u{1F4E6} MessageQueue.push: event type=",e.type,"waiters=",this.waiters.length,"queue size=",this.queue.length),this.waiters.length>0){let n=this.waiters.shift();A("\u{1F4E6} MessageQueue.push: Resolving waiter immediately"),n?.({value:e,done:!1})}else this.queue.push(e),A("\u{1F4E6} MessageQueue.push: Added to queue, new size=",this.queue.length)}complete(){for(this.closed=!0;this.waiters.length>0;)this.waiters.shift()?.({value:void 0,done:!0})}fail(e){this.error=e,this.closed=!0;let n={type:"error",error:e};if(this.waiters.length>0)for(this.waiters.shift()?.({value:n,done:!1});this.waiters.length>0;)this.waiters.shift()?.({value:void 0,done:!0});else this.queue.push(n)}isClosed(){return this.closed}hasError(){return this.error}size(){return this.queue.length}async*[Symbol.asyncIterator](){for(A("\u{1F4E6} MessageQueue: Iterator started");;){if(this.queue.length>0){let n=this.queue.shift();if(A("\u{1F4E6} MessageQueue: Yielding queued event, type=",n?.type),n&&(yield n,n.type==="error")){A("\u{1F4E6} MessageQueue: Stopping after error");return}continue}if(this.closed){A("\u{1F4E6} MessageQueue: Closed and empty, stopping");return}A("\u{1F4E6} MessageQueue: Waiting for next event...");let e=await new Promise(n=>{this.waiters.push(n)});if(A("\u{1F4E6} MessageQueue: Got result, done=",e.done,"type=",e.value?.type),e.done)return;if(yield e.value,e.value.type==="error"){A("\u{1F4E6} MessageQueue: Stopping after error");return}}}};import Io from"@anthropic-ai/sdk";var As="claude-code-20250219,oauth-2025-04-20",Ps="claude-cli/1.0.0 (external, cli)",_s="x-anthropic-billing-header: cc_version=1.0.0.test; cc_entrypoint=cli; cch=00000;";function qe(t){return t.startsWith("sk-ant-oat01-")?"oauth":"api-key"}function Dt(t,e){return e==="oauth"?{authToken:t}:{apiKey:t}}function ze(t,e,n){return t!=="oauth"?{}:{"anthropic-beta":As,"x-app":"cli","User-Agent":Ps,"X-Claude-Code-Session-Id":e,"x-client-request-id":n}}function Nn(t){return t!=="oauth"?null:[{type:"text",text:_s}]}import{execFileSync as Hn}from"child_process";import{existsSync as Is,readFileSync as Rs,writeFileSync as Cs}from"fs";import{homedir as Un,userInfo as jn}from"os";import{join as Bn}from"path";var Ms="9d1c250a-e61b-44d9-88ed-5944d1962f5e",Os="https://platform.claude.com/v1/oauth/token",Ds=300*1e3;function Kn(){let t=Wn();if(t===void 0)return;let e=qn(t);if(e!==void 0){if(e.expiresAt!==void 0&&e.expiresAt<=Date.now()){process.stderr.write("agent-afk: Claude Code OAuth token in keychain is expired. Run `claude login` to refresh.\n");return}return e.accessToken}}async function Gn(){let t=Wn();if(t===void 0)return;let e=qn(t);if(e===void 0)return;if(e.expiresAt!==void 0&&e.expiresAt>Date.now()+Ds)return e.accessToken;if(!e.refreshToken){process.stderr.write("agent-afk: OAuth token expired and no refresh token available. Run `claude login` to refresh.\n");return}let n=await Fs(e.refreshToken);if(!n){process.stderr.write("agent-afk: OAuth token refresh failed. Run `claude login` to refresh.\n");return}try{let r={};try{r=JSON.parse(t)}catch{}let o=r.claudeAiOauth??{};r.claudeAiOauth={...o,accessToken:n.accessToken,expiresAt:n.expiresAt,...n.refreshToken!==void 0?{refreshToken:n.refreshToken}:{}},Ls(JSON.stringify(r))}catch{process.stderr.write(`agent-afk: Refreshed OAuth token but failed to write back to credential store.
|
|
109
|
+
`)}return n.accessToken}function Wn(){if(process.platform==="darwin")try{return Hn("security",["find-generic-password","-s","Claude Code-credentials","-a",jn().username,"-w"],{stdio:["ignore","pipe","ignore"],encoding:"utf-8"}).trim()}catch{return}if(process.platform==="linux"){let t=Bn(Un(),".claude",".credentials.json");if(!Is(t))return;try{return Rs(t,"utf-8")}catch{return}}}function qn(t){let e;try{e=JSON.parse(t)}catch{return}if(typeof e!="object"||e===null)return;let n=e.claudeAiOauth;if(typeof n!="object"||n===null)return;let r=n,o=r.accessToken;if(typeof o!="string"||o.length===0)return;let s={accessToken:o},i=r.refreshToken;typeof i=="string"&&i.length>0&&(s.refreshToken=i);let a=r.expiresAt;return typeof a=="number"&&(s.expiresAt=a),s}async function Fs(t){try{let e=await fetch(Os,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({grant_type:"refresh_token",refresh_token:t,client_id:Ms})});if(!e.ok)return;let n=await e.json(),r=n.access_token,o=n.expires_in;if(typeof r!="string"||typeof o!="number")return;let s=n.refresh_token;return{accessToken:r,expiresAt:Date.now()+o*1e3,...typeof s=="string"&&s.length>0?{refreshToken:s}:{}}}catch{return}}function Ls(t){if(process.platform==="darwin")Hn("security",["add-generic-password","-U","-s","Claude Code-credentials","-a",jn().username,"-w",t],{stdio:["ignore","ignore","ignore"]});else if(process.platform==="linux"){let e=Bn(Un(),".claude",".credentials.json");Cs(e,t,"utf-8")}}import{randomUUID as dt}from"node:crypto";function Ve(){let t=process.env.AFK_DISABLE_PROMPT_CACHE;if(t===void 0||t.length===0)return!0;let e=t.toLowerCase();return!(e==="1"||e==="true"||e==="yes"||e==="on")}function Ye(){let t=process.env.AFK_PROMPT_CACHE_TTL;return t==="5m"?"5m":"1h"}function zn(t,e){if(t.length===0)return t;let n=t[t.length-1],r=Yn(n,e);return r===n?t:[...t.slice(0,-1),r]}function Vn(t,e){if(t.length===0)return t;let n=t[t.length-1],r=$s(n,e);return r===n?t:[...t.slice(0,-1),r]}function $s(t,e){let n=t.content;if(typeof n=="string")return n.length===0?t:{...t,content:[{type:"text",text:n,cache_control:{type:"ephemeral",ttl:e}}]};if(!Array.isArray(n)||n.length===0)return t;let r=n[n.length-1],o=Yn(r,e);return o===r?t:{...t,content:[...n.slice(0,-1),o]}}function Yn(t,e){return t.type==="thinking"||t.type==="redacted_thinking"?t:{...t,cache_control:{type:"ephemeral",ttl:e}}}import{randomUUID as Us}from"node:crypto";function Jn(t,e){if(!t)return{stopReason:e??null};let n={inputTokens:t.input_tokens,outputTokens:t.output_tokens,stopReason:e??null};return t.cache_read_input_tokens!=null&&(n.cachedInputTokens=t.cache_read_input_tokens),t.cache_creation_input_tokens!=null&&(n.cacheCreationTokens=t.cache_creation_input_tokens),n.totalTokens=(t.input_tokens??0)+(t.output_tokens??0),n}function Qn(t,e){let n=(d,u)=>{if(!(d==null&&u==null))return(d??0)+(u??0)},r=(d,u)=>u!==void 0?u:d,o={stopReason:e.stopReason??t.stopReason??null},s=n(t.inputTokens,e.inputTokens);s!==void 0&&(o.inputTokens=s);let i=n(t.outputTokens,e.outputTokens);i!==void 0&&(o.outputTokens=i);let a=r(t.cachedInputTokens,e.cachedInputTokens);a!==void 0&&(o.cachedInputTokens=a);let l=r(t.cacheCreationTokens,e.cacheCreationTokens);l!==void 0&&(o.cacheCreationTokens=l);let c=n(t.totalTokens,e.totalTokens);return c!==void 0&&(o.totalTokens=c),o}function Ns(t){let e=t.trim();if(e.length===0)return{};try{return JSON.parse(e)}catch{return{}}}function Hs(t,e,n){let r=[],o=[];for(let a of t)a&&(a.kind==="text"?(r.push({type:"text",text:a.text}),o.push(a.text)):a.kind==="thinking"?r.push({type:"thinking",thinking:a.thinking,signature:a.signature}):r.push({type:"tool_use",id:a.id,name:a.name,input:Ns(a.partialJson)}));let s=a=>a.type==="tool_use",i=r.filter(s);return{stopReason:e,assistantBlocks:r,toolUseBlocks:i,usage:n,text:o.join("")}}async function*Xn(t,e){let n=[],r=null,o=null,s=!1;try{process.env.AFK_TELEGRAM_TRACE&&console.log("[translate] starting SDK event iteration");for await(let i of t){switch(process.env.AFK_TELEGRAM_TRACE&&console.log("[translate] SDK evt:",i.type),i.type){case"message_start":{let a=i.message?.usage;a&&(o={...a});break}case"content_block_start":{let a=i.content_block;a.type==="text"?n[i.index]={kind:"text",text:""}:a.type==="thinking"?n[i.index]={kind:"thinking",thinking:"",signature:""}:a.type==="tool_use"&&(n[i.index]={kind:"tool_use",id:a.id,name:a.name,partialJson:""},yield{kind:"event",event:{type:"tool.use.start",toolUseId:a.id,toolName:a.name,toolInput:" \u2026",sessionId:e.sessionId}});break}case"content_block_delta":{let a=n[i.index],l=i.delta;l.type==="text_delta"?(a&&a.kind==="text"&&(a.text+=l.text),yield{kind:"event",event:{type:"delta.text",text:l.text,sessionId:e.sessionId}}):l.type==="input_json_delta"?a&&a.kind==="tool_use"&&(a.partialJson+=l.partial_json):l.type==="thinking_delta"?(a&&a.kind==="thinking"&&(a.thinking+=l.thinking),yield{kind:"event",event:{type:"delta.reasoning",text:l.thinking,sessionId:e.sessionId}}):l.type==="signature_delta"&&a&&a.kind==="thinking"&&(a.signature=l.signature);break}case"content_block_stop":{let a=n[i.index];a&&a.kind==="tool_use"&&(yield{kind:"event",event:{type:"tool.use",summary:a.name,toolUseIds:[a.id],sessionId:e.sessionId}});break}case"message_delta":{i.delta&&i.delta.stop_reason!==void 0&&(r=i.delta.stop_reason);let a=i.usage;a&&(o!==null?(o.output_tokens=a.output_tokens,a.cache_creation_input_tokens!=null&&(o.cache_creation_input_tokens=a.cache_creation_input_tokens),a.cache_read_input_tokens!=null&&(o.cache_read_input_tokens=a.cache_read_input_tokens),a.input_tokens!=null&&(o.input_tokens=a.input_tokens)):o={cache_creation:null,cache_creation_input_tokens:a.cache_creation_input_tokens??null,cache_read_input_tokens:a.cache_read_input_tokens??null,inference_geo:null,input_tokens:a.input_tokens??0,output_tokens:a.output_tokens,server_tool_use:null,service_tier:null});break}case"message_stop":{s=!0;break}default:break}if(s)break}process.env.AFK_TELEGRAM_TRACE&&console.log("[translate] SDK iteration ended naturally, stopped=",s)}catch(i){process.env.AFK_TELEGRAM_TRACE&&console.log("[translate] SDK iteration threw:",i.message),yield{kind:"event",event:{type:"error",error:i instanceof Error?i:new Error(String(i))}};return}process.env.AFK_TELEGRAM_TRACE&&console.log("[translate] yielding turn-result"),yield{kind:"turn-result",result:Hs(n,r,o)}}var js=0;function Bs(t){if(!t||typeof t!="object")return"";let e=t,n=e.file_path??e.path??e.filePath;if(typeof n=="string")return" "+n;let r=e.command??e.cmd;if(typeof r=="string"){let s=r.split(`
|
|
110
|
+
`)[0];return" "+(s.length>80?s.slice(0,77)+"\u2026":s)}let o=e.query??e.pattern??e.url??e.description;return typeof o=="string"?" "+o:""}async function*Ft(t){let e=t.maxToolUseIterations??js,n={stopReason:null},r=0,o=Us(),s=Date.now();for(;;){if(t.signal.aborted)return;let i=Ve()?Vn(t.messages,Ye()):t.messages,a={model:t.model,max_tokens:t.maxTokens,messages:i,stream:!0,...t.system!==null?{system:t.system}:{},...t.tools!==null&&t.tools.length>0?{tools:t.tools}:{}},l;try{l=await Promise.resolve(t.client.messages.create(a,{headers:t.headers,signal:t.signal}))}catch(g){if(t.signal.aborted)return;yield{type:"error",error:g instanceof Error?g:new Error(String(g))};return}let c=null,d=!1;try{process.env.AFK_TELEGRAM_TRACE&&console.log("[loop] awaiting translateMessageStream events");for await(let g of Xn(l,t.ctx))if(process.env.AFK_TELEGRAM_TRACE&&console.log("[loop] translate yielded:",g.kind,g.kind==="event"?g.event.type:""),g.kind==="event"){if(g.event.type==="error"){yield g.event,d=!0;break}yield g.event}else{c=g.result;break}process.env.AFK_TELEGRAM_TRACE&&console.log("[loop] translate loop exited, turnResult=",c?"set":"null")}catch(g){if(t.signal.aborted)return;yield{type:"error",error:g instanceof Error?g:new Error(String(g))};return}if(d)return;if(c===null){yield{type:"turn.completed",usage:n,sessionId:t.ctx.sessionId};return}if(n=Qn(n,Jn(c.usage,c.stopReason)),c.stopReason!=="tool_use"){c.text.length>0&&(yield{type:"assistant.message",text:c.text,sessionId:t.ctx.sessionId},c.text.length<=200&&(yield{type:"suggestion",suggestion:c.text,sessionId:t.ctx.sessionId})),t.messages.push({role:"assistant",content:c.assistantBlocks}),yield{type:"turn.completed",usage:n,sessionId:t.ctx.sessionId};return}t.messages.push({role:"assistant",content:c.assistantBlocks});let u=[];for(let g of c.toolUseBlocks)u.push({id:g.id,name:g.name,input:g.input,signal:t.signal}),yield{type:"tool.use.start",toolUseId:g.id,toolName:g.name,toolInput:Bs(g.input),sessionId:t.ctx.sessionId};if(t.signal.aborted)return;let p;if(t.toolDispatcher.executeBatch)p=await t.toolDispatcher.executeBatch(u);else{p=[];for(let g of u){if(t.signal.aborted){p.push({content:"Tool call aborted",isError:!0});continue}try{p.push(await t.toolDispatcher.execute(g))}catch(y){let b=y instanceof Error?y.message:String(y);p.push({content:`Tool execution threw: ${b}`,isError:!0})}}}let m=[];for(let g=0;g<u.length;g++){let y=u[g],b=p[g];yield{type:"tool.output",toolUseId:y.id,content:b.content,...b.isError===!0?{isError:!0}:{},sessionId:t.ctx.sessionId},m.push({type:"tool_result",tool_use_id:y.id,content:b.content,...b.isError===!0?{is_error:!0}:{}})}let f={role:"user",content:m};t.messages.push(f),r+=1;let h=c.toolUseBlocks[c.toolUseBlocks.length-1];if(yield{type:"progress",progress:{taskId:o,description:"Tool-use loop",summary:`Iteration ${r}: used ${h?.name??"unknown"}`,lastToolName:h?.name,totalTokens:n.totalTokens??0,toolUses:r,durationMs:Date.now()-s},sessionId:t.ctx.sessionId},e>0&&r>=e){yield{type:"turn.completed",usage:{...n,stopReason:"tool_use_loop_capped"},sessionId:t.ctx.sessionId};return}}}var Ks=["You are a conversation-summarization assistant. The user will paste a","prior conversation between a user and an AI assistant that includes tool","calls and tool results. Produce a concise but complete summary that lets","the AI continue the conversation without losing track.","","Preserve, in this priority order:","1. The user's original intent, explicit asks, constraints, corrections,"," and preferences stated during the conversation.","2. Tool decisions and their outcomes \u2014 file paths read or written, shell"," commands run, search queries, URLs fetched, code edits made, tests"," run, errors observed, and whether each action succeeded or failed.","3. Current state: what has been completed, what remains unresolved, and"," the safest next action.","4. Open questions, pending decisions, blockers, and assumptions.","5. Key facts the assistant discovered (function locations, schemas,"," observed behaviors, important external findings).","","Drop prose narration, conversational filler, and exploratory dead-ends.","Drop verbatim tool output unless an exact snippet, error, path, command,","or result is needed for continuation.","Do not invent details. If something is uncertain, mark it explicitly.","Output plain text, no markdown headers. Aim for ~250 words; use up to","~400 only when needed to preserve tool state or unresolved tasks."].join(`
|
|
111
|
+
`),Zn="[Compacted summary of earlier conversation]",er="Acknowledged. Continuing from the summary above.";function Gs(t){if(t.role!=="user")return!1;let e=t.content;if(typeof e=="string")return!0;if(!Array.isArray(e))return!1;for(let n of e)if(n.type==="tool_result")return!1;return!0}function tr(t,e){if(e<=0)return t.length;let n=0;for(let r=t.length-1;r>=0;r--){let o=t[r];if(o&&Gs(o)&&(n+=1,n===e))return r}return-1}function nr(t,e,n){let r=Ws(t);return{model:e,max_tokens:n,system:Ks,messages:[{role:"user",content:`Summarize the following conversation transcript. Follow the system instructions exactly.
|
|
25
112
|
|
|
26
113
|
<transcript>
|
|
27
114
|
`+r+`
|
|
28
|
-
</transcript>`}],stream:!0}}function
|
|
115
|
+
</transcript>`}],stream:!0}}function rr(t,e,n){return[{role:"user",content:Zn+`
|
|
29
116
|
|
|
30
|
-
`+n},{role:"assistant",content:
|
|
31
|
-
`).trim()}function
|
|
117
|
+
`+n},{role:"assistant",content:er},...t.slice(e)]}function or(t,e,n){let r=qs(t.slice(0,e)),o=Zn.length+2+n.length+er.length,s=Math.max(0,r-o);return Math.round(s/4)}function Ws(t){let e=[];for(let n of t){let r=n.role==="user"?"User":"Assistant";if(e.push(r+":"),typeof n.content=="string")e.push(n.content);else if(Array.isArray(n.content))for(let o of n.content){let s=o.type;if(s==="text"&&"text"in o)e.push(o.text);else if(s==="tool_use"){let i=o.name??"unknown",a=sr(o.input);e.push(`[tool call: ${i} ${a}]`)}else if(s==="tool_result"){let i=o.content;e.push(`[tool result: ${ir(i)}]`)}else s==="image"?e.push("[image]"):s==="document"&&e.push("[document]")}e.push("")}return e.join(`
|
|
118
|
+
`).trim()}function sr(t){try{let e=JSON.stringify(t);return e.length>240?e.slice(0,237)+"...":e}catch{return"{}"}}function ir(t){if(typeof t=="string")return t.length>320?t.slice(0,317)+"...":t;if(Array.isArray(t)){let e=[];for(let r of t)r.type==="text"&&"text"in r&&e.push(r.text);let n=e.join(" ");return n.length>320?n.slice(0,317)+"...":n}return""}function qs(t){let e=0;for(let n of t)if(typeof n.content=="string")e+=n.content.length;else if(Array.isArray(n.content))for(let r of n.content){let o=r.type;o==="text"&&"text"in r?e+=r.text.length:o==="tool_use"?e+=sr(r.input).length:o==="tool_result"&&(e+=ir(r.content).length)}return e}import{z as _}from"zod";import{mkdir as xr,appendFile as Er}from"fs/promises";import{join as Ht}from"path";var ar={"audit-fit":{"01-skill-inspector.md":`# Skill Inspector
|
|
32
119
|
|
|
33
120
|
You are an inspector auditing skills for correct type categorization. Skills come from two sources:
|
|
34
121
|
- **User-scope** \u2014 authored directly by the user under \`~/.afk/skills/<name>/SKILL.md\`
|
|
@@ -820,9 +907,9 @@ Field semantics:
|
|
|
820
907
|
- \`status_reason\` \u2014 short reason when \`FAIL\`; omit when \`PASS\`.
|
|
821
908
|
- \`issues\` \u2014 concrete blockers with file:line citations where possible. Empty array when \`PASS\`.
|
|
822
909
|
- \`summary\` \u2014 optional narrative; the orchestrator may surface it to the user. Keep it concise.
|
|
823
|
-
`}};function
|
|
824
|
-
Available skills: ${n.join(", ")}`:"";throw new Error(`Skill not found: ${t}${r}`)}function
|
|
825
|
-
`;await
|
|
910
|
+
`}};function P(t){let e=ar[t];if(!e){let n=Object.keys(ar).sort(),r=n.length>0?"Available: "+n.join(", "):"";throw new Error("Unknown skill: "+t+". "+r)}return e}var Je=new Map;function X(t){Je.set(t.name,t)}function z(t){let e=Je.get(t);if(e)return e;let n=Array.from(Je.keys()).sort(),r=n.length>0?`
|
|
911
|
+
Available skills: ${n.join(", ")}`:"";throw new Error(`Skill not found: ${t}${r}`)}function lr(){return Array.from(Je.keys()).sort()}var Qe=class{nodes=new Map;register(e,n){this.nodes.has(e)||this.nodes.set(e,{controller:n,children:new Set,listeners:new Set,cascading:!1})}has(e){return this.nodes.has(e)}getController(e){return this.nodes.get(e)?.controller}linkChild(e,n){let r=this.nodes.get(e),o=this.nodes.get(n);if(!r)throw new Error(`AbortGraph: parent ${e} not registered`);if(!o)throw new Error(`AbortGraph: child ${n} not registered`);if(o.parentId=e,r.children.add(n),r.controller.signal.aborted){o.controller.signal.aborted||(o.cascading=!0,o.controller.abort(r.controller.signal.reason));return}r.controller.signal.addEventListener("abort",()=>{let s=this.nodes.get(n);!s||s.parentId!==e||s.controller.signal.aborted||(s.cascading=!0,s.controller.abort(r.controller.signal.reason))},{once:!0}),o.controller.signal.addEventListener("abort",()=>{let s=this.nodes.get(n);if(!s||s.parentId!==e||s.cascading)return;let i=this.nodes.get(e);if(!i)return;let a={parentId:e,childId:n,reason:s.controller.signal.reason};for(let l of i.listeners)try{l(a)}catch{}},{once:!0})}onChildAborted(e,n){let r=this.nodes.get(e);if(!r)throw new Error(`AbortGraph: ${e} not registered`);return r.listeners.add(n),()=>{r.listeners.delete(n)}}abort(e,n){let r=this.nodes.get(e);if(!r||r.controller.signal.aborted)return;let o=[],s=[...r.children],i=new Set;for(;s.length;){let a=s.shift();if(i.has(a))continue;i.add(a);let l=this.nodes.get(a);if(l){l.cascading=!0,o.push(a);for(let c of l.children)s.push(c)}}r.controller.abort(n);for(let a of o){let l=this.nodes.get(a);l&&!l.controller.signal.aborted&&l.controller.abort(n)}}dispose(e){let n=this.nodes.get(e);if(n){n.parentId&&this.nodes.get(n.parentId)?.children.delete(e);for(let r of n.children){let o=this.nodes.get(r);o&&(o.parentId=void 0)}this.nodes.delete(e)}}};var Xe=0,Lt=5e3;async function Ze(t,e,n={}){if(!Number.isFinite(e)||e<=0)return t;let r,o=new Promise((s,i)=>{r=setTimeout(()=>{let a=n.label?` (${n.label})`:"",l=new Ge(`Operation timed out after ${e}ms${a}`,e);n.controller&&!n.controller.signal.aborted&&n.controller.abort(l),i(l)},e)});try{return await Promise.race([t,o])}finally{r!==void 0&&clearTimeout(r)}}async function cr(t,e,n={}){t&&await t.dispatch(e,n.signal)}async function dr(t,e,n={}){if(!t)return{};try{return await t.dispatch(e,n.signal)}catch(r){return r instanceof W||r instanceof q?(A(`SubagentStop hook swallowed ${r.name}: ${r.message}`),n.onError?.(r),{}):(A(`SubagentStop hook unexpected error: ${String(r)}`),n.onError?.(r instanceof Error?r:new Error(String(r))),{})}}import{mkdir as zs,writeFile as Vs}from"fs/promises";import{dirname as Ys,join as Js}from"path";function Qs(){return Js(ce(),"routing-decisions.jsonl")}async function ie(t){if(!(process.env.VITEST||process.env.NODE_ENV==="test"))try{let e=Qs();await zs(Ys(e),{recursive:!0});let r={ts:new Date().toISOString().split(".")[0]+"Z",surface:"afk"};for(let[s,i]of Object.entries(t))i!==void 0&&(r[s]=i);let o=JSON.stringify(r)+`
|
|
912
|
+
`;await Vs(e,o,{flag:"a"})}catch{}}import{AsyncLocalStorage as Xs}from"node:async_hooks";var Zs=new Xs;function Z(){return Zs.getStore()}function ur(t){let e=ei(t);return e!==void 0?e:ti(t)}function ei(t){let e=/```(?:json)?\s*([\s\S]*?)```/gi,n,r;for(;(r=e.exec(t))!==null;)n=r[1];if(n)return pr(n.trim())}function ti(t){for(let e=t.length-1;e>=0;e--){if(t[e]!=="}")continue;let n=ni(t,e);if(n===-1)continue;let r=t.slice(n,e+1),o=pr(r);if(o!==void 0)return o}}function ni(t,e){let n=0,r=!1,o=!1;for(let s=e;s>=0;s--){let i=t[s];if(o){o=!1;continue}if(r){if(i==="\\"){o=!0;continue}i==='"'&&(r=!1);continue}if(i==='"'){r=!0;continue}if(i==="}")n++;else if(i==="{"&&(n--,n===0))return s}return-1}function pr(t){try{return JSON.parse(t)}catch{return}}function mr(t,e,n,r){if(!r)return{id:t,status:e,message:n};let o=ur(n.content),s=r.safeParse(o);return s.success?{id:t,status:e,message:n,output:s.data}:{id:t,status:"failed",message:n,error:new Error(`structured output did not match schema: ${s.error.message}`,{cause:s.error}),schemaError:s.error}}function fr(t,e,n){let r=n instanceof Error?n:new Error(String(n));return{id:t,status:e,error:r}}function I(t){return`${t.status}${t.error?`: ${t.error.message}`:""}`}var et=class{constructor(e,n,r,o,s,i,a,l,c,d,u,p,m){this.id=e;this.session=n;this.controller=r;this.abortGraph=o;this.outputSchema=s;this.timeoutMs=i;this.hookRegistry=a;this.onTerminal=l;this.parentInputStreamRef=c;this.parentAbortSignal=d;this.agentType=u;this.progressSink=p,this.parentId=m}id;session;controller;abortGraph;outputSchema;timeoutMs;hookRegistry;onTerminal;parentInputStreamRef;parentAbortSignal;agentType;currentStatus="idle";inFlight=null;lastMessage;lastDurationMs;latestTerminalStatus;stopDispatched=!1;progressSink;parentId;get status(){return this.currentStatus}async run(e){if(this.currentStatus==="running")throw new Error(`Subagent ${this.id} is already running`);if(this.currentStatus==="cancelled")throw new Error(`Subagent ${this.id} is cancelled`);this.currentStatus="running";let n=Date.now(),r=Ze(this.streamToFinalMessage(e),this.timeoutMs,{controller:this.controller,label:this.id});this.inFlight=r;try{let o=await r;return this.lastMessage=o.content,this.lastDurationMs=Date.now()-n,this.currentStatus="succeeded",this.latestTerminalStatus="succeeded",this.onTerminal(),o}catch(o){throw this.lastDurationMs=Date.now()-n,this.currentStatus!=="cancelled"&&(this.currentStatus="failed",this.latestTerminalStatus="failed"),this.onTerminal(),o}finally{this.inFlight=null}}async streamToFinalMessage(e){let n,r="",o,s=this.progressSink??Z(),i={subagentId:this.id,...this.parentId!==void 0&&{parentId:this.parentId},...this.agentType!==void 0&&{agentType:this.agentType}};for await(let a of this.session.sendMessageStream(e))if(s&&s(a,i),a.type==="chunk"&&a.chunk.type==="content"&&(r+=a.chunk.content),a.type==="message")n=a.message;else if(a.type==="error"){o=a.error;break}else if(a.type==="done")break;if(o)throw o;if(n)return n;if(r.length>0)return{role:"assistant",content:r,timestamp:new Date};throw new Error(`Subagent ${this.id} produced no terminal message`)}async runToResult(e){try{let n=await this.run(e);return mr(this.id,this.currentStatus,n,this.outputSchema)}catch(n){return fr(this.id,this.currentStatus,n)}}runInBackground(e,n){this.runToResult(e).then(r=>{n?.(r)})}async cancel(){if(this.currentStatus==="cancelled"||this.stopDispatched)return;let e=this.latestTerminalStatus??"cancelled";this.currentStatus="cancelled";try{this.abortGraph.abort(this.id,"cancelled")}catch{}try{this.inFlight&&await this.session.interrupt()}catch{}try{await this.session.close()}finally{await this.dispatchStopAndRelease(e)}}async teardown(){if(this.stopDispatched)return;let e=this.latestTerminalStatus??"cancelled";try{this.inFlight&&await this.session.interrupt()}catch{}try{await this.session.close()}finally{await this.dispatchStopAndRelease(e)}}async dispatchStopAndRelease(e){if(this.stopDispatched){this.onTerminal();return}this.stopDispatched=!0;let n=await dr(this.hookRegistry,{event:"SubagentStop",subagentId:this.id,status:e,lastMessage:this.lastMessage,agentType:this.agentType,durationMs:this.lastDurationMs});if(n.injectContext&&this.parentInputStreamRef)if(this.parentAbortSignal?.aborted)A(`Skipping SubagentStop injectContext for ${this.id}: parent is aborted`);else try{this.parentInputStreamRef.pushUserMessage(n.injectContext)}catch(r){A(`Failed to inject context from SubagentStop handler: ${String(r)}`)}this.onTerminal()}};var S=class{active=new Map;parentCanUseTool;hookRegistry;progressSink;parentApiKey;abortGraph=new Qe;rootId;rootController;counter=0;constructor(e={}){if(this.parentCanUseTool=e.canUseTool,this.hookRegistry=e.hookRegistry,this.progressSink=e.progressSink,this.parentApiKey=e.apiKey,this.rootId=`manager-root-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,this.rootController=new AbortController,this.abortGraph.register(this.rootId,this.rootController),e.parentAbortSignal){let n=e.parentAbortSignal;n.aborted?this.rootController.abort(n.reason):n.addEventListener("abort",()=>{this.rootController.signal.aborted||this.rootController.abort(n.reason)},{once:!0})}}list(){return[...this.active.values()].map(e=>({id:e.id,status:e.status}))}get(e){return this.active.get(e)}onChildAborted(e){return this.abortGraph.onChildAborted(this.rootId,e)}abortAll(e){this.abortGraph.abort(this.rootId,e)}async forkSubagent(e){let n=`${e.idPrefix??"subagent"}-${Date.now()}-${++this.counter}`,r=e.parent.sessionId,o=e.config.hookRegistry??this.hookRegistry;o&&await cr(o,{event:"SubagentStart",subagentId:n,parentSessionId:e.parent.sessionId},{signal:this.rootController.signal});let s=new AbortController;this.abortGraph.register(n,s),this.abortGraph.linkChild(this.rootId,n);let i={...e.config,resume:r,forkSession:r?!0:e.config.forkSession,abortSignal:s.signal,apiKey:e.config.apiKey||this.parentApiKey,hookRegistry:e.config.hookRegistry??this.hookRegistry,permissionBubbler:e.config.permissionBubbler??(this.parentCanUseTool!==void 0&&e.config.canUseTool===void 0?{canUseTool:this.parentCanUseTool}:void 0)},a=new ae(i),l=e.parent.getInputStreamRef?.(),c=e.parent.abortSignal,d=this.progressSink??Z(),u=new et(n,a,s,this.abortGraph,e.outputSchema,e.config.timeoutMs??Xe,o,()=>{this.active.delete(n),this.abortGraph.dispose(n)},l,c,e.idPrefix,d,e.parent.sessionId);return this.active.set(n,u),await ie({event:"subagent.dispatched",subagent_id:n,id_prefix:e.idPrefix,parent_session_id:e.parent.sessionId}),u}async kill(e){let n=this.active.get(e);return n?(await n.cancel(),!0):!1}async killAll(){await Promise.allSettled([...this.active.values()].map(e=>e.cancel()))}async teardownAll(){await Promise.allSettled([...this.active.values()].map(e=>e.teardown()))}};async function tt(t,e={}){let{failFast:n=!0,teardown:r=!0}=e;if(t.length===0)return[];let o=new Array(t.length),s=new Set(t.map((a,l)=>l)),i=t.map((a,l)=>a.handle.runToResult(a.prompt).then(c=>{if(o[l]=c,s.delete(l),n&&c.status!=="succeeded")for(let d of s){let u=t[d];u&&u.handle.status==="running"&&u.handle.cancel().catch(()=>{})}}));return await Promise.all(i),r&&await Promise.allSettled(t.map(a=>a.handle.teardown())),o}import{fileURLToPath as ri}from"node:url";import{dirname as oi}from"node:path";var si=ri(import.meta.url),Hu=oi(si),H={name:"research-agent",systemPrompt:`---
|
|
826
913
|
name: research-agent
|
|
827
914
|
description: Read-only sub-agent for research, validation, verification, and codebase inspection. Mechanically locked to Read, Grep, Glob, WebFetch, WebSearch \u2014 cannot Edit, Write, Bash, commit, or push. Delegates git queries to \`git-investigator\`. Use when the dispatched task is findings-only.
|
|
828
915
|
model: sonnet
|
|
@@ -872,45 +959,45 @@ Unless the dispatcher specifies a different schema, return:
|
|
|
872
959
|
\`\`\`
|
|
873
960
|
|
|
874
961
|
If \`scope_check\` flags implementation (non-git), the orchestrator should dispatch a different sub-agent type for follow-up. Do not re-dispatch the same task through \`research-agent\`.
|
|
875
|
-
`,sourcePath:"agent-framework-private/agents/research-agent.md",allowedTools:["Read","Grep","Glob","WebFetch","WebSearch"],description:"Read-only sub-agent for research, validation, verification, and codebase inspection. Mechanically locked to Read, Grep, Glob, WebFetch, WebSearch \u2014 cannot Edit, Write, Bash, commit, or push. Delegates git queries to `git-investigator`. Use when the dispatched task is findings-only."};import{existsSync as
|
|
876
|
-
`)}function
|
|
962
|
+
`,sourcePath:"agent-framework-private/agents/research-agent.md",allowedTools:["Read","Grep","Glob","WebFetch","WebSearch"],description:"Read-only sub-agent for research, validation, verification, and codebase inspection. Mechanically locked to Read, Grep, Glob, WebFetch, WebSearch \u2014 cannot Edit, Write, Bash, commit, or push. Delegates git queries to `git-investigator`. Use when the dispatched task is findings-only."};import{existsSync as le,readdirSync as mi,readFileSync as fi}from"fs";import{join as te}from"path";import{existsSync as $t,readFileSync as li,readdirSync as ci,statSync as di}from"fs";import{join as xe,resolve as hr}from"path";import{existsSync as ii,mkdirSync as Bu,readFileSync as ai,renameSync as Ku,writeFileSync as Gu,unlinkSync as Wu}from"fs";function gr(t=De()){if(!ii(t))return nt();try{let e=ai(t,"utf8"),n=JSON.parse(e);if(!n||typeof n!="object")return nt();let r=n,o=r.plugins&&typeof r.plugins=="object"?r.plugins:{};if(r.version===1)return{version:2,plugins:o,marketplaces:{}};if(r.version===2){let s=r.marketplaces&&typeof r.marketplaces=="object"?r.marketplaces:{};return{version:2,plugins:o,marketplaces:s}}return nt()}catch{return nt()}}function nt(){return{version:2,plugins:{},marketplaces:{}}}var ui=5,yr="cache";function ee(t=me()){if(!$t(t))return[];let e=t===me()?De():xe(t,".index.json"),n=gr(e),r=[];return br(t,t,0,r,new Set,n.plugins),r}function br(t,e,n,r,o,s){if(n>ui||o.has(e))return;if(o.add(e),$t(xe(e,".claude-plugin","plugin.json"))){let a=Nt(t,e);if(a===null){r.push({type:"local",path:e});return}if(a.layout==="cache"){let c=s[a.key];if(!c||c.enabled===!1)return;r.push({type:"local",path:e});return}let l=s[a.key];if(l&&l.enabled===!1)return;r.push({type:"local",path:e});return}let i;try{i=ci(e)}catch{return}for(let a of i){if(a.startsWith("."))continue;let l=xe(e,a),c;try{c=di(l)}catch{continue}c.isDirectory()&&br(t,l,n+1,r,o,s)}}function Nt(t,e){if(!e.startsWith(t))return null;let n=e.slice(t.length).replace(/^\/+/,"");if(!n)return null;let r=n.split("/").filter(s=>s.length>0);if(r.length===0)return null;if(r[0]===yr&&r.length>=3){let s=r[1];if(s){let i=xe(t,yr,s),l=pi(i,e)??r[2];if(l)return{layout:"cache",key:`${s}:${l}`}}}let o=r[0];return o?{layout:"flat",key:o}:null}function pi(t,e){let n=xe(t,".claude-plugin","marketplace.json");if(!$t(n))return null;let r;try{r=JSON.parse(li(n,"utf8"))}catch{return null}if(!r||typeof r!="object")return null;let o=r.plugins;if(!Array.isArray(o))return null;let s=hr(e);for(let i of o){if(!i||typeof i!="object")continue;let a=i;if(!(typeof a.name!="string"||typeof a.source!="string")&&!(!a.source.startsWith("./")&&!a.source.startsWith("../"))&&hr(t,a.source)===s)return a.name}return null}var wr=["command","agent"];function vr(t=Y()){let e=[],n=te(t,"skills");if(le(n))for(let r of rt(n)){let o=te(n,r,"SKILL.md");le(o)&&e.push({path:o,type:"skill",source:"user"})}for(let r of wr){let o=te(t,`${r}s`);if(le(o))for(let s of rt(o))s.endsWith(".md")&&e.push({path:te(o,s),type:r,source:"user"})}return e}function kr(t=me()){if(!le(t))return[];let e=[],n=ee(t);for(let r of n){let s=Nt(t,r.path)?.key,i=te(r.path,"skills");if(le(i))for(let a of rt(i)){let l=te(i,a,"SKILL.md");if(!le(l))continue;let c={path:l,type:"skill",source:"plugin"};s&&(c.plugin_key=s),e.push(c)}for(let a of wr){let l=te(r.path,`${a}s`);if(le(l))for(let c of rt(l)){if(!c.endsWith(".md"))continue;let d={path:te(l,c),type:a,source:"plugin"};s&&(d.plugin_key=s),e.push(d)}}}return e}function Sr(t=te(Y(),"settings.json")){if(!le(t))return[];try{let e=fi(t,"utf8"),r=JSON.parse(e).hooks;if(!r||typeof r!="object")return[];let o=[];for(let[s,i]of Object.entries(r))if(Array.isArray(i))for(let a=0;a<i.length;a++)o.push({event:s,index:a,raw:i[a]});return o}catch{return[]}}function rt(t){try{return mi(t).filter(e=>!e.startsWith("."))}catch{return[]}}var Ar=_.object({path:_.string(),type:_.enum(["skill","command","agent","hook"]),source:_.enum(["user","plugin"]),plugin_key:_.string().optional(),verdict:_.enum(["correct","misfit","outlier"]),recommended_type:_.string(),rationale:_.string(),confidence:_.enum(["high","med","low"])}),Tr=_.record(_.string(),_.record(_.string(),_.number())),fp=_.object({inventory:_.object({user:Tr,plugin:Tr}),misfits:_.array(Ar),briefs_written:_.number(),total_artifacts:_.number()}),gi=_.object({writeBriefs:_.boolean().optional(),scope:_.enum(["user","plugin","all"]).optional()}),hi=["skill","command","agent"],Pr=["skill","command","agent","hook"];function yi(t){return{runUserDiscovery:t!=="plugin",runPluginDiscovery:t!=="user",runHookInspector:t!=="plugin"}}function bi(t){let e=()=>{let s={};for(let i of Pr)s[i]={correct:0,misfit:0,outlier:0};return s},n={user:e(),plugin:e()};for(let s of t)n[s.source][s.type][s.verdict]+=1;let r={high:0,med:1,low:2},o=t.filter(s=>s.verdict==="misfit").slice().sort((s,i)=>r[s.confidence]-r[i.confidence]);return{inventory:n,misfits:o}}function wi(t){return t.verdict==="misfit"&&t.confidence==="high"&&t.source==="user"}function vi(t){let e=t.filter(o=>o.source==="user"),n=t.filter(o=>o.source==="plugin"),r=["","## Discovered artifacts (audit only these)",""];if(r.push('### User-scope artifacts (set `"source": "user"`, omit `plugin_key`)'),e.length===0)r.push("(none discovered)");else for(let o of e)r.push(`- ${o.path}`);if(r.push(""),r.push('### Plugin-scope artifacts (set `"source": "plugin"`, copy `plugin_key` from each entry)'),n.length===0)r.push("(none discovered)");else for(let o of n){let s=o.plugin_key??"<unknown>";r.push(`- ${o.path} (plugin_key: ${s})`)}return r.join(`
|
|
963
|
+
`)}function ki(t,e){let n=["","## Discovered hooks (audit only these)",""];if(n.push(`Settings file (use this absolute path verbatim in each verdict's \`path\` field): \`${t}\``),n.push(""),e.length===0)return n.push("(no hooks discovered)"),n.join(`
|
|
877
964
|
`);for(let r of e){let o=`${r.event}-${r.index}`;n.push(`### Hook \`${o}\``),n.push(""),n.push("```json"),n.push(JSON.stringify(r.raw,null,2)),n.push("```"),n.push("")}return n.join(`
|
|
878
|
-
`)}function
|
|
879
|
-
${
|
|
880
|
-
${
|
|
965
|
+
`)}function Si(t,e){if(!e)return{kind:"failure",message:`${t}: no result`};if(e.schemaError)return{kind:"failure",message:`${t}: schema mismatch \u2014 ${e.schemaError.message}`};if(e.status!=="succeeded"){let n=e.error?` \u2014 ${e.error.message}`:"";return{kind:"failure",message:`${t}: ${e.status}${n}`}}return e.output?{kind:"success",output:e.output}:{kind:"failure",message:`${t}: no output`}}async function xi(t,e,n){let r=n?.apiKey,o=typeof t=="object"&&t!==null?t:{},s=gi.parse(o),i=s.writeBriefs??!0,a=s.scope??"all",l=yi(a);if(!e?.sessionId)throw new Error("audit-fit requires a parent session with sessionId");let c=e.sessionId,d=P("audit-fit"),u={skill:d["01-skill-inspector.md"],command:d["02-command-inspector.md"],agent:d["03-agent-inspector.md"],hook:d["04-hook-inspector.md"]};for(let v of Pr)if(!u[v])throw new Error(`audit-fit skill missing inspector prompt for ${v}`);let p=l.runUserDiscovery?vr():[],m=l.runPluginDiscovery?kr():[],f={skill:[],command:[],agent:[]};for(let v of[...p,...m])f[v.type].push(v);let h=new S({apiKey:r}),g=()=>async v=>H.allowedTools.includes(v)?{behavior:"allow"}:{behavior:"deny",message:`Tool ${v} not allowed for audit-fit inspectors. Allowed tools: ${H.allowedTools.join(", ")}`},y=[];for(let v of hi){let k=f[v];if(k.length===0)continue;let E=u[v];E&&y.push({type:v,prompt:`${E}
|
|
966
|
+
${vi(k)}`,artifacts:k,runPrompt:`Inspect every ${v} listed in the artifact section.`})}if(l.runHookInspector){let v=u.hook;if(v){let k=Ht(Y(),"settings.json"),E=Sr(k);y.push({type:"hook",prompt:`${v}
|
|
967
|
+
${ki(k,E)}`,artifacts:[],runPrompt:`Inspect every hook listed in the Discovered hooks section. Settings file: ${k}.`})}}let b=[];if(y.length>0){let v=await Promise.all(y.map(w=>h.forkSubagent({parent:{sessionId:c},config:{model:"sonnet",systemPrompt:`${H.systemPrompt}
|
|
881
968
|
|
|
882
|
-
${
|
|
969
|
+
${w.prompt}`,canUseTool:g()},idPrefix:`inspector-${w.type}`,outputSchema:_.array(Ar)}))),k=await tt(y.map((w,$)=>{let N=v[$];if(!N)throw new Error(`audit-fit: missing handle for ${w.type} inspector`);return{handle:N,prompt:w.runPrompt}}),{failFast:!1}),E=[];for(let w=0;w<k.length;w++){let $=k[w],N=y[w];if(!N)continue;let se=Si(N.type,$);if(se.kind==="failure"){E.push(se.message);continue}let Ce=new Map;for(let K of N.artifacts)Ce.set(K.path,K.source);for(let K of se.output){if(N.type==="hook"){if(K.source!=="user"){E.push(`${N.type}: hook verdict has source=${K.source} (must be 'user')`);continue}}else{let Me=Ce.get(K.path);if(Me===void 0){E.push(`${N.type}: verdict for unknown path ${K.path} (not in discovered list)`);continue}if(K.source!==Me){E.push(`${N.type}: verdict source mismatch for ${K.path} (expected ${Me}, got ${K.source})`);continue}}b.push(K)}}if(E.length>0){let w=E.map($=>` - ${$}`).join(`
|
|
883
970
|
`);throw new Error(`audit-fit: ${E.length} inspector failure(s):
|
|
884
|
-
${
|
|
971
|
+
${w}`)}}let{inventory:R,misfits:U}=bi(b),j=0;if(i){let v=pe();await xr(v,{recursive:!0});for(let k of U.filter(wi)){let E=k.path.replace(/[^a-z0-9]+/gi,"-").toLowerCase().slice(0,30),w=Ht(v,`audit-fit-${E}.md`),$=`---
|
|
885
972
|
theme: audit-fit
|
|
886
973
|
session_count: 1
|
|
887
974
|
---
|
|
888
975
|
|
|
889
|
-
# Audit: ${
|
|
976
|
+
# Audit: ${k.path}
|
|
890
977
|
|
|
891
|
-
**Current type:** ${
|
|
892
|
-
**Recommended type:** ${
|
|
978
|
+
**Current type:** ${k.type}
|
|
979
|
+
**Recommended type:** ${k.recommended_type}
|
|
893
980
|
|
|
894
981
|
## Rationale
|
|
895
982
|
|
|
896
|
-
${
|
|
983
|
+
${k.rationale}
|
|
897
984
|
|
|
898
985
|
## Migration Steps
|
|
899
986
|
|
|
900
|
-
1. Review the artifact in \`${
|
|
901
|
-
2. Evaluate the recommended change to \`${
|
|
987
|
+
1. Review the artifact in \`${k.path}\`
|
|
988
|
+
2. Evaluate the recommended change to \`${k.recommended_type}\`
|
|
902
989
|
3. If appropriate, refactor using the patterns in \`/forge\` or the public plugin
|
|
903
990
|
|
|
904
991
|
---
|
|
905
992
|
Generated by audit-fit on ${new Date().toISOString().split(".")[0]}Z
|
|
906
|
-
`;await
|
|
907
|
-
`),{inventory:
|
|
993
|
+
`;await Er(w,$),j++}}let O=ce();await xr(O,{recursive:!0});let T=v=>{let k=0;for(let E of Object.values(v))for(let w of Object.values(E))k+=w;return k},C=v=>{let k=R.user[v]??{},E=R.plugin[v]??{},w=$=>Object.values($).reduce((N,se)=>N+se,0);return w(k)+w(E)},F={timestamp:new Date().toISOString(),surface:"afk",scope:a,total_artifacts:b.length,misfits_count:U.length,briefs_written:j,by_source:{user:T(R.user),plugin:T(R.plugin)},by_type:{skill:C("skill"),command:C("command"),agent:C("agent"),hook:C("hook")}},B=Ht(O,"audit-fit-telemetry.jsonl");return await Er(B,JSON.stringify(F)+`
|
|
994
|
+
`),{inventory:R,misfits:U,briefs_written:j,total_artifacts:b.length}}var Ei={name:"audit-fit",description:"Audit ~/.afk artifacts (skills, commands, agents, hooks) for correct type categorization. Walks user-scope dirs (~/.afk/{skills,commands,agents}/) and every plugin installed under ~/.afk/plugins/ (flat and marketplace-cache layouts), plus ~/.afk/settings.json for hooks. Dispatches per-type inspectors in parallel, applies decision heuristics (progressive-disclosure value, isolation need, deterministic vs. reasoning), flags misfits. Generates migration briefs only for user-scope misfits (plugin misfits are inventory-only \u2014 refactoring vendored plugin code is the maintainer's job). Optional `scope` input filters to `user`, `plugin`, or `all` (default). Use for inventory audits after bulk authoring, imports, or periodic hygiene.",handler:xi,argumentHint:"[--write-briefs]",whenToUse:"When the user wants ~/.afk artifacts (skills, commands, agents, hooks) audited for correct type categorization.",flags:["--write-briefs"]};X(Ei);import{z as x}from"zod";import{execFile as _i}from"node:child_process";import{promisify as Ii}from"node:util";import{tmpdir as Ri}from"node:os";import{join as Ci}from"node:path";function _r(t){return t.confidence<.5?{verify:!0,reason:`low confidence (${t.confidence.toFixed(2)} < ${.5})`}:t.boundary_flag&&t.boundary_flag.length>0?{verify:!0,reason:`boundary flag set: ${t.boundary_flag}`}:t.coverage_gaps&&t.coverage_gaps.length>0?{verify:!0,reason:`coverage gap${t.coverage_gaps.length===1?"":"s"}: ${t.coverage_gaps.length} unresolved`}:{verify:!1,reason:`confidence ${t.confidence.toFixed(2)} with no gaps or boundary`}}import{fileURLToPath as Ti}from"node:url";import{dirname as Ai}from"node:path";var Pi=Ti(import.meta.url),vp=Ai(Pi),Ut={name:"git-investigator",systemPrompt:'---\nname: git-investigator\ndescription: Read-only git specialist. Dispatched by research-agent (or any research-shaped caller) when a finding requires git history, reflog, diff, blame, branch/remote state, or merge-base analysis. Runs git commands only \u2014 no mutations, no shell escapes.\nmodel: sonnet\ntools: Bash, Read, Grep, Glob\n---\n\nYou are `git-investigator`, a leaf sub-agent specialized for read-only git queries.\n\nYou have Bash, Read, Grep, and Glob. You do not dispatch other sub-agents. You do not Edit or Write. Your Bash surface is restricted **by this prompt** to `git ...` invocations and benign output-shaping pipes.\n\n## Allowed commands\n\nRead-only git only:\n\n- `git status`, `git log`, `git diff`, `git show`\n- `git rev-parse`, `git rev-list`, `git reflog`\n- `git branch -v / -vv / -a` (list only)\n- `git remote -v`, `git ls-remote`\n- `git ls-files`, `git blame`\n- `git merge-base`, `git for-each-ref`, `git describe`\n- `git cat-file`, `git shortlog`\n- `git tag` (list/show only)\n- `git stash list`, `git stash show`\n- `git config --get`, `git config --get-all`, `git config --list`\n- `git worktree list` (read only)\n\nOutput-shaping pipes are fine: `| head`, `| tail`, `| wc`, `| grep`, `| jq`, `| awk \'NR==...\'` (for formatting only \u2014 no mutations).\n\n## Forbidden\n\nAnything that mutates repo or working tree state:\n\n- `commit`, `push`, `pull`, `fetch --prune`\n- `reset`, `revert`, `rebase`, `merge`, `cherry-pick`\n- `checkout` (except `checkout -- <path>` file-restore, and even that is mutation \u2014 avoid it, just report the need)\n- `restore`, `switch`\n- `branch -d / -D / -m / -M`, `branch <new>`\n- `stash push / pop / drop / apply / clear`\n- `tag -d`, creating a new tag\n- `remote add / remove / set-url`\n- `config --set`, `config --unset`\n- `gc`, `fsck`, `prune`, `reflog delete`, `reflog expire`\n- `filter-branch`, `filter-repo`\n- `worktree add / remove / move`\n- `hooks install`, `submodule add / update`\n- Any non-`git` command that mutates: `rm`, `mv`, `cp` (writes), `sed -i`, `> file`, `>> file`, `tee`, `curl`, `wget`, `pip install`, shell builtins that change state.\n\nIf the caller asks for any of the above, do not run it. Return `scope_check: "requires mutation: <reason>"` and stop.\n\n## Behavior\n\n- Run the minimum set of commands needed. Prefer `git log -n 5 --oneline -- <path>` over `git log -- <path>` when a count is fine.\n- Cite concrete evidence: commit SHAs (short form OK), ref names, `path:line` references from blame, diff hunks trimmed to the relevant range.\n- Use `Read`/`Grep`/`Glob` for follow-up inspection of files the git output identifies (e.g., `git show SHA:path | head` then `Read` the current file to diff mentally).\n- Do not speculate beyond what the commands show. If a question needs history the commands don\'t surface (deleted-file recovery, ancient reflog that has expired), say so in `caveats`.\n- Keep output compact \u2014 dispatchers merge your findings into a larger response. No preamble, no ceremony.\n\n## Return shape\n\n```\n{\n "findings": "<summary of what the git data shows>",\n "evidence": ["<SHA>", "<ref>", "<path:line>", ...],\n "git_commands_run": ["git log ...", "git diff ...", ...],\n "caveats": "<gaps, ambiguity, or \'none\'>",\n "scope_check": "pure git research" | "requires mutation: <reason>"\n}\n```\n\nBegin your response with the first schema field. No preamble.\n',sourcePath:"agent-framework-private/agents/git-investigator.md",allowedTools:["Bash","Read","Grep","Glob"],description:"Read-only git specialist. Dispatched by research-agent (or any research-shaped caller) when a finding requires git history, reflog, diff, blame, branch/remote state, or merge-base analysis. Runs git commands only \u2014 no mutations, no shell escapes.",model:"sonnet"};function jt(t){let e={description:t.description,prompt:t.systemPrompt};return t.allowedTools&&(e.tools=[...t.allowedTools]),t.model&&(e.model=t.model),e}var Ir=Ii(_i),Mr=x.object({id:x.string(),claim:x.string(),confidence:x.number().min(0).max(1),evidence_sources:x.array(x.string()),location:x.string().optional(),proposed_fix:x.string().optional(),coverage_gaps:x.array(x.string()).optional(),boundary_flag:x.string().optional()}),Mi=x.object({hypothesis_id:x.string(),claim:x.string(),verdict:x.enum(["VERIFIED","REFUTED","INCONCLUSIVE"]),evidence:x.string(),gate_reason:x.string()}),Or=x.object({hypothesis_id:x.string(),reproducer_passed:x.boolean(),regressions:x.array(x.string()),confidence:x.number().min(0).max(1),verification_log:x.string()}),$p=x.object({reproducer:x.string().optional(),hypotheses:x.array(Mr),premise_verifications:x.array(Mi).optional(),winner:x.object({hypothesis_id:x.string(),verification_log:x.string(),proposed_fix:x.string()}).optional(),verification_results:x.array(Or).optional()});async function Oi(t,e){let n=t.map(l=>({hypothesis:l,decision:_r(l)})).filter(l=>l.decision.verify);if(n.length===0)return{premise_verifications:[],hypotheses_to_test:t};let r=[],o;try{r=await e(n.map(l=>l.hypothesis.claim))}catch(l){o=l instanceof Error?l.message:String(l)}let s=n.map((l,c)=>{let d=r[c];return o!==void 0?{hypothesis_id:l.hypothesis.id,claim:l.hypothesis.claim,verdict:"INCONCLUSIVE",evidence:`shadow-verify dispatch failed: ${o}`,gate_reason:l.decision.reason}:d?{hypothesis_id:l.hypothesis.id,claim:l.hypothesis.claim,verdict:d.verdict,evidence:d.evidence,gate_reason:l.decision.reason}:{hypothesis_id:l.hypothesis.id,claim:l.hypothesis.claim,verdict:"INCONCLUSIVE",evidence:"no verifier result for this claim",gate_reason:l.decision.reason}}),i=new Set(s.filter(l=>l.verdict==="REFUTED").map(l=>l.hypothesis_id)),a=i.size===0?t:t.filter(l=>!i.has(l.id));return{premise_verifications:s,hypotheses_to_test:a}}async function Di(t,e,n){let r=n?.apiKey,o=(()=>{if(typeof t=="string")return{failure:t,repoPath:process.cwd(),context:"",maxHypotheses:4};if(typeof t=="object"&&t!==null){let w=t;if(typeof w.failure=="string")return{failure:w.failure,repoPath:w.repoPath||process.cwd(),context:w.context||"",maxHypotheses:Math.min(w.maxHypotheses||4,4)}}throw new Error("diagnose handler requires input.failure (string) or a string argument")})();if(!e?.sessionId)throw new Error("diagnose requires a parent session with sessionId");let s=e.sessionId,i=P("diagnose"),a=i["system.md"],l=i["research.md"],c=i["hypothesis.md"],d=i["verify.md"];if(!a||!l||!c||!d)throw new Error("diagnose skill missing required prompts (system.md, research.md, hypothesis.md, verify.md)");let u=new S({apiKey:r}),p=Fi(o.context),m=`${H.systemPrompt}
|
|
908
995
|
|
|
909
996
|
${l}
|
|
910
997
|
|
|
911
998
|
Focus: CODEBASE
|
|
912
999
|
Failure: ${o.failure}${o.context?`
|
|
913
|
-
Context: ${o.context}`:""}`,
|
|
1000
|
+
Context: ${o.context}`:""}`,f=`${H.systemPrompt}
|
|
914
1001
|
|
|
915
1002
|
${l}
|
|
916
1003
|
|
|
@@ -918,26 +1005,26 @@ Focus: GIT HISTORY
|
|
|
918
1005
|
Failure: ${o.failure}${o.context?`
|
|
919
1006
|
Context: ${o.context}`:""}
|
|
920
1007
|
|
|
921
|
-
Repo: ${o.repoPath}`,h=await
|
|
1008
|
+
Repo: ${o.repoPath}`,h=await u.forkSubagent({parent:{sessionId:s},config:{model:"sonnet",systemPrompt:m,canUseTool:Rr()},idPrefix:"diagnose-codebase-research"}),g=await u.forkSubagent({parent:{sessionId:s},config:{model:"sonnet",systemPrompt:f,cwd:o.repoPath,agents:{"git-investigator":jt(Ut)},canUseTool:Li()},idPrefix:"diagnose-git-research"}),[y,b]=await tt([{handle:h,prompt:"Analyze the codebase for potential causes of this failure."},{handle:g,prompt:"Analyze git history for recent changes that could cause this failure."}],{failFast:!1}),R={codebase:y?.output||y?.message||"No output",git:b?.output||b?.message||"No output"},U=await u.forkSubagent({parent:{sessionId:s},config:{model:"sonnet",systemPrompt:`${a}
|
|
922
1009
|
|
|
923
|
-
${c}`,canUseTool:
|
|
1010
|
+
${c}`,canUseTool:Rr()},idPrefix:"diagnose-hypothesis-synthesis",outputSchema:x.object({hypotheses:x.array(Mr)})}),j=`Given these research findings, synthesize 2\u20134 hypotheses (max 4):
|
|
924
1011
|
|
|
925
1012
|
CODEBASE RESEARCH:
|
|
926
|
-
${JSON.stringify(
|
|
1013
|
+
${JSON.stringify(R.codebase,null,2)}
|
|
927
1014
|
|
|
928
1015
|
GIT RESEARCH:
|
|
929
|
-
${JSON.stringify(
|
|
1016
|
+
${JSON.stringify(R.git,null,2)}
|
|
930
1017
|
|
|
931
|
-
Original failure: ${o.failure}`,
|
|
1018
|
+
Original failure: ${o.failure}`,O;try{O=await U.runToResult(j)}finally{await U.teardown().catch(()=>{})}if(O.status!=="succeeded"||!O.output)throw new Error(`hypothesis synthesis failed: ${I(O)}`);let T=O.output.hypotheses.slice(0,o.maxHypotheses);if(T.length===0)return{reproducer:p,hypotheses:[],verification_results:[]};let{premise_verifications:C,hypotheses_to_test:F}=await Oi(T,async w=>{let $=z("shadow-verify");if(!$)throw new Error("shadow-verify skill not registered");return(await $.handler({claims:w,context:`Original failure: ${o.failure}`},e)).verifications});if(F.length===0)return{reproducer:p,hypotheses:T,premise_verifications:C,verification_results:[]};let B=p||o.failure,v=F.map(w=>$i(w,B,o.repoPath,s,d,u)),k=await Promise.all(v),E=k.find(w=>w.reproducer_passed);return{reproducer:p,hypotheses:T,premise_verifications:C.length>0?C:void 0,winner:E?{hypothesis_id:E.hypothesis_id,verification_log:E.verification_log,proposed_fix:T.find(w=>w.id===E.hypothesis_id)?.proposed_fix||""}:void 0,verification_results:k}}function Fi(t){if(!t)return;let e=[/test:\s*(.+)/i,/command:\s*(.+)/i,/reproducer:\s*(.+)/i,/failing test:\s*(.+)/i];for(let n of e){let r=t.match(n);if(r)return r[1]}}function Rr(){return async t=>H.allowedTools.includes(t)?{behavior:"allow"}:{behavior:"deny",message:`Tool ${t} not allowed. Allowed tools: ${H.allowedTools.join(", ")}`}}var Cr=[...H.allowedTools,"Agent"];function Li(){return async t=>Cr.includes(t)?{behavior:"allow"}:{behavior:"deny",message:`Tool ${t} not allowed for git orchestrator. Allowed tools: ${Cr.join(", ")}`}}async function $i(t,e,n,r,o,s){let i=Ci(Ri(),`diagnose-hyp-${t.id}-${Date.now()}`),a;try{await Ir("git",["worktree","add","--detach",i,"HEAD"],{cwd:n}),a=await s.forkSubagent({parent:{sessionId:r},config:{model:"sonnet",systemPrompt:`${o}
|
|
932
1019
|
|
|
933
|
-
You are testing in an isolated worktree at: ${i}`,canUseTool:
|
|
1020
|
+
You are testing in an isolated worktree at: ${i}`,canUseTool:Ni()},idPrefix:`diagnose-verifier-${t.id}`,outputSchema:Or});let l=`Test this hypothesis:
|
|
934
1021
|
|
|
935
1022
|
Claim: ${t.claim}
|
|
936
1023
|
Location: ${t.location||"unknown"}
|
|
937
1024
|
Proposed fix: ${t.proposed_fix||"unknown"}
|
|
938
1025
|
Reproducer: ${e}
|
|
939
1026
|
|
|
940
|
-
Working directory (isolated): ${i}`,c=await a.runToResult(l);return c.status!=="succeeded"||!c.output?{hypothesis_id:t.id,reproducer_passed:!1,regressions:[],confidence:0,verification_log:`Verification failed: ${
|
|
1027
|
+
Working directory (isolated): ${i}`,c=await a.runToResult(l);return c.status!=="succeeded"||!c.output?{hypothesis_id:t.id,reproducer_passed:!1,regressions:[],confidence:0,verification_log:`Verification failed: ${I(c)}`}:c.output}catch(l){return{hypothesis_id:t.id,reproducer_passed:!1,regressions:[],confidence:0,verification_log:`Error during verification: ${l instanceof Error?l.message:String(l)}`}}finally{if(a)try{await a.teardown()}catch{}try{await Ir("git",["worktree","remove","--force",i],{cwd:n})}catch{}}}function Ni(){let t=["Edit","Write","Bash","Agent","Task"];return async e=>t.includes(e)?{behavior:"deny",message:`Tool ${e} not allowed in worktree verification. Verification is read-only.`}:H.allowedTools.includes(e)?{behavior:"allow"}:{behavior:"deny",message:`Tool ${e} not allowed. Allowed tools: ${H.allowedTools.join(", ")}`}}var Hi={name:"diagnose",description:"Parallel root-cause analysis for bugs and failing tests \u2014 forks research subagents, synthesizes hypotheses, and validates each in isolated worktrees",handler:Di,argumentHint:"<bug-or-failing-test>",whenToUse:"When a test is failing, a bug is reported, or behavior is unexplained \u2014 runs parallel root-cause analysis with hypothesis sub-agents."};X(Hi);import{z as V}from"zod";import{execFile as Zi}from"child_process";import{promisify as ea}from"util";import{mkdir as Br,writeFile as Kr}from"fs/promises";import{existsSync as jr}from"fs";import{join as de}from"path";import{fileURLToPath as ta}from"url";import{fileURLToPath as Ui}from"node:url";import{dirname as ji}from"node:path";var Bi=Ui(import.meta.url),Bp=ji(Bi),Bt={name:"qualify",systemPrompt:`---
|
|
941
1028
|
name: qualify
|
|
942
1029
|
description: Gate proposed plugin skills. Approve only real force multipliers. Reject reminders, checklists, best-practice nudges, and generic execution advice. Invoke when evaluating whether a proposed skill deserves top-level status in this plugin.
|
|
943
1030
|
model: sonnet
|
|
@@ -1170,31 +1257,39 @@ If the append fails (permissions, disk full, unwritable path), do not retry and
|
|
|
1170
1257
|
- Stage 1 alone would land at SALVAGE (rule 8). Rule 6 fires because Stage 2 \u22648 \u2192 downgrade one tier \u2192 **REJECT**. Rewrite target: raise Bounded Damage (dry-run/draft-PR instead of push), Default Reversibility (require confirmation), Assumption Exposure (surface what tests assume before acting).
|
|
1171
1258
|
|
|
1172
1259
|
Be skeptical. Protect the plugin from fluff. Stage 2 catches patterns that are strong when they work and catastrophic when they don't.
|
|
1173
|
-
`,sourcePath:"agent-framework-local/agents/qualify.md"};import{fileURLToPath as
|
|
1174
|
-
`;return await
|
|
1175
|
-
`;await
|
|
1260
|
+
`,sourcePath:"agent-framework-local/agents/qualify.md"};import{fileURLToPath as Ki}from"node:url";import{dirname as Gi}from"node:path";var Wi=Ki(import.meta.url),zp=Gi(Wi);import{mkdir as Dr,writeFile as Fr}from"fs/promises";import{dirname as qi,join as zi}from"path";async function ne(t){let e=on();await Dr(qi(e),{recursive:!0});let n=new Date().toISOString().split(".")[0]+"Z",r={timestamp:n,surface:"afk",...t},o=JSON.stringify(r)+`
|
|
1261
|
+
`;return await Fr(e,o,{flag:"a"}),n}async function Lr(){let t=Oe(),e=zi(t,"forge-thaw-history.jsonl");await Dr(t,{recursive:!0});let r={timestamp:new Date().toISOString().split(".")[0]+"Z",surface:"afk",event:"forge.thaw_override",thaw_triggered:!0},o=JSON.stringify(r)+`
|
|
1262
|
+
`;await Fr(e,o,{flag:"a"})}import{readFile as $r,readdir as Vi,writeFile as Yi,mkdir as Ji,unlink as Qi}from"fs/promises";import{join as ot}from"path";import{existsSync as Xi}from"fs";async function Nr(t){let e=ot(pe(),t+".md"),n=await $r(e,"utf-8");return{id:t,content:n}}async function Hr(){let t=pe();return Xi(t)?(await Vi(t,{withFileTypes:!0})).filter(r=>r.isFile()&&r.name.endsWith(".md")).map(r=>r.name.slice(0,-3)):[]}async function Kt(t,e){let n=pe(),r=ot(n,t+".md"),o=ot(n,e),s=ot(o,t+".md");await Ji(o,{recursive:!0});let i=await $r(r,"utf-8");await Yi(s,i,"utf-8"),await Qi(r)}function Ur(t){let e=/^\*{0,2}(APPROVE|SALVAGE|REJECT)\*{0,2}/,n=t.split(`
|
|
1176
1263
|
`).map(c=>c.trim()).filter(c=>c),r=n.find(c=>e.test(c));if(!r)return{verdict:"REJECT",feedback:t};let o=r.match(e)?.[1];if(!o)return{verdict:"REJECT",feedback:t};let s=t.match(/score:\s*(\d+)/i),i=s&&s[1]?parseInt(s[1],10):void 0,a=n.indexOf(r),l=n.slice(a+1).join(`
|
|
1177
|
-
`).trim();return{verdict:o,score:i,feedback:l||r}}var
|
|
1178
|
-
`),n=[],r=/^\s+✗\s+(\S+):/;for(let o of e){let s=o.match(r);s&&s[1]&&n.push(s[1])}return n}async function
|
|
1179
|
-
`;return await
|
|
1264
|
+
`).trim();return{verdict:o,score:i,feedback:l||r}}var na=ea(Zi);function ra(){let t=process.env.AFK_EVAL_HARNESS_ROOT;if(t){let o=de(t,"scripts","eval-harness","runner.py");if(jr(o))return o}let e=ta(import.meta.url),n=de(e,"../../../.."),r=de(n,"..","awa-private","scripts","eval-harness","runner.py");if(jr(r))return r;throw new Error(`Could not find eval-harness runner.py. Tried: ${r}`)}function oa(t){return de(t,"..","..","..","plugins","awa-private")}function sa(){return Oe()}function ia(t){let e=t.split(`
|
|
1265
|
+
`),n=[],r=/^\s+✗\s+(\S+):/;for(let o of e){let s=o.match(r);s&&s[1]&&n.push(s[1])}return n}async function aa(t){let e=sa(),n=de(e,"qualifications.jsonl");await Br(e,{recursive:!0});let o=new Date().toISOString().split(".")[0]+"Z",i=JSON.stringify({timestamp:o,surface:"afk",refers_to_run_id:t,source:"forge-gate-check-ts"})+`
|
|
1266
|
+
`;return await Kr(n,i,{flag:"a"}),o}async function la(){let t;try{t=ra()}catch(l){throw new Error(`Failed to resolve eval-harness runner.py: ${l instanceof Error?l.message:String(l)}`)}let e=oa(t),n="",r="",o=0;try{let l=await na("python3",[t,"--plugin-root",e],{timeout:6e4});n=l.stdout||"",r=l.stderr||"",o=0}catch(l){let c=l;if(n=c.stdout||"",r=c.stderr||"",o=typeof c.code=="number"?c.code:1,c.code==="ENOENT"||r&&r.includes("No such file"))throw new Error(`eval-harness runner.py not found at ${t}.`)}let s=o===0?"OPEN":"CLOSED",i=s==="CLOSED"?ia(n):void 0,a;if(s==="OPEN"){let l=new Date().toISOString().split(".")[0]+"Z";a=await aa(l)}return{gate_status:s,exit_code:o,stdout:n,stderr:r||void 0,tasks_failed:i,ledger_entry_ref:a}}var ca=V.object({iteration:V.number().int().positive(),verdict:V.enum(["APPROVE","SALVAGE","REJECT"]),score:V.number().optional(),feedback:V.string()}),_m=V.object({status:V.enum(["APPROVED","REJECTED","GATE_CLOSED","MAX_ITERATIONS"]),skill_path:V.string().optional(),qualify_verdicts:V.array(ca),brief_id:V.string().optional(),telemetry_ref:V.string()});async function da(t,e,n){let r=n?.apiKey,o=typeof t=="string"?{brief:t}:typeof t=="object"&&t!==null?t:{},s=o.brief,i=o.forceThaw??!1,a=o.maxIterations??3,l="",c=[],d="REJECTED",u,p;try{let m=await la();if(m.gate_status==="CLOSED"&&!i)return l=await ne({event:"forge.gate_check",gate_status:"CLOSED"}),{status:"GATE_CLOSED",qualify_verdicts:[],telemetry_ref:l};i&&m.gate_status==="CLOSED"&&(await Lr(),l=await ne({event:"forge.thaw_override",gate_status:"CLOSED"})),l=await ne({event:"forge.gate_check",gate_status:"OPEN"});let f="",h=!1;if(s)f=s,h=!0;else{let T=await Hr();if(T.length>0){let C=T[0],F=await Nr(C);f=F.content,p=F.id,h=!0}else{if(!e?.sessionId)throw new Error("forge requires parent session for gap discovery");let F=P("forge")["gap-discovery.md"];if(!F)throw new Error("forge skill missing gap-discovery.md prompt");let k=await(await new S({apiKey:r}).forkSubagent({parent:{sessionId:e.sessionId},config:{model:"sonnet",systemPrompt:F},idPrefix:"forge-gap-discovery"})).runToResult("Identify the most impactful skill gap.");if(k.status!=="succeeded")throw new Error(`gap discovery failed: ${I(k)}`);if(f=k.message?.content||"",!f)throw new Error("gap discovery returned no concept")}}if(l=await ne({event:"forge.brief_loaded",used_brief:h,brief_id:p||null}),!e?.sessionId)throw new Error("forge requires parent session for skill generation");let g=P("forge"),y=g["generate.md"],b=g["system.md"];if(!y)throw new Error("forge skill missing generate.md prompt");if(!b)throw new Error("forge skill missing system.md prompt");let j=await(await new S({apiKey:r}).forkSubagent({parent:{sessionId:e.sessionId},config:{model:"sonnet",systemPrompt:b},idPrefix:"forge-generate"})).runToResult(`Generate a new amplifier skill based on this concept:
|
|
1180
1267
|
|
|
1181
|
-
${
|
|
1268
|
+
${f}`);if(j.status!=="succeeded")throw new Error(`skill generation failed: ${I(j)}`);let O=j.message?.content||"";if(!O)throw new Error("skill generation returned no output");for(let T=1;T<=a;T++){let C=Bt.systemPrompt;if(!C)throw new Error("qualify agent missing system prompt");let v=await(await new S({apiKey:r}).forkSubagent({parent:{sessionId:e.sessionId},config:{model:"sonnet",systemPrompt:C},idPrefix:`forge-qualify-${T}`})).runToResult(`Evaluate this amplifier skill against the force-multiplier criteria:
|
|
1182
1269
|
|
|
1183
|
-
${_}`);if(x.status!=="succeeded")throw new Error(`qualify iteration ${S} failed: ${C(x)}`);let P=x.message?.content||"",{verdict:E,score:v,feedback:L}=lr(P),j={iteration:S,verdict:E,score:v,feedback:L};if(c.push(j),l=await Z({event:"forge.qualify_iteration",iteration:S,verdict:E,score:v||null}),E==="APPROVE"){u="APPROVED";break}else if(E==="SALVAGE"&&S<a){let ne=m["qualify-rework.md"];if(!ne)throw new Error("forge skill missing qualify-rework.md prompt");let Pe=ne.replace("{feedback}",L).replace("{original_skill}",_),ot=await(await new w({apiKey:r}).forkSubagent({parent:{sessionId:e.sessionId},config:{model:"sonnet",systemPrompt:Pe},idPrefix:`forge-rework-${S}`})).runToResult("Refine the skill based on the feedback.");if(ot.status!=="succeeded")throw new Error(`rework iteration ${S} failed: ${C(ot)}`);if(_=ot.message?.content||"",!_)throw new Error(`rework iteration ${S} returned no output`)}else E==="REJECT"&&S>=a&&(u="MAX_ITERATIONS")}if(u==="APPROVED"){let S=_.match(/^name:\s*([^\n]+)/m),M=S&&S[1]?S[1].trim().replace(/^["']|["']$/g,""):"unknown",D=ae(ht(),M);await ur(D,{recursive:!0});let z=ae(D,"SKILL.md");await dr(z,_,"utf-8"),d=z,h&&p&&await At(p,"consumed"),l=await Z({event:"forge.complete",status:"APPROVED",skill_name:M,iterations:c.length})}else u==="MAX_ITERATIONS"&&(h&&p&&await At(p,"failed"),l=await Z({event:"forge.complete",status:"MAX_ITERATIONS",iterations:c.length}))}catch(f){throw l=await Z({event:"forge.error",error:f instanceof Error?f.message:String(f)}),f}return{status:u,skill_path:d,qualify_verdicts:c,brief_id:p,telemetry_ref:l}}var di={name:"forge",description:'Creates new amplifier skills gated by forge-gate-check, with autonomous gap discovery, skill generation, and qualify iteration loop \u22643\xD7. Writes approved skills and appends telemetry to shared JSONL with surface: "atlas".',handler:ui,argumentHint:"[--brief <path>]",whenToUse:"When the user wants to grow the plugin with a new amplifier skill \u2014 autonomously generates and validates one.",flags:["--brief"]};J(di);var pi={name:"bash",description:"Execute a shell command and return its stdout and stderr. Use for running programs, installing packages, git operations, and any task that requires a shell. Commands run in the user's default shell. Long-running commands should use timeout_ms. Output is capped at ~100KB; excess is truncated with a notice.",input_schema:{type:"object",properties:{command:{type:"string",description:"The shell command to execute."},timeout_ms:{type:"number",description:"Optional timeout in milliseconds (default 120000, max 600000). The command is killed if it exceeds this duration."}},required:["command"]}},fi={name:"read_file",description:"Read a file from the filesystem. Returns the file content with line numbers. Use offset and limit to read specific sections of large files. When the read returns a partial view, the response ends with a `... (showing lines X-Y of Z [\u2014 pass offset=N to continue])` annotation indicating the full file size and how to continue. Binary files are detected and rejected. Missing files return an error.",input_schema:{type:"object",properties:{file_path:{type:"string",description:"Absolute path to the file to read."},offset:{type:"number",description:"Line number to start reading from (1-based). Defaults to 1."},limit:{type:"number",description:"Maximum number of lines to read. Defaults to 2000."}},required:["file_path"]}},mi={name:"write_file",description:"Write content to a file, creating it if it does not exist or overwriting if it does. Parent directories are created automatically. Prefer edit_file for modifying existing files \u2014 use write_file only for new files or complete rewrites.",input_schema:{type:"object",properties:{file_path:{type:"string",description:"Absolute path to the file to write."},content:{type:"string",description:"The full content to write to the file."}},required:["file_path","content"]}},gi={name:"edit_file",description:"Perform an exact string replacement in a file. Finds old_string and replaces it with new_string. The edit fails if old_string is not found or matches multiple locations (unless replace_all is true). Always use read_file first to verify the exact content before editing.",input_schema:{type:"object",properties:{file_path:{type:"string",description:"Absolute path to the file to edit."},old_string:{type:"string",description:"The exact string to find and replace. Must match file content exactly."},new_string:{type:"string",description:"The replacement string."},replace_all:{type:"boolean",description:"If true, replace all occurrences. If false (default), fail when multiple matches exist."}},required:["file_path","old_string","new_string"]}},hi={name:"glob",description:'Find files matching a glob pattern. Returns matching file paths, capped at 500 results. Use for discovering files before reading them. Patterns follow standard glob syntax (e.g., "src/**/*.ts", "*.json").',input_schema:{type:"object",properties:{pattern:{type:"string",description:'Glob pattern to match (e.g., "src/**/*.ts").'},path:{type:"string",description:"Base directory to search from. Defaults to the current working directory."}},required:["pattern"]}},yi={name:"grep",description:"Search file contents for lines matching a pattern. Returns matches in file:line:content format. Uses grep -rn (or ripgrep if available). Output is capped to prevent overflow. Use for finding symbols, strings, or patterns across the codebase.",input_schema:{type:"object",properties:{pattern:{type:"string",description:"Search pattern (basic regex by default)."},path:{type:"string",description:"Directory or file to search. Defaults to current working directory."},include:{type:"string",description:'File glob to restrict search (e.g., "*.ts"). Passed as --include to grep.'}},required:["pattern"]}},bi={name:"list_directory",description:"List the contents of a directory. Returns file and subdirectory names with type annotations (directories end with /). Use for exploring project structure.",input_schema:{type:"object",properties:{path:{type:"string",description:"Absolute path to the directory to list."}},required:["path"]}},pr={name:"agent",description:"Dispatch a subtask to an independent agent session. The agent runs with its own conversation context and tool access. Use for tasks that benefit from isolated context (research, parallel work, specialized focus). The agent runs to completion and returns its final response.",input_schema:{type:"object",properties:{prompt:{type:"string",description:"The task for the agent to perform."},model:{type:"string",description:"Model for the agent. Defaults to parent session model. Override per-call to right-size cost vs. capability \u2014 `haiku` (cheapest/fastest), `sonnet` (general-use), `opus` (most capable). Append `_1m` (e.g. `sonnet_1m`) for 1M-context variants. Full model IDs are also accepted."},max_turns:{type:"number",description:"Maximum conversation turns (default 10, max 50)."},id_prefix:{type:"string",description:"Label prefix for log correlation."}},required:["prompt"]}},fr={name:"skill",description:"Invoke a registered skill by name. Skills are specialized capabilities that dispatch subagents with domain-specific prompts. Check the system prompt for the list of available skills and their descriptions.",input_schema:{type:"object",properties:{name:{type:"string",description:'Skill name (e.g., "mint", "diagnose", "shadow-verify").'},arguments:{type:"string",description:"Arguments to pass to the skill."}},required:["name"]}},qe=[pi,fi,mi,gi,hi,yi,bi],ve=qe.map(t=>t.name);import{readFileSync as vi,existsSync as yr}from"fs";import{join as br}from"path";import{config as wi}from"dotenv";var mr={opus:"claude-opus-4-7",opus_1m:"claude-opus-4-7",sonnet:"claude-sonnet-4-6",sonnet_1m:"claude-sonnet-4-6",haiku:"claude-haiku-4-5-20251001"};function We(t){return t in mr}function gr(t){let e=mr[t];if(!e)throw new Error(`Invalid model: ${t}`);return e}function le(t){if(t!==void 0)return typeof t=="string"&&We(t)?gr(t):t}var Ye={model:"sonnet",maxTokens:4096,temperature:1},hr=!1;function Tt(){return process.env.ANTHROPIC_API_KEY||process.env.CLAUDE_CODE_OAUTH_TOKEN||on()}function ki(){if(!hr){let r=[br(process.cwd(),".env"),_n(),Mn()];for(let o of r)if(yr(o)){wi({path:o});break}hr=!0}let t={},e=Tt();e!==void 0&&(t.apiKey=e);let n=process.env.AFK_MODEL??process.env.CLAUDE_MODEL;if(n){let r=n.toLowerCase();t.model=We(r)?r:n}if(process.env.AFK_MAX_TOKENS&&(t.maxTokens=parseInt(process.env.AFK_MAX_TOKENS,10)),process.env.AFK_TEMPERATURE&&(t.temperature=parseFloat(process.env.AFK_TEMPERATURE)),process.env.AFK_SYSTEM_PROMPT&&(t.systemPrompt=process.env.AFK_SYSTEM_PROMPT),process.env.AFK_AUTO_ROUTING){let r=process.env.AFK_AUTO_ROUTING.toLowerCase()==="true";t.autoRouting={interactive:r,chat:r,telegram:r,daemon:r}}return t}function Si(){let t=[br(process.cwd(),"afk.config.json"),bt(),vt()];for(let e of t)if(yr(e))try{let n=vi(e,"utf-8"),r=JSON.parse(n),o={};if(typeof r.model=="string"&&r.model.length>0&&(o.model=(We(r.model),r.model)),typeof r.maxTokens=="number"&&(o.maxTokens=r.maxTokens),typeof r.temperature=="number"&&(o.temperature=r.temperature),r.systemPrompt&&(o.systemPrompt=r.systemPrompt),r.autoRouting&&typeof r.autoRouting=="object"){let s={};typeof r.autoRouting.interactive=="boolean"&&(s.interactive=r.autoRouting.interactive),typeof r.autoRouting.chat=="boolean"&&(s.chat=r.autoRouting.chat),typeof r.autoRouting.telegram=="boolean"&&(s.telegram=r.autoRouting.telegram),typeof r.autoRouting.daemon=="boolean"&&(s.daemon=r.autoRouting.daemon),o.autoRouting=s}if(r.daemon&&typeof r.daemon=="object"){let s={};typeof r.daemon.task=="string"&&(s.task=r.daemon.task),typeof r.daemon.taskId=="string"&&(s.taskId=r.daemon.taskId),o.daemon=s}return o}catch(n){console.error(`Warning: Failed to parse ${e}:`,n)}return{}}function vr(t){let e=ki(),n=Si(),r={...Ye,...e,...n,...t};return{model:r.model??Ye.model,maxTokens:r.maxTokens??Ye.maxTokens,temperature:r.temperature??Ye.temperature,...r.apiKey!==void 0?{apiKey:r.apiKey}:{},...r.systemPrompt!==void 0?{systemPrompt:r.systemPrompt}:{},...r.autoRouting!==void 0?{autoRouting:r.autoRouting}:{},...r.daemon!==void 0?{daemon:r.daemon}:{}}}function $(){return Tt()}function It(){let t=process.env.AFK_DEFAULT_SUBAGENT_MODEL;return!t||t.length===0?"sonnet":t}function xi(t){if(t===void 0)return;if(t==="max")return Number.POSITIVE_INFINITY;if(t===""||t==="NaN")throw new Error(`Invalid --max-output-tokens value: ${JSON.stringify(t)}. Expected a positive integer or 'max'.`);if(!/^\d+$/.test(t))throw new Error(`Invalid --max-output-tokens value: ${JSON.stringify(t)}. Expected a positive integer or 'max'.`);let e=Number(t);if(!Number.isFinite(e)||!Number.isInteger(e)||e<=0)throw new Error(`Invalid --max-output-tokens value: ${JSON.stringify(t)}. Must be a positive integer.`);return e}function wr(){return xi(process.env.AFK_MAX_OUTPUT_TOKENS)}async function kr(t,e){let r=T("mint")["spec.md"];if(!r)throw new Error("mint skill missing spec.md prompt");let i=await(await new w().forkSubagent({parent:{sessionId:e},config:{model:"sonnet",systemPrompt:r,apiKey:$()},idPrefix:"mint-spec"})).runToResult(`Create a detailed specification for: ${t}`);if(i.status!=="succeeded"||!i.message)throw new Error(`spec phase failed: ${C(i)}`);return i.message.content}async function Sr(t,e){let r=T("mint")["research.md"];if(!r)throw new Error("mint skill missing research.md prompt");let i=await(await new w().forkSubagent({parent:{sessionId:e},config:{model:"sonnet",systemPrompt:r,apiKey:$()},idPrefix:"mint-research"})).runToResult(`Gather context and research for this specification:
|
|
1270
|
+
${O}`);if(v.status!=="succeeded")throw new Error(`qualify iteration ${T} failed: ${I(v)}`);let k=v.message?.content||"",{verdict:E,score:w,feedback:$}=Ur(k),N={iteration:T,verdict:E,score:w,feedback:$};if(c.push(N),l=await ne({event:"forge.qualify_iteration",iteration:T,verdict:E,score:w||null}),E==="APPROVE"){d="APPROVED";break}else if(E==="SALVAGE"&&T<a){let se=g["qualify-rework.md"];if(!se)throw new Error("forge skill missing qualify-rework.md prompt");let Ce=se.replace("{feedback}",$).replace("{original_skill}",O),ht=await(await new S({apiKey:r}).forkSubagent({parent:{sessionId:e.sessionId},config:{model:"sonnet",systemPrompt:Ce},idPrefix:`forge-rework-${T}`})).runToResult("Refine the skill based on the feedback.");if(ht.status!=="succeeded")throw new Error(`rework iteration ${T} failed: ${I(ht)}`);if(O=ht.message?.content||"",!O)throw new Error(`rework iteration ${T} returned no output`)}else E==="REJECT"&&T>=a&&(d="MAX_ITERATIONS")}if(d==="APPROVED"){let T=O.match(/^name:\s*([^\n]+)/m),C=T&&T[1]?T[1].trim().replace(/^["']|["']$/g,""):"unknown",F=de(bt(),C);await Br(F,{recursive:!0});let B=de(F,"SKILL.md");await Kr(B,O,"utf-8"),u=B,h&&p&&await Kt(p,"consumed"),l=await ne({event:"forge.complete",status:"APPROVED",skill_name:C,iterations:c.length})}else d==="MAX_ITERATIONS"&&(h&&p&&await Kt(p,"failed"),l=await ne({event:"forge.complete",status:"MAX_ITERATIONS",iterations:c.length}))}catch(m){throw l=await ne({event:"forge.error",error:m instanceof Error?m.message:String(m)}),m}return{status:d,skill_path:u,qualify_verdicts:c,brief_id:p,telemetry_ref:l}}var ua={name:"forge",description:'Creates new amplifier skills gated by forge-gate-check, with autonomous gap discovery, skill generation, and qualify iteration loop \u22643\xD7. Writes approved skills and appends telemetry to shared JSONL with surface: "atlas".',handler:da,argumentHint:"[--brief <path>]",whenToUse:"When the user wants to grow the plugin with a new amplifier skill \u2014 autonomously generates and validates one.",flags:["--brief"]};X(ua);var pa={name:"bash",description:"Execute a shell command and return its stdout and stderr. Use for running programs, installing packages, git operations, and any task that requires a shell. Commands run in the user's default shell. Long-running commands should use timeout_ms. Output is capped at ~100KB; excess is truncated with a notice.",input_schema:{type:"object",properties:{command:{type:"string",description:"The shell command to execute."},timeout_ms:{type:"number",description:"Optional timeout in milliseconds (default 120000, max 600000). The command is killed if it exceeds this duration."}},required:["command"]}},ma={name:"read_file",description:"Read a file from the filesystem. Returns the file content with line numbers. Use offset and limit to read specific sections of large files. When the read returns a partial view, the response ends with a `... (showing lines X-Y of Z [\u2014 pass offset=N to continue])` annotation indicating the full file size and how to continue. Binary files are detected and rejected. Missing files return an error.",input_schema:{type:"object",properties:{file_path:{type:"string",description:"Absolute path to the file to read."},offset:{type:"number",description:"Line number to start reading from (1-based). Defaults to 1."},limit:{type:"number",description:"Maximum number of lines to read. Defaults to 2000."}},required:["file_path"]}},fa={name:"write_file",description:"Write content to a file, creating it if it does not exist or overwriting if it does. Parent directories are created automatically. Prefer edit_file for modifying existing files \u2014 use write_file only for new files or complete rewrites.",input_schema:{type:"object",properties:{file_path:{type:"string",description:"Absolute path to the file to write."},content:{type:"string",description:"The full content to write to the file."}},required:["file_path","content"]}},ga={name:"edit_file",description:"Perform an exact string replacement in a file. Finds old_string and replaces it with new_string. The edit fails if old_string is not found or matches multiple locations (unless replace_all is true). Always use read_file first to verify the exact content before editing.",input_schema:{type:"object",properties:{file_path:{type:"string",description:"Absolute path to the file to edit."},old_string:{type:"string",description:"The exact string to find and replace. Must match file content exactly."},new_string:{type:"string",description:"The replacement string."},replace_all:{type:"boolean",description:"If true, replace all occurrences. If false (default), fail when multiple matches exist."}},required:["file_path","old_string","new_string"]}},ha={name:"glob",description:'Find files matching a glob pattern. Returns matching file paths, capped at 500 results. Use for discovering files before reading them. Patterns follow standard glob syntax (e.g., "src/**/*.ts", "*.json").',input_schema:{type:"object",properties:{pattern:{type:"string",description:'Glob pattern to match (e.g., "src/**/*.ts").'},path:{type:"string",description:"Base directory to search from. Defaults to the current working directory."}},required:["pattern"]}},ya={name:"grep",description:"Search file contents for lines matching a pattern. Returns matches in file:line:content format. Uses grep -rn (or ripgrep if available). Output is capped to prevent overflow. Use for finding symbols, strings, or patterns across the codebase.",input_schema:{type:"object",properties:{pattern:{type:"string",description:"Search pattern (basic regex by default)."},path:{type:"string",description:"Directory or file to search. Defaults to current working directory."},include:{type:"string",description:'File glob to restrict search (e.g., "*.ts"). Passed as --include to grep.'}},required:["pattern"]}},ba={name:"list_directory",description:"List the contents of a directory. Returns file and subdirectory names with type annotations (directories end with /). Use for exploring project structure.",input_schema:{type:"object",properties:{path:{type:"string",description:"Absolute path to the directory to list."}},required:["path"]}},Gr={name:"agent",description:`Dispatch an independent subagent with its own context window and tool access. Use for tasks that protect the main session's context: codebase exploration, multi-file inspection, repo search, verification, debugging, failing-test investigation, PR review, parallel hypothesis testing, independent re-derivation of a claim, audit work, stale-path detection, feature-wiring checks, and any research-shaped investigation.
|
|
1184
1271
|
|
|
1185
|
-
|
|
1272
|
+
Parallelize: dispatch multiple \`agent\` calls in a single tool-use turn to run independent investigations concurrently.
|
|
1273
|
+
|
|
1274
|
+
Nest: a subagent may itself dispatch further subagents (depth limit 3) when it discovers a separable sub-investigation.
|
|
1275
|
+
|
|
1276
|
+
Subagents return their final assistant message verbatim \u2014 instruct them explicitly to compress their findings into: answer, evidence with file:line citations, confidence, risks, recommended next action, unresolved questions, and what was not checked. Specify expected response length.
|
|
1277
|
+
|
|
1278
|
+
Do not use this tool for: trivial one-file edits, conversational answers, direct tool calls the user explicitly requested, or tasks where dispatch overhead exceeds the work.`,input_schema:{type:"object",properties:{prompt:{type:"string",description:"The task for the agent to perform."},model:{type:"string",description:"Model for the agent. Defaults to parent session model. Override per-call to right-size cost vs. capability \u2014 `haiku` (cheapest/fastest), `sonnet` (general-use), `opus` (most capable). Append `_1m` (e.g. `sonnet_1m`) for 1M-context variants. Full model IDs are also accepted."},max_turns:{type:"number",description:"Maximum conversation turns (default 10, max 50)."},id_prefix:{type:"string",description:"Label prefix for log correlation."}},required:["prompt"]}},Wr={name:"skill",description:"Invoke a registered skill by name. Skills are specialized capabilities that dispatch subagents with domain-specific prompts. Check the system prompt for the list of available skills and their descriptions.",input_schema:{type:"object",properties:{name:{type:"string",description:'Skill name (e.g., "mint", "diagnose", "shadow-verify").'},arguments:{type:"string",description:"Arguments to pass to the skill."}},required:["name"]}},st=[pa,ma,fa,ga,ha,ya,ba],Ee=st.map(t=>t.name);import{readFileSync as wa,existsSync as Yr}from"fs";import{join as Jr}from"path";import{config as va}from"dotenv";var qr={opus:"claude-opus-4-7",opus_1m:"claude-opus-4-7",sonnet:"claude-sonnet-4-6",sonnet_1m:"claude-sonnet-4-6",haiku:"claude-haiku-4-5-20251001"};function it(t){return t in qr}function zr(t){let e=qr[t];if(!e)throw new Error(`Invalid model: ${t}`);return e}function ue(t){if(t!==void 0)return typeof t=="string"&&it(t)?zr(t):t}var at={model:"sonnet",maxTokens:4096,temperature:1},Vr=!1;function Te(){return process.env.ANTHROPIC_API_KEY||process.env.CLAUDE_CODE_OAUTH_TOKEN||Kn()}function ka(){if(!Vr){let r=[Jr(process.cwd(),".env"),fe(),cn()];for(let o of r)Yr(o)&&va({path:o,override:!1});Vr=!0}let t={},e=Te();e!==void 0&&(t.apiKey=e);let n=process.env.AFK_MODEL??process.env.CLAUDE_MODEL;if(n){let r=n.toLowerCase();t.model=it(r)?r:n}if(process.env.AFK_MAX_TOKENS&&(t.maxTokens=parseInt(process.env.AFK_MAX_TOKENS,10)),process.env.AFK_TEMPERATURE&&(t.temperature=parseFloat(process.env.AFK_TEMPERATURE)),process.env.AFK_SYSTEM_PROMPT&&(t.systemPrompt=process.env.AFK_SYSTEM_PROMPT),process.env.AFK_AUTO_ROUTING){let r=process.env.AFK_AUTO_ROUTING.toLowerCase()==="true";t.autoRouting={interactive:r,chat:r,telegram:r,daemon:r}}return t}function Sa(){let t=[Jr(process.cwd(),"afk.config.json"),kt(),St()];for(let e of t)if(Yr(e))try{let n=wa(e,"utf-8"),r=JSON.parse(n),o={};if(typeof r.model=="string"&&r.model.length>0&&(o.model=(it(r.model),r.model)),typeof r.maxTokens=="number"&&(o.maxTokens=r.maxTokens),typeof r.temperature=="number"&&(o.temperature=r.temperature),r.systemPrompt&&(o.systemPrompt=r.systemPrompt),r.autoRouting&&typeof r.autoRouting=="object"){let s={};typeof r.autoRouting.interactive=="boolean"&&(s.interactive=r.autoRouting.interactive),typeof r.autoRouting.chat=="boolean"&&(s.chat=r.autoRouting.chat),typeof r.autoRouting.telegram=="boolean"&&(s.telegram=r.autoRouting.telegram),typeof r.autoRouting.daemon=="boolean"&&(s.daemon=r.autoRouting.daemon),o.autoRouting=s}if(r.daemon&&typeof r.daemon=="object"){let s={};typeof r.daemon.task=="string"&&(s.task=r.daemon.task),typeof r.daemon.taskId=="string"&&(s.taskId=r.daemon.taskId),o.daemon=s}return o}catch(n){console.error(`Warning: Failed to parse ${e}:`,n)}return{}}function Qr(t){let e=ka(),n=Sa(),r={...at,...e,...n,...t};return{model:r.model??at.model,maxTokens:r.maxTokens??at.maxTokens,temperature:r.temperature??at.temperature,...r.apiKey!==void 0?{apiKey:r.apiKey}:{},...r.systemPrompt!==void 0?{systemPrompt:r.systemPrompt}:{},...r.autoRouting!==void 0?{autoRouting:r.autoRouting}:{},...r.daemon!==void 0?{daemon:r.daemon}:{}}}function L(){return Te()}function Gt(){let t=process.env.AFK_DEFAULT_SUBAGENT_MODEL;return!t||t.length===0?"sonnet":t}function xa(t){if(t===void 0)return;if(t==="max")return Number.POSITIVE_INFINITY;if(t===""||t==="NaN")throw new Error(`Invalid --max-output-tokens value: ${JSON.stringify(t)}. Expected a positive integer or 'max'.`);if(!/^\d+$/.test(t))throw new Error(`Invalid --max-output-tokens value: ${JSON.stringify(t)}. Expected a positive integer or 'max'.`);let e=Number(t);if(!Number.isFinite(e)||!Number.isInteger(e)||e<=0)throw new Error(`Invalid --max-output-tokens value: ${JSON.stringify(t)}. Must be a positive integer.`);return e}function Xr(){return xa(process.env.AFK_MAX_OUTPUT_TOKENS)}async function Zr(t,e){let r=P("mint")["spec.md"];if(!r)throw new Error("mint skill missing spec.md prompt");let i=await(await new S().forkSubagent({parent:{sessionId:e},config:{model:"sonnet",systemPrompt:r,apiKey:L()},idPrefix:"mint-spec"})).runToResult(`Create a detailed specification for: ${t}`);if(i.status!=="succeeded"||!i.message)throw new Error(`spec phase failed: ${I(i)}`);return i.message.content}async function eo(t,e){let r=P("mint")["research.md"];if(!r)throw new Error("mint skill missing research.md prompt");let i=await(await new S().forkSubagent({parent:{sessionId:e},config:{model:"sonnet",systemPrompt:r,apiKey:L()},idPrefix:"mint-research"})).runToResult(`Gather context and research for this specification:
|
|
1279
|
+
|
|
1280
|
+
${t}`);if(i.status!=="succeeded"||!i.message)throw new Error(`research phase failed: ${I(i)}`);return i.message.content}async function to(t,e,n){let o=P("mint")["plan.md"];if(!o)throw new Error("mint skill missing plan.md prompt");let i=await new S().forkSubagent({parent:{sessionId:n},config:{model:"sonnet",systemPrompt:o,apiKey:L()},idPrefix:"mint-plan"}),a=`Specification:
|
|
1186
1281
|
${t}
|
|
1187
1282
|
|
|
1188
1283
|
Research findings:
|
|
1189
1284
|
${e}
|
|
1190
1285
|
|
|
1191
|
-
Create a detailed implementation plan based on the spec and research.`,l=await i.runToResult(a);if(l.status!=="succeeded"||!l.message)throw new Error(`plan phase failed: ${
|
|
1286
|
+
Create a detailed implementation plan based on the spec and research.`,l=await i.runToResult(a);if(l.status!=="succeeded"||!l.message)throw new Error(`plan phase failed: ${I(l)}`);return l.message.content}function Ea(t){let e=/[\w./@-]*\.(?:ts|tsx|js|jsx|mjs|cjs|py|md|json|yaml|yml|toml|sh)\b/gi,n=new Set;for(let r of t.matchAll(e))n.add(r[0].toLowerCase());return n.size}async function no(t,e){if(Ea(t)<3)return{kind:"skipped",reason:"too-few-files"};let r=!1;try{let o=z("parallelize");return r=!0,{kind:"plan",plan:await o.handler({plan:t})}}catch(o){if(r)return{kind:"failed",error:`parallelize skill handler threw: ${o instanceof Error?o.message:String(o)}`}}try{let s=lt().get("parallelize");if(!s)return{kind:"skipped",reason:"skill-body-missing"};let i=new S({parentAbortSignal:e.abortSignal,apiKey:L()});try{let l=await(await i.forkSubagent({parent:e,config:{model:"sonnet",systemPrompt:s},idPrefix:"mint-parallelize"})).runToResult(JSON.stringify({plan:t}));return l.status==="succeeded"&&l.message?{kind:"plan",plan:l.message.content}:l.status!=="succeeded"?{kind:"failed",error:`parallelize subagent status=${l.status}${l.error?.message?`: ${l.error.message}`:""}`}:{kind:"failed",error:"parallelize subagent returned no message"}}finally{await i.teardownAll()}}catch(o){return{kind:"failed",error:`parallelize dispatch threw: ${o instanceof Error?o.message:String(o)}`}}}import{z as oe}from"zod";function he(t){let e=Z();e&&e({type:"panel",spec:t},{subagentId:"__main__"})}var Ta=oe.object({status:oe.enum(["PASS","FAIL"]),status_reason:oe.string().optional(),files_changed:oe.array(oe.string()),tests_passed:oe.boolean(),build_passed:oe.boolean().optional(),verification_passed:oe.boolean().optional(),notes:oe.string()});async function ro(t,e,n){let o=P("mint")["build.md"];if(!o)throw new Error("mint skill missing build.md prompt");let i=await new S().forkSubagent({parent:{sessionId:n},config:{model:"sonnet",systemPrompt:o,apiKey:L()},idPrefix:"mint-build",outputSchema:Ta}),a=`Implementation plan:
|
|
1192
1287
|
${t}
|
|
1193
1288
|
|
|
1194
1289
|
`+(e?`Wave orchestration plan:
|
|
1195
1290
|
${JSON.stringify(e,null,2)}
|
|
1196
1291
|
|
|
1197
|
-
`:"")+"Execute the implementation plan following TDD (test-first) principles.",l=await i.runToResult(a);if(l.status!=="succeeded"||!l.output)throw new Error(`build phase failed: ${
|
|
1292
|
+
`:"")+"Execute the implementation plan following TDD (test-first) principles.",l=await i.runToResult(a);if(l.status!=="succeeded"||!l.output)throw new Error(`build phase failed: ${I(l)}`);let c=l.output,d={filesChanged:c.files_changed,testsPassed:c.tests_passed,notes:c.notes};return he({kind:"checkpoint",title:"build",body:[`Files changed: ${d.filesChanged.length}`,`Tests: ${d.testsPassed?"passed":"failed"}`,"Next: verify"]}),d}import{z as ye}from"zod";var Aa=ye.object({status:ye.enum(["PASS","FAIL"]),status_reason:ye.string().optional(),issues:ye.array(ye.string()).default([]),summary:ye.string().optional()});async function Wt(t,e,n,r,o){let i=await new S().forkSubagent({parent:{sessionId:r},config:{model:"sonnet",systemPrompt:o,apiKey:L()},idPrefix:`mint-verify-${t}`,outputSchema:Aa}),a=`Plan:
|
|
1198
1293
|
${e}
|
|
1199
1294
|
|
|
1200
1295
|
Build results:
|
|
@@ -1202,22 +1297,22 @@ ${JSON.stringify(n,null,2)}
|
|
|
1202
1297
|
|
|
1203
1298
|
Mode: ${t}
|
|
1204
1299
|
|
|
1205
|
-
Run ${t} verification on the implementation.`,l;try{l=await i.runToResult(a)}finally{await i.teardown().catch(()=>{})}if(l.status!=="succeeded"||!l.output)return{passed:!1,issues:[`${t} verification failed: ${
|
|
1300
|
+
Run ${t} verification on the implementation.`,l;try{l=await i.runToResult(a)}finally{await i.teardown().catch(()=>{})}if(l.status!=="succeeded"||!l.output)return{passed:!1,issues:[`${t} verification failed: ${I(l)}`]};let c=l.output,d=c.status==="PASS";return{passed:d,issues:d?void 0:c.issues}}async function ct(t,e,n){let o=P("mint")["verify.md"];if(!o)throw new Error("mint skill missing verify.md prompt");let[s,i,a]=await Promise.all([Wt("test",t,e,n,o),Wt("lint",t,e,n,o),Wt("design-review",t,e,n,o)]),l=[];s.issues&&l.push(...s.issues),i.issues&&l.push(...i.issues),a.issues&&l.push(...a.issues);let c={testsPassed:s.passed,lintPassed:i.passed,designReviewPassed:a.passed,...l.length>0?{issues:l}:{}},d=c.testsPassed&&c.lintPassed&&c.designReviewPassed,u=p=>p?"passed":"failed";return he({kind:d?"checkpoint":"diagnosis",title:"verify",body:[`Tests: ${u(c.testsPassed)} \xB7 Lint: ${u(c.lintPassed)}`,`Design review: ${u(c.designReviewPassed)}`,...d?["Next: ship"]:[`Issues: ${l.length} (heal loop will retry)`]]}),c}async function oo(t,e,n,r,o){if(n.testsPassed&&n.lintPassed&&n.designReviewPassed)return{healed:!0,newHealIterations:r,newVerifyResults:n};if(r>=2)return{healed:!1,newHealIterations:r,newVerifyResults:n};try{let s=z("diagnose"),i=`Verification failures:
|
|
1206
1301
|
Tests: ${n.testsPassed?"PASS":"FAIL"}
|
|
1207
1302
|
Lint: ${n.lintPassed?"PASS":"FAIL"}
|
|
1208
1303
|
Design: ${n.designReviewPassed?"PASS":"FAIL"}
|
|
1209
1304
|
Issues: ${n.issues?.join(`
|
|
1210
|
-
`)||"none"}`,a=await s.handler({failure:i,repoPath:process.cwd(),context:t}),l="";if(typeof a=="object"&&a!==null&&"winner"in a&&typeof a.winner=="object"&&a.winner!==null){let
|
|
1211
|
-
`)??"none",
|
|
1305
|
+
`)||"none"}`,a=await s.handler({failure:i,repoPath:process.cwd(),context:t}),l="";if(typeof a=="object"&&a!==null&&"winner"in a&&typeof a.winner=="object"&&a.winner!==null){let R=a.winner;typeof R.proposed_fix=="string"&&(l=R.proposed_fix)}let d=P("mint")["heal.md"];if(!d)throw new Error("mint skill missing heal.md prompt");let p=await new S().forkSubagent({parent:{sessionId:o.sessionId},config:{model:"sonnet",systemPrompt:d,apiKey:L()},idPrefix:"mint-heal"}),m=n.issues?.join(`
|
|
1306
|
+
`)??"none",f=`Plan:
|
|
1212
1307
|
${t}
|
|
1213
1308
|
|
|
1214
1309
|
Proposed fix from diagnosis:
|
|
1215
1310
|
${l}
|
|
1216
1311
|
|
|
1217
1312
|
Verification issues:
|
|
1218
|
-
${
|
|
1313
|
+
${m}
|
|
1219
1314
|
|
|
1220
|
-
Apply the fix and update the implementation.`,h=await p.runToResult(
|
|
1315
|
+
Apply the fix and update the implementation.`,h=await p.runToResult(f);if(h.status!=="succeeded"||!h.message)throw new Error(`heal phase failed: ${I(h)}`);let g=/^\s*FIX_APPLIED:\s*(true|false)/im.exec(h.message.content)?.[1]?.toLowerCase()==="true",y=r+1;if(!g)return{healed:!1,newHealIterations:y,newVerifyResults:n};if(!o.sessionId)throw new Error("Parent session ID required for verification");let b=await ct(t,e,o.sessionId);return{healed:b.testsPassed&&b.lintPassed&&b.designReviewPassed,newHealIterations:y,newVerifyResults:b}}catch{return{healed:!1,newHealIterations:r+1,newVerifyResults:n}}}async function so(t,e){let r=P("mint")["ship.md"];if(!r)throw new Error("mint skill missing ship.md prompt");let s=await new S().forkSubagent({parent:{sessionId:e},config:{model:"sonnet",systemPrompt:r,apiKey:L()},idPrefix:"mint-ship"}),i=`Idea: ${t.idea}
|
|
1221
1316
|
|
|
1222
1317
|
Specification:
|
|
1223
1318
|
${t.spec}
|
|
@@ -1231,23 +1326,23 @@ ${JSON.stringify(t.buildResults,null,2)}
|
|
|
1231
1326
|
Verification results:
|
|
1232
1327
|
${JSON.stringify(t.verifyResults,null,2)}
|
|
1233
1328
|
|
|
1234
|
-
Create a ship-ready summary with next steps.`,a=await s.runToResult(i);if(a.status!=="succeeded"||!a.message)throw new Error(`ship phase failed: ${
|
|
1329
|
+
Create a ship-ready summary with next steps.`,a=await s.runToResult(i);if(a.status!=="succeeded"||!a.message)throw new Error(`ship phase failed: ${I(a)}`);let l=t.buildResults?.filesChanged.length??0,c=t.healIterations;return he({kind:"checkpoint",title:"ship \u2014 done",body:[`Files changed: ${l}`,`Heal iterations: ${c}`,`Idea: ${t.idea}`]}),a.message.content}import{existsSync as io,mkdirSync as Pa,readFileSync as _a,unlinkSync as Ia,writeFileSync as Ra}from"fs";import{dirname as Ca,join as Ma}from"path";function qt(t){return Ma(ln(),t,"mint-state.json")}function ao(t,e){let n=qt(t);Pa(Ca(n),{recursive:!0}),Ra(n,JSON.stringify(e,null,2),"utf-8")}function Oa(t){if(typeof t!="object"||t===null)return!1;let e=t;return typeof e.currentPhase=="string"&&typeof e.idea=="string"&&typeof e.spec=="string"&&typeof e.healIterations=="number"&&Array.isArray(e.history)}function lo(t){let e=qt(t);if(!io(e))return null;try{let n=JSON.parse(_a(e,"utf-8"));return Oa(n)?n:null}catch{return null}}function zt(t){let e=qt(t);if(io(e))try{Ia(e)}catch{}}var Da=2,co=/^\s*(?:--continue(?:\s+(?:approved|yes|y))?|approved?|yes|y|lgtm)\s*$/i,Fa='To approve and run the rest of the pipeline, say "approve", "yes", or "lgtm" \u2014 or invoke /mint --continue approved. The handler will reload the spec state from disk.';function J(t,e,n){t.history.push({phase:e,output:n,timestamp:Date.now()})}var uo=240;function La(t){return t.length<=uo?t:t.slice(0,uo)+"\u2026"}function $a(t){if(typeof t=="string")return co.test(t)?{userApproved:!0}:{idea:t};if(typeof t=="object"&&t!==null){let e=t,n=typeof e.idea=="string"?e.idea:void 0;if(n!==void 0&&co.test(n))return{userApproved:!0};if("idea"in e||"resumeFrom"in e||e.userApproved===!0)return e}throw new Error("mint handler requires input.idea (string), input as string, or {userApproved: true} to resume")}async function po(t,e){if(!e.sessionId)throw new Error("runPhasesAfterSpec requires parentSession.sessionId");let n=e.sessionId;try{t.currentPhase="research",t.research=await eo(t.spec,n),J(t,"research",t.research),t.currentPhase="plan",t.plan=await to(t.spec,t.research,n),J(t,"plan",t.plan),t.currentPhase="parallelize";let r=await no(t.plan,e);if(r.kind==="plan")t.waveOrchestrationPlan=r.plan,J(t,"parallelize",JSON.stringify(r.plan));else if(r.kind==="skipped")t.waveOrchestrationPlan=void 0,J(t,"parallelize",`skipped: ${r.reason}`);else if(r.kind==="failed"){t.waveOrchestrationPlan=void 0;let i=La(r.error);J(t,"parallelize",`failed: ${i}`),ie({event:"fallback.inline",parent_session_id:n,reason:"parallelize-dispatch-failed",error_message:i}),console.warn(`[mint] parallelize dispatch failed (single-lane fallback): ${i}`)}else{let i=r}t.currentPhase="build",t.buildResults=await ro(t.plan,t.waveOrchestrationPlan,n),J(t,"build",JSON.stringify(t.buildResults)),t.currentPhase="verify",t.verifyResults=await ct(t.plan,t.buildResults,n),J(t,"verify",JSON.stringify(t.verifyResults)),t.currentPhase="heal";let o=t.verifyResults.testsPassed&&t.verifyResults.lintPassed&&t.verifyResults.designReviewPassed;for(;!o&&t.healIterations<Da;){let i=await oo(t.plan,t.buildResults,t.verifyResults,t.healIterations,e);t.healIterations=i.newHealIterations,t.verifyResults=i.newVerifyResults,o=i.healed,J(t,"heal",`Iterations: ${t.healIterations}, Success: ${o}`)}if(!o)return{paused:!0,phase:"heal-failed",reason:`Heal capped at ${t.healIterations} iterations; still have failures`,state:t,nextStep:"Heal loop exhausted. Inspect verifyResults, fix manually, then re-invoke /mint with a fresh idea \u2014 resume is not supported from heal-failed."};t.currentPhase="ship";let s=await so(t,n);return J(t,"ship",s),{completed:!0,artifact:s,state:t}}catch(r){throw new Error(`mint failed at ${t.currentPhase}: ${r}`)}}function mo(t,e){return("completed"in e||e.phase==="heal-failed")&&zt(t),e}async function Na(t,e){let n=$a(t);if(!e?.sessionId)throw new Error("mint handler requires a parent session to fork subagents");let r=e.sessionId;if(n.userApproved){let i=n.resumeFrom??lo(r);if(!i)throw new Error("mint: no paused spec found for this session to continue. Run /mint <idea> first, then /mint --continue approved.");let a=await po(i,e);return mo(r,a)}if(!n.idea)throw new Error("mint: no idea provided. Run /mint <idea> to start, or /mint --continue approved to resume a paused spec.");zt(r);let o={currentPhase:"spec",idea:n.idea,healIterations:0,history:[]};try{o.spec=await Zr(n.idea,r),J(o,"spec",o.spec)}catch(i){throw new Error(`mint failed at spec: ${i}`)}if(!n.autoApprove)return ao(r,o),{paused:!0,phase:"spec",spec:o.spec,state:o,nextStep:Fa};let s=await po(o,e);return mo(r,s)}var Ha={name:"mint",description:"Takes a feature idea or refactor scope and delivers a ship-ready, verified implementation end-to-end",handler:Na,argumentHint:"<idea> | --continue [approved]",whenToUse:"When the user wants a feature or refactor delivered end-to-end (spec \u2192 research \u2192 build \u2192 verify) in one ship-ready pass. After the spec phase pauses for approval, invoke `/mint --continue approved` (or call mint with `{userApproved: true}`) to resume \u2014 the handler reloads the spec state from disk.",flags:["--continue"]};X(Ha);import{existsSync as Ua,readdirSync as ja,readFileSync as Ba,statSync as Ka}from"fs";import{join as Ga}from"path";function Vt(t){let e=[];function n(r,o=0){if(o>10||!Ua(r))return;let s;try{s=ja(r)}catch{return}for(let i of s){if(i.startsWith("."))continue;let a=Ga(r,i),l;try{l=Ka(a)}catch{continue}if(l.isFile()&&i==="SKILL.md"){let c=Wa(a);c.name&&e.push(c)}else l.isDirectory()&&n(a,o+1)}}return n(t),e}function Wa(t){try{let e=Ba(t,"utf-8");if(!e.startsWith(`---
|
|
1235
1330
|
`))return{};let n=e.slice(4),r=n.indexOf(`
|
|
1236
1331
|
---`);if(r===-1)return{};let o=n.slice(0,r),s=n.slice(r+4).trim(),i={},a=o.split(`
|
|
1237
|
-
`);for(let l of a){if(!l)continue;let c=l.indexOf(":");if(c===-1)continue;let
|
|
1238
|
-
`)}function we(t){let e=[],n=new Set;for(let o of Pn()){let s=q(o);e.push({name:o,description:s.description,source:s.origin==="user"?"user":s.origin==="project"?"project":"builtin",argumentHint:s.argumentHint,whenToUse:s.whenToUse}),n.add(o)}let r=t??[...G(ye()),...G(),...G(yt())];for(let o of r){if(o.type!=="local")continue;let s=Rt(o.path);for(let i of s)!i.name||n.has(i.name)||(e.push({name:i.name,description:i.description??`Skill from plugin at ${o.path}`,source:"plugin"}),n.add(i.name))}return e}function Je(t){let e=new Map,n=t??[...G(ye()),...G(),...G(yt())];for(let r of n){if(r.type!=="local")continue;let o=Rt(r.path);for(let s of o)s.name&&s.body&&s.body.length>0&&e.set(s.name,s.body)}return e}var zi={opus:128e3,opus_1m:128e3,sonnet:64e3,sonnet_1m:64e3,haiku:64e3,"claude-opus-4-7":128e3,"claude-opus-4-6":128e3,"claude-sonnet-4-6":64e3,"claude-haiku-4-5-20251001":64e3},Vi=64e3;function Fr(t){return zi[t]??Vi}var qi={opus:2e5,opus_1m:1e6,sonnet:2e5,sonnet_1m:1e6,haiku:2e5},Wi=2e5;function $r(t){return qi[t]??Wi}var Yi=3,Ji="claude-haiku-4-5-20251001",Qi=1024,Xi=[{value:"claude-sonnet-4-5-20250929",displayName:"Claude Sonnet 4.5",description:"Latest balanced Claude \u2014 recommended default"},{value:"claude-opus-4-5-20250929",displayName:"Claude Opus 4.5",description:"Highest-capability Claude"},{value:"claude-haiku-4-5-20250929",displayName:"Claude Haiku 4.5",description:"Fastest, cheapest Claude"}],Ze=class{client;authMode;initSessionId;promptStream;toolDispatcher;maxTokens;tools;systemPrefix;userSystem;tokenRefresher;currentModel;currentPermissionMode;messages=[];closed=!1;abortController=null;pendingAbortReason=null;closedPromise;closeResolve=null;lastUsage=null;refreshPromise=null;constructor(e){this.client=e.client,this.authMode=e.authMode,this.initSessionId=Xe(),this.promptStream=e.promptStream,this.toolDispatcher=e.toolDispatcher,this.maxTokens=e.maxTokens,this.tools=e.tools,this.systemPrefix=e.systemPrefix,this.userSystem=e.userSystem,this.currentModel=e.model,this.currentPermissionMode=e.permissionMode??"default",this.tokenRefresher=e.tokenRefresher,this.closedPromise=new Promise(n=>{this.closeResolve=()=>n("__closed__")})}async*[Symbol.asyncIterator](){yield{type:"session.init",info:{sessionId:this.initSessionId,model:this.currentModel,permissionMode:this.currentPermissionMode,cwd:process.cwd(),tools:[],slashCommands:[],skills:[],plugins:[],mcpServers:[],apiKeySource:this.authMode,version:"anthropic-direct-v1"}};let n=this.promptStream[Symbol.asyncIterator]();try{for(;!this.closed;){let r=await Promise.race([n.next(),this.closedPromise]);if(r==="__closed__")break;let o=r;if(o.done)break;let s=o.value,i=new AbortController;if(this.abortController=i,this.pendingAbortReason!==null&&!i.signal.aborted&&(i.abort(this.pendingAbortReason),this.pendingAbortReason=null),i.signal.aborted)return;this.messages.push({role:"user",content:s.content});let a=this.composeSystem(),l=De(this.authMode,this.initSessionId,Xe()),c={client:this.client,messages:this.messages,system:a,tools:this.tools,toolDispatcher:this.toolDispatcher,model:this.currentModel,maxTokens:this.maxTokens,headers:l,signal:i.signal,ctx:{sessionId:this.initSessionId}};try{for await(let u of this.turnWithAuthRetry(c)){if(this.closed)return;u.type==="turn.completed"&&(this.lastUsage=u.usage),yield u}}catch(u){if(i.signal.aborted)return;yield{type:"error",error:u instanceof Error?u:new Error(String(u))};return}finally{this.abortController===i&&(this.abortController=null)}}}catch(r){yield{type:"error",error:r instanceof Error?r:new Error(String(r))}}finally{try{await n.return?.()}catch{}}}async*turnWithAuthRetry(e){let n=null;for await(let o of ft(e)){if(this.closed)return;if(o.type==="error"&&this.isRetryableAuth(o.error)){n=o;break}yield o}if(!n)return;let r=null;try{if(this.refreshPromise)r=await this.refreshPromise;else{this.refreshPromise=this.tokenRefresher();try{r=await this.refreshPromise??null}finally{this.refreshPromise=null}}}catch{this.refreshPromise=null}if(!r){yield n;return}this.client=r,e.client=this.client,e.headers=De(this.authMode,this.initSessionId,Xe()),yield*ft(e)}isRetryableAuth(e){return this.authMode==="oauth"&&this.tokenRefresher!==void 0&&"status"in e&&e.status===401}composeSystem(){let e=this.systemPrefix,n=this.userSystem,r=[];return e&&e.length>0&&r.push(...e),n&&n.length>0&&r.push({type:"text",text:n}),r.length===0?null:Oe()?cn(r,Fe()):r}async interrupt(){let e=this.abortController;if(e&&!e.signal.aborted){e.abort("interrupted");return}this.pendingAbortReason="interrupted"}async setModel(e){e!==void 0&&e.length>0&&(this.currentModel=e)}async setPermissionMode(e){this.currentPermissionMode=e}async supportedCommands(){try{return we().map(n=>{let r={name:n.name,description:n.description};return n.argumentHint&&(r.argumentHint=n.argumentHint),r})}catch{return[]}}async supportedModels(){return Xi.map(e=>({...e}))}async supportedAgents(){return[]}async getContextUsage(){let e=this.lastUsage,n=$r(this.currentModel),r;if(e&&n>0){let o=(e.inputTokens??0)+(e.outputTokens??0)+(e.cachedInputTokens??0)+(e.cacheCreationTokens??0);r=Math.min(100,Math.max(0,o/n*100))}return{tools:[],agents:[],isAutoCompactEnabled:!1,apiUsage:this.lastUsage,...r!==void 0?{percentage:r}:{},maxTokens:n}}async mcpServerStatus(){return[]}async accountInfo(){return{subscriptionType:this.authMode==="oauth"?"claude-subscription":"api-key"}}async rewindFiles(e,n){return{canRewind:!1,error:"anthropic-direct provider does not support file checkpoint rewind"}}async compact(){let e=this.messages.length;if(this.closed)return{compacted:!1,reason:"session-closed",messagesBefore:e,messagesAfter:e};if(this.abortController!==null)return{compacted:!1,reason:"turn-in-flight",messagesBefore:e,messagesAfter:e};let n=Zi(),r=yn(this.messages,n);if(r<=0)return{compacted:!1,reason:"history-too-short",messagesBefore:e,messagesAfter:e};let o=this.messages.slice(0,r),s=ea(),i=bn(o,s,Qi),a=new AbortController;this.abortController=a,this.pendingAbortReason!==null&&!a.signal.aborted&&(a.abort(this.pendingAbortReason),this.pendingAbortReason=null);let l;try{if(a.signal.aborted)return{compacted:!1,reason:"aborted",messagesBefore:e,messagesAfter:e};let d=De(this.authMode,this.initSessionId,Xe()),p=this.client,f=await Promise.resolve(p.messages.create(i,{headers:d,signal:a.signal}));l=await ta(f)}catch(d){return a.signal.aborted?{compacted:!1,reason:"aborted",messagesBefore:e,messagesAfter:e}:{compacted:!1,reason:"summarization-failed: "+(d instanceof Error?d.message:String(d)),messagesBefore:e,messagesAfter:e}}finally{this.abortController===a&&(this.abortController=null)}if(l.trim().length===0)return{compacted:!1,reason:"empty-summary",messagesBefore:e,messagesAfter:e};let c=wn(this.messages,r,l),u=vn(this.messages,r,l);return this.messages.splice(0,this.messages.length,...u),{compacted:!0,messagesBefore:e,messagesAfter:this.messages.length,tokensSavedEstimate:c}}close(){this.closed=!0;let e=this.abortController;e&&!e.signal.aborted?e.abort("closed"):this.pendingAbortReason="closed",this.closeResolve?.()}};function Zi(){let t=process.env.AFK_COMPACT_KEEP_LAST_TURNS;if(t!==void 0&&t.length>0){let e=Number.parseInt(t,10);if(Number.isFinite(e)&&e>0)return e}return Yi}function ea(){let t=process.env.AFK_COMPACT_MODEL;return t!==void 0&&t.length>0?t:Ji}async function ta(t){let e="";for await(let n of t)if(n.type==="content_block_delta"){let r=n.delta;r.type==="text_delta"&&typeof r.text=="string"&&(e+=r.text)}return e}function Dt(t,e){return e?.allowedTools?e.allowedTools.includes(t)?{allowed:!0}:{allowed:!1,reason:`Tool "${t}" is not in the configured allowlist`}:{allowed:!0}}var na=new Set(["agent","read_file","glob","grep","list_directory"]);function ra(t){return na.has(t)}function oa(t,e){return t.reduce((n,r,o)=>{let s=e(r.name,r.input),i=n[n.length-1];return i&&s&&i.isConcurrencySafe?i.indices.push(o):n.push({isConcurrencySafe:s,indices:[o]}),n},[])}var ke=class{handlers;schemas;hookRegistry;permissions;subagentExecutor;skillExecutor;classifier;constructor(e){this.handlers=e.handlers,this.schemas=e.schemas,this.hookRegistry=e.hookRegistry,this.permissions=e.permissions,this.subagentExecutor=e.subagentExecutor,this.skillExecutor=e.skillExecutor,this.classifier=e.concurrencyClassifier??ra}get toolDefs(){return this.schemas}async execute(e){if(e.signal.aborted)return{content:"Tool call aborted",isError:!0};if(this.hookRegistry){let s={event:"PreToolUse",toolName:e.name,input:e.input};try{await this.hookRegistry.dispatch(s,e.signal)}catch(i){if(i instanceof K)return{content:`Tool "${e.name}" blocked by PreToolUse hook: ${i.message}`,isError:!0};throw i}}let n=Dt(e.name,this.permissions);if(!n.allowed)return{content:n.reason??`Tool "${e.name}" is not permitted`,isError:!0};if(e.name==="agent"){if(!this.subagentExecutor)return{content:"Agent tool is not available in this session configuration",isError:!0};let s;try{s=await this.subagentExecutor.execute(e)}catch(i){s={content:`Agent tool error: ${i instanceof Error?i.message:String(i)}`,isError:!0}}if(this.hookRegistry){let i={event:"PostToolUse",toolName:e.name,output:s.content};try{await this.hookRegistry.dispatch(i,e.signal)}catch{}}return s}if(e.name==="skill"){if(!this.skillExecutor)return{content:"Skill tool is not available in this session configuration",isError:!0};let s;try{s=await this.skillExecutor.execute(e)}catch(i){s={content:`Skill tool error: ${i instanceof Error?i.message:String(i)}`,isError:!0}}if(this.hookRegistry){let i={event:"PostToolUse",toolName:e.name,output:s.content};try{await this.hookRegistry.dispatch(i,e.signal)}catch{}}return s}let r=this.handlers.get(e.name);if(!r)return{content:`Unknown tool "${e.name}". Available tools: ${[...this.handlers.keys()].join(", ")}`,isError:!0};let o;try{o=await r(e.input,e.signal)}catch(s){o={content:`Tool execution error: ${s instanceof Error?s.message:String(s)}`,isError:!0}}if(this.hookRegistry){let s={event:"PostToolUse",toolName:e.name,output:o.content};try{await this.hookRegistry.dispatch(s,e.signal)}catch{}}return o}async executeBatch(e){if(e.length===0)return[];if(e.length===1)return[await this.execute(e[0])];let n=new Array(e.length),r=new Set;for(let i=0;i<e.length;i++){let a=e[i];if(a.signal.aborted){n[i]={content:"Tool call aborted",isError:!0},r.add(i);continue}if(this.hookRegistry){let c={event:"PreToolUse",toolName:a.name,input:a.input};try{await this.hookRegistry.dispatch(c,a.signal)}catch(u){if(u instanceof K){n[i]={content:`Tool "${a.name}" blocked by PreToolUse hook: ${u.message}`,isError:!0},r.add(i);continue}throw u}}let l=Dt(a.name,this.permissions);l.allowed||(n[i]={content:l.reason??`Tool "${a.name}" is not permitted`,isError:!0},r.add(i))}let o=e.map((i,a)=>({call:i,originalIndex:a})).filter((i,a)=>!r.has(a));if(o.length===0)return n;let s=oa(o.map(i=>i.call),this.classifier);for(let i of s){if(e[0].signal.aborted){for(let a of i.indices){let l=o[a].originalIndex;n[l]={content:"Tool call aborted",isError:!0}}continue}if(i.isConcurrencySafe){let a=await Promise.allSettled(i.indices.map(async l=>{let{call:c,originalIndex:u}=o[l];return{result:await this.executeCore(c),originalIndex:u}}));for(let l of a)if(l.status==="fulfilled")n[l.value.originalIndex]=l.value.result;else{let c=l.reason instanceof Error?l.reason.message:String(l.reason),u=i.indices[a.indexOf(l)];n[o[u].originalIndex]={content:`Tool execution error: ${c}`,isError:!0}}}else for(let a of i.indices){let{call:l,originalIndex:c}=o[a];if(l.signal.aborted){n[c]={content:"Tool call aborted",isError:!0};continue}n[c]=await this.executeCore(l)}}return n}async executeCore(e){if(e.name==="agent"){if(!this.subagentExecutor)return{content:"Agent tool is not available in this session configuration",isError:!0};let o;try{o=await this.subagentExecutor.execute(e)}catch(s){o={content:`Agent tool error: ${s instanceof Error?s.message:String(s)}`,isError:!0}}return this.firePostToolUse(e.name,o.content,e.signal),o}if(e.name==="skill"){if(!this.skillExecutor)return{content:"Skill tool is not available in this session configuration",isError:!0};let o;try{o=await this.skillExecutor.execute(e)}catch(s){o={content:`Skill tool error: ${s instanceof Error?s.message:String(s)}`,isError:!0}}return this.firePostToolUse(e.name,o.content,e.signal),o}let n=this.handlers.get(e.name);if(!n)return{content:`Unknown tool "${e.name}". Available tools: ${[...this.handlers.keys()].join(", ")}`,isError:!0};let r;try{r=await n(e.input,e.signal)}catch(o){r={content:`Tool execution error: ${o instanceof Error?o.message:String(o)}`,isError:!0}}return this.firePostToolUse(e.name,r.content,e.signal),r}firePostToolUse(e,n,r){if(!this.hookRegistry)return;let o={event:"PostToolUse",toolName:e,output:n};this.hookRegistry.dispatch(o,r).catch(()=>{})}};import{spawn as sa}from"child_process";function ia(t){if(typeof t!="object"||t===null)throw new Error("Input must be an object");let e=t;if(typeof e.command!="string")throw new Error('Input must have a "command" field of type string');let n=12e4;if(e.timeout_ms!==void 0){if(typeof e.timeout_ms!="number")throw new Error("timeout_ms must be a number");if(e.timeout_ms<0||e.timeout_ms>6e5)throw new Error("timeout_ms must be between 0 and 600000");n=e.timeout_ms}return{command:e.command,timeout_ms:n}}function aa(t){return t.replace(/\x1b\[[0-9;]*[a-zA-Z]/g,"")}var Lr=async(t,e)=>{let{command:n,timeout_ms:r}=ia(t);return e.aborted?{content:"Command aborted",isError:!0}:new Promise(o=>{let s=!1;function i(p){s||(s=!0,clearTimeout(l),e.removeEventListener("abort",d),o(p))}let a=sa(n,{shell:!0,stdio:["ignore","pipe","pipe"]}),l=setTimeout(()=>{a.kill(),i({content:`Command timed out after ${r}ms`,isError:!0})},r),c="",u="";a.stdout.on("data",p=>{c+=p.toString()}),a.stderr.on("data",p=>{u+=p.toString()});let d=()=>{a.kill(),i({content:"Command aborted",isError:!0})};e.addEventListener("abort",d),a.on("close",()=>{let p=(c+u).trimEnd();p=aa(p);let f=1e5;p.length>f&&(p=p.slice(0,f)+`
|
|
1239
|
-
[output truncated \u2014 exceeded 100KB]`),i({content:p})}),a.on("error",p=>{i({content:`Failed to execute: ${p.message}`,isError:!0})})})};import{promises as
|
|
1240
|
-
`),
|
|
1241
|
-
`);if(p.length<
|
|
1242
|
-
... (showing lines ${
|
|
1243
|
-
`),o=0,s=0;for(let c=0;c<r.length;c++){let
|
|
1244
|
-
`)}...`}var
|
|
1245
|
-
|
|
1246
|
-
${
|
|
1332
|
+
`);for(let l of a){if(!l)continue;let c=l.indexOf(":");if(c===-1)continue;let d=l.slice(0,c).trim(),u=l.slice(c+1).trim();d==="name"?i.name=u.replace(/^["']|["']$/g,""):d==="description"?i.description=u.replace(/^["']|["']$/g,""):d==="argumentHint"&&(i.argumentHint=u.replace(/^["']|["']$/g,""))}return s.length>0&&(i.body=s),i}catch{return{}}}function fo(t){let e=Ae(t);if(e.length===0)return"";let n=[];for(let r of e){let o=r.argumentHint?`${r.argumentHint}`:"",s=o?`- \`${r.name} ${o}\`: ${r.description}`:`- ${r.name}: ${r.description}`;n.push(s),r.whenToUse&&n.push(` When to use: ${r.whenToUse}`)}return["Available skills (invoke via the `skill` tool):","","Each skill dispatches one or more context-isolated subagents internally. Calling `skill` is a delegation primitive \u2014 it preserves the main session's context. Prefer a skill over inline investigation when the task shape matches.","",...n].join(`
|
|
1333
|
+
`)}function Ae(t){let e=[],n=new Set;for(let o of lr()){let s=z(o);e.push({name:o,description:s.description,source:s.origin==="user"?"user":s.origin==="project"?"project":"builtin",argumentHint:s.argumentHint,whenToUse:s.whenToUse}),n.add(o)}let r=t??[...ee(wt()),...ee(),...ee(vt())];for(let o of r){if(o.type!=="local")continue;let s=Vt(o.path);for(let i of s)!i.name||n.has(i.name)||(e.push({name:i.name,description:i.description??`Skill from plugin at ${o.path}`,source:"plugin"}),n.add(i.name))}return e}function lt(t){let e=new Map,n=t??[...ee(wt()),...ee(),...ee(vt())];for(let r of n){if(r.type!=="local")continue;let o=Vt(r.path);for(let s of o)s.name&&s.body&&s.body.length>0&&e.set(s.name,s.body)}return e}var qa={opus:128e3,opus_1m:128e3,sonnet:64e3,sonnet_1m:64e3,haiku:64e3,"claude-opus-4-7":128e3,"claude-opus-4-6":128e3,"claude-sonnet-4-6":64e3,"claude-haiku-4-5-20251001":64e3},za=64e3;function go(t){return qa[t]??za}var Va={opus:2e5,opus_1m:1e6,sonnet:2e5,sonnet_1m:1e6,haiku:2e5},Ya=2e5;function ho(t){return Va[t]??Ya}var Ja=3,Qa="claude-haiku-4-5-20251001",Xa=1024,Za=[{value:"claude-sonnet-4-5-20250929",displayName:"Claude Sonnet 4.5",description:"Latest balanced Claude \u2014 recommended default"},{value:"claude-opus-4-5-20250929",displayName:"Claude Opus 4.5",description:"Highest-capability Claude"},{value:"claude-haiku-4-5-20250929",displayName:"Claude Haiku 4.5",description:"Fastest, cheapest Claude"}],ut=class{client;authMode;initSessionId;promptStream;toolDispatcher;maxTokens;tools;systemPrefix;userSystem;tokenRefresher;currentModel;currentPermissionMode;messages=[];closed=!1;abortController=null;pendingAbortReason=null;closedPromise;closeResolve=null;lastUsage=null;refreshPromise=null;constructor(e){this.client=e.client,this.authMode=e.authMode,this.initSessionId=dt(),this.promptStream=e.promptStream,this.toolDispatcher=e.toolDispatcher,this.maxTokens=e.maxTokens,this.tools=e.tools,this.systemPrefix=e.systemPrefix,this.userSystem=e.userSystem,this.currentModel=e.model,this.currentPermissionMode=e.permissionMode??"default",this.tokenRefresher=e.tokenRefresher,this.closedPromise=new Promise(n=>{this.closeResolve=()=>n("__closed__")})}async*[Symbol.asyncIterator](){yield{type:"session.init",info:{sessionId:this.initSessionId,model:this.currentModel,permissionMode:this.currentPermissionMode,cwd:process.cwd(),tools:[],slashCommands:[],skills:[],plugins:[],mcpServers:[],apiKeySource:this.authMode,version:"anthropic-direct-v1"}};let n=this.promptStream[Symbol.asyncIterator]();try{for(;!this.closed;){let r=await Promise.race([n.next(),this.closedPromise]);if(r==="__closed__")break;let o=r;if(o.done)break;let s=o.value,i=new AbortController;if(this.abortController=i,this.pendingAbortReason!==null&&!i.signal.aborted&&(i.abort(this.pendingAbortReason),this.pendingAbortReason=null),i.signal.aborted)return;this.messages.push({role:"user",content:s.content});let a=this.composeSystem(),l=ze(this.authMode,this.initSessionId,dt()),c={client:this.client,messages:this.messages,system:a,tools:this.tools,toolDispatcher:this.toolDispatcher,model:this.currentModel,maxTokens:this.maxTokens,headers:l,signal:i.signal,ctx:{sessionId:this.initSessionId}};try{for await(let d of this.turnWithAuthRetry(c)){if(this.closed)return;d.type==="turn.completed"&&(this.lastUsage=d.usage),yield d}}catch(d){if(i.signal.aborted)return;yield{type:"error",error:d instanceof Error?d:new Error(String(d))};return}finally{this.abortController===i&&(this.abortController=null)}}}catch(r){yield{type:"error",error:r instanceof Error?r:new Error(String(r))}}finally{try{await n.return?.()}catch{}}}async*turnWithAuthRetry(e){let n=null;for await(let o of Ft(e)){if(this.closed)return;if(o.type==="error"&&this.isRetryableAuth(o.error)){n=o;break}yield o}if(!n)return;let r=null;try{if(this.refreshPromise)r=await this.refreshPromise;else{this.refreshPromise=this.tokenRefresher();try{r=await this.refreshPromise??null}finally{this.refreshPromise=null}}}catch{this.refreshPromise=null}if(!r){yield n;return}this.client=r,e.client=this.client,e.headers=ze(this.authMode,this.initSessionId,dt()),yield*Ft(e)}isRetryableAuth(e){return this.authMode==="oauth"&&this.tokenRefresher!==void 0&&"status"in e&&e.status===401}composeSystem(){let e=this.systemPrefix,n=this.userSystem,r=[];return e&&e.length>0&&r.push(...e),n&&n.length>0&&r.push({type:"text",text:n}),r.length===0?null:Ve()?zn(r,Ye()):r}async interrupt(){let e=this.abortController;if(e&&!e.signal.aborted){e.abort("interrupted");return}this.pendingAbortReason="interrupted"}async setModel(e){e!==void 0&&e.length>0&&(this.currentModel=e)}async setPermissionMode(e){this.currentPermissionMode=e}async supportedCommands(){try{return Ae().map(n=>{let r={name:n.name,description:n.description};return n.argumentHint&&(r.argumentHint=n.argumentHint),r})}catch{return[]}}async supportedModels(){return Za.map(e=>({...e}))}async supportedAgents(){return[]}async getContextUsage(){let e=this.lastUsage,n=ho(this.currentModel),r;if(e&&n>0){let o=(e.inputTokens??0)+(e.outputTokens??0)+(e.cachedInputTokens??0)+(e.cacheCreationTokens??0);r=Math.min(100,Math.max(0,o/n*100))}return{tools:[],agents:[],isAutoCompactEnabled:!1,apiUsage:this.lastUsage,...r!==void 0?{percentage:r}:{},maxTokens:n}}async mcpServerStatus(){return[]}async accountInfo(){return{subscriptionType:this.authMode==="oauth"?"claude-subscription":"api-key"}}async rewindFiles(e,n){return{canRewind:!1,error:"anthropic-direct provider does not support file checkpoint rewind"}}async compact(){let e=this.messages.length;if(this.closed)return{compacted:!1,reason:"session-closed",messagesBefore:e,messagesAfter:e};if(this.abortController!==null)return{compacted:!1,reason:"turn-in-flight",messagesBefore:e,messagesAfter:e};let n=el(),r=tr(this.messages,n);if(r<=0)return{compacted:!1,reason:"history-too-short",messagesBefore:e,messagesAfter:e};let o=this.messages.slice(0,r),s=tl(),i=nr(o,s,Xa),a=new AbortController;this.abortController=a,this.pendingAbortReason!==null&&!a.signal.aborted&&(a.abort(this.pendingAbortReason),this.pendingAbortReason=null);let l;try{if(a.signal.aborted)return{compacted:!1,reason:"aborted",messagesBefore:e,messagesAfter:e};let u=ze(this.authMode,this.initSessionId,dt()),p=this.client,m=await Promise.resolve(p.messages.create(i,{headers:u,signal:a.signal}));l=await nl(m)}catch(u){return a.signal.aborted?{compacted:!1,reason:"aborted",messagesBefore:e,messagesAfter:e}:{compacted:!1,reason:"summarization-failed: "+(u instanceof Error?u.message:String(u)),messagesBefore:e,messagesAfter:e}}finally{this.abortController===a&&(this.abortController=null)}if(l.trim().length===0)return{compacted:!1,reason:"empty-summary",messagesBefore:e,messagesAfter:e};let c=or(this.messages,r,l),d=rr(this.messages,r,l);return this.messages.splice(0,this.messages.length,...d),{compacted:!0,messagesBefore:e,messagesAfter:this.messages.length,tokensSavedEstimate:c}}close(){this.closed=!0;let e=this.abortController;e&&!e.signal.aborted?e.abort("closed"):this.pendingAbortReason="closed",this.closeResolve?.()}};function el(){let t=process.env.AFK_COMPACT_KEEP_LAST_TURNS;if(t!==void 0&&t.length>0){let e=Number.parseInt(t,10);if(Number.isFinite(e)&&e>0)return e}return Ja}function tl(){let t=process.env.AFK_COMPACT_MODEL;return t!==void 0&&t.length>0?t:Qa}async function nl(t){let e="";for await(let n of t)if(n.type==="content_block_delta"){let r=n.delta;r.type==="text_delta"&&typeof r.text=="string"&&(e+=r.text)}return e}function Yt(t,e){return e?.allowedTools?e.allowedTools.includes(t)?{allowed:!0}:{allowed:!1,reason:`Tool "${t}" is not in the configured allowlist`}:{allowed:!0}}var rl=new Set(["agent","read_file","glob","grep","list_directory","memory_search"]);function ol(t){return rl.has(t)}function sl(t,e){return t.reduce((n,r,o)=>{let s=e(r.name,r.input),i=n[n.length-1];return i&&s&&i.isConcurrencySafe?i.indices.push(o):n.push({isConcurrencySafe:s,indices:[o]}),n},[])}var Pe=class{handlers;schemas;hookRegistry;permissions;subagentExecutor;skillExecutor;classifier;constructor(e){this.handlers=e.handlers,this.schemas=e.schemas,this.hookRegistry=e.hookRegistry,this.permissions=e.permissions,this.subagentExecutor=e.subagentExecutor,this.skillExecutor=e.skillExecutor,this.classifier=e.concurrencyClassifier??ol}get toolDefs(){return this.schemas}async execute(e){if(e.signal.aborted)return{content:"Tool call aborted",isError:!0};if(this.hookRegistry){let s={event:"PreToolUse",toolName:e.name,input:e.input};try{await this.hookRegistry.dispatch(s,e.signal)}catch(i){if(i instanceof W)return{content:`Tool "${e.name}" blocked by PreToolUse hook: ${i.message}`,isError:!0};throw i}}let n=Yt(e.name,this.permissions);if(!n.allowed)return{content:n.reason??`Tool "${e.name}" is not permitted`,isError:!0};if(e.name==="agent"){if(!this.subagentExecutor)return{content:"Agent tool is not available in this session configuration",isError:!0};let s;try{s=await this.subagentExecutor.execute(e)}catch(i){s={content:`Agent tool error: ${i instanceof Error?i.message:String(i)}`,isError:!0}}if(this.hookRegistry){let i={event:"PostToolUse",toolName:e.name,output:s.content};try{await this.hookRegistry.dispatch(i,e.signal)}catch{}}return s}if(e.name==="skill"){if(!this.skillExecutor)return{content:"Skill tool is not available in this session configuration",isError:!0};let s;try{s=await this.skillExecutor.execute(e)}catch(i){s={content:`Skill tool error: ${i instanceof Error?i.message:String(i)}`,isError:!0}}if(this.hookRegistry){let i={event:"PostToolUse",toolName:e.name,output:s.content};try{await this.hookRegistry.dispatch(i,e.signal)}catch{}}return s}let r=this.handlers.get(e.name);if(!r)return{content:`Unknown tool "${e.name}". Available tools: ${[...this.handlers.keys()].join(", ")}`,isError:!0};let o;try{o=await r(e.input,e.signal)}catch(s){o={content:`Tool execution error: ${s instanceof Error?s.message:String(s)}`,isError:!0}}if(this.hookRegistry){let s={event:"PostToolUse",toolName:e.name,output:o.content};try{await this.hookRegistry.dispatch(s,e.signal)}catch{}}return o}async executeBatch(e){if(e.length===0)return[];if(e.length===1)return[await this.execute(e[0])];let n=new Array(e.length),r=new Set;for(let i=0;i<e.length;i++){let a=e[i];if(a.signal.aborted){n[i]={content:"Tool call aborted",isError:!0},r.add(i);continue}if(this.hookRegistry){let c={event:"PreToolUse",toolName:a.name,input:a.input};try{await this.hookRegistry.dispatch(c,a.signal)}catch(d){if(d instanceof W){n[i]={content:`Tool "${a.name}" blocked by PreToolUse hook: ${d.message}`,isError:!0},r.add(i);continue}throw d}}let l=Yt(a.name,this.permissions);l.allowed||(n[i]={content:l.reason??`Tool "${a.name}" is not permitted`,isError:!0},r.add(i))}let o=e.map((i,a)=>({call:i,originalIndex:a})).filter((i,a)=>!r.has(a));if(o.length===0)return n;let s=sl(o.map(i=>i.call),this.classifier);for(let i of s){if(e[0].signal.aborted){for(let a of i.indices){let l=o[a].originalIndex;n[l]={content:"Tool call aborted",isError:!0}}continue}if(i.isConcurrencySafe){let a=await Promise.allSettled(i.indices.map(async l=>{let{call:c,originalIndex:d}=o[l];return{result:await this.executeCore(c),originalIndex:d}}));for(let l of a)if(l.status==="fulfilled")n[l.value.originalIndex]=l.value.result;else{let c=l.reason instanceof Error?l.reason.message:String(l.reason),d=i.indices[a.indexOf(l)];n[o[d].originalIndex]={content:`Tool execution error: ${c}`,isError:!0}}}else for(let a of i.indices){let{call:l,originalIndex:c}=o[a];if(l.signal.aborted){n[c]={content:"Tool call aborted",isError:!0};continue}n[c]=await this.executeCore(l)}}return n}async executeCore(e){if(e.name==="agent"){if(!this.subagentExecutor)return{content:"Agent tool is not available in this session configuration",isError:!0};let o;try{o=await this.subagentExecutor.execute(e)}catch(s){o={content:`Agent tool error: ${s instanceof Error?s.message:String(s)}`,isError:!0}}return this.firePostToolUse(e.name,o.content,e.signal),o}if(e.name==="skill"){if(!this.skillExecutor)return{content:"Skill tool is not available in this session configuration",isError:!0};let o;try{o=await this.skillExecutor.execute(e)}catch(s){o={content:`Skill tool error: ${s instanceof Error?s.message:String(s)}`,isError:!0}}return this.firePostToolUse(e.name,o.content,e.signal),o}let n=this.handlers.get(e.name);if(!n)return{content:`Unknown tool "${e.name}". Available tools: ${[...this.handlers.keys()].join(", ")}`,isError:!0};let r;try{r=await n(e.input,e.signal)}catch(o){r={content:`Tool execution error: ${o instanceof Error?o.message:String(o)}`,isError:!0}}return this.firePostToolUse(e.name,r.content,e.signal),r}firePostToolUse(e,n,r){if(!this.hookRegistry)return;let o={event:"PostToolUse",toolName:e,output:n};this.hookRegistry.dispatch(o,r).catch(()=>{})}};import{spawn as il}from"child_process";function al(t){if(typeof t!="object"||t===null)throw new Error("Input must be an object");let e=t;if(typeof e.command!="string")throw new Error('Input must have a "command" field of type string');let n=12e4;if(e.timeout_ms!==void 0){if(typeof e.timeout_ms!="number")throw new Error("timeout_ms must be a number");if(e.timeout_ms<0||e.timeout_ms>6e5)throw new Error("timeout_ms must be between 0 and 600000");n=e.timeout_ms}return{command:e.command,timeout_ms:n}}function ll(t){return t.replace(/\x1b\[[0-9;]*[a-zA-Z]/g,"")}var yo=async(t,e)=>{let{command:n,timeout_ms:r}=al(t);return e.aborted?{content:"Command aborted",isError:!0}:new Promise(o=>{let s=!1;function i(p){s||(s=!0,clearTimeout(l),e.removeEventListener("abort",u),o(p))}let a=il(n,{shell:!0,stdio:["ignore","pipe","pipe"]}),l=setTimeout(()=>{a.kill(),i({content:`Command timed out after ${r}ms`,isError:!0})},r),c="",d="";a.stdout.on("data",p=>{c+=p.toString()}),a.stderr.on("data",p=>{d+=p.toString()});let u=()=>{a.kill(),i({content:"Command aborted",isError:!0})};e.addEventListener("abort",u),a.on("close",()=>{let p=(c+d).trimEnd();p=ll(p);let m=1e5;p.length>m&&(p=p.slice(0,m)+`
|
|
1334
|
+
[output truncated \u2014 exceeded 100KB]`),i({content:p})}),a.on("error",p=>{i({content:`Failed to execute: ${p.message}`,isError:!0})})})};import{promises as cl}from"fs";var bo=async(t,e)=>{if(!t||typeof t!="object")return{content:"Invalid input: expected an object",isError:!0};let n=t,r=n.file_path,o=n.offset??1,s=n.limit??2e3;if(typeof r!="string")return{content:"Invalid input: file_path must be a string",isError:!0};if(typeof o!="number"||o<1)return{content:"Invalid input: offset must be a positive number",isError:!0};if(typeof s!="number"||s<1)return{content:"Invalid input: limit must be a positive number",isError:!0};try{let i=await cl.readFile(r),a=Math.min(8192,i.length);for(let g=0;g<a;g++)if(i[g]===0)return{content:`File appears to be binary: ${r}`,isError:!0};let l=i.toString("utf-8");if(l.length===0)return{content:""};let c=l.split(`
|
|
1335
|
+
`),d=Math.max(0,o-1),u=Math.min(c.length,d+s),p=c.slice(d,u),m=c.length;if(p.length===0)return{content:`... (offset ${o} is past end of file \u2014 file has ${m} lines)`};let f=String(m).length,h=p.map((g,y)=>{let b=d+y+1;return`${String(b).padStart(f," ")} ${g}`}).join(`
|
|
1336
|
+
`);if(p.length<m){let g=d+1,y=d+p.length,b=y<m?` \u2014 pass offset=${y+1} to continue`:"";return{content:`${h}
|
|
1337
|
+
... (showing lines ${g}-${y} of ${m}${b})`}}return{content:h}}catch(i){if(i instanceof Error){let a=i;return a.code==="ENOENT"?{content:`File not found: ${r}`,isError:!0}:a.code==="EACCES"?{content:`Permission denied: ${r}`,isError:!0}:{content:`Error reading file: ${i.message}`,isError:!0}}return{content:"Unknown error reading file",isError:!0}}};import{writeFile as dl}from"fs/promises";import{mkdir as ul}from"fs/promises";import{dirname as pl}from"path";function ml(t){if(typeof t!="object"||t===null)throw new Error("Input must be an object");let e=t;if(typeof e.file_path!="string")throw new Error('Input must have a "file_path" field of type string');if(typeof e.content!="string")throw new Error('Input must have a "content" field of type string');return{file_path:e.file_path,content:e.content}}var wo=async(t,e)=>{if(e.aborted)return{content:"Aborted",isError:!0};let{file_path:n,content:r}=ml(t);try{let o=pl(n);return await ul(o,{recursive:!0}),await dl(n,r,{signal:e}),{content:`Wrote ${Buffer.byteLength(r,"utf8")} bytes to ${n}`}}catch(o){return o instanceof Error?"code"in o&&o.code==="EACCES"?{content:`Permission denied: ${n}`,isError:!0}:{content:`Error writing file: ${o.message}`,isError:!0}:{content:"Unknown error writing file",isError:!0}}};import{readFile as fl,writeFile as gl}from"fs/promises";function hl(t){if(typeof t!="object"||t===null)throw new Error("Input must be an object");let e=t;if(typeof e.file_path!="string")throw new Error('Input must have a "file_path" field of type string');if(typeof e.old_string!="string")throw new Error('Input must have an "old_string" field of type string');if(typeof e.new_string!="string")throw new Error('Input must have a "new_string" field of type string');let n=!1;if(e.replace_all!==void 0){if(typeof e.replace_all!="boolean")throw new Error("replace_all must be a boolean");n=e.replace_all}return{file_path:e.file_path,old_string:e.old_string,new_string:e.new_string,replace_all:n}}function yl(t,e){if(e.length===0)return 0;let n=0,r=0;for(;(r=t.indexOf(e,r))!==-1;)n++,r+=e.length;return n}function bl(t,e,n){let r=t.split(`
|
|
1338
|
+
`),o=0,s=0;for(let c=0;c<r.length;c++){let d=r[c]?.length??0,u=o+d+1;if(o+d>=n+e.length){s=c;break}o=u}let i=Math.max(0,s-2),a=Math.min(r.length,s+3);return`...${r.slice(i,a).join(`
|
|
1339
|
+
`)}...`}var vo=async(t,e)=>{if(e.aborted)return{content:"Aborted",isError:!0};let{file_path:n,old_string:r,new_string:o,replace_all:s}=hl(t);try{let i=await fl(n,"utf-8"),a=yl(i,r);if(a===0)return{content:`old_string not found in ${n}`,isError:!0};if(a>1&&!s)return{content:`old_string matches ${a} locations in ${n}. Use replace_all: true or provide more context.`,isError:!0};let l,c;s?(l=i.split(r).join(o),c=i.indexOf(r)):(c=i.indexOf(r),l=i.slice(0,c)+o+i.slice(c+r.length)),await gl(n,l,"utf-8");let d=bl(i,r,c);return{content:`${a===1?`Replaced 1 occurrence in ${n}`:`Replaced ${a} occurrences in ${n}`}
|
|
1340
|
+
|
|
1341
|
+
${d}`}}catch(i){return{content:`Error: ${i instanceof Error?i.message:String(i)}`,isError:!0}}};import{promises as So}from"fs";import wl from"path";function vl(t,e){let n=t.replace(/\\/g,"/"),r=e.replace(/\\/g,"/");if(r.includes("**")){let s=r.split("**"),i=0;for(let a=0;a<s.length;a++){let l=s[a]??"",c=ko(l);if(a===0){let d=n.match(new RegExp(`^${c}`));if(!d)return!1;i=d[0].length}else if(a===s.length-1){let d=new RegExp(`${c}$`);if(!n.slice(i).match(d))return!1}else{let d=new RegExp(c),u=n.slice(i).match(d);if(!u)return!1;let p=u.index??0;i+=p+u[0].length}}return!0}return new RegExp(`^${ko(r)}$`).test(n)}function ko(t){return t.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,"[^/]*").replace(/\?/g,"[^/]")}async function kl(t,e){let n=[];async function o(s,i){if(n.length>=500)return!0;try{let a=await So.readdir(s,{withFileTypes:!0});for(let l of a){if(n.length>=500)return!0;let c=wl.join(s,l.name),d=i?`${i}/${l.name}`:l.name;if(vl(d,e)&&n.push(d),l.isDirectory()&&await o(c,d))return!0}}catch{}return!1}return await o(t,""),n}var xo=async(t,e)=>{if(!t||typeof t!="object")return{content:"Invalid input: expected an object",isError:!0};let n=t,r=n.pattern,o=n.path??process.cwd();if(typeof r!="string")return{content:"Invalid input: pattern must be a string",isError:!0};if(r.trim()==="")return{content:"Invalid input: pattern cannot be empty",isError:!0};if(typeof o!="string")return{content:"Invalid input: path must be a string",isError:!0};try{if(!(await So.stat(o)).isDirectory())return{content:`Invalid input: path is not a directory: ${o}`,isError:!0};let i=await kl(o,r);if(i.length===0)return{content:`No files matched pattern '${r}' in ${o}`};let a=i.join(`
|
|
1247
1342
|
`);return i.length>=500&&(a+=`
|
|
1248
|
-
[results capped at 500 entries]`),{content:a}}catch(s){return s instanceof Error?"code"in s&&s.code==="ENOENT"?{content:`Path not found: ${o}`,isError:!0}:"code"in s&&s.code==="EACCES"?{content:`Permission denied: ${o}`,isError:!0}:{content:`Error scanning directory: ${s.message}`,isError:!0}:{content:"Unknown error scanning directory",isError:!0}}};import{spawn as
|
|
1249
|
-
[output truncated]`),a({content:
|
|
1250
|
-
`)}}catch(o){if(o instanceof Error){let s=o;return s.code==="ENOENT"?{content:`Directory not found: ${r}`,isError:!0}:s.code==="ENOTDIR"?{content:`Not a directory: ${r}`,isError:!0}:s.code==="EACCES"?{content:`Permission denied: ${r}`,isError:!0}:{content:`Error listing directory: ${o.message}`,isError:!0}}return{content:"Unknown error listing directory",isError:!0}}};function
|
|
1343
|
+
[results capped at 500 entries]`),{content:a}}catch(s){return s instanceof Error?"code"in s&&s.code==="ENOENT"?{content:`Path not found: ${o}`,isError:!0}:"code"in s&&s.code==="EACCES"?{content:`Permission denied: ${o}`,isError:!0}:{content:`Error scanning directory: ${s.message}`,isError:!0}:{content:"Unknown error scanning directory",isError:!0}}};import{spawn as Sl}from"child_process";function xl(t){if(typeof t!="object"||t===null)throw new Error("Input must be an object");let e=t;if(typeof e.pattern!="string")throw new Error('Input must have a "pattern" field of type string');let n=typeof e.path=="string"?e.path:process.cwd(),r;if(e.include!==void 0){if(typeof e.include!="string")throw new Error("include must be a string");r=e.include}return{pattern:e.pattern,path:n,include:r}}function El(t){return t.replace(/\x1b\[[0-9;]*[a-zA-Z]/g,"")}var Eo=async(t,e)=>{let{pattern:n,path:r,include:o}=xl(t);return e.aborted?{content:"Search aborted",isError:!0}:new Promise(s=>{let i=!1;function a(m){i||(i=!0,e.removeEventListener("abort",p),s(m))}let l=["-rn"];o&&l.push(`--include=${o}`),l.push(n,r);let c=Sl("grep",l),d="",u="";c.stdout.on("data",m=>{d+=m.toString()}),c.stderr.on("data",m=>{u+=m.toString()});let p=()=>{c.kill(),a({content:"Search aborted",isError:!0})};e.addEventListener("abort",p),c.on("close",m=>{if(m===1){a({content:`No matches found for '${n}' in ${r}`});return}if(m===2){a({content:`grep error: ${u.trim()}`,isError:!0});return}let f=d.trimEnd();f=El(f);let h=1e5;f.length>h&&(f=f.slice(0,h)+`
|
|
1344
|
+
[output truncated]`),a({content:f})}),c.on("error",m=>{a({content:`Failed to execute grep: ${m.message}`,isError:!0})})})};import{promises as Tl}from"fs";var To=async(t,e)=>{if(!t||typeof t!="object")throw new Error("Invalid input: expected an object");let r=t.path;if(typeof r!="string")throw new Error("Invalid input: path must be a string");try{let o=await Tl.readdir(r,{withFileTypes:!0}),s=o.filter(c=>c.isDirectory()).map(c=>`${c.name}/`),i=o.filter(c=>!c.isDirectory()).map(c=>c.name);s.sort(),i.sort();let a=[...s,...i];return a.length===0?{content:"(empty directory)"}:{content:a.join(`
|
|
1345
|
+
`)}}catch(o){if(o instanceof Error){let s=o;return s.code==="ENOENT"?{content:`Directory not found: ${r}`,isError:!0}:s.code==="ENOTDIR"?{content:`Not a directory: ${r}`,isError:!0}:s.code==="EACCES"?{content:`Permission denied: ${r}`,isError:!0}:{content:`Error listing directory: ${o.message}`,isError:!0}}return{content:"Unknown error listing directory",isError:!0}}};function Ao(){return new Map([["bash",yo],["read_file",bo],["write_file",wo],["edit_file",vo],["glob",xo],["grep",Eo],["list_directory",To]])}var Po=`You have access to tools for working with the filesystem and running commands. Follow these conventions:
|
|
1251
1346
|
|
|
1252
1347
|
- Use read_file before editing to verify the exact content you want to change.
|
|
1253
1348
|
- Prefer edit_file over write_file for modifying existing files \u2014 write_file is for new files or complete rewrites.
|
|
@@ -1256,29 +1351,35 @@ ${u}`}}catch(i){return{content:`Error: ${i instanceof Error?i.message:String(i)}
|
|
|
1256
1351
|
- Use glob and grep to discover files before reading individual files.
|
|
1257
1352
|
- When bash output is very long, it may be truncated. If you need the full output, redirect to a file and read it.
|
|
1258
1353
|
- Use absolute paths for file operations.
|
|
1354
|
+
- Prefer \`agent\` (and \`skill\`) for multi-file investigation, verification, parallel hypotheses, and any work that would otherwise consume large amounts of inline context. The main session is the coordinator; subagents are the investigators.
|
|
1259
1355
|
|
|
1260
|
-
When you see a \`<command-name>\` tag in the current conversation turn, the skill has ALREADY been loaded by the user typing a slash command. Do NOT re-invoke the skill tool to dispatch the same skill again. Instead, treat the \`<command-message>\` as the skill name and \`<command-args>\` as its arguments, then follow the instructions in the body block immediately following the tag.`;
|
|
1261
|
-
-
|
|
1356
|
+
When you see a \`<command-name>\` tag in the current conversation turn, the skill has ALREADY been loaded by the user typing a slash command. Do NOT re-invoke the skill tool to dispatch the same skill again. Instead, treat the \`<command-message>\` as the skill name and \`<command-args>\` as its arguments, then follow the instructions in the body block immediately following the tag.`;import{mkdirSync as Al,appendFileSync as Pl,existsSync as _l}from"fs";import{resolve as Il}from"path";import{dirname as Rl}from"path";var Cl=`# AFK PROMPT DUMP \u2014 May contain secrets. Inspect before sharing.
|
|
1357
|
+
`,Ml=/key|token|secret|password|credential|auth/i,Ol=[[/sk-ant-[A-Za-z0-9_\-]{8,200}/g,t=>`<REDACTED sk-ant length=${t[0].length}>`],[/Bearer\s+[A-Za-z0-9\-._~+/]+=*/gi,t=>`<REDACTED Bearer length=${t[0].length}>`],[/AKIA[A-Z0-9]{16}/g,t=>`<REDACTED AKIA length=${t[0].length}>`],[/xox[baprs]-[A-Za-z0-9\-]{10,200}/g,t=>`<REDACTED xox token length=${t[0].length}>`],[/([A-Z_]{3,}(?:KEY|TOKEN|SECRET|PASSWORD|CREDENTIAL|AUTH)[A-Z_]*)=([^\s]{16,})/g,t=>`${t[1]??""}=<REDACTED length=${(t[2]??"").length}>`]];function Dl(t){let e=t;for(let[n,r]of Ol)e=e.replace(n,(...o)=>{let s=o.slice(0,o.length-2);return r(s)});return e}function Jt(t){return typeof t=="string"?Dl(t):Array.isArray(t)?t.map(Jt):t}function Fl(t){if(t===null||typeof t!="object")return t;let e=t,n={...e},r=e.env;if(r&&typeof r=="object"){let o={};for(let[s,i]of Object.entries(r))Ml.test(s)&&typeof i=="string"?o[s]=`<REDACTED length=${i.length}>`:o[s]=i;n.env=o}return"system"in e&&(n.system=Jt(e.system)),"systemPrompt"in e&&(n.systemPrompt=Jt(e.systemPrompt)),n}function Ll(t){if(t==null)return{kind:"undefined",note:"SDK uses minimal prompt; claude_code preset NOT loaded"};if(typeof t=="string")return{kind:"custom-string",note:"SDK uses this string as full system prompt; claude_code preset NOT loaded"};if(Array.isArray(t))return{kind:"custom-string-array",note:"SDK uses array as full system prompt with cache boundaries; claude_code preset NOT loaded"};if(typeof t=="object"){let e=t;if(e.type==="preset"&&e.preset==="claude_code"){let n={kind:"preset-claude-code",note:"claude_code preset loaded"};return typeof e.append=="string"&&(n.append={length:e.append.length}),e.excludeDynamicSections===!0&&(n.excludeDynamicSections=!0),n}return{kind:"custom-string",note:"Unrecognized systemPrompt shape; treated as opaque"}}return{kind:"custom-string",note:"Unrecognized systemPrompt shape; treated as opaque"}}function _o(t){let e=process.env.AFK_DUMP_PROMPT;if(!e||e===""||e==="0"||e.toLowerCase()==="false")return;process.stderr.write(`[--dump-prompt] WARNING: dump may contain secrets from system prompt or messages. Inspect before sharing.
|
|
1358
|
+
`);let n=t.options,r=typeof n=="object"&&n!==null?n.systemPrompt:void 0,o=Ll(r),s={timestamp:new Date().toISOString(),prompt:t.prompt,options:Fl(t.options),provenance:t.provenance,resolution:o};if(e==="1"||e.toLowerCase()==="true"||e.toLowerCase()==="stderr"){let l=JSON.stringify(s,null,2)+`
|
|
1359
|
+
`;process.stderr.write(l);return}let i=Il(e),a=Rl(i);try{Al(a,{recursive:!0});let c=(!_l(i)?Cl:"")+JSON.stringify(s)+`
|
|
1360
|
+
`;Pl(i,c)}catch(l){let c=`[prompt-dump] Failed to write to ${i}: ${String(l)}
|
|
1361
|
+
`;process.stderr.write(c)}}var Ro="anthropic-direct",$l="claude-sonnet-4-5-20250929",Co=null;var re=class{name=Ro;tools;memoryStore;providerFactory;skillExecutor;constructor(e={}){let n=[...st];e.subagentExecutor&&n.push(Gr),e.skillExecutor&&n.push(Wr),n.push(...Tt);let r=Ao();this.memoryStore=e.memoryStore??new Q;let o=At(this.memoryStore,void 0,e.surface??"cli");for(let[s,i]of o)r.set(s,i);this.tools=e.tools??new Pe({handlers:r,schemas:n,hookRegistry:e.hookRegistry,permissions:e.permissions,subagentExecutor:e.subagentExecutor,skillExecutor:e.skillExecutor}),this.skillExecutor=e.skillExecutor,e.clientFactory&&(this.providerFactory=e.clientFactory)}close(){this.memoryStore.close()}query(e){let n=e.config,r=n.apiKey&&n.apiKey.length>0?n.apiKey:process.env.ANTHROPIC_API_KEY||process.env.CLAUDE_CODE_OAUTH_TOKEN||"";if(!r||r.length===0)throw new Error(`${Ro} provider requires config.apiKey (resolved from ANTHROPIC_API_KEY or CLAUDE_CODE_OAUTH_TOKEN)`);let o=qe(r),s=Dt(r,o),i=this.providerFactory??Co,a=i?i(s):new Io(s),l=Nn(o),c=Nl(n.systemPrompt),d=typeof n.model=="string"&&n.model.length>0?ue(n.model)??n.model:$l,u=Hl(n,d),p=this.tools instanceof Pe?[...this.tools.toolDefs]:[...st],m=this.skillExecutor?fo():"",f=n.cwd||process.cwd(),h=[Po];h.push(`# Environment
|
|
1362
|
+
- Working directory: ${f}`),m.length>0&&h.push(m),c&&h.push(c);let g=h.join(`
|
|
1262
1363
|
|
|
1263
|
-
`),
|
|
1364
|
+
`);_o({prompt:e.prompt,options:{model:d,maxTokens:u,system:g},provenance:{systemPrompt:{source:n.systemPromptSource??"none",shape:typeof n.systemPrompt=="string"?"string":Array.isArray(n.systemPrompt)?"string[]":n.systemPrompt!=null?"preset":"undefined",...typeof n.systemPrompt=="string"?{length:n.systemPrompt.length}:{}},...n.apiKey?{apiKey:{source:"config"}}:{}}});let y;if(o==="oauth"){let b=this.providerFactory??Co;y=async()=>{let R=await Gn();if(!R)return null;let U=Dt(R,"oauth");return b?b(U):new Io(U)}}return new ut({client:a,authMode:o,promptStream:e.prompt,toolDispatcher:this.tools,model:d,...n.permissionMode!==void 0?{permissionMode:n.permissionMode}:{},maxTokens:u,tools:p,userSystem:g,systemPrefix:l,tokenRefresher:y})}};function Nl(t){if(t===void 0)return null;if(typeof t=="string")return t.length>0?t:null;if(typeof t=="object"&&t!==null&&"append"in t){let e=t.append;return e&&e.length>0?e:null}return null}function Hl(t,e){let n=t.maxOutputTokens;return typeof n=="number"&&Number.isFinite(n)&&n>0?Math.floor(n):go(e)}var Mo=new re;import{Codex as Do}from"@openai/codex-sdk";import{mkdtempSync as Ul,rmSync as jl,writeFileSync as Bl}from"node:fs";import{tmpdir as Kl}from"node:os";import{join as Oo}from"node:path";var _e="openai-codex",Gl=[{value:"gpt-5.4",displayName:"GPT-5.4",description:"Codex default"},{value:"gpt-5.4-mini",displayName:"GPT-5.4 mini",description:"Faster, cheaper Codex variant"}];function Wl(t){let e=[];if(t.continue&&e.push("continue"),t.resumeSessionAt!==void 0&&e.push("resumeSessionAt"),t.forkSession&&e.push("forkSession"),t.persistSession===!1&&e.push("persistSession=false"),t.enableFileCheckpointing&&e.push("enableFileCheckpointing"),t.thinking!==void 0&&e.push("thinking"),t.maxBudgetUsd!==void 0&&e.push("maxBudgetUsd"),t.taskBudget!==void 0&&e.push("taskBudget"),t.plugins&&t.plugins.length>0&&e.push("plugins"),t.agents&&e.push("agents"),t.agent!==void 0&&e.push("agent"),t.onElicitation&&e.push("onElicitation"),t.hooks&&e.push("hooks"),t.canUseTool&&e.push("canUseTool"),t.mcpServers&&e.push("mcpServers"),t.includeHookEvents&&e.push("includeHookEvents"),t.agentProgressSummaries&&e.push("agentProgressSummaries"),t.includePartialMessages&&e.push("includePartialMessages"),e.length>0)throw new Se(_e,e.join(", "),`${_e} provider does not support AgentConfig fields: ${e.join(", ")}`)}function Fo(t){return t==="plan"?{sandboxMode:"read-only",approvalPolicy:"untrusted"}:{sandboxMode:"workspace-write",approvalPolicy:"never"}}function ql(t){if(t)switch(t){case"minimal":case"low":case"medium":case"high":case"xhigh":return t;case"max":return"xhigh";default:return}}function zl(t){let e=t.systemPrompt;if(e!==void 0){if(typeof e=="string")return e.length>0?e:void 0;if(typeof e=="object"&&e!==null&&"append"in e){let n=e.append;return n&&n.length>0?n:void 0}}}function Vl(t){let e=Ul(Oo(Kl(),"afk-codex-instr-")),n=Oo(e,"instructions.md");return Bl(n,t,"utf-8"),{path:n,dispose:()=>{try{jl(e,{recursive:!0,force:!0})}catch{}}}}function Yl(t){if(t.apiKey)return t.apiKey;let e=process.env.OPENAI_API_KEY??process.env.CODEX_API_KEY;return e&&e.length>0?e:void 0}function*Jl(t,e,n,r){if(t.type!=="thread.started"&&t.type!=="turn.started"){if(t.type==="turn.completed"){let o=t.usage;yield{type:"turn.completed",usage:{inputTokens:o.input_tokens,outputTokens:o.output_tokens,cachedInputTokens:o.cached_input_tokens,totalTokens:o.input_tokens+o.output_tokens+o.cached_input_tokens,resultSubtype:"success",isError:!1,raw:{input_tokens:o.input_tokens,output_tokens:o.output_tokens,cached_input_tokens:o.cached_input_tokens}},...e!==void 0?{sessionId:e}:{}};return}if(t.type==="turn.failed"){yield{type:"error",error:new Error(t.error.message)};return}if(t.type==="error"){yield{type:"error",error:new Error(t.message)};return}(t.type==="item.started"||t.type==="item.updated"||t.type==="item.completed")&&(yield*Ql(t.item,t.type==="item.completed",e,n,r))}}function*Ql(t,e,n,r,o){if(t.type==="agent_message"){let s=r.get(t.id)??"";if(t.text!==s){let i=t.text.startsWith(s)?t.text.slice(s.length):t.text;r.set(t.id,t.text),i.length>0&&(yield{type:"delta.text",text:i,...n!==void 0?{sessionId:n}:{}})}e&&(yield{type:"assistant.message",text:t.text,...n!==void 0?{sessionId:n}:{}},r.delete(t.id));return}if(t.type==="reasoning"){let s=o.get(t.id)??"";if(t.text!==s){let i=t.text.startsWith(s)?t.text.slice(s.length):t.text;o.set(t.id,t.text),i.length>0&&(yield{type:"delta.reasoning",text:i,...n!==void 0?{sessionId:n}:{}})}e&&o.delete(t.id);return}if(t.type==="command_execution"){if(e){let s=t.status==="failed",i=t.exit_code!==void 0?` (exit ${t.exit_code})`:"",a=`$ ${t.command}${i}
|
|
1264
1365
|
`+(t.aggregated_output??"");yield{type:"tool.output",toolUseId:t.id,content:a,isError:s,...n!==void 0?{sessionId:n}:{}}}return}if(t.type==="file_change"){if(e){let s=t.changes.map(i=>`${i.kind} ${i.path}`).join(`
|
|
1265
|
-
`);yield{type:"tool.output",toolUseId:t.id,content:s,isError:t.status==="failed",...n!==void 0?{sessionId:n}:{}}}return}if(t.type==="mcp_tool_call"){if(e){let s=t.status==="failed",i;t.error?i=t.error.message:t.result?i=JSON.stringify(t.result,null,2):i="",yield{type:"tool.output",toolUseId:t.id,content:i,isError:s,...n!==void 0?{sessionId:n}:{}}}return}if(t.type==="web_search"){e&&(yield{type:"tool.output",toolUseId:t.id,content:`web_search: ${t.query}`,...n!==void 0?{sessionId:n}:{}});return}if(t.type!=="todo_list"&&t.type==="error"){e&&(yield{type:"error",error:new Error(t.message)});return}}var
|
|
1266
|
-
`);
|
|
1267
|
-
`);if(r.length<=1&&t.length<=80)return{content:t,truncated:!1,sizeBytes:e,sizeLabel:n};if(r.length<=1)return t.length<=80?{content:t,truncated:!1,sizeBytes:e,sizeLabel:n}:{content:t.substring(0,80)+"\u2026",truncated:!0,sizeBytes:e,sizeLabel:n};if(t.length<=80)return{content:t,truncated:!1,sizeBytes:e,sizeLabel:n};let o=r[0]??"",s=o;return o.length>80&&(s=o.substring(0,80)+"\u2026"),{content:s+`\u2026+${r.length} lines`,truncated:!0,lineCount:r.length,sizeBytes:e,sizeLabel:n}}function za(t,e){let n={...t.raw??{}};return t.inputTokens!==void 0&&(n.input_tokens=t.inputTokens),t.outputTokens!==void 0&&(n.output_tokens=t.outputTokens),t.cachedInputTokens!==void 0&&(n.cache_read_input_tokens=t.cachedInputTokens),t.cacheCreationTokens!==void 0&&(n.cache_creation_input_tokens=t.cacheCreationTokens),t.totalTokens!==void 0&&(n.total_tokens=t.totalTokens),{sessionId:e,stopReason:t.stopReason??void 0,resultSubtype:t.resultSubtype,durationMs:t.durationMs,durationApiMs:t.durationApiMs,totalCostUsd:t.totalCostUsd,isError:t.isError,usage:Object.keys(n).length>0?n:void 0,modelUsage:t.modelUsage,permissionDenials:t.permissionDenials,errors:t.errors}}function Va(t,e){let n=e.info;t.setSessionMetadata(r=>({...r,sessionId:n.sessionId,model:n.model??r.model,...n.permissionMode!==void 0?{permissionMode:n.permissionMode}:{},...n.cwd!==void 0?{cwd:n.cwd}:{},tools:n.tools?[...n.tools]:r.tools,slashCommands:n.slashCommands?[...n.slashCommands]:r.slashCommands,skills:n.skills?[...n.skills]:r.skills,plugins:n.plugins?n.plugins.map(o=>({...o})):r.plugins,mcpServers:n.mcpServers?n.mcpServers.map(o=>({...o})):r.mcpServers,...n.apiKeySource!==void 0?{apiKeySource:n.apiKeySource}:{},...n.version!==void 0?{claudeCodeVersion:n.version}:{},...n.outputStyle!==void 0?{outputStyle:n.outputStyle}:{}})),t.updateSessionIdentity(n.sessionId),t.resolveInitialization()}function qa(t,e){t.setSessionMetadata(n=>({...n,sessionId:e.sessionId,...e.permissionMode!==void 0?{permissionMode:e.permissionMode}:{permissionMode:n.permissionMode},...e.status!==void 0?{status:e.status}:{}}))}function Wa(t,e){let n=Ba(e.content);if(n){t.push({type:"chunk",chunk:{type:"tool_result",toolUseId:e.toolUseId,content:`Output persisted (${n.sizeLabel}) \u2192 ${n.absolutePath}`,isError:e.isError===!0,persistedPath:n.absolutePath,sizeBytes:n.sizeBytes,sizeLabel:n.sizeLabel}});return}let{content:r,truncated:o,lineCount:s,sizeBytes:i,sizeLabel:a}=Ga(e.content);t.push({type:"chunk",chunk:{type:"tool_result",toolUseId:e.toolUseId,content:r,isError:e.isError===!0,sizeBytes:i,sizeLabel:a,...o&&{truncated:o},...s!==void 0&&{lineCount:s}}})}function Ya(t,e){if(!e)return;let n={role:"assistant",content:e,timestamp:new Date};t.conversationHistory.push(n),t.messageQueue.push({type:"message",message:n})}async function so(t){try{for await(let e of t.providerStream)switch(e.type){case"session.init":Va(t,e);break;case"session.status":qa(t,e);break;case"delta.text":t.messageQueue.push({type:"chunk",chunk:{type:"content",content:e.text,metadata:{eventType:"delta",deltaType:"text_delta"}}});break;case"delta.reasoning":t.messageQueue.push({type:"chunk",chunk:{type:"thinking",content:e.text,metadata:{eventType:"delta",deltaType:"thinking_delta"}}});break;case"assistant.message":e.sessionId&&t.updateSessionIdentity(e.sessionId),Ya(t,e.text);break;case"tool.use.start":t.messageQueue.push({type:"chunk",chunk:{type:"tool_use_detail",toolUseId:e.toolUseId,toolName:e.toolName,toolInput:e.toolInput}});break;case"tool.use":t.messageQueue.push({type:"chunk",chunk:{type:"tool_use",content:e.summary,metadata:{eventType:"tool_use_summary",precedingToolUseIds:e.toolUseIds}}});break;case"tool.output":Wa(t.messageQueue,e);break;case"progress":t.messageQueue.push({type:"progress",progress:{taskId:e.progress.taskId,description:e.progress.description,...e.progress.summary!==void 0?{summary:e.progress.summary}:{},...e.progress.lastToolName!==void 0?{lastToolName:e.progress.lastToolName}:{},totalTokens:e.progress.totalTokens,toolUses:e.progress.toolUses,durationMs:e.progress.durationMs}});break;case"suggestion":t.messageQueue.push({type:"suggestion",suggestion:e.suggestion});break;case"turn.completed":let n=za(e.usage,e.sessionId??t.getSessionMetadata().sessionId);t.setLastResponseMetadata(n);for(let r=t.conversationHistory.length-1;r>=0;r--){let o=t.conversationHistory[r];if(o?.role==="assistant"){o.metadata=n;break}}t.messageQueue.push({type:"done",metadata:n});break;case"error":throw e.error}t.resolveInitializationIfNeeded(),t.messageQueue.complete()}catch(e){let n=e instanceof Error?e:new Error(String(e));throw t.resolveInitializationIfNeeded(),t.messageQueue.fail(n),n}}function io(t,e,n){t&&(t.aborted?e.abort(t.reason):t.addEventListener("abort",()=>{e.signal.aborted||e.abort(t.reason)},{once:!0})),e.signal.addEventListener("abort",n,{once:!0})}function ao(t,e){let n=t.permissionMode??"bypassPermissions",r=t.persistSession??!0,o={sessionId:t.sessionId,configuredSessionId:t.sessionId,resume:t.resume,resumeSessionAt:t.resumeSessionAt,continue:t.continue,forkSession:t.forkSession,persistSession:r},s={sessionId:t.sessionId,model:e,permissionMode:n};return{sessionIdentity:o,metadata:s}}async function lo(t){try{await ro(t.hookRegistry,{event:"SessionStart",sessionId:t.sessionId()},{signal:t.abortSignal}),await so({providerStream:t.providerQuery,messageQueue:t.messageQueue,conversationHistory:t.conversationHistory,getSessionMetadata:()=>t.stateManager.getSessionMetadata(),setSessionMetadata:e=>t.stateManager.setSessionMetadata(e),updateSessionIdentity:e=>t.stateManager.updateSessionIdentity(e),resolveInitialization:()=>t.stateManager.resolveInitializationOnce(),resolveInitializationIfNeeded:()=>t.stateManager.resolveInitializationIfNeeded(),setLastResponseMetadata:t.setLastResponseMetadata})}catch(e){let n=e instanceof Error?e:new Error(String(e));t.stateManager.isInitializationSettled()||t.stateManager.rejectInitializationOnce(n),await t.dispatchEnd("error").catch(()=>{})}}var nt=class{initializationPromise;resolveInitialization;rejectInitialization;initializationSettled=!1;sessionMetadata;sessionIdentity;constructor(e,n){this.sessionIdentity=e,this.sessionMetadata=n,this.initializationPromise=new Promise((r,o)=>{this.resolveInitialization=r,this.rejectInitialization=o})}waitForInitialization(){return this.initializationPromise}getSessionIdentity(){return{...this.sessionIdentity,sessionId:this.getSessionId()}}getSessionMetadata(){return{...this.sessionMetadata,sessionId:this.getSessionId()}}getSessionId(){return this.sessionMetadata.sessionId??this.sessionIdentity.sessionId}updateSessionIdentity(e){e&&(this.sessionIdentity={...this.sessionIdentity,sessionId:e},this.sessionMetadata={...this.sessionMetadata,sessionId:e})}setSessionMetadata(e){this.sessionMetadata=e(this.sessionMetadata)}resolveInitializationIfNeeded(){this.initializationSettled||(this.initializationSettled=!0,this.resolveInitialization(this.getSessionMetadata()))}resolveInitializationOnce(){this.initializationSettled||(this.initializationSettled=!0,this.resolveInitialization(this.getSessionMetadata()))}rejectInitializationOnce(e){this.initializationSettled||(this.initializationSettled=!0,this.rejectInitialization(e))}isInitializationSettled(){return this.initializationSettled}};async function co(t,e){return await new Promise((n,r)=>{let o=null,s="",i=!1,a=c=>{i||(i=!0,clearTimeout(l),c())},l=Number.isFinite(e)&&e>0?setTimeout(()=>{a(()=>r(new Error("Response timeout")))},e):void 0;(async()=>{try{for await(let c of t){if(process.env.AFK_CODEX_DEBUG&&console.log("[wait] got event:",c.type),c.type==="error"){a(()=>r(c.error));return}if(c.type==="chunk"&&c.chunk.type==="content"&&(s+=c.chunk.content),c.type==="message"&&c.message.role==="assistant"&&(o=c.message),c.type==="done"){if(process.env.AFK_CODEX_DEBUG&&console.log("[wait] settling with done; assistantMessage=",!!o,"streamedContent=",s.length),o){let u=o;a(()=>n({...u,metadata:c.metadata}));return}if(s){a(()=>n({role:"assistant",content:s,metadata:c.metadata,timestamp:new Date}));return}}}a(o?()=>n(o):s?()=>n({role:"assistant",content:s,timestamp:new Date}):()=>r(new Error("No assistant response received")))}catch(c){a(()=>r(c instanceof Error?c:new Error(String(c))))}})()})}var re=class{config;currentState="idle";messageQueue;providerQuery;conversationHistory=[];turnCount=0;lastResponseMetadata=null;processingPromise=null;inputStream;abortController;hookRegistry;sessionEndDispatched=!1;stateManager;constructor(e){this.config=e,this.abortController=new AbortController,this.hookRegistry=e.hookRegistry,io(e.abortSignal,this.abortController,()=>{this.onAbort()}),this.initSdkLifecycle()}initSdkLifecycle(){this.messageQueue=new Re;let e=le(this.config.model)??this.config.model,{sessionIdentity:n,metadata:r}=ao(this.config,e);this.stateManager=new nt(n,r),this.inputStream=new tt(()=>this.sessionId);let o=this.config.provider??no(e);A(`\u{1F7E2} AgentSession: Creating query session via provider=${o.name}`),this.providerQuery=o.query({prompt:this.inputStream.createIterable(),config:this.config}),this.conversationHistory=[],this.turnCount=0,this.lastResponseMetadata=null,this.sessionEndDispatched=!1,this.currentState="idle",this.processingPromise=lo({providerQuery:this.providerQuery,messageQueue:this.messageQueue,conversationHistory:this.conversationHistory,stateManager:this.stateManager,hookRegistry:this.hookRegistry,abortSignal:this.abortController.signal,sessionId:()=>this.sessionId,setLastResponseMetadata:s=>this.lastResponseMetadata=s,dispatchEnd:s=>this.dispatchSessionEndOnce(s)})}get state(){return this.currentState}get sessionId(){return this.stateManager.getSessionId()}get abortSignal(){return this.abortController.signal}async sendMessage(e,n={}){this.assertCanSend(),this.currentState=n.stream?"streaming":"processing";let r={role:"user",content:e,timestamp:new Date};this.conversationHistory.push(r);let o=this.config.timeoutMs??je;try{this.inputStream.pushUserMessage(e);let s=await He(co(this.messageQueue,o),o,{controller:this.abortController,label:this.sessionId??"session"});return this.turnCount++,s}finally{this.state!=="closed"&&(this.currentState="idle")}}async*sendMessageStream(e){this.assertCanSend(),this.currentState="streaming";let r={role:"user",content:typeof e=="string"?e:this.summarizeContentBlocks(e),timestamp:new Date};this.conversationHistory.push(r),this.inputStream.pushUserMessage(e);try{for await(let o of this.messageQueue)if(o.type==="done"&&this.turnCount++,yield o,o.type==="done"||o.type==="error")break}finally{this.state!=="closed"&&(this.currentState="idle")}}summarizeContentBlocks(e){let n=[],r=0;for(let s of e)s.type==="text"?n.push(s.text):s.type==="image"&&r++;let o=n.join(" ");return r>0&&(o=o?`${o} [+ ${r} image(s)]`:`[+ ${r} image(s)]`),o||"[content block(s)]"}async interrupt(){this.currentState!=="streaming"&&this.currentState!=="processing"||(this.currentState="idle",await this.providerQuery.interrupt())}async reset(){if(this.currentState==="closed")throw new Error("Cannot reset: session is closed");if(this.abortController.signal.aborted)throw new V("Cannot reset: session aborted");if(this.currentState==="processing"||this.currentState==="streaming")try{await this.providerQuery.interrupt()}catch{}await this.dispatchSessionEndOnce("reset");try{await this.providerQuery.close()}catch{}this.processingPromise&&await Promise.race([this.processingPromise,new Promise(e=>setTimeout(e,mt))]).catch(()=>{}),this.messageQueue.complete(),this.stateManager.resolveInitializationIfNeeded();try{this.initSdkLifecycle()}catch(e){throw this.currentState="closed",new Error(`Session reset failed during lifecycle rebuild: ${e instanceof Error?e.message:String(e)}`,{cause:e})}}async onAbort(){try{await this.providerQuery.interrupt()}catch{}}async setModel(e){let n=le(e),r=this.stateManager.getSessionMetadata();await this.providerQuery.setModel(n??r.model??""),n&&this.stateManager.setSessionMetadata(o=>({...o,model:n}))}async setPermissionMode(e){await this.providerQuery.setPermissionMode(e),this.stateManager.setSessionMetadata(n=>({...n,permissionMode:e}))}waitForInitialization(){return this.stateManager.waitForInitialization()}getSessionIdentity(){return this.stateManager.getSessionIdentity()}getSessionMetadata(){return this.stateManager.getSessionMetadata()}getQuery(){return this.providerQuery}supportedCommands(){return this.providerQuery.supportedCommands()}supportedModels(){return this.providerQuery.supportedModels()}supportedAgents(){return this.providerQuery.supportedAgents()}getContextUsage(){return this.providerQuery.getContextUsage()}mcpServerStatus(){return this.providerQuery.mcpServerStatus()}accountInfo(){return this.providerQuery.accountInfo()}rewindFiles(e,n){return this.providerQuery.rewindFiles(e,n)}async compact(){if(this.currentState==="closed")throw new Error("Cannot compact: session is closed");if(this.currentState!=="idle")return{compacted:!1,reason:"session-busy",messagesBefore:0,messagesAfter:0};let e=this.providerQuery.compact?.bind(this.providerQuery);return e?e():{compacted:!1,reason:"not-supported",messagesBefore:0,messagesAfter:0}}getLastResponseMetadata(){return this.lastResponseMetadata}getOutputStream(){return this.messageQueue}getInputStreamRef(){return{pushUserMessage:e=>this.inputStream.pushUserMessage(e)}}getHistory(){return[...this.conversationHistory]}getTurnCount(){return this.turnCount}async close(){if(this.currentState!=="closed"){this.currentState="closed",this.abortController.signal.aborted||this.abortController.abort("closed"),this.stateManager.resolveInitializationIfNeeded();try{this.providerQuery.close()}catch{}if(this.processingPromise)try{await Promise.race([this.processingPromise,new Promise(e=>setTimeout(e,mt))])}catch{}this.messageQueue.complete(),await this.dispatchSessionEndOnce("close")}}async dispatchSessionEndOnce(e){this.sessionEndDispatched||(this.sessionEndDispatched=!0,await oo(this.hookRegistry,{event:"SessionEnd",sessionId:this.sessionId,reason:e}))}assertCanSend(){if(this.currentState==="closed")throw new Error("Cannot send message: session is closed");if(this.abortController.signal.aborted)throw new V("Cannot send message: session aborted");if(this.currentState==="processing"||this.currentState==="streaming")throw new Error("Cannot send message: session is busy");if(this.config.maxTurns&&this.turnCount>=this.config.maxTurns)throw new Error(`Maximum turns (${this.config.maxTurns}) exceeded`)}};var $t=class{handlers=new Map;register(e,n){let r=this.handlers.get(e);return r||(r=[],this.handlers.set(e,r)),r.push(n),()=>{let o=this.handlers.get(e);if(!o)return;let s=o.indexOf(n);s>=0&&o.splice(s,1)}}count(e){return this.handlers.get(e)?.length??0}async dispatch(e,n){Ft(n,e.event);let r=this.handlers.get(e.event);if(!r||r.length===0)return{};let o=r.slice(),s={};for(let i of o){Ft(n,e.event);let a;try{a=await i(e)}catch(l){throw new K(`hook handler threw during ${e.event}`,e.event,l instanceof Error?l.message:String(l),{cause:l})}if(Ft(n,e.event),Ja(a))throw new K(`hook handler blocked ${e.event}${a.reason?`: ${a.reason}`:""}`,e.event,a.reason);s=a}return s}};function Ja(t){return t.continue===!1||t.decision==="block"}function Ft(t,e){if(t?.aborted){let n=t.reason,r=`aborted during ${e}${n?`: ${String(n)}`:""}`;throw new V(r)}}function uo(){return new $t}function po(){return uo()}var Qa=["shadow-verify","shadow_verify","resolve","diagnose","appmap","qualify","mint"],Xa=[/\bverdict(s)?\b/i,/\brecommend(ation)?s?\b/i,/\bshould\s+(delete|remove|rewrite|refactor|rename|reject|merge|revert|disable)\b/i,/\b(USELESS|KEEP|REJECT|APPROVE|SALVAGE|BLOCK|FAIL)\b/,/\b(redundant|duplicated|superseded|obsolete)\b/i,/\bvulnerab\w*\b/i,/\bunused\b/i,/\bbroken\b/i,/\bregress\w*\b/i,/\|\s*(status|verdict|decision|severity|risk|finding|priority|holds\??)\s*\|/i,/\bfound\s+\d+\s*(issue|problem|bug|error|finding|vulnerabilit)/i,/\b(critical|high|medium|low)\s+(severity|priority|risk)\b/i,/\bclaim(s)?\b[^\n]{0,80}\b(holds?|refuted|verified|partial|confirmed|disputed)\b/i,/\b(root\s*cause|incident)\b/i,/\brecommend\s+(removing|deleting|rewriting|refactoring|merging|reverting)\b/i,/\bI\s+(applied|committed|pushed|edited|wrote|fixed|patched|reset|restored|staged)\b/i,/\b(applied|committed|pushed|fixed|patched)\s+(the|these|those)\s+(change|commit|fix|patch|edit)/i],Za=[/\bverifier_verdict\b/i,/"\s*claim\s*"\s*:/i,/\bre-derived\b[^.\n]{0,80}\bindependent/i,/\bindependently\s+(re-derived|re-verified|verified|checked)\b/i,/\bverifier\s+(agrees|disagrees|confirms|refutes)\b/i],el=`shadow-verify nudge:
|
|
1366
|
+
`);yield{type:"tool.output",toolUseId:t.id,content:s,isError:t.status==="failed",...n!==void 0?{sessionId:n}:{}}}return}if(t.type==="mcp_tool_call"){if(e){let s=t.status==="failed",i;t.error?i=t.error.message:t.result?i=JSON.stringify(t.result,null,2):i="",yield{type:"tool.output",toolUseId:t.id,content:i,isError:s,...n!==void 0?{sessionId:n}:{}}}return}if(t.type==="web_search"){e&&(yield{type:"tool.output",toolUseId:t.id,content:`web_search: ${t.query}`,...n!==void 0?{sessionId:n}:{}});return}if(t.type!=="todo_list"&&t.type==="error"){e&&(yield{type:"error",error:new Error(t.message)});return}}var Qt=class{startOpts;promptStream;codex;thread;currentModel;currentSandbox;currentApproval;abortController=null;pendingAbortReason=null;closed=!1;initSessionId;dispose;closeResolve=null;closedPromise;constructor(e,n,r){this.startOpts=e,this.promptStream=n,this.initSessionId=r,this.codex=new Do(e.codexOptions),this.thread=e.resumeId?this.codex.resumeThread(e.resumeId,e.threadOptions):this.codex.startThread(e.threadOptions),this.currentModel=e.threadOptions.model,this.currentSandbox=e.threadOptions.sandboxMode??"workspace-write",this.currentApproval=e.threadOptions.approvalPolicy??"never",e.instructionsDispose!==void 0&&(this.dispose=e.instructionsDispose),this.closedPromise=new Promise(o=>{this.closeResolve=()=>o("__closed__")})}async*[Symbol.asyncIterator](){yield{type:"session.init",info:{sessionId:this.initSessionId,...this.currentModel!==void 0?{model:this.currentModel}:{},permissionMode:this.sandboxToPermissionMode(),cwd:this.startOpts.threadOptions.workingDirectory??process.cwd(),tools:["Bash","Read","Write","Edit"],slashCommands:[],skills:[],plugins:[],mcpServers:[],apiKeySource:this.startOpts.codexOptions.apiKey!==void 0?"apiKey":"codex-cli",version:"codex-sdk"}};let n=new Map,r=new Map,o=this.initSessionId,s=this.promptStream[Symbol.asyncIterator]();try{for(;!this.closed;){let i=await Promise.race([s.next(),this.closedPromise]);if(i==="__closed__")break;let a=i;if(a.done)break;let l=a.value,c=new AbortController;if(this.abortController=c,this.pendingAbortReason!==null&&!c.signal.aborted&&(c.abort(this.pendingAbortReason),this.pendingAbortReason=null),c.signal.aborted)return;let d;try{let u=typeof l.content=="string"?l.content:l.content.map(p=>{if(typeof p=="object"&&p&&"type"in p){if(p.type==="text")return p.text;if(p.type==="image")return"[image omitted]"}return""}).join(`
|
|
1367
|
+
`);d=await this.thread.runStreamed(u,{signal:c.signal})}catch(u){if(c.signal.aborted)return;yield{type:"error",error:u instanceof Error?u:new Error(String(u))};return}try{for await(let u of d.events){if(this.closed)return;u.type==="thread.started"&&(o=u.thread_id),yield*Jl(u,o,n,r)}}catch(u){if(c.signal.aborted)return;yield{type:"error",error:u instanceof Error?u:new Error(String(u))};return}finally{this.abortController===c&&(this.abortController=null)}}}catch(i){yield{type:"error",error:i instanceof Error?i:new Error(String(i))}}finally{try{await s.return?.()}catch{}}}sandboxToPermissionMode(){return this.currentSandbox==="read-only"||this.currentApproval==="untrusted"?"plan":"bypassPermissions"}async interrupt(){let e=this.abortController;if(e&&!e.signal.aborted){e.abort("interrupted");return}this.pendingAbortReason="interrupted"}async setModel(e){this.currentModel=e;let n={...this.startOpts.threadOptions,...e!==void 0?{model:e}:{},sandboxMode:this.currentSandbox,approvalPolicy:this.currentApproval},r=this.thread.id;this.thread=r?this.codex.resumeThread(r,n):this.codex.startThread(n),this.startOpts.threadOptions=n}async setPermissionMode(e){let{sandboxMode:n,approvalPolicy:r}=Fo(e);this.currentSandbox=n,this.currentApproval=r;let o={...this.startOpts.threadOptions,sandboxMode:n,approvalPolicy:r},s=this.thread.id;this.thread=s?this.codex.resumeThread(s,o):this.codex.startThread(o),this.startOpts.threadOptions=o}async supportedCommands(){return[]}async supportedModels(){return Gl.map(e=>({...e}))}async supportedAgents(){return[]}async getContextUsage(){return{tools:[],agents:[],isAutoCompactEnabled:!1,apiUsage:null}}async mcpServerStatus(){return[]}async accountInfo(){return{}}async rewindFiles(e,n){throw new Se(_e,"rewindFiles",`${_e} provider does not support file checkpoint rewind.`)}close(){this.closed=!0;let e=this.abortController;e&&!e.signal.aborted?e.abort("closed"):this.pendingAbortReason="closed",this.closeResolve?.(),this.dispose?.()}getThread(){return this.thread}},Xl=null;var pt=class{name=_e;query(e){Wl(e.config);let n=Yl(e.config),r=ql(e.config.effort),{sandboxMode:o,approvalPolicy:s}=Fo(e.config.permissionMode),i={...e.config.model!==void 0?{model:e.config.model}:{},sandboxMode:o,approvalPolicy:s,...r!==void 0?{modelReasoningEffort:r}:{},skipGitRepoCheck:!0,workingDirectory:process.cwd()},a=zl(e.config),l={};n!==void 0&&(l.apiKey=n);let c;if(a!==void 0){let{path:f,dispose:h}=Vl(a);l.config={...l.config??{},model_instructions_file:f},c=h}A(`\u{1F7E2} OpenAICodexProvider: creating Codex thread (model=${String(e.config.model)}, sandbox=${o}, approval=${s})`);let d=Xl,u=d??(f=>new Do(f)),p=`codex-pending-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,m=new Qt({threadOptions:i,codexOptions:l,...e.config.resume!==void 0?{resumeId:e.config.resume}:{},...c!==void 0?{instructionsDispose:c}:{}},e.prompt,p);if(d){let f=u(l);m.codex=f,m.thread=e.config.resume?f.resumeThread(e.config.resume,i):f.startThread(i)}return m}},Lo=new pt;var Zl=new Set(["opus","opus_1m","sonnet","sonnet_1m","haiku","auto"]);function ge(t){if(!t)return"anthropic-direct";let e=t.trim().toLowerCase();return!e||Zl.has(e)||e.startsWith("claude-")||e.startsWith("claude_")?"anthropic-direct":e.startsWith("gpt-")||e.startsWith("gpt_")||e.startsWith("o1")||e.startsWith("o3")||e.startsWith("o4")||e.startsWith("codex-")||e.startsWith("codex_")||e==="codex"?"openai-codex":"anthropic-direct"}function $o(t){return ge(t)==="openai-codex"?Lo:Mo}async function No(t,e,n={}){t&&await t.dispatch(e,n.signal)}async function Ho(t,e,n={}){if(t)try{await t.dispatch(e,n.signal)}catch(r){if(r instanceof W||r instanceof q){A(`SessionEnd hook swallowed ${r.name}: ${r.message}`),n.onError?.(r);return}A(`SessionEnd hook unexpected error: ${String(r)}`),n.onError?.(r instanceof Error?r:new Error(String(r)))}}var mt=class{pendingResolve=null;bufferedMessage=null;getSessionId;constructor(e){this.getSessionId=e}pushUserMessage(e){if(this.pendingResolve){let n=this.pendingResolve;this.pendingResolve=null;let r=this.getSessionId();n({content:e,...r!==void 0?{sessionId:r}:{}});return}this.bufferedMessage=e}createIterable(){let e=this;return{[Symbol.asyncIterator](){return{next(){if(e.bufferedMessage!==null){let n=e.bufferedMessage;e.bufferedMessage=null;let r=e.getSessionId();return Promise.resolve({value:{content:n,...r!==void 0?{sessionId:r}:{}},done:!1})}return new Promise(n=>{e.pendingResolve=r=>n({value:r,done:!1})})},return(){return Promise.resolve({value:void 0,done:!0})}}}}}};function ec(t){let e=/Output too large \((\d+(?:\.\d+)?)\s*(B|KB|MB|GB)\)\.\s*Full output saved to:\s*(\/[^\n]+)/,n=t.match(e);if(!n||!n[1]||!n[2]||!n[3])return null;let r=n[1],o=n[2],s=n[3],i=parseFloat(r),a=i;o==="KB"?a=i*1024:o==="MB"?a=i*1024*1024:o==="GB"&&(a=i*1024*1024*1024);let l=r;return i%1===0&&(l=String(Math.floor(i))),l+=o,{sizeLabel:l,sizeBytes:Math.round(a),absolutePath:s.trim()}}function tc(t){if(t<1024)return`${t}B`;let e=t/1024;if(e<1024)return e%1===0?`${Math.floor(e)}KB`:`${e.toFixed(1)}KB`;let n=e/1024;if(n<1024)return n%1===0?`${Math.floor(n)}MB`:`${n.toFixed(1)}MB`;let r=n/1024;return r%1===0?`${Math.floor(r)}GB`:`${r.toFixed(1)}GB`}function nc(t){let e=Buffer.byteLength(t,"utf8"),n=tc(e),r=t.split(`
|
|
1368
|
+
`);if(r.length<=1&&t.length<=80)return{content:t,truncated:!1,sizeBytes:e,sizeLabel:n};if(r.length<=1)return t.length<=80?{content:t,truncated:!1,sizeBytes:e,sizeLabel:n}:{content:t.substring(0,80)+"\u2026",truncated:!0,sizeBytes:e,sizeLabel:n};if(t.length<=80)return{content:t,truncated:!1,sizeBytes:e,sizeLabel:n};let o=r[0]??"",s=o;return o.length>80&&(s=o.substring(0,80)+"\u2026"),{content:s+`\u2026+${r.length} lines`,truncated:!0,lineCount:r.length,sizeBytes:e,sizeLabel:n}}function rc(t,e){let n={...t.raw??{}};return t.inputTokens!==void 0&&(n.input_tokens=t.inputTokens),t.outputTokens!==void 0&&(n.output_tokens=t.outputTokens),t.cachedInputTokens!==void 0&&(n.cache_read_input_tokens=t.cachedInputTokens),t.cacheCreationTokens!==void 0&&(n.cache_creation_input_tokens=t.cacheCreationTokens),t.totalTokens!==void 0&&(n.total_tokens=t.totalTokens),{sessionId:e,stopReason:t.stopReason??void 0,resultSubtype:t.resultSubtype,durationMs:t.durationMs,durationApiMs:t.durationApiMs,totalCostUsd:t.totalCostUsd,isError:t.isError,usage:Object.keys(n).length>0?n:void 0,modelUsage:t.modelUsage,permissionDenials:t.permissionDenials,errors:t.errors}}function oc(t,e){let n=e.info;t.setSessionMetadata(r=>({...r,sessionId:n.sessionId,model:n.model??r.model,...n.permissionMode!==void 0?{permissionMode:n.permissionMode}:{},...n.cwd!==void 0?{cwd:n.cwd}:{},tools:n.tools?[...n.tools]:r.tools,slashCommands:n.slashCommands?[...n.slashCommands]:r.slashCommands,skills:n.skills?[...n.skills]:r.skills,plugins:n.plugins?n.plugins.map(o=>({...o})):r.plugins,mcpServers:n.mcpServers?n.mcpServers.map(o=>({...o})):r.mcpServers,...n.apiKeySource!==void 0?{apiKeySource:n.apiKeySource}:{},...n.version!==void 0?{claudeCodeVersion:n.version}:{},...n.outputStyle!==void 0?{outputStyle:n.outputStyle}:{}})),t.updateSessionIdentity(n.sessionId),t.resolveInitialization()}function sc(t,e){t.setSessionMetadata(n=>({...n,sessionId:e.sessionId,...e.permissionMode!==void 0?{permissionMode:e.permissionMode}:{permissionMode:n.permissionMode},...e.status!==void 0?{status:e.status}:{}}))}function ic(t,e){let n=ec(e.content);if(n){t.push({type:"chunk",chunk:{type:"tool_result",toolUseId:e.toolUseId,content:`Output persisted (${n.sizeLabel}) \u2192 ${n.absolutePath}`,isError:e.isError===!0,persistedPath:n.absolutePath,sizeBytes:n.sizeBytes,sizeLabel:n.sizeLabel}});return}let{content:r,truncated:o,lineCount:s,sizeBytes:i,sizeLabel:a}=nc(e.content);t.push({type:"chunk",chunk:{type:"tool_result",toolUseId:e.toolUseId,content:r,isError:e.isError===!0,sizeBytes:i,sizeLabel:a,...o&&{truncated:o},...s!==void 0&&{lineCount:s}}})}function ac(t,e){if(!e)return;let n={role:"assistant",content:e,timestamp:new Date};t.conversationHistory.push(n),t.messageQueue.push({type:"message",message:n})}async function Uo(t){try{for await(let e of t.providerStream)switch(e.type){case"session.init":oc(t,e);break;case"session.status":sc(t,e);break;case"delta.text":t.messageQueue.push({type:"chunk",chunk:{type:"content",content:e.text,metadata:{eventType:"delta",deltaType:"text_delta"}}});break;case"delta.reasoning":t.messageQueue.push({type:"chunk",chunk:{type:"thinking",content:e.text,metadata:{eventType:"delta",deltaType:"thinking_delta"}}});break;case"assistant.message":e.sessionId&&t.updateSessionIdentity(e.sessionId),ac(t,e.text);break;case"tool.use.start":t.messageQueue.push({type:"chunk",chunk:{type:"tool_use_detail",toolUseId:e.toolUseId,toolName:e.toolName,toolInput:e.toolInput}});break;case"tool.use":t.messageQueue.push({type:"chunk",chunk:{type:"tool_use",content:e.summary,metadata:{eventType:"tool_use_summary",precedingToolUseIds:e.toolUseIds}}});break;case"tool.output":ic(t.messageQueue,e);break;case"progress":t.messageQueue.push({type:"progress",progress:{taskId:e.progress.taskId,description:e.progress.description,...e.progress.summary!==void 0?{summary:e.progress.summary}:{},...e.progress.lastToolName!==void 0?{lastToolName:e.progress.lastToolName}:{},totalTokens:e.progress.totalTokens,toolUses:e.progress.toolUses,durationMs:e.progress.durationMs}});break;case"suggestion":t.messageQueue.push({type:"suggestion",suggestion:e.suggestion});break;case"turn.completed":let n=rc(e.usage,e.sessionId??t.getSessionMetadata().sessionId);t.setLastResponseMetadata(n);for(let r=t.conversationHistory.length-1;r>=0;r--){let o=t.conversationHistory[r];if(o?.role==="assistant"){o.metadata=n;break}}t.messageQueue.push({type:"done",metadata:n});break;case"error":throw e.error}t.resolveInitializationIfNeeded(),t.messageQueue.complete()}catch(e){let n=e instanceof Error?e:new Error(String(e));throw t.resolveInitializationIfNeeded(),t.messageQueue.fail(n),n}}function jo(t,e,n){t&&(t.aborted?e.abort(t.reason):t.addEventListener("abort",()=>{e.signal.aborted||e.abort(t.reason)},{once:!0})),e.signal.addEventListener("abort",n,{once:!0})}function Bo(t,e){let n=t.permissionMode??"bypassPermissions",r=t.persistSession??!0,o={sessionId:t.sessionId,configuredSessionId:t.sessionId,resume:t.resume,resumeSessionAt:t.resumeSessionAt,continue:t.continue,forkSession:t.forkSession,persistSession:r},s={sessionId:t.sessionId,model:e,permissionMode:n};return{sessionIdentity:o,metadata:s}}async function Ko(t){try{await No(t.hookRegistry,{event:"SessionStart",sessionId:t.sessionId()},{signal:t.abortSignal}),await Uo({providerStream:t.providerQuery,messageQueue:t.messageQueue,conversationHistory:t.conversationHistory,getSessionMetadata:()=>t.stateManager.getSessionMetadata(),setSessionMetadata:e=>t.stateManager.setSessionMetadata(e),updateSessionIdentity:e=>t.stateManager.updateSessionIdentity(e),resolveInitialization:()=>t.stateManager.resolveInitializationOnce(),resolveInitializationIfNeeded:()=>t.stateManager.resolveInitializationIfNeeded(),setLastResponseMetadata:t.setLastResponseMetadata})}catch(e){let n=e instanceof Error?e:new Error(String(e));t.stateManager.isInitializationSettled()||t.stateManager.rejectInitializationOnce(n),await t.dispatchEnd("error").catch(()=>{})}}var ft=class{initializationPromise;resolveInitialization;rejectInitialization;initializationSettled=!1;sessionMetadata;sessionIdentity;constructor(e,n){this.sessionIdentity=e,this.sessionMetadata=n,this.initializationPromise=new Promise((r,o)=>{this.resolveInitialization=r,this.rejectInitialization=o})}waitForInitialization(){return this.initializationPromise}getSessionIdentity(){return{...this.sessionIdentity,sessionId:this.getSessionId()}}getSessionMetadata(){return{...this.sessionMetadata,sessionId:this.getSessionId()}}getSessionId(){return this.sessionMetadata.sessionId??this.sessionIdentity.sessionId}updateSessionIdentity(e){e&&(this.sessionIdentity={...this.sessionIdentity,sessionId:e},this.sessionMetadata={...this.sessionMetadata,sessionId:e})}setSessionMetadata(e){this.sessionMetadata=e(this.sessionMetadata)}resolveInitializationIfNeeded(){this.initializationSettled||(this.initializationSettled=!0,this.resolveInitialization(this.getSessionMetadata()))}resolveInitializationOnce(){this.initializationSettled||(this.initializationSettled=!0,this.resolveInitialization(this.getSessionMetadata()))}rejectInitializationOnce(e){this.initializationSettled||(this.initializationSettled=!0,this.rejectInitialization(e))}isInitializationSettled(){return this.initializationSettled}};async function Go(t,e){return await new Promise((n,r)=>{let o=null,s="",i=!1,a=c=>{i||(i=!0,clearTimeout(l),c())},l=Number.isFinite(e)&&e>0?setTimeout(()=>{a(()=>r(new Error("Response timeout")))},e):void 0;(async()=>{try{for await(let c of t){if(process.env.AFK_CODEX_DEBUG&&console.log("[wait] got event:",c.type),c.type==="error"){a(()=>r(c.error));return}if(c.type==="chunk"&&c.chunk.type==="content"&&(s+=c.chunk.content),c.type==="message"&&c.message.role==="assistant"&&(o=c.message),c.type==="done"){if(process.env.AFK_CODEX_DEBUG&&console.log("[wait] settling with done; assistantMessage=",!!o,"streamedContent=",s.length),o){let d=o;a(()=>n({...d,metadata:c.metadata}));return}if(s){a(()=>n({role:"assistant",content:s,metadata:c.metadata,timestamp:new Date}));return}}}a(o?()=>n(o):s?()=>n({role:"assistant",content:s,timestamp:new Date}):()=>r(new Error("No assistant response received")))}catch(c){a(()=>r(c instanceof Error?c:new Error(String(c))))}})()})}var ae=class{config;currentState="idle";messageQueue;providerQuery;conversationHistory=[];turnCount=0;lastResponseMetadata=null;processingPromise=null;inputStream;abortController;hookRegistry;sessionEndDispatched=!1;stateManager;constructor(e){this.config=e,this.abortController=new AbortController,this.hookRegistry=e.hookRegistry,jo(e.abortSignal,this.abortController,()=>{this.onAbort()}),this.initSdkLifecycle()}initSdkLifecycle(){this.messageQueue=new We;let e=ue(this.config.model)??this.config.model,{sessionIdentity:n,metadata:r}=Bo(this.config,e);this.stateManager=new ft(n,r),this.inputStream=new mt(()=>this.sessionId);let o=this.config.provider??$o(e);A(`\u{1F7E2} AgentSession: Creating query session via provider=${o.name}`),this.providerQuery=o.query({prompt:this.inputStream.createIterable(),config:this.config}),this.conversationHistory=[],this.turnCount=0,this.lastResponseMetadata=null,this.sessionEndDispatched=!1,this.currentState="idle",this.processingPromise=Ko({providerQuery:this.providerQuery,messageQueue:this.messageQueue,conversationHistory:this.conversationHistory,stateManager:this.stateManager,hookRegistry:this.hookRegistry,abortSignal:this.abortController.signal,sessionId:()=>this.sessionId,setLastResponseMetadata:s=>this.lastResponseMetadata=s,dispatchEnd:s=>this.dispatchSessionEndOnce(s)})}get state(){return this.currentState}get sessionId(){return this.stateManager.getSessionId()}get abortSignal(){return this.abortController.signal}async sendMessage(e,n={}){this.assertCanSend(),this.currentState=n.stream?"streaming":"processing";let r={role:"user",content:e,timestamp:new Date};this.conversationHistory.push(r);let o=this.config.timeoutMs??Xe;try{this.inputStream.pushUserMessage(e);let s=await Ze(Go(this.messageQueue,o),o,{controller:this.abortController,label:this.sessionId??"session"});return this.turnCount++,s}finally{this.state!=="closed"&&(this.currentState="idle")}}async*sendMessageStream(e){this.assertCanSend(),this.currentState="streaming";let r={role:"user",content:typeof e=="string"?e:this.summarizeContentBlocks(e),timestamp:new Date};this.conversationHistory.push(r),this.inputStream.pushUserMessage(e);try{for await(let o of this.messageQueue)if(o.type==="done"&&this.turnCount++,yield o,o.type==="done"||o.type==="error")break}finally{this.state!=="closed"&&(this.currentState="idle")}}summarizeContentBlocks(e){let n=[],r=0;for(let s of e)s.type==="text"?n.push(s.text):s.type==="image"&&r++;let o=n.join(" ");return r>0&&(o=o?`${o} [+ ${r} image(s)]`:`[+ ${r} image(s)]`),o||"[content block(s)]"}async interrupt(){this.currentState!=="streaming"&&this.currentState!=="processing"||(this.currentState="idle",await this.providerQuery.interrupt())}async reset(){if(this.currentState==="closed")throw new Error("Cannot reset: session is closed");if(this.abortController.signal.aborted)throw new q("Cannot reset: session aborted");if(this.currentState==="processing"||this.currentState==="streaming")try{await this.providerQuery.interrupt()}catch{}await this.dispatchSessionEndOnce("reset");try{await this.providerQuery.close()}catch{}this.processingPromise&&await Promise.race([this.processingPromise,new Promise(e=>setTimeout(e,Lt))]).catch(()=>{}),this.messageQueue.complete(),this.stateManager.resolveInitializationIfNeeded();try{this.initSdkLifecycle()}catch(e){throw this.currentState="closed",new Error(`Session reset failed during lifecycle rebuild: ${e instanceof Error?e.message:String(e)}`,{cause:e})}}async onAbort(){try{await this.providerQuery.interrupt()}catch{}}async setModel(e){let n=ue(e),r=this.stateManager.getSessionMetadata();await this.providerQuery.setModel(n??r.model??""),n&&this.stateManager.setSessionMetadata(o=>({...o,model:n}))}async setPermissionMode(e){await this.providerQuery.setPermissionMode(e),this.stateManager.setSessionMetadata(n=>({...n,permissionMode:e}))}waitForInitialization(){return this.stateManager.waitForInitialization()}getSessionIdentity(){return this.stateManager.getSessionIdentity()}getSessionMetadata(){return this.stateManager.getSessionMetadata()}getQuery(){return this.providerQuery}supportedCommands(){return this.providerQuery.supportedCommands()}supportedModels(){return this.providerQuery.supportedModels()}supportedAgents(){return this.providerQuery.supportedAgents()}getContextUsage(){return this.providerQuery.getContextUsage()}mcpServerStatus(){return this.providerQuery.mcpServerStatus()}accountInfo(){return this.providerQuery.accountInfo()}rewindFiles(e,n){return this.providerQuery.rewindFiles(e,n)}async compact(){if(this.currentState==="closed")throw new Error("Cannot compact: session is closed");if(this.currentState!=="idle")return{compacted:!1,reason:"session-busy",messagesBefore:0,messagesAfter:0};let e=this.providerQuery.compact?.bind(this.providerQuery);return e?e():{compacted:!1,reason:"not-supported",messagesBefore:0,messagesAfter:0}}getLastResponseMetadata(){return this.lastResponseMetadata}getOutputStream(){return this.messageQueue}getInputStreamRef(){return{pushUserMessage:e=>this.inputStream.pushUserMessage(e)}}getHistory(){return[...this.conversationHistory]}getTurnCount(){return this.turnCount}async close(){if(this.currentState!=="closed"){this.currentState="closed",this.abortController.signal.aborted||this.abortController.abort("closed"),this.stateManager.resolveInitializationIfNeeded();try{this.providerQuery.close()}catch{}if(this.processingPromise)try{await Promise.race([this.processingPromise,new Promise(e=>setTimeout(e,Lt))])}catch{}this.messageQueue.complete(),await this.dispatchSessionEndOnce("close")}}async dispatchSessionEndOnce(e){this.sessionEndDispatched||(this.sessionEndDispatched=!0,await Ho(this.hookRegistry,{event:"SessionEnd",sessionId:this.sessionId,reason:e}))}assertCanSend(){if(this.currentState==="closed")throw new Error("Cannot send message: session is closed");if(this.abortController.signal.aborted)throw new q("Cannot send message: session aborted");if(this.currentState==="processing"||this.currentState==="streaming")throw new Error("Cannot send message: session is busy");if(this.config.maxTurns&&this.turnCount>=this.config.maxTurns)throw new Error(`Maximum turns (${this.config.maxTurns}) exceeded`)}};var Zt=class{handlers=new Map;register(e,n){let r=this.handlers.get(e);return r||(r=[],this.handlers.set(e,r)),r.push(n),()=>{let o=this.handlers.get(e);if(!o)return;let s=o.indexOf(n);s>=0&&o.splice(s,1)}}count(e){return this.handlers.get(e)?.length??0}async dispatch(e,n){Xt(n,e.event);let r=this.handlers.get(e.event);if(!r||r.length===0)return{};let o=r.slice(),s={};for(let i of o){Xt(n,e.event);let a;try{a=await i(e)}catch(l){throw new W(`hook handler threw during ${e.event}`,e.event,l instanceof Error?l.message:String(l),{cause:l})}if(Xt(n,e.event),lc(a))throw new W(`hook handler blocked ${e.event}${a.reason?`: ${a.reason}`:""}`,e.event,a.reason);s=a}return s}};function lc(t){return t.continue===!1||t.decision==="block"}function Xt(t,e){if(t?.aborted){let n=t.reason,r=`aborted during ${e}${n?`: ${String(n)}`:""}`;throw new q(r)}}function Wo(){return new Zt}function qo(){return Wo()}var cc=["shadow-verify","shadow_verify","resolve","diagnose","appmap","qualify","mint"],dc=[/\bverdict(s)?\b/i,/\brecommend(ation)?s?\b/i,/\bshould\s+(delete|remove|rewrite|refactor|rename|reject|merge|revert|disable)\b/i,/\b(USELESS|KEEP|REJECT|APPROVE|SALVAGE|BLOCK|FAIL)\b/,/\b(redundant|duplicated|superseded|obsolete)\b/i,/\bvulnerab\w*\b/i,/\bunused\b/i,/\bbroken\b/i,/\bregress\w*\b/i,/\|\s*(status|verdict|decision|severity|risk|finding|priority|holds\??)\s*\|/i,/\bfound\s+\d+\s*(issue|problem|bug|error|finding|vulnerabilit)/i,/\b(critical|high|medium|low)\s+(severity|priority|risk)\b/i,/\bclaim(s)?\b[^\n]{0,80}\b(holds?|refuted|verified|partial|confirmed|disputed)\b/i,/\b(root\s*cause|incident)\b/i,/\brecommend\s+(removing|deleting|rewriting|refactoring|merging|reverting)\b/i,/\bI\s+(applied|committed|pushed|edited|wrote|fixed|patched|reset|restored|staged)\b/i,/\b(applied|committed|pushed|fixed|patched)\s+(the|these|those)\s+(change|commit|fix|patch|edit)/i],uc=[/\bverifier_verdict\b/i,/"\s*claim\s*"\s*:/i,/\bre-derived\b[^.\n]{0,80}\bindependent/i,/\bindependently\s+(re-derived|re-verified|verified|checked)\b/i,/\bverifier\s+(agrees|disagrees|confirms|refutes)\b/i],pc=`shadow-verify nudge:
|
|
1268
1369
|
|
|
1269
1370
|
The sub-agent that just finished returned output that reads like **decision-driving findings** (verdicts, recommendations, audit conclusions, or claim-style results that could drive file edits, deletions, commits, or external side-effects).
|
|
1270
1371
|
|
|
1271
1372
|
Single-pass sub-agent reports are prone to confident hallucination \u2014 polished output that falls apart on re-derivation. Before acting on these conclusions, consider dispatching \`/shadow-verify\`. Independent verifiers will re-derive the 2\u20133 most load-bearing claims from scratch (without seeing the original reasoning) and flag any that don't hold up.
|
|
1272
1373
|
|
|
1273
|
-
Skip when: the findings are purely exploratory, the sub-agent ran inside an already-verifying orchestrator, the user is about to dismiss the report, or the stakes are low (read-only Q&A).`;function
|
|
1374
|
+
Skip when: the findings are purely exploratory, the sub-agent ran inside an already-verifying orchestrator, the user is about to dismiss the report, or the stakes are low (read-only Q&A).`;function mc(t){if(!t)return!1;let e=t.toLowerCase();return cc.some(n=>e.includes(n))}function fc(t){return uc.some(e=>e.test(t))}function gc(t){let e=0;for(let n of dc)n.test(t)&&e++;return e}function zo(t){if(t.event!=="SubagentStop")return{};let e=t.lastMessage??"";return e.length<600?{}:mc(t.agentType)?{}:fc(e)?{}:gc(e)<2?{}:{injectContext:pc}}function en(t,e,n){let r=qo();r.register("SubagentStop",zo);let o=n??new Q;return r.register("SessionEnd",Et(o,e)),t&&r.register("SubagentStop",s=>s.event!=="SubagentStop"?{}:s.status==="idle"||s.status==="running"?{}:(t({subagentId:s.subagentId,status:s.status,durationMs:s.durationMs,agentType:s.agentType}),{})),{registry:r,memoryStore:o}}var hc="[skill-routing: active]\n\nRoute recurring work through registered skills instead of rolling ad-hoc solutions:\n\n- Multi-file implementation or new features \u2192 `/mint`\n- Bugs, failing tests, or regressions \u2192 `/diagnose`\n- High-stakes sub-agent output that will drive edits or commits \u2192 `/shadow-verify` before acting\n- Refactor needing parallel waves \u2192 `/parallelize`\n\nCommon composed sequences \u2014 reach for these when the task shape matches:\n\n- Bug with failing test and non-trivial fix \u2192 `/diagnose` \u2192 `/shadow-verify` on the proposed fix\n- Refactor needing parallel waves \u2192 plan \u2192 `/parallelize` \u2192 build waves\n\nReach for context-isolated investigators when the task is exploratory:\n\n- Map an unfamiliar module before editing \u2192 `/gather` or `/research`\n- Re-derive a load-bearing claim independently \u2192 `/shadow-verify`\n- Audit a diff before merge \u2192 `/review`\n- Survey git + infra + memory before non-trivial work \u2192 `/ground-state`\n- Generate alternatives before committing to a plan \u2192 `/devils-advocate`\n\nOr dispatch a raw `agent` call when no skill matches but the work is parallelizable, verification-heavy, or would otherwise consume substantial inline context.\n\nSkip orchestration for: single-line edits, trivial Q&A, and direct tool calls the user explicitly requested. The goal is leverage, not ceremony \u2014 if a skill would add overhead without adding value, don't invoke it.";function tn(t,e){return!t||!e?t:`${t}
|
|
1274
1375
|
|
|
1275
|
-
${
|
|
1276
|
-
How to get a bot token:`),console.error(" 1. Open Telegram and search for @BotFather"),console.error(" 2. Send /newbot and follow the instructions"),console.error(" 3.
|
|
1277
|
-
This is an allowlist that gates who can message the bot.`),console.error("
|
|
1278
|
-
To find your chat ID, DM the bot and inspect the update, or use @userinfobot.`),process.exit(1)),console.log("\u{1F916} Starting Agent AFK Telegram Bot..."),console.log(`\u{1F4E1} Model: ${t.model} \xB7 Provider: ${e}`),console.log(`\u{1F512} Allowlist: ${r.size} chat ID(s)`);let o=new _e({botToken:n,apiKey:t.apiKey??"",dataDir:process.env.TELEGRAM_DATA_DIR||"./data/telegram-sessions",defaultModel:t.model,verbose:process.env.TELEGRAM_VERBOSE==="true",allowedChatIds:r,settingSources:["user","project"],createSession:async s=>{let i=le(s.model)??s.model;console.log(`Creating session with model: ${s.model} -> ${i}`);let l=de(i)==="openai-codex",c=l?void 0:wr(),u;if(!l){let h,m=s.apiKey??t.apiKey??"",y=new w({apiKey:m}),b={get sessionId(){return h?.sessionId},getInputStreamRef(){return h?.getInputStreamRef?.()??{pushUserMessage:()=>{}}},get abortSignal(){return h?.abortSignal??new AbortController().signal}},F=mo(),N=new rt({subagentManager:y,parentSession:b,defaultConfig:{apiKey:m,systemPrompt:s.systemPrompt??t.systemPrompt},defaultSubagentModel:It(),childProviderFactory:F,childSkillExecutorFactory:go(s.model,m)}),H=new me({parentSession:b,defaultModel:s.model,defaultSubagentModel:It(),apiKey:m}),_=[...ve,"agent","skill"];u=new ee({permissions:{allowedTools:_},subagentExecutor:N,skillExecutor:H});let S=s.systemPrompt||t.systemPrompt,M=t.autoRouting?.telegram??!1,D=typeof S=="string"?jt(S,M):S,z=new re({...s.apiKey!==void 0?{apiKey:s.apiKey}:{},model:s.model,...D!==void 0?{systemPrompt:D}:{},maxTurns:100,...c!==void 0?{maxOutputTokens:c}:{},provider:u,hookRegistry:Lt()});return h=z,z}let d=s.systemPrompt||t.systemPrompt,p=t.autoRouting?.telegram??!1,f=typeof d=="string"?jt(d,p):d;return new re({...s.apiKey!==void 0?{apiKey:s.apiKey}:{},model:s.model,...f!==void 0?{systemPrompt:f}:{},maxTurns:100,...c!==void 0?{maxOutputTokens:c}:{},hookRegistry:Lt()})}});try{o.start(),console.log("\u2705 Bot started successfully!"),console.log(`
|
|
1376
|
+
${hc}`}function yc(t){if(typeof t!="object"||t===null)return;let e=t.name;if(typeof e!="string")return;let n=e.trim();return n.length>0?n:void 0}function bc(t){if(typeof t!="object"||t===null)throw new Error("Skill tool input must be an object");let e=t,n=e.name;if(typeof n!="string"||n.trim().length===0)throw new Error('Skill tool input must have a non-empty "name" field');let r,o=e.arguments;if(o!==void 0){if(typeof o!="string")throw new Error('Skill tool "arguments" must be a string');r=o}return{name:n.trim(),arguments:r}}var be=class{constructor(e){this.ctx=e}ctx;pluginBodies=null;async execute(e){if(e.signal.aborted)return{content:"Skill tool call aborted",isError:!0};let n=this.ctx.depth??0,r=this.ctx.maxDepth??Ie;if(n>=r){let l=yc(e.input);return ie({event:"delegation.skipped",parent_session_id:this.ctx.parentSession.sessionId,reason:"max_depth",depth:n,requested_name:l}).catch(()=>{}),{content:`Skill tool not available at nesting depth ${n} (max ${r})`,isError:!0}}let o;try{o=bc(e.input)}catch(l){return{content:`Skill tool input validation failed: ${l instanceof Error?l.message:String(l)}`,isError:!0}}try{let l=z(o.name);return await this.executeRegistrySkill(l,o.arguments,e.signal)}catch{}let s=this.getPluginSkillBody(o.name);if(s)return await this.executePluginSkill(o.name,s,o.arguments,e.signal);let a=Ae(this.ctx.pluginConfigs).map(l=>l.name).join(", ");return{content:`Skill "${o.name}" not found. Available skills: ${a||"(none)"}`,isError:!0}}async executeRegistrySkill(e,n,r){if(r.aborted)return{content:"Skill call aborted",isError:!0};if(e.context==="fork")return this.executeForkedRegistrySkill(e,n,r);try{let o=await e.handler(n&&n.length>0?n:void 0,this.ctx.parentSession,{apiKey:this.ctx.apiKey,defaultModel:this.ctx.defaultModel,defaultSubagentModel:this.ctx.defaultSubagentModel});return{content:typeof o=="string"?o:o!=null?JSON.stringify(o):"Skill completed successfully."}}catch(o){return{content:`Skill execution error: ${o instanceof Error?o.message:String(o)}`,isError:!0}}}async executeForkedRegistrySkill(e,n,r){if(r.aborted)return{content:"Skill call aborted",isError:!0};let o;try{if(o=P(e.name)["system.md"],!o)return{content:`Skill "${e.name}" has context: "fork" but no prompts/system.md found`,isError:!0}}catch(i){return{content:`Failed to load skill prompts: ${i instanceof Error?i.message:String(i)}`,isError:!0}}let s=new S({parentAbortSignal:r,apiKey:this.ctx.apiKey,progressSink:Z()});try{let i=await s.forkSubagent({parent:this.ctx.parentSession,config:{model:e.model??this.ctx.defaultSubagentModel??this.ctx.defaultModel??"sonnet",systemPrompt:o},idPrefix:`skill-fork-${e.name}`}),a=n&&n.length>0?n:"Run the skill.",l=await i.runToResult(a);return l.status==="succeeded"&&l.message?{content:l.message.content}:{content:l.error?.message??"Forked skill failed with no output",isError:!0}}catch(i){return{content:`Forked skill execution error: ${i instanceof Error?i.message:String(i)}`,isError:!0}}finally{await s.teardownAll()}}async executePluginSkill(e,n,r,o){if(o.aborted)return{content:"Skill call aborted",isError:!0};let s=new S({parentAbortSignal:o,apiKey:this.ctx.apiKey,progressSink:Z()});try{let i=await s.forkSubagent({parent:this.ctx.parentSession,config:{model:this.ctx.defaultSubagentModel??this.ctx.defaultModel??"sonnet",systemPrompt:n},idPrefix:`skill-${e}`}),a=r&&r.length>0?r:"Run the skill.",l=await i.runToResult(a);return l.status==="succeeded"&&l.message?{content:l.message.content}:{content:l.error?.message??"Plugin skill failed with no output",isError:!0}}catch(i){return{content:`Plugin skill execution error: ${i instanceof Error?i.message:String(i)}`,isError:!0}}finally{await s.teardownAll()}}getPluginSkillBody(e){return this.pluginBodies||(this.pluginBodies=lt(this.ctx.pluginConfigs)),this.pluginBodies.get(e)}};var Ie=3;function nn(t){return{sessionId:void 0,getInputStreamRef:()=>({pushUserMessage:()=>{}}),abortSignal:t}}var wc=[...Ee,"agent","skill"];function Vo(){return({childExecutor:t,childSkillExecutor:e})=>new re({permissions:{allowedTools:wc},subagentExecutor:t,skillExecutor:e})}function Yo(t,e){return(n,r,o)=>new be({parentSession:nn(o),defaultModel:t,apiKey:e,depth:n,maxDepth:r})}function vc(t){if(typeof t!="object"||t===null)throw new Error("Agent tool input must be an object");let e=t,n=e.prompt;if(typeof n!="string")throw new Error('Agent tool input must have a "prompt" field of type string');if(n.trim().length===0)throw new Error("Agent tool prompt cannot be empty");let r,o=e.model;if(o!==void 0){if(typeof o!="string")throw new Error("Agent tool model must be a string");r=o}let s=10,i=e.max_turns;if(i!==void 0){if(typeof i!="number")throw new Error("Agent tool max_turns must be a number");s=Math.max(1,Math.min(50,Math.floor(i)))}let a="agent-tool",l=e.id_prefix;if(l!==void 0){if(typeof l!="string")throw new Error("Agent tool id_prefix must be a string");a=l}return{prompt:n,model:r,max_turns:s,id_prefix:a}}function rn(t){try{return ie(t).catch(()=>{})}catch{return Promise.resolve()}}function Re(t,e=240){return t.length<=e?t:t.slice(0,e)+"\u2026"}function Qo(t){if(t!=null){if(typeof t=="string")return t.length;try{return JSON.stringify(t).length}catch{return}}}var kc=4096,Jo=1024;function Sc(t){if(t==null)return;let e=Qo(t);return e!==void 0&&e>kc?{truncated:!0,chars:e}:t}function xc(t){let e={status:t.status,error:Re(t.errorMessage,Jo),subagent_id:t.subagentId};t.schemaErrorMessage&&(e.schemaError=Re(t.schemaErrorMessage,Jo));let n=Sc(t.partialOutput);return n!==void 0&&(e.partialOutput=n),e}var gt=class t{constructor(e){this.ctx=e}ctx;async execute(e){if(e.signal.aborted)return{content:"Agent tool call aborted",isError:!0};let n;try{n=vc(e.input)}catch(u){return{content:`Agent tool input validation failed: ${u instanceof Error?u.message:String(u)}`,isError:!0}}let r=this.ctx.depth??0,o=this.ctx.maxDepth??Ie,s,i={model:n.model??this.ctx.defaultSubagentModel??"sonnet",apiKey:this.ctx.defaultConfig.apiKey,systemPrompt:this.ctx.defaultConfig.systemPrompt,maxTurns:n.max_turns};if(this.ctx.childProviderFactory&&r<o){s=new S({parentAbortSignal:e.signal});let u=new t({subagentManager:s,parentSession:nn(e.signal),defaultConfig:this.ctx.defaultConfig,defaultSubagentModel:this.ctx.defaultSubagentModel,childProviderFactory:this.ctx.childProviderFactory,childSkillExecutorFactory:this.ctx.childSkillExecutorFactory,depth:r+1,maxDepth:o}),p=this.ctx.childSkillExecutorFactory?this.ctx.childSkillExecutorFactory(r+1,o,e.signal):void 0;i.provider=this.ctx.childProviderFactory({childExecutor:u,childSkillExecutor:p})}let a;try{a=await this.ctx.subagentManager.forkSubagent({parent:this.ctx.parentSession,config:i,idPrefix:n.id_prefix})}catch(u){return{content:`Failed to fork subagent: ${u instanceof Error?u.message:String(u)}`,isError:!0}}let l=()=>{a.cancel()};e.signal.addEventListener("abort",l,{once:!0});let c=Date.now(),d=this.ctx.parentSession.sessionId;try{let u=await a.runToResult(n.prompt);if(u.status==="succeeded"&&u.message){let f=u.message.content;return rn({event:"subagent.completed",subagent_id:a.id,parent_session_id:d,status:u.status,duration_ms:Date.now()-c,content_chars:typeof f=="string"?f.length:void 0,depth:r}),{content:f}}let p=u.error?.message??"Subagent failed with no output";rn({event:"subagent.failed",subagent_id:a.id,parent_session_id:d,status:u.status,duration_ms:Date.now()-c,error_message:Re(p),schema_error:u.schemaError?Re(u.schemaError.message):void 0,partial_output_chars:Qo(u.partialOutput),depth:r});let m=xc({status:u.status,errorMessage:p,schemaErrorMessage:u.schemaError?.message,partialOutput:u.partialOutput,subagentId:a.id});return{content:JSON.stringify(m),isError:!0}}catch(u){let p=u instanceof Error?u.message:String(u);throw rn({event:"subagent.failed",subagent_id:a.id,parent_session_id:d,status:"failed",duration_ms:Date.now()-c,error_message:Re(p),depth:r}),u}finally{e.signal.removeEventListener("abort",l),await s?.teardownAll(),await a.teardown()}}};async function Ac(){let t;try{t=Qr()}catch(l){console.error("\u274C Configuration error:",l.message),process.exit(1)}let e=ge(t.model);if(e==="openai-codex"){let l=process.env.OPENAI_API_KEY||process.env.CODEX_API_KEY;console.log(l?"\u{1F4DD} Using OPENAI_API_KEY / CODEX_API_KEY for Codex auth":"\u{1F4DD} Using existing `codex login` state on disk for Codex auth")}else{let l=Te();(!l||l.length===0)&&(console.error("\u274C Claude models require ANTHROPIC_API_KEY or CLAUDE_CODE_OAUTH_TOKEN."),console.error(" Set one in your environment, run `afk login`, or sign in to Claude Code."),process.exit(1)),qe(l)==="oauth"?(process.env.CLAUDE_CODE_OAUTH_TOKEN=l,console.log("\u{1F4DD} Using CLAUDE_CODE_OAUTH_TOKEN for Anthropic auth (OAuth, auto-refresh on 401)")):(process.env.ANTHROPIC_API_KEY=l,console.log("\u{1F4DD} Using ANTHROPIC_API_KEY for Anthropic auth")),t.apiKey=l}Ic(fe());let n=process.env.TELEGRAM_BOT_TOKEN;n||(console.error("\u274C Error: TELEGRAM_BOT_TOKEN environment variable is required"),console.error(`
|
|
1377
|
+
How to get a bot token:`),console.error(" 1. Open Telegram and search for @BotFather"),console.error(" 2. Send /newbot and follow the instructions"),console.error(" 3. Run: afk telegram setup"),process.exit(1));let r=Fn(process.env.AFK_TELEGRAM_ALLOWED_CHAT_IDS,console.warn);r.size===0&&(console.error("\u274C Error: AFK_TELEGRAM_ALLOWED_CHAT_IDS must list at least one chat ID"),console.error(`
|
|
1378
|
+
This is an allowlist that gates who can message the bot.`),console.error("Run `afk telegram setup` to set it interactively, or set it manually:"),console.error(" AFK_TELEGRAM_ALLOWED_CHAT_IDS=123456789,-100987654321"),process.exit(1)),console.log("\u{1F50E} Validating bot token...");let o=await $n(n);o||(console.error("\u274C Error: TELEGRAM_BOT_TOKEN was rejected by Telegram (getMe failed)"),console.error(" The token may be revoked, malformed, or your network may be unreachable."),console.error(" Re-run `afk telegram setup` to refresh it."),process.exit(1));let s=o.username?`@${o.username}`:o.firstName;console.log(""),console.log(`\u{1F916} Starting Agent AFK Telegram Bot as ${s} (id ${o.id})`),console.log(`\u{1F4E1} Model: ${t.model} \xB7 Provider: ${e}`),console.log(`\u{1F512} Allowlist: ${r.size} chat ID(s)`);let i=new Q,a=new Ke({botToken:n,apiKey:t.apiKey??"",dataDir:process.env.TELEGRAM_DATA_DIR||"./data/telegram-sessions",defaultModel:t.model,verbose:process.env.TELEGRAM_VERBOSE==="true",allowedChatIds:r,settingSources:["user","project"],createSession:async l=>{let c=ue(l.model)??l.model;console.log(`Creating session with model: ${l.model} -> ${c}`);let u=ge(c)==="openai-codex",p=u?void 0:Xr(),m;if(!u){let b,R=l.apiKey??t.apiKey??"",U=new S({apiKey:R}),j={get sessionId(){return b?.sessionId},getInputStreamRef(){return b?.getInputStreamRef?.()??{pushUserMessage:()=>{}}},get abortSignal(){return b?.abortSignal??new AbortController().signal}},O=Vo(),T=new gt({subagentManager:U,parentSession:j,defaultConfig:{apiKey:R,systemPrompt:l.systemPrompt??t.systemPrompt},defaultSubagentModel:Gt(),childProviderFactory:O,childSkillExecutorFactory:Yo(l.model,R)}),C=new be({parentSession:j,defaultModel:l.model,defaultSubagentModel:Gt(),apiKey:R}),F=[...Ee,"agent","skill"];m=new re({permissions:{allowedTools:F},subagentExecutor:T,skillExecutor:C});let B=l.systemPrompt||t.systemPrompt,v=t.autoRouting?.telegram??!1,k=typeof B=="string"?tn(B,v):B,E=new ae({...l.apiKey!==void 0?{apiKey:l.apiKey}:{},model:l.model,...k!==void 0?{systemPrompt:k}:{},maxTurns:100,...p!==void 0?{maxOutputTokens:p}:{},provider:m,hookRegistry:en(void 0,"telegram",i).registry});return b=E,E}let f=l.systemPrompt||t.systemPrompt,h=t.autoRouting?.telegram??!1,g=typeof f=="string"?tn(f,h):f;return new ae({...l.apiKey!==void 0?{apiKey:l.apiKey}:{},model:l.model,...g!==void 0?{systemPrompt:g}:{},maxTurns:100,...p!==void 0?{maxOutputTokens:p}:{},hookRegistry:en(void 0,"telegram",i).registry})}});try{a.start(),console.log("\u2705 Bot started successfully!"),console.log(`
|
|
1279
1379
|
\u{1F4DD} Slash commands (Agent SDK):`),console.log(" /start - Welcome and command list"),console.log(" /help - Show command list"),console.log(" /clear - Clear conversation history"),console.log(" /compact - Compact history (summarize older messages)"),console.log(" /model - Switch model (opus/sonnet/haiku/gpt-5.4/...)"),console.log(`
|
|
1280
1380
|
\u{1F4AC} Send any message to chat with the agent.`),console.log(`
|
|
1281
|
-
\u23F9\uFE0F Press Ctrl+C to stop the bot.`);let
|
|
1282
|
-
\u{1F4CA} Stats: ${
|
|
1381
|
+
\u23F9\uFE0F Press Ctrl+C to stop the bot.`);let l=setInterval(()=>{let d=a.getStats();console.log(`
|
|
1382
|
+
\u{1F4CA} Stats: ${d.activeSessions} active sessions, ${d.totalChats} total chats`)},3e5),c=async()=>{console.log(`
|
|
1283
1383
|
|
|
1284
|
-
\u{1F6D1} Shutting down bot...`),clearInterval(
|
|
1384
|
+
\u{1F6D1} Shutting down bot...`),clearInterval(l),await a.stop(),i.close(),console.log("\u2705 Bot stopped."),process.exit(0)};process.on("SIGINT",c),process.on("SIGTERM",c)}catch(l){console.error("\u274C Failed to start bot:",l),process.exit(1)}}var Pc=["TELEGRAM_BOT_TOKEN","AFK_TELEGRAM_ALLOWED_CHAT_IDS","TELEGRAM_VERBOSE","TELEGRAM_DATA_DIR"];function _c(t){let e=new Map;if(!Ec(t))return e;try{let n=Tc(t,"utf-8");for(let r of n.split(`
|
|
1385
|
+
`)){let o=r.trim();if(!o||o.startsWith("#"))continue;let s=o.indexOf("=");if(s===-1)continue;let i=o.slice(0,s).trim(),a=o.slice(s+1).trim();(a.startsWith('"')&&a.endsWith('"')||a.startsWith("'")&&a.endsWith("'"))&&(a=a.slice(1,-1)),e.set(i,a)}}catch{}return e}function Ic(t){let e=_c(t);for(let n of Pc){let r=e.get(n);if(r===void 0)continue;let o=process.env[n];if(o!==void 0&&o!==r){let s=i=>{if(n!=="TELEGRAM_BOT_TOKEN")return i;let a=i.indexOf(":");return a===-1?`${i.slice(0,4)}***`:`${i.slice(0,a+1)}***`};console.log(`\u{1F527} ${n}: file value (${s(r)}) overrides shell value (${s(o)})`)}process.env[n]=r}}Ac().catch(t=>{console.error("\u274C Unhandled error:",t),process.exit(1)});
|