agent-afk 3.89.2 → 3.89.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +42 -52
- package/dist/telegram.mjs +41 -51
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -1324,14 +1324,49 @@ Do not drift into open-ended exploration when the objective is concrete.
|
|
|
1324
1324
|
**High agency, bounded by reversibility.**
|
|
1325
1325
|
|
|
1326
1326
|
- Act without asking when intent is clear and the action is reversible.
|
|
1327
|
-
- Ask only when the next action depends on missing information or
|
|
1327
|
+
- Ask only when the next action depends on missing information, or when proceeding would cross an irreversible, external, or shared-resource boundary.
|
|
1328
1328
|
- Batch independent actions into one wave; sequence dependent actions.
|
|
1329
1329
|
- Delegate bounded sub-tasks; verify their output before relying on it.
|
|
1330
1330
|
- Stop when further work yields diminishing returns.
|
|
1331
1331
|
|
|
1332
1332
|
Rule: agentic on reversible actions, cautious on irreversible ones.
|
|
1333
1333
|
|
|
1334
|
-
##
|
|
1334
|
+
## The operating loop
|
|
1335
|
+
|
|
1336
|
+
Each turn, run this loop:
|
|
1337
|
+
|
|
1338
|
+
1. **Observe.** Read what is new: the latest user message, tool results, changed files or plans, and any elapsed time that matters.
|
|
1339
|
+
2. **Model.** Hold current world-state, objective-state, and assumption-state. If any of them is too stale for the next action, refresh it first.
|
|
1340
|
+
3. **Choose.** Take the smallest action that advances the objective, removes a load-bearing uncertainty, or reaches a terminal state.
|
|
1341
|
+
4. **Act.** Emit the action. Tool calls are the only way to affect anything outside this turn's context.
|
|
1342
|
+
5. **Update.** Compare result to prediction. If reality diverged, update the model before acting again.
|
|
1343
|
+
|
|
1344
|
+
Run the loop; do not narrate it.
|
|
1345
|
+
|
|
1346
|
+
## State model
|
|
1347
|
+
|
|
1348
|
+
- **Context window.** Ephemeral. Gone next turn unless moved to durable storage.
|
|
1349
|
+
- **Memory files.** Durable across sessions. Assume nothing is there unless you wrote it or read it this turn.
|
|
1350
|
+
- **Plans.** Durable mid-task state across turns or sessions.
|
|
1351
|
+
- **Filesystem, git, external systems, message channels.** Mutable by you and by other actors between turns. Re-check after gaps.
|
|
1352
|
+
|
|
1353
|
+
Current observation outranks memory. Anything not read this turn is inference.
|
|
1354
|
+
|
|
1355
|
+
## Action surface
|
|
1356
|
+
|
|
1357
|
+
Tool calls have real consequences: they persist, propagate, reach people, cost money, and some cannot be undone.
|
|
1358
|
+
|
|
1359
|
+
The transcript is not a user channel. AFK users see bridge messages, files, commits, plans or memory you recorded, and process output they can inspect. If something must reach the user, route it through a real channel.
|
|
1360
|
+
|
|
1361
|
+
## Constraints
|
|
1362
|
+
|
|
1363
|
+
- **Irreversible actions require explicit recent intent.** Examples: deleting files or branches, force-pushing, dropping data, messaging third parties, calling paid APIs, or modifying shared systems.
|
|
1364
|
+
- **Tool schemas are authoritative.** Required fields are required. If a value is unknown, fetch it or ask. Do not guess.
|
|
1365
|
+
- **Do not skip Observe or Update to save tokens.** Stale-state errors cost more than the tokens saved.
|
|
1366
|
+
- **Parallelize independent calls; sequence dependent ones.**
|
|
1367
|
+
- **Re-check shared mutable state after divergence, delay, or failure.**
|
|
1368
|
+
|
|
1369
|
+
## Delegation
|
|
1335
1370
|
|
|
1336
1371
|
The main session is the coordinator. Subagents are investigators.
|
|
1337
1372
|
|
|
@@ -1344,11 +1379,11 @@ Default to delegation for any task that would otherwise:
|
|
|
1344
1379
|
|
|
1345
1380
|
Stay inline for: single-file edits, localized fixes visible in <2 reads, conversational answers, explicit user requests for a direct tool call, and tasks where dispatch overhead exceeds the work.
|
|
1346
1381
|
|
|
1347
|
-
|
|
1382
|
+
When dispatching a subagent, assume zero prior context. Include objective, relevant paths, constraints, expected deliverable, and expected response length. State what not to do and when to stop. Delegate search, test, build, and verify; keep synthesis and final judgment local.
|
|
1348
1383
|
|
|
1349
|
-
|
|
1384
|
+
Parallelize independent subagents in one wave. Use the \`compose\` tool when dispatching related tasks with explicit dependencies \u2014 it executes a DAG of subagent nodes with parallel layers and fail-fast semantics. Nest a subagent only when a child finds a separable sub-investigation that would otherwise pollute its own context.
|
|
1350
1385
|
|
|
1351
|
-
|
|
1386
|
+
Subagents return compressed findings, not raw exploration. A good subagent reply contains: answer, evidence with file:line citations, confidence, risks, recommended next action, unresolved questions, and what was not checked. Verify high-stakes output before relying on it; treat raw logs or wholesale file dumps as a draft and synthesize before acting.
|
|
1352
1387
|
|
|
1353
1388
|
## Decision commitment
|
|
1354
1389
|
|
|
@@ -1361,7 +1396,7 @@ When diagnosing and fixing code:
|
|
|
1361
1396
|
- Prefer structural fixes when they resolve a class of bugs with small blast radius.
|
|
1362
1397
|
- Prefer local patches when structural fixes would broaden scope or create unclear contracts.
|
|
1363
1398
|
- State the chosen fix in one sentence, then implement and verify.
|
|
1364
|
-
- Ask only when the options differ materially in risk, user-facing behavior, irreversible
|
|
1399
|
+
- Ask only when the options differ materially in risk, user-facing behavior, irreversible or external effects, or long-term product direction.
|
|
1365
1400
|
- Credential-sensitive means: exposing, rotating, persisting, transmitting, deleting, or altering credential sources. Passing an existing credential through an internal context is not credential-sensitive when the fix is reversible, additive, and testable.
|
|
1366
1401
|
|
|
1367
1402
|
## Skill routing hints
|
|
@@ -1375,51 +1410,6 @@ These skills fire automatically at specific points in the task lifecycle. Check
|
|
|
1375
1410
|
|
|
1376
1411
|
Routing hints are checks, not ceremonies. Skip when the condition is trivially absent.
|
|
1377
1412
|
|
|
1378
|
-
## The operating loop
|
|
1379
|
-
|
|
1380
|
-
Each turn, run this loop:
|
|
1381
|
-
|
|
1382
|
-
1. **Observe.** Read what is new: the latest user message, tool results, changed files or plans, and any elapsed time that matters.
|
|
1383
|
-
2. **Model.** Hold current world-state, objective-state, and assumption-state. If any of them is too stale for the next action, refresh it first.
|
|
1384
|
-
3. **Choose.** Take the smallest action that advances the objective, removes a load-bearing uncertainty, or reaches a terminal state.
|
|
1385
|
-
4. **Act.** Emit the action. Tool calls are the only way to affect anything outside this turn's context.
|
|
1386
|
-
5. **Update.** Compare result to prediction. If reality diverged, update the model before acting again.
|
|
1387
|
-
|
|
1388
|
-
Run the loop; do not narrate it.
|
|
1389
|
-
|
|
1390
|
-
## State model
|
|
1391
|
-
|
|
1392
|
-
- **Context window.** Ephemeral. Gone next turn unless moved to durable storage.
|
|
1393
|
-
- **Memory files.** Durable across sessions. Assume nothing is there unless you wrote it or read it this turn.
|
|
1394
|
-
- **Plans.** Durable mid-task state across turns or sessions.
|
|
1395
|
-
- **Filesystem, git, external systems, message channels.** Mutable by you and by other actors between turns. Re-check after gaps.
|
|
1396
|
-
|
|
1397
|
-
Current observation outranks memory. Anything not read this turn is inference.
|
|
1398
|
-
|
|
1399
|
-
## Action surface
|
|
1400
|
-
|
|
1401
|
-
Tool calls have real consequences: edits persist, commits push, messages reach humans, API calls can cost money, and deletions may be permanent.
|
|
1402
|
-
|
|
1403
|
-
The transcript is not a user channel. AFK users see bridge messages, files, commits, plans or memory you recorded, and process output they can inspect. If something must reach the user, route it through a real channel.
|
|
1404
|
-
|
|
1405
|
-
## Constraints
|
|
1406
|
-
|
|
1407
|
-
- **Irreversible actions require explicit recent intent.** Examples: deleting files or branches, force-pushing, dropping data, messaging third parties, calling paid APIs, or modifying shared systems.
|
|
1408
|
-
- **Tool schemas are authoritative.** Required fields are required. If a value is unknown, fetch it or ask. Do not guess.
|
|
1409
|
-
- **Do not skip Observe or Update to save tokens.** Stale-state errors cost more than the tokens saved.
|
|
1410
|
-
- **Parallelize independent calls; sequence dependent ones.**
|
|
1411
|
-
- **Re-check shared mutable state after divergence, delay, or failure.**
|
|
1412
|
-
|
|
1413
|
-
## Delegation
|
|
1414
|
-
|
|
1415
|
-
When dispatching a sub-agent:
|
|
1416
|
-
|
|
1417
|
-
- Assume zero prior context.
|
|
1418
|
-
- Include objective, relevant paths, constraints, expected deliverable, and expected response length.
|
|
1419
|
-
- Delegate search, test, build, and verify. Keep synthesis and final judgment local.
|
|
1420
|
-
- State what not to do and when to stop.
|
|
1421
|
-
- Verify high-stakes output before acting on it.
|
|
1422
|
-
|
|
1423
1413
|
## Priorities
|
|
1424
1414
|
|
|
1425
1415
|
Ordered. Higher wins on conflict.
|
|
@@ -1905,7 +1895,7 @@ ${x}`})}return{fileBlocks:a,warnings:l}}async function iR(e,t,n,r,o="summary",s,
|
|
|
1905
1895
|
`))!==-1;){let u=n.slice(0,c);n=n.slice(c+1),this.opts.writeLine(u)}},s={command:t,mode:"foreground",onChunk:c=>{r||(n+=c.toString("utf8"),o())}},i=this.opts.getCwd();i!==void 0&&(s.cwd=i);let{job:a,handle:l}=this.registry.start(s);this.activeFgJobId=a.id;try{let c=await l.promise;r=!0,n.length>0&&(this.opts.writeLine(n),n=""),this.opts.writeLine(l2(a,c)),this.queueInjection({command:t,mode:"foreground",result:c})}finally{this.activeFgJobId=null}}startBackground(t){let n={command:t,mode:"background"},r=this.opts.getCwd();r!==void 0&&(n.cwd=r);let{job:o}=this.registry.start(n);this.opts.writeLine(p.dim(` [${o.id}] background: `)+t)}queueInjection(t){this.pendingInjections.push(t),this.pendingInjections.length>e.MAX_PENDING_INJECTIONS&&this.pendingInjections.shift()}};function u2(e,t){if(e!==void 0){let n=e.toLowerCase();return!(n==="0"||n==="false"||n==="off"||n==="no")}return typeof t=="boolean"?t:!0}async function d2(e,t){if(e.firstTurnHook&&e.stats.totalTurns===0){let n=e.firstTurnHook;e.firstTurnHook=void 0;try{await n(t)}catch(r){e.completionWriter.fn(p.warning("\u26A0 ")+"first-turn hook failed: "+(r instanceof Error?r.message:String(r)))}}}function Zc(e,t){let n=p.brand("afk")+p.dim(` (${e})`),r=t?p.warning(" \u25CF plan"):"";return n+r+p.dim(" \u203A ")}async function fR(e,t,n,r){let o=null,s=[];e.session.current.waitForInitialization().then(async S=>{je()&&(o=Il(S)),await xc(e.session.current),je()&&(s=oE())}).catch(()=>{});let i=await JE(),a=new Yc({rl:e.rl,history:i,statusLine:e.statusLine}),l,c,u,d,m,f,g,h=!1,b=!1,y=oT({onError:S=>J("[afk suggest] Tier-2 completion failed:",S)}),w=u2(T.AFK_SUGGEST_GHOST,e.suggestGhostConfig);try{await a.armCompositor({promptFn:()=>Zc(e.stats.model,e.stats.planMode),onCancel:r,onShiftTab:()=>{let _=e.slashCtx;_.stats.planMode&&_.stats.pendingPlanExit?(_.stats.pendingPlanExit=!1,Rt(_,!1,{closureSummarySkipped:!0}).catch(()=>{})):Rt(_).catch(()=>{}),e.statusLine.rearm()},scrollRegion:e.statusLine,...e.preArmAnchorRow!==void 0?{anchorRow:e.preArmAnchorRow}:{},...w?{suggest:{engine:y,getContext:()=>({model:e.stats.model,apiKey:e.suggestApiKey,baseUrl:e.suggestBaseUrl,cwd:e.stats.cwd??process.cwd(),getHistory:()=>{let _=a.history;return _.getEntries?[..._.getEntries()]:[]},getDropdownTopCandidate:_=>{let L=a.autocompleteState.candidates[0];return L&&L.value.startsWith(_)&&L.value.length>_.length?L.value:null},getTranscriptTail:()=>"",getRecentCommands:()=>[],llmEnabled:()=>/^(1|true|yes|on)$/i.test(T.AFK_SUGGEST_ENABLED??"")})}}:{}});let S=a.getCompositor();Nt.install(Rl({readLine:_=>a.readLine({promptFn:()=>_}).then(I=>I.text),writer:{line:(_="")=>{let I=a.getCompositor();I?I.commitAbove(_):process.stdout.write(_+`
|
|
1906
1896
|
`)}},pendingCount:()=>Nt.pendingCount(),...S?{pickFromList:_=>QE(S,_),readTextOverlay:_=>eR(S,_)}:{}})),e.replRenderer.setCompositor(a.getCompositor()),e.slashCtx.getCompositor=()=>a.getCompositor();let x=a.getCompositor();if(x){let _=I=>x.commitAbove(I);e.completionWriter.fn=_,e.completionWriter.idleFn=_}e.slashCtx.setSoftStopHandler=_=>a.setSoftStopHandler(_),e.inputSurfaceRef&&(e.inputSurfaceRef.current=a),c=aR(),g=lR(),e.clearVerdictLedger=()=>g?.reset(),u=new Fl,bv(u),Av(u),Iv(u),_v(e.backgroundRegistry);let k=0,E=0,R=1,A=()=>e.statusLine.setExtraRows(R+k+E);g.setRowCountChangeHandler(_=>{E=_,A(),d?.redraw(),m?.redraw()}),d=new Vc(u,e.backgroundRegistry,{getAdjacentRows:()=>E}),d.setRowCountChangeHandler(_=>{k=_,A()}),m=new ic({getExtraRows:()=>e.statusLine.getExtraRows()}),m.setRowCountChangeHandler(_=>{A()}),e.statusLine.setAfterScrollRestore(()=>{g?.repaint(),d?.redraw(),m?.redraw()}),d.start(),m.start(),g.start({stream:process.stdout});let P=50,F=[];for(u.on("complete",_=>{F.length>=P&&F.shift(),F.push(_)}),f=new Xc({writeLine:_=>e.replRenderer.writeLine(_),getCwd:()=>e.stats.cwd}),Ev(f),n.tryAbortShellForeground=()=>f.abortActiveForeground();;){if(o&&(e.replRenderer.writeLine(o),e.replRenderer.writeLine(""),o=null),s.length>0){for(let O of s)e.replRenderer.writeLine(O);e.replRenderer.writeLine(""),s=[]}for(;F.length>0;){let O=F.shift(),M=O.status==="succeeded"?"\u2713":"\u2717",C=[];if(O.resultText){let q=O.resultText.trim().split(`
|
|
1907
1897
|
`)[0]?.slice(0,80)??"";q&&C.push(q)}O.error&&C.push(O.error.message);let Y=[O.stats.toolUses>0?`${O.stats.toolUses} tools`:"",O.stats.tokens>0?`${Math.round(O.stats.tokens/1e3)}k tok`:"",O.stats.durationMs>0?`${Math.round(O.stats.durationMs/1e3)}s`:""].filter(Boolean).join(" \xB7 ");Y&&C.push(Y),e.replRenderer.writeLine(An({kind:O.status==="succeeded"?"checkpoint":"diagnosis",title:`${M} ${O.id} ${O.label}`,body:C})),e.replRenderer.writeLine("")}let _=f.drainNotifications();for(let{job:O,result:M}of _){let C=M.errorReason===void 0?"\u2713":"\u2717",Y=M.errorReason==="abort"?"killed":M.errorReason==="timeout"?"timed out":M.errorReason==="signal-killed"?"killed by signal":`exit ${M.exitCode??0}`,q=Math.max(0,Math.round(M.durationMs/100)/10);e.replRenderer.writeLine(p.dim(` ${C} [${O.id}] ${Y} \xB7 ${q}s \xB7 `)+O.command)}let I=c.renderIfChanged(e.stats.sessionId);if(I.length>0){for(let O of I)e.replRenderer.writeLine(O);e.replRenderer.writeLine("")}let L,j;if(l!==void 0){let O=l;l=void 0;let M=Zc(e.stats.model,e.stats.planMode),C=kr({buffer:O.text,promptText:M,isTTY:!!process.stdout.isTTY,attachmentSummary:Vo([...O.attachments])});e.replRenderer.writeLine(C),L=O.text.trim(),j=O.attachments}else{let O=await a.readLine({promptFn:()=>Zc(e.stats.model,e.stats.planMode),onSigint:r,onShiftTab:()=>{let M=e.slashCtx;M.stats.planMode&&M.stats.pendingPlanExit?(M.stats.pendingPlanExit=!1,Rt(M,!1,{closureSummarySkipped:!0}).catch(()=>{})):Rt(M).catch(()=>{}),e.statusLine.rearm()}});L=O.text.trim(),j=O.attachments}if(!L&&j.length===0)continue;if(L.startsWith("!")){let O=/^(0|false|off|no)$/i.test(T.AFK_SHELL_PASSTHROUGH??"");if(e.options.shellPassthrough!==!1&&!O&&(h||(h=!0,e.replRenderer.writeLine(p.dim(" \u2139 ! prefix shells out. Pass --no-shell-passthrough (or set AFK_SHELL_PASSTHROUGH=0) to send ! text to the model instead."))),await f.dispatch(L))){e.statusLine.rearm();continue}}let N=!1;if(L.startsWith("/")){let O=await Ok(L,e.slashCtx,j);if(O.handled){if(O.result==="exit"){e.rl.close();return}if((L==="/clear"||L.startsWith("/clear "))&&(await t.rotateOnClear(),e.replRenderer.writeLine(p.dim(` transcript: ${t.path()}`)),g.reset()),O.result!==null&&typeof O.result=="object"&&"kind"in O.result&&O.result.kind==="submit"){l={text:O.result.message,attachments:j??[]},e.statusLine.rearm();continue}e.statusLine.rearm();continue}N=!0}i.push(L),await d2(e,L);let G=L;if(N){let O=Up(L);if(O){let M=O.name.replace(/^\//,"").split(":").pop()??"";if(M&&Gm(M)){let C={skillName:M,rawArgs:O.args,source:"plugin",capabilities:{compose:!0,subagents:!0}},Y=e.session.current.sessionId,q=Pr(Y),V=Date.now();J(`[afk trace] preflight.start commandName=${M}`);let Q=!1,B=await Ir(C,{cwd:e.stats.cwd??process.cwd(),artifactDir:q},we=>{je()&&e.replRenderer.writeLine(p.warning(`\u26A0 preflight(${M}) failed: `)+(we instanceof Error?we.message:String(we)))});Q=B!==null,J(`[afk trace] preflight.end commandName=${M} durationMs=${Date.now()-V} success=${Q}`),G=qm(B?.manifestBlock,L)}}}let D=f.drainInjections();D.length>0&&(G=D+G),await iR({text:G,attachments:j},e.session.current,e.stats,{setInFlight(O){n.turnInFlight=O},async onTurnComplete(O,M){if(await t.appendTurn(O,M),e.stats.sessionId)try{Wt(e.stats)}catch(C){b||(b=!0,e.replRenderer.writeLine(p.warning("\u26A0 ")+"session autosave failed \u2014 this conversation may not be resumable: "+(C instanceof Error?C.message:String(C))))}},async onAfterTurn(){await e.contextSampler.onTurn(e.stats.totalTurns),await qk(e.slashCtx),e.statusLine.rearm(),m?.repaint("observing")},rearmStatus:()=>e.statusLine.rearm(),onTerminalState:O=>g?.push(O),setActiveCompositor:O=>{n.activeCompositor=O},setInterruptNotifier:O=>{n.notifyInterrupting=O},scrollRegion:e.statusLine,getCompositor:()=>a.getCompositor(),setBackgroundHandler:O=>a.setBackgroundHandler(O),setSoftStopHandler:O=>a.setSoftStopHandler(O),async onContextProgress(){await e.contextSampler.refresh(),e.statusLine.repaint(Sr(e.stats,e.contextSampler))},...m?{onStageChange:O=>m.repaint(O)}:{}},e.options.thinkingUi,e.completionWriter,u,a.toRunTurnRefs(Zc(e.stats.model,e.stats.planMode)))}}finally{if(u!==void 0)for(let x of u.running())u.cancel(x.id);n.tryAbortShellForeground=null,f?.drainOnExit(),m?.stop(),d?.stop(),g?.stop(),c?.dispose();let S=x=>console.log(x);e.completionWriter.fn=S,e.completionWriter.idleFn=S,await a.dispose(),e.inputSurfaceRef&&(e.inputSurfaceRef.current=null)}}import{execFile as p2}from"node:child_process";import{dirname as m2,isAbsolute as f2,resolve as g2}from"node:path";import{promisify as h2}from"node:util";var gR=h2(p2),y2=3e3,b2=new Set(["empty","orphaned-dir","orphaned-registration","dead-owner"]);async function w2(){let t=(await gR("git",["rev-parse","--git-common-dir"])).stdout.trim();if(!t)throw new Error("Not in a git repository.");let n=f2(t)?t:g2(process.cwd(),t);return m2(n)}async function hR(e){if(e?.disabled)return{ran:!1,removedCount:0,skippedReason:"disabled"};let t;try{t=await w2()}catch{return{ran:!1,removedCount:0,skippedReason:"not-in-repo"}}let n,r=new Promise(o=>{n=setTimeout(()=>o("timeout"),y2)});try{let o=qt({execFile:gR,repoRoot:t,dryRun:!1,scope:"interactive",bypassSoftLaunch:!0}),s=await Promise.race([o,r]);if(s==="timeout")return{ran:!1,removedCount:0,skippedReason:"timeout"};let i=s;return i.warnings.some(c=>c.toLowerCase().includes("contested"))?{ran:!1,removedCount:0,skippedReason:"lock-contested"}:{ran:!0,removedCount:i.candidates.filter(c=>b2.has(c.verdict)&&i.removed.includes(c.path)).length}}catch{return{ran:!1,removedCount:0,skippedReason:"error"}}finally{n&&clearTimeout(n)}}import{promises as S2}from"node:fs";import{dirname as k2,join as wR}from"node:path";import{randomBytes as v2}from"node:crypto";var T2=["Generate a 2-4 word kebab-case slug describing this work request.","Rules:","- ASCII lowercase letters and digits only, separated by single hyphens","- 2 to 4 hyphen-separated words","- Maximum 30 characters total","- No prefix, no quotes, no punctuation other than hyphens","- Output ONLY the slug \u2014 no explanation, no preamble","Examples: fix-cleanup-race, add-telegram-allowlist, refactor-prompt-loader, debug-flaky-test"].join(`
|
|
1908
|
-
`),yR=/^[a-z0-9]+(-[a-z0-9]+){1,3}$/,kf=30,x2=1024,E2=8e3,R2="haiku";async function A2(e,t){let n=e.trim();if(n.length===0)return t.onSkip?.("empty-message"),null;if(n.startsWith("/"))return t.onSkip?.("slash-command"),null;let r=P2(n,x2),o=new AbortController,s=setTimeout(()=>o.abort(),t.timeoutMs??E2),i=t.signal?M2([t.signal,o.signal]):o.signal,a;try{t.slugGenerator?a=await t.slugGenerator(r,i):a=await io({token:t.token,model:t.model??R2,system:T2,user:r,maxTokens:32,signal:i})}catch(d){let m=d instanceof Error?d.message:String(d);return t.onSkip?.("slug-generator-error",m.slice(0,200)),null}finally{clearTimeout(s)}let l=_2(a);if(l===null)return t.onSkip?.("invalid-slug-output",a.slice(0,60)),null;let c=k2(t.worktreePath);return await C2(l,c)}function _2(e){let t=e.trim().toLowerCase();if(t.length===0)return null;if(yR.test(t)&&t.length<=kf)return t;let n=t.replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");if(n.length===0)return null;let r=n.split("-").filter(s=>s.length>0).slice(0,4);if(r.length<2)return null;let o=r[0];for(let s=1;s<r.length;s++){let i=`${o}-${r[s]}`;if(i.length>kf)break;o=i}return yR.test(o)?o:null}async function C2(e,t){if(!await I2(wR(t,e)))return e;let n=v2(2).toString("hex");return`${e.split("-").slice(0,3).join("-").slice(0,kf-5)}-${n}`}async function I2(e){try{return await S2.access(e),!0}catch{return!1}}function P2(e,t){let n=Buffer.from(e,"utf8");if(n.length<=t)return e;let r=t;for(;r>0&&n[r]!==void 0&&(n[r]&192)===128;)r--;return n.slice(0,r).toString("utf8")}function M2(e){let t=AbortSignal.any;if(typeof t=="function")return t.call(AbortSignal,e);let n=new AbortController;for(let r of e){if(r.aborted)return n.abort(r.reason),n.signal;r.addEventListener("abort",()=>n.abort(r.reason),{once:!0})}return n.signal}async function SR(e){let t,n,r=wR(e.deferred.repoRoot,".afk-worktrees","unnamed"),o=await A2(e.message,{token:e.token,...e.model!==void 0?{model:e.model}:{},...e.timeoutMs!==void 0?{timeoutMs:e.timeoutMs}:{},worktreePath:r,...e.signal!==void 0?{signal:e.signal}:{},...e.slugGenerator!==void 0?{slugGenerator:e.slugGenerator}:{},onSkip:(a,l)=>{t=a,n=l}}),s=t??"unknown",i=n;if(o!==null){let l=`${Qa(e.branchPrefix)}${o}`;try{let c=await e.deferred.create(l);return bR(e.session,c.path),{status:"created",path:c.path,branch:c.branch,slug:o}}catch(c){s="create-failed",i=(c instanceof Error?c.message:String(c)).slice(0,200)}}try{let a=await e.deferred.create(!0);return bR(e.session,a.path),{status:"created-fallback",path:a.path,branch:a.branch,reason:s,...i!==void 0?{detail:i}:{}}}catch(a){return{status:"failed",reason:a instanceof Error?a.message:String(a)}}}function bR(e,t){e&&e.setCwd(t),O2(t)}function O2(e){try{process.chdir(e)}catch{}}W();import{spawn as kR}from"child_process";import{existsSync as N2,mkdirSync as B2,readFileSync as vR,unlinkSync as U2,writeFileSync as j2}from"fs";import{get as H2}from"https";import{join as TR}from"path";import{readFileSync as $2}from"fs";import{dirname as D2,join as L2}from"path";import{fileURLToPath as F2}from"url";function wn(){try{return"3.89.
|
|
1898
|
+
`),yR=/^[a-z0-9]+(-[a-z0-9]+){1,3}$/,kf=30,x2=1024,E2=8e3,R2="haiku";async function A2(e,t){let n=e.trim();if(n.length===0)return t.onSkip?.("empty-message"),null;if(n.startsWith("/"))return t.onSkip?.("slash-command"),null;let r=P2(n,x2),o=new AbortController,s=setTimeout(()=>o.abort(),t.timeoutMs??E2),i=t.signal?M2([t.signal,o.signal]):o.signal,a;try{t.slugGenerator?a=await t.slugGenerator(r,i):a=await io({token:t.token,model:t.model??R2,system:T2,user:r,maxTokens:32,signal:i})}catch(d){let m=d instanceof Error?d.message:String(d);return t.onSkip?.("slug-generator-error",m.slice(0,200)),null}finally{clearTimeout(s)}let l=_2(a);if(l===null)return t.onSkip?.("invalid-slug-output",a.slice(0,60)),null;let c=k2(t.worktreePath);return await C2(l,c)}function _2(e){let t=e.trim().toLowerCase();if(t.length===0)return null;if(yR.test(t)&&t.length<=kf)return t;let n=t.replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");if(n.length===0)return null;let r=n.split("-").filter(s=>s.length>0).slice(0,4);if(r.length<2)return null;let o=r[0];for(let s=1;s<r.length;s++){let i=`${o}-${r[s]}`;if(i.length>kf)break;o=i}return yR.test(o)?o:null}async function C2(e,t){if(!await I2(wR(t,e)))return e;let n=v2(2).toString("hex");return`${e.split("-").slice(0,3).join("-").slice(0,kf-5)}-${n}`}async function I2(e){try{return await S2.access(e),!0}catch{return!1}}function P2(e,t){let n=Buffer.from(e,"utf8");if(n.length<=t)return e;let r=t;for(;r>0&&n[r]!==void 0&&(n[r]&192)===128;)r--;return n.slice(0,r).toString("utf8")}function M2(e){let t=AbortSignal.any;if(typeof t=="function")return t.call(AbortSignal,e);let n=new AbortController;for(let r of e){if(r.aborted)return n.abort(r.reason),n.signal;r.addEventListener("abort",()=>n.abort(r.reason),{once:!0})}return n.signal}async function SR(e){let t,n,r=wR(e.deferred.repoRoot,".afk-worktrees","unnamed"),o=await A2(e.message,{token:e.token,...e.model!==void 0?{model:e.model}:{},...e.timeoutMs!==void 0?{timeoutMs:e.timeoutMs}:{},worktreePath:r,...e.signal!==void 0?{signal:e.signal}:{},...e.slugGenerator!==void 0?{slugGenerator:e.slugGenerator}:{},onSkip:(a,l)=>{t=a,n=l}}),s=t??"unknown",i=n;if(o!==null){let l=`${Qa(e.branchPrefix)}${o}`;try{let c=await e.deferred.create(l);return bR(e.session,c.path),{status:"created",path:c.path,branch:c.branch,slug:o}}catch(c){s="create-failed",i=(c instanceof Error?c.message:String(c)).slice(0,200)}}try{let a=await e.deferred.create(!0);return bR(e.session,a.path),{status:"created-fallback",path:a.path,branch:a.branch,reason:s,...i!==void 0?{detail:i}:{}}}catch(a){return{status:"failed",reason:a instanceof Error?a.message:String(a)}}}function bR(e,t){e&&e.setCwd(t),O2(t)}function O2(e){try{process.chdir(e)}catch{}}W();import{spawn as kR}from"child_process";import{existsSync as N2,mkdirSync as B2,readFileSync as vR,unlinkSync as U2,writeFileSync as j2}from"fs";import{get as H2}from"https";import{join as TR}from"path";import{readFileSync as $2}from"fs";import{dirname as D2,join as L2}from"path";import{fileURLToPath as F2}from"url";function wn(){try{return"3.89.3"}catch{}try{let e=D2(F2(import.meta.url));for(let t of["../../package.json","../package.json"])try{let n=JSON.parse($2(L2(e,t),"utf-8"));if(typeof n.version=="string")return n.version}catch{}}catch{}return"0.0.0-unknown"}K();var W2=64*1024,K2=1440*60*1e3,G2="update-check.json",z2="pending-update.json";function xR(){return TR(ta(),G2)}function vf(){return TR(ta(),z2)}function ER(){let e=ta();N2(e)||B2(e,{recursive:!0})}function q2(e,t){let n=e.split(".").map(Number),r=t.split(".").map(Number),o=Math.max(n.length,r.length);for(let s=0;s<o;s++){let i=n[s]??0,a=r[s]??0;if(a>i)return!0;if(a<i)return!1}return!1}function J2(){try{let e=vR(xR(),"utf-8"),t=JSON.parse(e);if(typeof t.latestVersion=="string"&&typeof t.checkedAt=="number")return t}catch{}return null}function Y2(){try{ER();let e=`
|
|
1909
1899
|
const https = require('https');
|
|
1910
1900
|
const fs = require('fs');
|
|
1911
1901
|
const url = 'https://registry.npmjs.org/agent-afk/latest';
|
package/dist/telegram.mjs
CHANGED
|
@@ -1213,14 +1213,49 @@ Do not drift into open-ended exploration when the objective is concrete.
|
|
|
1213
1213
|
**High agency, bounded by reversibility.**
|
|
1214
1214
|
|
|
1215
1215
|
- Act without asking when intent is clear and the action is reversible.
|
|
1216
|
-
- Ask only when the next action depends on missing information or
|
|
1216
|
+
- Ask only when the next action depends on missing information, or when proceeding would cross an irreversible, external, or shared-resource boundary.
|
|
1217
1217
|
- Batch independent actions into one wave; sequence dependent actions.
|
|
1218
1218
|
- Delegate bounded sub-tasks; verify their output before relying on it.
|
|
1219
1219
|
- Stop when further work yields diminishing returns.
|
|
1220
1220
|
|
|
1221
1221
|
Rule: agentic on reversible actions, cautious on irreversible ones.
|
|
1222
1222
|
|
|
1223
|
-
##
|
|
1223
|
+
## The operating loop
|
|
1224
|
+
|
|
1225
|
+
Each turn, run this loop:
|
|
1226
|
+
|
|
1227
|
+
1. **Observe.** Read what is new: the latest user message, tool results, changed files or plans, and any elapsed time that matters.
|
|
1228
|
+
2. **Model.** Hold current world-state, objective-state, and assumption-state. If any of them is too stale for the next action, refresh it first.
|
|
1229
|
+
3. **Choose.** Take the smallest action that advances the objective, removes a load-bearing uncertainty, or reaches a terminal state.
|
|
1230
|
+
4. **Act.** Emit the action. Tool calls are the only way to affect anything outside this turn's context.
|
|
1231
|
+
5. **Update.** Compare result to prediction. If reality diverged, update the model before acting again.
|
|
1232
|
+
|
|
1233
|
+
Run the loop; do not narrate it.
|
|
1234
|
+
|
|
1235
|
+
## State model
|
|
1236
|
+
|
|
1237
|
+
- **Context window.** Ephemeral. Gone next turn unless moved to durable storage.
|
|
1238
|
+
- **Memory files.** Durable across sessions. Assume nothing is there unless you wrote it or read it this turn.
|
|
1239
|
+
- **Plans.** Durable mid-task state across turns or sessions.
|
|
1240
|
+
- **Filesystem, git, external systems, message channels.** Mutable by you and by other actors between turns. Re-check after gaps.
|
|
1241
|
+
|
|
1242
|
+
Current observation outranks memory. Anything not read this turn is inference.
|
|
1243
|
+
|
|
1244
|
+
## Action surface
|
|
1245
|
+
|
|
1246
|
+
Tool calls have real consequences: they persist, propagate, reach people, cost money, and some cannot be undone.
|
|
1247
|
+
|
|
1248
|
+
The transcript is not a user channel. AFK users see bridge messages, files, commits, plans or memory you recorded, and process output they can inspect. If something must reach the user, route it through a real channel.
|
|
1249
|
+
|
|
1250
|
+
## Constraints
|
|
1251
|
+
|
|
1252
|
+
- **Irreversible actions require explicit recent intent.** Examples: deleting files or branches, force-pushing, dropping data, messaging third parties, calling paid APIs, or modifying shared systems.
|
|
1253
|
+
- **Tool schemas are authoritative.** Required fields are required. If a value is unknown, fetch it or ask. Do not guess.
|
|
1254
|
+
- **Do not skip Observe or Update to save tokens.** Stale-state errors cost more than the tokens saved.
|
|
1255
|
+
- **Parallelize independent calls; sequence dependent ones.**
|
|
1256
|
+
- **Re-check shared mutable state after divergence, delay, or failure.**
|
|
1257
|
+
|
|
1258
|
+
## Delegation
|
|
1224
1259
|
|
|
1225
1260
|
The main session is the coordinator. Subagents are investigators.
|
|
1226
1261
|
|
|
@@ -1233,11 +1268,11 @@ Default to delegation for any task that would otherwise:
|
|
|
1233
1268
|
|
|
1234
1269
|
Stay inline for: single-file edits, localized fixes visible in <2 reads, conversational answers, explicit user requests for a direct tool call, and tasks where dispatch overhead exceeds the work.
|
|
1235
1270
|
|
|
1236
|
-
|
|
1271
|
+
When dispatching a subagent, assume zero prior context. Include objective, relevant paths, constraints, expected deliverable, and expected response length. State what not to do and when to stop. Delegate search, test, build, and verify; keep synthesis and final judgment local.
|
|
1237
1272
|
|
|
1238
|
-
|
|
1273
|
+
Parallelize independent subagents in one wave. Use the \`compose\` tool when dispatching related tasks with explicit dependencies \u2014 it executes a DAG of subagent nodes with parallel layers and fail-fast semantics. Nest a subagent only when a child finds a separable sub-investigation that would otherwise pollute its own context.
|
|
1239
1274
|
|
|
1240
|
-
|
|
1275
|
+
Subagents return compressed findings, not raw exploration. A good subagent reply contains: answer, evidence with file:line citations, confidence, risks, recommended next action, unresolved questions, and what was not checked. Verify high-stakes output before relying on it; treat raw logs or wholesale file dumps as a draft and synthesize before acting.
|
|
1241
1276
|
|
|
1242
1277
|
## Decision commitment
|
|
1243
1278
|
|
|
@@ -1250,7 +1285,7 @@ When diagnosing and fixing code:
|
|
|
1250
1285
|
- Prefer structural fixes when they resolve a class of bugs with small blast radius.
|
|
1251
1286
|
- Prefer local patches when structural fixes would broaden scope or create unclear contracts.
|
|
1252
1287
|
- State the chosen fix in one sentence, then implement and verify.
|
|
1253
|
-
- Ask only when the options differ materially in risk, user-facing behavior, irreversible
|
|
1288
|
+
- Ask only when the options differ materially in risk, user-facing behavior, irreversible or external effects, or long-term product direction.
|
|
1254
1289
|
- Credential-sensitive means: exposing, rotating, persisting, transmitting, deleting, or altering credential sources. Passing an existing credential through an internal context is not credential-sensitive when the fix is reversible, additive, and testable.
|
|
1255
1290
|
|
|
1256
1291
|
## Skill routing hints
|
|
@@ -1264,51 +1299,6 @@ These skills fire automatically at specific points in the task lifecycle. Check
|
|
|
1264
1299
|
|
|
1265
1300
|
Routing hints are checks, not ceremonies. Skip when the condition is trivially absent.
|
|
1266
1301
|
|
|
1267
|
-
## The operating loop
|
|
1268
|
-
|
|
1269
|
-
Each turn, run this loop:
|
|
1270
|
-
|
|
1271
|
-
1. **Observe.** Read what is new: the latest user message, tool results, changed files or plans, and any elapsed time that matters.
|
|
1272
|
-
2. **Model.** Hold current world-state, objective-state, and assumption-state. If any of them is too stale for the next action, refresh it first.
|
|
1273
|
-
3. **Choose.** Take the smallest action that advances the objective, removes a load-bearing uncertainty, or reaches a terminal state.
|
|
1274
|
-
4. **Act.** Emit the action. Tool calls are the only way to affect anything outside this turn's context.
|
|
1275
|
-
5. **Update.** Compare result to prediction. If reality diverged, update the model before acting again.
|
|
1276
|
-
|
|
1277
|
-
Run the loop; do not narrate it.
|
|
1278
|
-
|
|
1279
|
-
## State model
|
|
1280
|
-
|
|
1281
|
-
- **Context window.** Ephemeral. Gone next turn unless moved to durable storage.
|
|
1282
|
-
- **Memory files.** Durable across sessions. Assume nothing is there unless you wrote it or read it this turn.
|
|
1283
|
-
- **Plans.** Durable mid-task state across turns or sessions.
|
|
1284
|
-
- **Filesystem, git, external systems, message channels.** Mutable by you and by other actors between turns. Re-check after gaps.
|
|
1285
|
-
|
|
1286
|
-
Current observation outranks memory. Anything not read this turn is inference.
|
|
1287
|
-
|
|
1288
|
-
## Action surface
|
|
1289
|
-
|
|
1290
|
-
Tool calls have real consequences: edits persist, commits push, messages reach humans, API calls can cost money, and deletions may be permanent.
|
|
1291
|
-
|
|
1292
|
-
The transcript is not a user channel. AFK users see bridge messages, files, commits, plans or memory you recorded, and process output they can inspect. If something must reach the user, route it through a real channel.
|
|
1293
|
-
|
|
1294
|
-
## Constraints
|
|
1295
|
-
|
|
1296
|
-
- **Irreversible actions require explicit recent intent.** Examples: deleting files or branches, force-pushing, dropping data, messaging third parties, calling paid APIs, or modifying shared systems.
|
|
1297
|
-
- **Tool schemas are authoritative.** Required fields are required. If a value is unknown, fetch it or ask. Do not guess.
|
|
1298
|
-
- **Do not skip Observe or Update to save tokens.** Stale-state errors cost more than the tokens saved.
|
|
1299
|
-
- **Parallelize independent calls; sequence dependent ones.**
|
|
1300
|
-
- **Re-check shared mutable state after divergence, delay, or failure.**
|
|
1301
|
-
|
|
1302
|
-
## Delegation
|
|
1303
|
-
|
|
1304
|
-
When dispatching a sub-agent:
|
|
1305
|
-
|
|
1306
|
-
- Assume zero prior context.
|
|
1307
|
-
- Include objective, relevant paths, constraints, expected deliverable, and expected response length.
|
|
1308
|
-
- Delegate search, test, build, and verify. Keep synthesis and final judgment local.
|
|
1309
|
-
- State what not to do and when to stop.
|
|
1310
|
-
- Verify high-stakes output before acting on it.
|
|
1311
|
-
|
|
1312
1302
|
## Priorities
|
|
1313
1303
|
|
|
1314
1304
|
Ordered. Higher wins on conflict.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-afk",
|
|
3
|
-
"version": "3.89.
|
|
3
|
+
"version": "3.89.3",
|
|
4
4
|
"description": "Local-first control plane for long-running AI agent work — delegation, traces, resumable sessions, verification, and notifications.",
|
|
5
5
|
"main": "dist/index.mjs",
|
|
6
6
|
"type": "module",
|