@pencil-agent/nano-pencil 2.0.0-beta.9 → 2.0.1

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.
Files changed (44) hide show
  1. package/dist/build-meta.json +3 -3
  2. package/dist/core/extensions-host/index.d.ts +1 -1
  3. package/dist/core/extensions-host/types.d.ts +5 -8
  4. package/dist/core/mcp/mcp-client.d.ts +3 -1
  5. package/dist/core/mcp/mcp-client.js +6 -6
  6. package/dist/core/mcp/mcp-config.d.ts +3 -3
  7. package/dist/core/mcp/mcp-config.js +1 -1
  8. package/dist/core/mcp/mcp-manager.d.ts +5 -1
  9. package/dist/core/mcp/mcp-manager.js +1 -1
  10. package/dist/core/platform/config/resource-loader.d.ts +2 -0
  11. package/dist/core/platform/config/resource-loader.js +2 -2
  12. package/dist/core/runtime/agent-session.d.ts +12 -0
  13. package/dist/core/runtime/agent-session.js +8 -8
  14. package/dist/core/runtime/sdk.d.ts +8 -0
  15. package/dist/core/runtime/sdk.js +1 -1
  16. package/dist/extensions/builtin/goal/goal-controller.js +1 -1
  17. package/dist/extensions/builtin/goal/goal-prompts.js +4 -4
  18. package/dist/index.d.ts +5 -30
  19. package/dist/index.js +1 -1
  20. package/dist/models.d.ts +7 -0
  21. package/dist/models.js +1 -0
  22. package/dist/modes/interactive/interactive-mode.js +36 -36
  23. package/dist/node_modules/@pencil-agent/agent-core/dist/agent-loop.js +3 -2
  24. package/dist/node_modules/@pencil-agent/agent-core/dist/structured-adaptive-agent-loop.js +2 -1
  25. package/dist/packages/protocol/src/flags.d.ts +20 -0
  26. package/dist/packages/protocol/src/flags.js +0 -0
  27. package/dist/packages/protocol/src/hooks.d.ts +17 -0
  28. package/dist/packages/protocol/src/hooks.js +0 -0
  29. package/dist/packages/protocol/src/index.d.ts +4 -2
  30. package/dist/packages/protocol/src/index.js +1 -1
  31. package/dist/packages/protocol/src/lifecycle.d.ts +11 -21
  32. package/dist/public-config.d.ts +12 -0
  33. package/dist/public-config.js +1 -0
  34. package/dist/runtime.d.ts +9 -0
  35. package/dist/runtime.js +1 -0
  36. package/dist/session-compaction.d.ts +7 -0
  37. package/dist/session-compaction.js +1 -0
  38. package/dist/session.d.ts +7 -0
  39. package/dist/session.js +1 -0
  40. package/dist/skills.d.ts +7 -0
  41. package/dist/skills.js +1 -0
  42. package/dist/tools.d.ts +7 -0
  43. package/dist/tools.js +1 -0
  44. package/package.json +29 -1
@@ -1,3 +1,4 @@
1
- var ee=Object.defineProperty;var g=(e,t)=>ee(e,"name",{value:t,configurable:!0});import{EventStream as te}from"@pencil-agent/ai/events";import{isContextOverflow as se}from"@pencil-agent/ai/overflow";import{validateToolArguments as oe}from"@pencil-agent/ai/schema";import{streamSimple as ae}from"@pencil-agent/ai/stream";import{ToolNotFoundError as ne,ValidationError as Y}from"./errors.js";import{computeRecoveryMaxTokens as re,createOutputTokenRecoveryMessage as le,createTokenBudgetContinuation as ue}from"./agent-loop-continuations.js";import{createInterruptedToolResults as pe,createSkippedToolCallLimitResults as ie,enforceToolResultBatchSize as me}from"./agent-loop-tool-results.js";import{flushReadyToolUseSummaries as de,startToolUseSummary as ce}from"./agent-loop-tool-summaries.js";import{buildAgentRunPolicy as he,resolveAgentRunLoopFramework as ge}from"./agent-run-result.js";import{waitForAbortableOperation as N,waitForAssistantStream as _e,waitForAssistantStreamEvent as ye}from"./agent-loop-stream-events.js";const fe=256,Re=512,Te=3,Me=1,be=1;function He(e,t,s,a,o){const p=j();return(async()=>{const _=[...e],n={...t,messages:[...t.messages,...e]};try{p.push({type:"agent_start"}),p.push({type:"turn_start"});for(const m of e)p.push({type:"message_start",message:m}),p.push({type:"message_end",message:m});await G(n,_,s,a,p,o)}catch(m){z(p,_,s,m,a)}})(),p}g(He,"agentLoop");function Ke(e,t,s,a){if(e.messages.length===0)throw new Y("Cannot continue: no messages in context");if(e.messages[e.messages.length-1].role==="assistant")throw new Y("Cannot continue from message role: assistant");const o=j();return(async()=>{const p=[],_={...e};try{o.push({type:"agent_start"}),o.push({type:"turn_start"}),await G(_,p,t,s,o,a)}catch(n){z(o,p,t,n,s)}})(),o}g(Ke,"agentLoopContinue");function j(){return new te(e=>e.type==="agent_end",e=>e.type==="agent_end"?e.messages:[])}g(j,"createAgentStream");function E(e,t){return{role:"assistant",content:[{type:"text",text:""}],api:e.model.api,provider:e.model.provider,model:e.model.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"error",errorMessage:t,timestamp:Date.now()}}g(E,"createLoopLimitMessage");function z(e,t,s,a,o){const p=E(s,a instanceof Error?a.message:String(a));o?.aborted&&(p.stopReason="aborted"),t.push(p),e.push({type:"message_start",message:{...p}}),e.push({type:"message_end",message:p}),e.push({type:"turn_end",message:p,toolResults:[]}),I(e,t,{config:s,turnCount:0,toolCallCount:0,startedAt:Date.now(),usage:J(),permissionDenials:[],stopReason:p.stopReason,errorMessage:p.errorMessage,errorSubtype:o?.aborted?"aborted":"loop_error"})}g(z,"endWithLoopError");async function G(e,t,s,a,o,p){let _=!0,n=0,m=0;const b=Date.now(),M=J(),y=[],i=s.maxTurnsPerPrompt??fe,f=s.maxToolCallsPerPrompt??Re,k=s.maxStopHookContinuations??Te,R=s.maxModelErrorRecoveryAttempts??Me,x=s.maxOutputTokenRecoveryAttempts??be;let S=0,l=0,c=0,d,T={reason:"start"};const P=[],D=g(w=>(T=w,P.push(w),w),"recordTransition");let $=[],q=!1,U=0;const B=await N(s.getSteeringMessages?s.getSteeringMessages():[],a);if(B.type==="aborted"){K(o,e,t,{config:s,turnCount:n,toolCallCount:m,startedAt:b,usage:M,permissionDenials:y,transitions:P,lastTransition:T});return}let C=B.value||[];for(;;){let w=!0,L=null;for(;w||C.length>0;){if(_?_=!1:o.push({type:"turn_start"}),$=de($,e.messages,t,o),C.length>0){for(const r of C)o.push({type:"message_start",message:r}),o.push({type:"message_end",message:r}),e.messages.push(r),t.push(r);C=[]}if(n++,n>i){const r=E(s,`Stopped after ${i} assistant turns to prevent a runaway agent loop.`);e.messages.push(r),t.push(r),o.push({type:"message_start",message:{...r}}),o.push({type:"message_end",message:r}),o.push({type:"turn_end",message:r,toolResults:[]}),I(o,t,{config:s,turnCount:n,toolCallCount:m,startedAt:b,usage:M,permissionDenials:y,stopReason:r.stopReason,transitions:P,lastTransition:D({reason:"max_turns_reached",maxTurns:i,turnCount:n}),errorMessage:r.errorMessage,errorSubtype:"max_turns_reached"});return}const Z=t.length,h=await ke(e,s,a,o,p,d);if(Se(M,h.usage),d=void 0,t.push(h),h.stopReason==="error"||h.stopReason==="aborted"){const r=h.stopReason==="aborted"?"aborted":se(h,s.model.contextWindow)?"context_overflow":"model_error",A=pe(h);for(const u of A)e.messages.push(u),t.push(u),o.push({type:"message_start",message:u}),o.push({type:"message_end",message:u});if(h.stopReason==="error"&&s.recoverModelError&&S<R){const u=S+1,v=await s.recoverModelError({message:h,messages:e.messages,errorSubtype:r,attempt:u});if(v.action==="retry"){o.push({type:"turn_end",message:h,toolResults:A}),S=u,t.splice(Z),e.messages=v.messages,D(v.transition??{reason:"model_error_recovery",subtype:r,attempt:u});continue}}o.push({type:"turn_end",message:h,toolResults:A}),I(o,t,{config:s,turnCount:n,toolCallCount:m,startedAt:b,usage:M,permissionDenials:y,stopReason:h.stopReason,transitions:P,lastTransition:T,errorMessage:h.errorMessage,errorSubtype:r});return}const O=h.content.filter(r=>r.type==="toolCall");w=O.length>0;const F=[];if(w){if(m+O.length>f){const u=ie(h,`Tool call skipped because this prompt reached the ${f} tool-call limit.`);for(const W of u)e.messages.push(W),t.push(W),o.push({type:"message_start",message:W}),o.push({type:"message_end",message:W});const v=E(s,`Stopped before executing ${O.length} tool call${O.length===1?"":"s"} because this prompt reached the ${f} tool-call limit.`);e.messages.push(v),t.push(v),o.push({type:"message_start",message:{...v}}),o.push({type:"message_end",message:v}),o.push({type:"turn_end",message:v,toolResults:u}),I(o,t,{config:s,turnCount:n,toolCallCount:m,startedAt:b,usage:M,permissionDenials:y,stopReason:v.stopReason,transitions:P,lastTransition:D({reason:"tool_call_limit_reached",maxToolCalls:f,requestedToolCalls:O.length,toolCallCount:m}),errorMessage:v.errorMessage,errorSubtype:"tool_call_limit_reached"});return}m+=O.length;const r=await Ce(e.tools,h,a,o,s.getSteeringMessages,s.canUseTool);F.push(...me(r.toolResults,s.maxToolResultBatchSizeChars)),y.push(...ve(r.toolResults)),L=r.steeringMessages??null;for(const u of F)e.messages.push(u),t.push(u),o.push({type:"message_start",message:u}),o.push({type:"message_end",message:u});for(const u of r.contextMessages)e.messages.push(u),t.push(u),o.push({type:"message_start",message:u}),o.push({type:"message_end",message:u});const A=ce(s,{assistantMessage:h,toolResults:F,contextMessages:r.contextMessages,messages:e.messages});A&&$.push(A),D({reason:"tool_result",toolCallCount:O.length})}if(o.push({type:"turn_end",message:h,toolResults:F}),!w&&h.stopReason==="length"&&l<x){l+=1,d=re(s,h),C=[le(l)],D({reason:"max_output_tokens_recovery",attempt:l});continue}if(!w&&s.runStopHooks&&!q){q=!0;const r=await N(s.runStopHooks({message:h,messages:e.messages}),a);if(q=!1,r.type==="aborted"){K(o,e,t,{config:s,turnCount:n,toolCallCount:m,startedAt:b,usage:M,permissionDenials:y,transitions:P,lastTransition:T});return}const A=r.value;if(A.action==="continue"&&A.messages.length>0){if(U>=k){const u=E(s,`stop_hook_limit_reached: stopped after ${k} stop-hook continuation turns.`);e.messages.push(u),t.push(u),o.push({type:"message_start",message:{...u}}),o.push({type:"message_end",message:u}),o.push({type:"turn_end",message:u,toolResults:[]}),I(o,t,{config:s,turnCount:n,toolCallCount:m,startedAt:b,usage:M,permissionDenials:y,stopReason:u.stopReason,transitions:P,lastTransition:D({reason:"stop_hook_limit_reached",maxContinuations:k,continuationCount:U}),errorMessage:u.errorMessage,errorSubtype:"stop_hook_limit_reached"});return}U+=1,C=A.messages,D({reason:"stop_hook_blocking",continuationCount:U});continue}}if(!w){const r=ue(s,M.output,c);if(r){c+=1,C=[r.message],D({reason:"token_budget_continuation",continuationCount:c,outputTokens:r.outputTokens,targetTokens:r.targetTokens});continue}}L&&L.length>0?(C=L,L=null):C=await s.getSteeringMessages?.()||[]}const X=await N(s.getFollowUpMessages?s.getFollowUpMessages():[],a);if(X.type==="aborted"){K(o,e,t,{config:s,turnCount:n,toolCallCount:m,startedAt:b,usage:M,permissionDenials:y,transitions:P,lastTransition:T});return}const V=X.value||[];if(V.length>0){C=V,D({reason:"follow_up"});continue}break}I(o,t,{config:s,turnCount:n,toolCallCount:m,startedAt:b,usage:M,permissionDenials:y,stopReason:Q(t),transitions:P,lastTransition:T})}g(G,"runLoop");async function ke(e,t,s,a,o,p){let _=e.messages;if(t.transformContext){const l=await N(t.transformContext(_,s),s);if(l.type==="aborted")return H(e,a,t);_=l.value}const n=await N(t.convertToLlm(_),s);if(n.type==="aborted")return H(e,a,t);const m=n.value,b={systemPrompt:e.systemPrompt,messages:m,tools:e.tools},M=o||ae,y=await N(t.getApiKey?t.getApiKey(t.model.provider):void 0,s);if(y.type==="aborted")return H(e,a,t);const i=y.value||t.apiKey;a.push({type:"stream_request_start",model:t.model.id,provider:t.model.provider,api:t.model.api,messageCount:m.length,maxTokens:p??t.maxTokens});const f=await _e(M(t.model,b,{...t,maxTokens:p??t.maxTokens,apiKey:i,signal:s}),s);if(f==="aborted"){const l=E(t,"Request was aborted");return l.stopReason="aborted",e.messages.push(l),a.push({type:"message_start",message:{...l}}),a.push({type:"message_end",message:l}),l}let k=null,R=!1;const x=f[Symbol.asyncIterator]();for(;;){let l;try{l=await ye(x,s)}catch(d){const T=E(t,d instanceof Error?d.message:String(d));return R?e.messages[e.messages.length-1]=T:(e.messages.push(T),a.push({type:"message_start",message:{...T}})),a.push({type:"message_end",message:T}),T}if(l==="aborted"){x.return?.();const d=E(t,"Request was aborted");return d.stopReason="aborted",R?e.messages[e.messages.length-1]=d:(e.messages.push(d),a.push({type:"message_start",message:{...d}})),a.push({type:"message_end",message:d}),d}if(l.done)break;const c=l.value;switch(c.type){case"start":k=c.partial,e.messages.push(k),R=!0,a.push({type:"message_start",message:{...k}});break;case"text_start":case"text_delta":case"text_end":case"thinking_start":case"thinking_delta":case"thinking_end":case"toolcall_start":case"toolcall_delta":case"toolcall_end":k&&(k=c.partial,e.messages[e.messages.length-1]=k,a.push({type:"message_update",assistantMessageEvent:c,message:{...k}}));break;case"done":case"error":{const d=c.type==="done"?c.message:c.error;return R?e.messages[e.messages.length-1]=d:e.messages.push(d),R||a.push({type:"message_start",message:{...d}}),a.push({type:"message_end",message:d}),d}}}const S=f.resultIfResolved()??E(t,"Provider stream ended without a final assistant message");return R?e.messages[e.messages.length-1]=S:(e.messages.push(S),a.push({type:"message_start",message:{...S}})),a.push({type:"message_end",message:S}),S}g(ke,"streamAssistantResponse");function H(e,t,s){const a=E(s,"Request was aborted");return a.stopReason="aborted",e.messages.push(a),t.push({type:"message_start",message:{...a}}),t.push({type:"message_end",message:a}),a}g(H,"pushAbortedAssistantMessage");function K(e,t,s,a){const o=E(a.config,"Request was aborted");o.stopReason="aborted",t.messages.push(o),s.push(o),e.push({type:"message_start",message:{...o}}),e.push({type:"message_end",message:o}),e.push({type:"turn_end",message:o,toolResults:[]}),I(e,s,{...a,stopReason:"aborted",errorMessage:o.errorMessage,errorSubtype:"aborted"})}g(K,"finishStandardLoopWithAbortedTurn");function I(e,t,s){e.push({type:"agent_result",stopReason:s.stopReason??Q(t),loopFramework:ge(s.config),loopPolicy:he(s.config),turnCount:s.turnCount,toolCallCount:s.toolCallCount,durationMs:Date.now()-s.startedAt,usage:s.usage,permissionDenialCount:s.permissionDenials.length,permissionDenials:s.permissionDenials,transitions:s.transitions&&s.transitions.length>0?s.transitions:void 0,lastTransition:s.lastTransition,errorMessage:s.errorMessage,errorSubtype:s.errorSubtype}),e.push({type:"agent_end",messages:t}),e.end(t)}g(I,"finishStandardLoop");function J(){return{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}}}g(J,"emptyUsage");function Se(e,t){e.input+=t.input,e.output+=t.output,e.cacheRead+=t.cacheRead,e.cacheWrite+=t.cacheWrite,e.totalTokens+=t.totalTokens,e.cost.input+=t.cost.input,e.cost.output+=t.cost.output,e.cost.cacheRead+=t.cost.cacheRead,e.cost.cacheWrite+=t.cost.cacheWrite,e.cost.total+=t.cost.total}g(Se,"addUsage");function Q(e){for(let t=e.length-1;t>=0;t-=1){const s=e[t];if(s?.role==="assistant")return s.stopReason??"stop"}return"stop"}g(Q,"inferStopReason");function ve(e){const t=[];for(const s of e){const a=s.details;if(!a||typeof a!="object"||a.errorType!=="permission_denied")continue;const o=a.reason;t.push({toolCallId:s.toolCallId,toolName:s.toolName,reason:typeof o=="string"&&o.length>0?o:void 0})}return t}g(ve,"collectPermissionDenials");async function Ce(e,t,s,a,o,p){const _=t.content.filter(y=>y.type==="toolCall"),n=we(e),m=[],b=[];let M;for(let y=0;y<_.length;y++){const i=_[y],f=n.get(i.name),k=Date.now();a.push({type:"tool_execution_start",toolCallId:i.id,toolName:i.name,args:i.arguments});let R,x=!1;try{if(!f)throw new ne(i.name);const l=oe(f,i),c=await f.validateInput?.(l);if(typeof c=="string"&&c.trim())throw new Error(c);const d=await p?.({toolCallId:i.id,toolName:f.name,requestedToolName:i.name,input:l,rawInput:i.arguments,tool:f});if(d?.decision==="deny"){const T=d.reason?.trim();R={content:[{type:"text",text:T?`Permission denied: ${T}`:`Permission denied for ${f.name}`}],details:{errorType:"permission_denied",reason:T,toolName:f.name,toolCallId:i.id}},x=!0}else R=await f.execute(i.id,l,s,T=>{a.push({type:"tool_execution_update",toolCallId:i.id,toolName:i.name,args:i.arguments,partialResult:T})}),R=Ee(R,f.maxResultSizeChars)}catch(l){const c=l instanceof Error?l.message:String(l);R={content:[{type:"text",text:c}],details:Ae(c)?{errorType:"permission_denied",reason:c,toolName:f?.name??i.name,toolCallId:i.id}:{}},x=!0}a.push({type:"tool_execution_end",toolCallId:i.id,toolName:i.name,result:R,isError:x,durationMs:Date.now()-k});const S={role:"toolResult",toolCallId:i.id,toolName:i.name,content:R.content,details:R.details,isError:x,timestamp:Date.now()};if(m.push(S),b.push(...R.contextMessages??[]),o){const l=await o();if(l.length>0){M=l;const c=_.slice(y+1);for(const d of c)m.push(xe(d,a));break}}}return{toolResults:m,contextMessages:b,steeringMessages:M}}g(Ce,"executeToolCalls");function we(e){const t=new Map;for(const s of e??[]){t.set(s.name,s);for(const a of s.aliases??[])t.has(a)||t.set(a,s)}return t}g(we,"buildToolMap");function Ae(e){return/^Permission (denied|request was cancelled)/i.test(e.trim())}g(Ae,"isPermissionDeniedMessage");function Ee(e,t){if(!t||t<=0)return e;let s=Math.floor(t),a=!1;const o=e.content.map(n=>{if(n.type!=="text")return n;if(s<=0)return a=!0,{...n,text:""};if(n.text.length<=s)return s-=n.text.length,n;a=!0;const m=n.text.slice(0,s);return s=0,{...n,text:m}});if(!a)return e;const p=`
1
+ var se=Object.defineProperty;var h=(e,t)=>se(e,"name",{value:t,configurable:!0});import{EventStream as oe}from"@pencil-agent/ai/events";import{isContextOverflow as ae}from"@pencil-agent/ai/overflow";import{validateToolArguments as ne}from"@pencil-agent/ai/schema";import{streamSimple as re}from"@pencil-agent/ai/stream";import{ToolNotFoundError as le,ValidationError as G}from"./errors.js";import{computeRecoveryMaxTokens as ue,createOutputTokenRecoveryMessage as pe,createTokenBudgetContinuation as ie}from"./agent-loop-continuations.js";import{createInterruptedToolResults as me,createSkippedToolCallLimitResults as de,enforceToolResultBatchSize as ce}from"./agent-loop-tool-results.js";import{flushReadyToolUseSummaries as he,startToolUseSummary as ge}from"./agent-loop-tool-summaries.js";import{buildAgentRunPolicy as _e,resolveAgentRunLoopFramework as ye}from"./agent-run-result.js";import{waitForAbortableOperation as L,waitForAssistantStream as fe,waitForAssistantStreamEvent as Re}from"./agent-loop-stream-events.js";const Te=256,ke=512,Me=3,Se=1,be=1;function I(e){if(process.env.NANOPENCIL_DEBUG==="1")try{const{appendFileSync:t}=require("fs"),{join:s}=require("path"),{homedir:a}=require("os");t(s(a(),".nanopencil","agent","nanopencil-debug.log"),`[${new Date().toISOString()}] [loop] ${e}
2
+ `)}catch{}}h(I,"_tlog");function Ke(e,t,s,a,o){const i=J();return(async()=>{const p=[...e],n={...t,messages:[...t.messages,...e]};try{i.push({type:"agent_start"}),i.push({type:"turn_start"});for(const d of e)i.push({type:"message_start",message:d}),i.push({type:"message_end",message:d});await Z(n,p,s,a,i,o)}catch(d){Q(i,p,s,d,a)}})(),i}h(Ke,"agentLoop");function Xe(e,t,s,a){if(e.messages.length===0)throw new G("Cannot continue: no messages in context");if(e.messages[e.messages.length-1].role==="assistant")throw new G("Cannot continue from message role: assistant");const o=J();return(async()=>{const i=[],p={...e};try{o.push({type:"agent_start"}),o.push({type:"turn_start"}),await Z(p,i,t,s,o,a)}catch(n){Q(o,i,t,n,s)}})(),o}h(Xe,"agentLoopContinue");function J(){return new oe(e=>e.type==="agent_end",e=>e.type==="agent_end"?e.messages:[])}h(J,"createAgentStream");function x(e,t){return{role:"assistant",content:[{type:"text",text:""}],api:e.model.api,provider:e.model.provider,model:e.model.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"error",errorMessage:t,timestamp:Date.now()}}h(x,"createLoopLimitMessage");function Q(e,t,s,a,o){const i=x(s,a instanceof Error?a.message:String(a));o?.aborted&&(i.stopReason="aborted"),t.push(i),e.push({type:"message_start",message:{...i}}),e.push({type:"message_end",message:i}),e.push({type:"turn_end",message:i,toolResults:[]}),O(e,t,{config:s,turnCount:0,toolCallCount:0,startedAt:Date.now(),usage:ee(),permissionDenials:[],stopReason:i.stopReason,errorMessage:i.errorMessage,errorSubtype:o?.aborted?"aborted":"loop_error"})}h(Q,"endWithLoopError");async function Z(e,t,s,a,o,i){let p=!0,n=0,d=0;const k=Date.now(),D={loopStart:performance.now(),streamStart:0,firstTokenAt:0,turnCount:0};I("run_loop start");const g=ee(),r=[],T=s.maxTurnsPerPrompt??Te,C=s.maxToolCallsPerPrompt??ke,_=s.maxStopHookContinuations??Me,M=s.maxModelErrorRecoveryAttempts??Se,P=s.maxOutputTokenRecoveryAttempts??be;let S=0,l=0,y=0,c,R={reason:"start"};const E=[],$=h(A=>(R=A,E.push(A),A),"recordTransition");let H=[],B=!1,U=0;const j=await L(s.getSteeringMessages?s.getSteeringMessages():[],a);if(j.type==="aborted"){X(o,e,t,{config:s,turnCount:n,toolCallCount:d,startedAt:k,usage:g,permissionDenials:r,transitions:E,lastTransition:R});return}let v=j.value||[];for(;;){let A=!0,F=null;for(;A||v.length>0;){if(p?p=!1:o.push({type:"turn_start"}),H=he(H,e.messages,t,o),v.length>0){for(const u of v)o.push({type:"message_start",message:u}),o.push({type:"message_end",message:u}),e.messages.push(u),t.push(u);v=[]}if(n++,n>T){const u=x(s,`Stopped after ${T} assistant turns to prevent a runaway agent loop.`);e.messages.push(u),t.push(u),o.push({type:"message_start",message:{...u}}),o.push({type:"message_end",message:u}),o.push({type:"turn_end",message:u,toolResults:[]}),O(o,t,{config:s,turnCount:n,toolCallCount:d,startedAt:k,usage:g,permissionDenials:r,stopReason:u.stopReason,transitions:E,lastTransition:$({reason:"max_turns_reached",maxTurns:T,turnCount:n}),errorMessage:u.errorMessage,errorSubtype:"max_turns_reached"});return}D.turnCount++;const te=t.length,f=await Ce(e,s,a,o,i,c,D);if(ve(g,f.usage),c=void 0,t.push(f),f.stopReason==="error"||f.stopReason==="aborted"){const u=f.stopReason==="aborted"?"aborted":ae(f,s.model.contextWindow)?"context_overflow":"model_error",w=me(f);for(const m of w)e.messages.push(m),t.push(m),o.push({type:"message_start",message:m}),o.push({type:"message_end",message:m});if(f.stopReason==="error"&&s.recoverModelError&&S<M){const m=S+1,b=await s.recoverModelError({message:f,messages:e.messages,errorSubtype:u,attempt:m});if(b.action==="retry"){o.push({type:"turn_end",message:f,toolResults:w}),S=m,t.splice(te),e.messages=b.messages,$(b.transition??{reason:"model_error_recovery",subtype:u,attempt:m});continue}}o.push({type:"turn_end",message:f,toolResults:w}),O(o,t,{config:s,turnCount:n,toolCallCount:d,startedAt:k,usage:g,permissionDenials:r,stopReason:f.stopReason,transitions:E,lastTransition:R,errorMessage:f.errorMessage,errorSubtype:u});return}const N=f.content.filter(u=>u.type==="toolCall");A=N.length>0;const q=[];if(A){if(d+N.length>C){const m=de(f,`Tool call skipped because this prompt reached the ${C} tool-call limit.`);for(const W of m)e.messages.push(W),t.push(W),o.push({type:"message_start",message:W}),o.push({type:"message_end",message:W});const b=x(s,`Stopped before executing ${N.length} tool call${N.length===1?"":"s"} because this prompt reached the ${C} tool-call limit.`);e.messages.push(b),t.push(b),o.push({type:"message_start",message:{...b}}),o.push({type:"message_end",message:b}),o.push({type:"turn_end",message:b,toolResults:m}),O(o,t,{config:s,turnCount:n,toolCallCount:d,startedAt:k,usage:g,permissionDenials:r,stopReason:b.stopReason,transitions:E,lastTransition:$({reason:"tool_call_limit_reached",maxToolCalls:C,requestedToolCalls:N.length,toolCallCount:d}),errorMessage:b.errorMessage,errorSubtype:"tool_call_limit_reached"});return}d+=N.length;const u=await we(e.tools,f,a,o,s.getSteeringMessages,s.canUseTool);q.push(...ce(u.toolResults,s.maxToolResultBatchSizeChars)),r.push(...Ae(u.toolResults)),F=u.steeringMessages??null;for(const m of q)e.messages.push(m),t.push(m),o.push({type:"message_start",message:m}),o.push({type:"message_end",message:m});for(const m of u.contextMessages)e.messages.push(m),t.push(m),o.push({type:"message_start",message:m}),o.push({type:"message_end",message:m});const w=ge(s,{assistantMessage:f,toolResults:q,contextMessages:u.contextMessages,messages:e.messages});w&&H.push(w),$({reason:"tool_result",toolCallCount:N.length})}if(o.push({type:"turn_end",message:f,toolResults:q}),!A&&f.stopReason==="length"&&l<P){l+=1,c=ue(s,f),v=[pe(l)],$({reason:"max_output_tokens_recovery",attempt:l});continue}if(!A&&s.runStopHooks&&!B){B=!0;const u=await L(s.runStopHooks({message:f,messages:e.messages}),a);if(B=!1,u.type==="aborted"){X(o,e,t,{config:s,turnCount:n,toolCallCount:d,startedAt:k,usage:g,permissionDenials:r,transitions:E,lastTransition:R});return}const w=u.value;if(w.action==="continue"&&w.messages.length>0){if(U>=_){const m=x(s,`stop_hook_limit_reached: stopped after ${_} stop-hook continuation turns.`);e.messages.push(m),t.push(m),o.push({type:"message_start",message:{...m}}),o.push({type:"message_end",message:m}),o.push({type:"turn_end",message:m,toolResults:[]}),O(o,t,{config:s,turnCount:n,toolCallCount:d,startedAt:k,usage:g,permissionDenials:r,stopReason:m.stopReason,transitions:E,lastTransition:$({reason:"stop_hook_limit_reached",maxContinuations:_,continuationCount:U}),errorMessage:m.errorMessage,errorSubtype:"stop_hook_limit_reached"});return}U+=1,v=w.messages,$({reason:"stop_hook_blocking",continuationCount:U});continue}}if(!A){const u=ie(s,g.output,y);if(u){y+=1,v=[u.message],$({reason:"token_budget_continuation",continuationCount:y,outputTokens:u.outputTokens,targetTokens:u.targetTokens});continue}}F&&F.length>0?(v=F,F=null):v=await s.getSteeringMessages?.()||[]}const Y=await L(s.getFollowUpMessages?s.getFollowUpMessages():[],a);if(Y.type==="aborted"){X(o,e,t,{config:s,turnCount:n,toolCallCount:d,startedAt:k,usage:g,permissionDenials:r,transitions:E,lastTransition:R});return}const z=Y.value||[];if(z.length>0){v=z,$({reason:"follow_up"});continue}break}O(o,t,{config:s,turnCount:n,toolCallCount:d,startedAt:k,usage:g,permissionDenials:r,stopReason:V(t),transitions:E,lastTransition:R})}h(Z,"runLoop");async function Ce(e,t,s,a,o,i,p){let n=e.messages;if(t.transformContext){const l=await L(t.transformContext(n,s),s);if(l.type==="aborted")return K(e,a,t);n=l.value}const d=await L(t.convertToLlm(n),s);if(d.type==="aborted")return K(e,a,t);const k=d.value,D={systemPrompt:e.systemPrompt,messages:k,tools:e.tools},g=o||re,r=await L(t.getApiKey?t.getApiKey(t.model.provider):void 0,s);if(r.type==="aborted")return K(e,a,t);const T=r.value||t.apiKey;p&&(p.streamStart=performance.now(),I(`stream_request_start model=${t.model.id} provider=${t.model.provider} msgCount=${k.length} maxTokens=${i??t.maxTokens} (+${(p.streamStart-p.loopStart).toFixed(0)}ms from loop_start)`)),a.push({type:"stream_request_start",model:t.model.id,provider:t.model.provider,api:t.model.api,messageCount:k.length,maxTokens:i??t.maxTokens});const C=await fe(g(t.model,D,{...t,maxTokens:i??t.maxTokens,apiKey:T,signal:s}),s);if(C==="aborted"){const l=x(t,"Request was aborted");return l.stopReason="aborted",e.messages.push(l),a.push({type:"message_start",message:{...l}}),a.push({type:"message_end",message:l}),l}let _=null,M=!1;const P=C[Symbol.asyncIterator]();for(;;){let l;try{l=await Re(P,s)}catch(c){const R=x(t,c instanceof Error?c.message:String(c));return M?e.messages[e.messages.length-1]=R:(e.messages.push(R),a.push({type:"message_start",message:{...R}})),a.push({type:"message_end",message:R}),R}if(l==="aborted"){P.return?.();const c=x(t,"Request was aborted");return c.stopReason="aborted",M?e.messages[e.messages.length-1]=c:(e.messages.push(c),a.push({type:"message_start",message:{...c}})),a.push({type:"message_end",message:c}),c}if(l.done)break;const y=l.value;switch(p&&!p.firstTokenAt&&(p.firstTokenAt=performance.now(),I(`first_token ttft=${(p.firstTokenAt-p.streamStart).toFixed(0)}ms (+${(p.firstTokenAt-p.loopStart).toFixed(0)}ms from loop_start)`)),y.type){case"start":_=y.partial,e.messages.push(_),M=!0,a.push({type:"message_start",message:{..._}});break;case"text_start":case"text_delta":case"text_end":case"thinking_start":case"thinking_delta":case"thinking_end":case"toolcall_start":case"toolcall_delta":case"toolcall_end":_&&(_=y.partial,e.messages[e.messages.length-1]=_,a.push({type:"message_update",assistantMessageEvent:y,message:{..._}}));break;case"done":case"error":{const c=y.type==="done"?y.message:y.error;return M?e.messages[e.messages.length-1]=c:e.messages.push(c),M||a.push({type:"message_start",message:{...c}}),a.push({type:"message_end",message:c}),c}}}if(p){const l=performance.now();I(`stream_end duration=${(l-p.streamStart).toFixed(0)}ms total=${(l-p.loopStart).toFixed(0)}ms`)}const S=C.resultIfResolved()??x(t,"Provider stream ended without a final assistant message");return M?e.messages[e.messages.length-1]=S:(e.messages.push(S),a.push({type:"message_start",message:{...S}})),a.push({type:"message_end",message:S}),S}h(Ce,"streamAssistantResponse");function K(e,t,s){const a=x(s,"Request was aborted");return a.stopReason="aborted",e.messages.push(a),t.push({type:"message_start",message:{...a}}),t.push({type:"message_end",message:a}),a}h(K,"pushAbortedAssistantMessage");function X(e,t,s,a){const o=x(a.config,"Request was aborted");o.stopReason="aborted",t.messages.push(o),s.push(o),e.push({type:"message_start",message:{...o}}),e.push({type:"message_end",message:o}),e.push({type:"turn_end",message:o,toolResults:[]}),O(e,s,{...a,stopReason:"aborted",errorMessage:o.errorMessage,errorSubtype:"aborted"})}h(X,"finishStandardLoopWithAbortedTurn");function O(e,t,s){e.push({type:"agent_result",stopReason:s.stopReason??V(t),loopFramework:ye(s.config),loopPolicy:_e(s.config),turnCount:s.turnCount,toolCallCount:s.toolCallCount,durationMs:Date.now()-s.startedAt,usage:s.usage,permissionDenialCount:s.permissionDenials.length,permissionDenials:s.permissionDenials,transitions:s.transitions&&s.transitions.length>0?s.transitions:void 0,lastTransition:s.lastTransition,errorMessage:s.errorMessage,errorSubtype:s.errorSubtype}),I(`loop_finished stopReason=${s.stopReason??V(t)} turns=${s.turnCount} tools=${s.toolCallCount} duration=${Date.now()-s.startedAt}ms`),e.push({type:"agent_end",messages:t}),e.end(t)}h(O,"finishStandardLoop");function ee(){return{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}}}h(ee,"emptyUsage");function ve(e,t){e.input+=t.input,e.output+=t.output,e.cacheRead+=t.cacheRead,e.cacheWrite+=t.cacheWrite,e.totalTokens+=t.totalTokens,e.cost.input+=t.cost.input,e.cost.output+=t.cost.output,e.cost.cacheRead+=t.cost.cacheRead,e.cost.cacheWrite+=t.cost.cacheWrite,e.cost.total+=t.cost.total}h(ve,"addUsage");function V(e){for(let t=e.length-1;t>=0;t-=1){const s=e[t];if(s?.role==="assistant")return s.stopReason??"stop"}return"stop"}h(V,"inferStopReason");function Ae(e){const t=[];for(const s of e){const a=s.details;if(!a||typeof a!="object"||a.errorType!=="permission_denied")continue;const o=a.reason;t.push({toolCallId:s.toolCallId,toolName:s.toolName,reason:typeof o=="string"&&o.length>0?o:void 0})}return t}h(Ae,"collectPermissionDenials");async function we(e,t,s,a,o,i){const p=t.content.filter(g=>g.type==="toolCall"),n=xe(e),d=[],k=[];let D;for(let g=0;g<p.length;g++){const r=p[g],T=n.get(r.name),C=Date.now();I(`tool_exec_start [${g}] name=${r.name}`),a.push({type:"tool_execution_start",toolCallId:r.id,toolName:r.name,args:r.arguments});let _,M=!1;try{if(!T)throw new le(r.name);const l=ne(T,r),y=await T.validateInput?.(l);if(typeof y=="string"&&y.trim())throw new Error(y);const c=await i?.({toolCallId:r.id,toolName:T.name,requestedToolName:r.name,input:l,rawInput:r.arguments,tool:T});if(c?.decision==="deny"){const R=c.reason?.trim();_={content:[{type:"text",text:R?`Permission denied: ${R}`:`Permission denied for ${T.name}`}],details:{errorType:"permission_denied",reason:R,toolName:T.name,toolCallId:r.id}},M=!0}else _=await T.execute(r.id,l,s,R=>{a.push({type:"tool_execution_update",toolCallId:r.id,toolName:r.name,args:r.arguments,partialResult:R})}),_=$e(_,T.maxResultSizeChars)}catch(l){const y=l instanceof Error?l.message:String(l);_={content:[{type:"text",text:y}],details:Ee(y)?{errorType:"permission_denied",reason:y,toolName:T?.name??r.name,toolCallId:r.id}:{}},M=!0}const P=Date.now()-C;a.push({type:"tool_execution_end",toolCallId:r.id,toolName:r.name,result:_,isError:M,durationMs:P}),I(`tool_exec_end [${g}] name=${r.name} duration=${P}ms`);const S={role:"toolResult",toolCallId:r.id,toolName:r.name,content:_.content,details:_.details,isError:M,timestamp:Date.now()};if(d.push(S),k.push(..._.contextMessages??[]),o){const l=await o();if(l.length>0){D=l;const y=p.slice(g+1);for(const c of y)d.push(De(c,a));break}}}return{toolResults:d,contextMessages:k,steeringMessages:D}}h(we,"executeToolCalls");function xe(e){const t=new Map;for(const s of e??[]){t.set(s.name,s);for(const a of s.aliases??[])t.has(a)||t.set(a,s)}return t}h(xe,"buildToolMap");function Ee(e){return/^Permission (denied|request was cancelled)/i.test(e.trim())}h(Ee,"isPermissionDeniedMessage");function $e(e,t){if(!t||t<=0)return e;let s=Math.floor(t),a=!1;const o=e.content.map(n=>{if(n.type!=="text")return n;if(s<=0)return a=!0,{...n,text:""};if(n.text.length<=s)return s-=n.text.length,n;a=!0;const d=n.text.slice(0,s);return s=0,{...n,text:d}});if(!a)return e;const i=`
2
3
 
3
- [Tool result truncated to ${Math.floor(t)} characters.]`;let _=-1;for(let n=o.length-1;n>=0;n-=1)if(o[n]?.type==="text"){_=n;break}if(_>=0){const n=o[_];o[_]={...n,text:`${n.text}${p}`}}else o.push({type:"text",text:p.trimStart()});return{...e,content:o}}g(Ee,"enforceMaxResultSize");function xe(e,t){const s={content:[{type:"text",text:"Skipped due to queued user message."}],details:{}};return t.push({type:"tool_execution_start",toolCallId:e.id,toolName:e.name,args:e.arguments}),t.push({type:"tool_execution_end",toolCallId:e.id,toolName:e.name,result:s,isError:!0}),{role:"toolResult",toolCallId:e.id,toolName:e.name,content:s.content,details:{},isError:!0,timestamp:Date.now()}}g(xe,"skipToolCall");export{He as agentLoop,Ke as agentLoopContinue};
4
+ [Tool result truncated to ${Math.floor(t)} characters.]`;let p=-1;for(let n=o.length-1;n>=0;n-=1)if(o[n]?.type==="text"){p=n;break}if(p>=0){const n=o[p];o[p]={...n,text:`${n.text}${i}`}}else o.push({type:"text",text:i.trimStart()});return{...e,content:o}}h($e,"enforceMaxResultSize");function De(e,t){const s={content:[{type:"text",text:"Skipped due to queued user message."}],details:{}};return t.push({type:"tool_execution_start",toolCallId:e.id,toolName:e.name,args:e.arguments}),t.push({type:"tool_execution_end",toolCallId:e.id,toolName:e.name,result:s,isError:!0}),{role:"toolResult",toolCallId:e.id,toolName:e.name,content:s.content,details:{},isError:!0,timestamp:Date.now()}}h(De,"skipToolCall");export{Ke as agentLoop,Xe as agentLoopContinue};
@@ -1 +1,2 @@
1
- var q=Object.defineProperty;var d=(e,s)=>q(e,"name",{value:s,configurable:!0});import{EventStream as $}from"@pencil-agent/ai/events";import{isContextOverflow as z}from"@pencil-agent/ai/overflow";import{streamSimple as N}from"@pencil-agent/ai/stream";import{resolveMaxToolConcurrency as X,runStructuredAdaptiveTools as V}from"./structured-adaptive-tool-orchestration.js";import{StructuredAdaptiveStreamingToolExecutor as Y}from"./structured-adaptive-streaming-tool-executor.js";import{ValidationError as L}from"./errors.js";import{computeRecoveryMaxTokens as Q,createOutputTokenRecoveryMessage as j,createTokenBudgetContinuation as G}from"./agent-loop-continuations.js";import{createInterruptedToolResults as J,createSkippedToolCallLimitResults as Z,enforceToolResultBatchSize as x}from"./agent-loop-tool-results.js";import{flushReadyToolUseSummaries as ee,startToolUseSummary as se}from"./agent-loop-tool-summaries.js";import{buildAgentRunPolicy as te,resolveAgentRunLoopFramework as oe}from"./agent-run-result.js";import{waitForAbortableOperation as E,waitForAssistantStream as ae,waitForAssistantStreamEvent as ne}from"./agent-loop-stream-events.js";const re=256,ue=512,pe=1,ie=3,le=1;function Me(e,s,o,r,a){const p=F();return(async()=>{const _=[...e],y={...s,messages:[...s.messages,...e]};try{p.push({type:"agent_start"}),p.push({type:"turn_start"});for(const C of e)p.push({type:"message_start",message:C}),p.push({type:"message_end",message:C});await W(y,_,o,r,p,a)}catch(C){B(p,_,o,C,r)}})(),p}d(Me,"structuredAdaptiveAgentLoop");function be(e,s,o,r){if(e.messages.length===0)throw new L("Cannot continue: no messages in context");if(e.messages[e.messages.length-1].role==="assistant")throw new L("Cannot continue from message role: assistant");const a=F();return(async()=>{const p=[],_={...e};try{a.push({type:"agent_start"}),a.push({type:"turn_start"}),await W(_,p,s,o,a,r)}catch(y){B(a,p,s,y,o)}})(),a}d(be,"structuredAdaptiveAgentLoopContinue");function F(){return new $(e=>e.type==="agent_end",e=>e.type==="agent_end"?e.messages:[])}d(F,"createAgentStream");async function W(e,s,o,r,a,p){const _=o.maxTurnsPerPrompt??re,y=o.maxToolCallsPerPrompt??ue,C=o.maxOutputTokenRecoveryAttempts??pe,b=o.maxStopHookContinuations??ie,U=o.maxModelErrorRecoveryAttempts??le,A=await E(o.getSteeringMessages?o.getSteeringMessages():[],r),t={config:o,turnCount:0,toolCallCount:0,transition:{reason:"start"},transitions:[],pendingMessages:A.type==="resolved"?A.value||[]:[],pendingToolUseSummaries:[],stopHookActive:!1,stopHookContinuationCount:0,maxOutputTokensRecoveryCount:0,modelErrorRecoveryCount:0,tokenBudgetContinuationCount:0,hasAttemptedReactiveCompact:!1,startedAt:Date.now(),usage:K(),permissionDenials:[]};if(A.type==="aborted"){H(a,e,s,t);return}let O=!0;for(;;){if(O?O=!1:a.push({type:"turn_start"}),t.pendingToolUseSummaries=ee(t.pendingToolUseSummaries,e.messages,s,a),t.pendingMessages.length>0){for(const n of t.pendingMessages)a.push({type:"message_start",message:n}),a.push({type:"message_end",message:n}),e.messages.push(n),s.push(n);t.pendingMessages=[]}if(t.turnCount+=1,t.turnCount>_){const n=T(o,`max_turns_reached: stopped after ${_} assistant turns to prevent a runaway agent loop.`);e.messages.push(n),s.push(n),a.push({type:"message_start",message:{...n}}),a.push({type:"message_end",message:n}),a.push({type:"turn_end",message:n,toolResults:[]}),v(t,{reason:"max_turns_reached",maxTurns:_,turnCount:t.turnCount}),t.finalStopReason="error",t.finalErrorMessage=n.errorMessage,t.finalErrorSubtype="max_turns_reached",M(a,s,t);return}const k=new Y(e.tools,r,a,X(o.maxToolConcurrency),o.canUseTool),g=s.length,u=await me(e,o,r,a,p,t.maxOutputTokensOverride,k);if(s.push(u),de(t.usage,u.usage),t.maxOutputTokensOverride=void 0,u.stopReason==="error"||u.stopReason==="aborted"){const n=u.stopReason==="aborted"?"aborted":z(u,o.model.contextWindow)?"context_overflow":"model_error",l=k.size>0?await k.discardAndDrain(u.stopReason==="aborted"?"assistant stream aborted":"assistant stream error",u.stopReason==="aborted"?"cancel":"all"):{toolResults:[],contextMessages:[],permissionDenials:[]},f=x(l.toolResults,o.maxToolResultBatchSizeChars),w=J(u,new Set(f.map(i=>i.toolCallId))),S=[...f,...w];for(const i of S)e.messages.push(i),s.push(i),a.push({type:"message_start",message:i}),a.push({type:"message_end",message:i});for(const i of l.contextMessages)e.messages.push(i),s.push(i),a.push({type:"message_start",message:i}),a.push({type:"message_end",message:i});if(u.stopReason==="error"&&o.recoverModelError&&t.modelErrorRecoveryCount<U){const i=t.modelErrorRecoveryCount+1,D=await o.recoverModelError({message:u,messages:e.messages,errorSubtype:n,attempt:i});if(D.action==="retry"){a.push({type:"turn_end",message:u,toolResults:S}),t.modelErrorRecoveryCount=i,s.splice(g),e.messages=D.messages,v(t,D.transition??{reason:"model_error_recovery",subtype:n,attempt:i});continue}}t.permissionDenials.push(...l.permissionDenials),a.push({type:"turn_end",message:u,toolResults:S}),t.finalStopReason=u.stopReason,t.finalErrorMessage=u.errorMessage,t.finalErrorSubtype=n,M(a,s,t);return}const R=u.content.filter(n=>n.type==="toolCall");if(R.length===0){if(a.push({type:"turn_end",message:u,toolResults:[]}),u.stopReason==="length"&&t.maxOutputTokensRecoveryCount<C){t.maxOutputTokensRecoveryCount+=1,t.maxOutputTokensOverride=Q(o,u),t.pendingMessages=[j(t.maxOutputTokensRecoveryCount)],v(t,{reason:"max_output_tokens_recovery",attempt:t.maxOutputTokensRecoveryCount});continue}if(o.runStopHooks&&!t.stopHookActive){t.stopHookActive=!0;const w=await E(o.runStopHooks({message:u,messages:e.messages}),r);if(t.stopHookActive=!1,w.type==="aborted"){H(a,e,s,t);return}const S=w.value;if(S.action==="continue"&&S.messages.length>0){if(t.stopHookContinuationCount>=b){const i=T(o,`stop_hook_limit_reached: stopped after ${b} stop-hook continuation turns.`);e.messages.push(i),s.push(i),a.push({type:"message_start",message:{...i}}),a.push({type:"message_end",message:i}),a.push({type:"turn_end",message:i,toolResults:[]}),v(t,{reason:"stop_hook_limit_reached",maxContinuations:b,continuationCount:t.stopHookContinuationCount}),t.finalStopReason="error",t.finalErrorMessage=i.errorMessage,t.finalErrorSubtype="stop_hook_limit_reached",M(a,s,t);return}t.stopHookContinuationCount+=1,t.pendingMessages=S.messages,v(t,{reason:"stop_hook_blocking",continuationCount:t.stopHookContinuationCount});continue}}const n=G(o,t.usage.output,t.tokenBudgetContinuationCount);if(n){t.tokenBudgetContinuationCount+=1,t.pendingMessages=[n.message],v(t,{reason:"token_budget_continuation",continuationCount:t.tokenBudgetContinuationCount,outputTokens:n.outputTokens,targetTokens:n.targetTokens});continue}const l=await E(o.getFollowUpMessages?o.getFollowUpMessages():[],r);if(l.type==="aborted"){H(a,e,s,t);return}const f=l.value||[];if(f.length===0)break;t.pendingMessages=f,v(t,{reason:"follow_up"});continue}if(t.toolCallCount+R.length>y){const n=Z(u,`Tool call skipped because this prompt reached the ${y} tool-call limit.`);for(const f of n)e.messages.push(f),s.push(f),a.push({type:"message_start",message:f}),a.push({type:"message_end",message:f});const l=T(o,`tool_call_limit_reached: stopped before executing ${R.length} tool call${R.length===1?"":"s"} because this prompt reached the ${y} tool-call limit.`);e.messages.push(l),s.push(l),a.push({type:"message_start",message:{...l}}),a.push({type:"message_end",message:l}),a.push({type:"turn_end",message:l,toolResults:n}),v(t,{reason:"tool_call_limit_reached",maxToolCalls:y,requestedToolCalls:R.length,toolCallCount:t.toolCallCount}),t.finalStopReason="error",t.finalErrorMessage=l.errorMessage,t.finalErrorSubtype="tool_call_limit_reached",M(a,s,t);return}t.toolCallCount+=R.length;const c=k.size>0?await k.drain():await V(R,e.tools,r,a,o.getSteeringMessages,o.maxToolConcurrency,o.canUseTool),m=x(c.toolResults,o.maxToolResultBatchSizeChars);t.permissionDenials.push(...c.permissionDenials);for(const n of m)e.messages.push(n),s.push(n),a.push({type:"message_start",message:n}),a.push({type:"message_end",message:n});for(const n of c.contextMessages)e.messages.push(n),s.push(n),a.push({type:"message_start",message:n}),a.push({type:"message_end",message:n});const h=se(o,{assistantMessage:u,toolResults:m,contextMessages:c.contextMessages,messages:e.messages});h&&t.pendingToolUseSummaries.push(h),a.push({type:"turn_end",message:u,toolResults:m}),c.steeringMessages&&c.steeringMessages.length>0?t.pendingMessages=c.steeringMessages:t.pendingMessages=await o.getSteeringMessages?.()||[],v(t,{reason:"tool_result",toolCallCount:R.length})}t.finalStopReason=t.finalStopReason??I(s),M(a,s,t)}d(W,"runStructuredAdaptiveQueryLoop");async function me(e,s,o,r,a,p,_){let y=e.messages;if(s.transformContext){const m=await E(s.transformContext(y,o),o);if(m.type==="aborted")return P(e,r,s);y=m.value}const C=await E(s.convertToLlm(y),o);if(C.type==="aborted")return P(e,r,s);const b=C.value,U={systemPrompt:e.systemPrompt,messages:b,tools:e.tools},A=a||N,t=await E(s.getApiKey?s.getApiKey(s.model.provider):void 0,o);if(t.type==="aborted")return P(e,r,s);const O=t.value||s.apiKey;r.push({type:"stream_request_start",model:s.model.id,provider:s.model.provider,api:s.model.api,messageCount:b.length,maxTokens:p??s.maxTokens});const k=await ae(A(s.model,U,{...s,maxTokens:p??s.maxTokens,apiKey:O,signal:o}),o);if(k==="aborted"){const m=T(s,"Request was aborted");return m.stopReason="aborted",e.messages.push(m),r.push({type:"message_start",message:{...m}}),r.push({type:"message_end",message:m}),m}let g=null,u=!1;const R=k[Symbol.asyncIterator]();for(;;){let m;try{m=await ne(R,o)}catch(n){const l=T(s,n instanceof Error?n.message:String(n));return u?e.messages[e.messages.length-1]=l:(e.messages.push(l),r.push({type:"message_start",message:{...l}})),r.push({type:"message_end",message:l}),l}if(m==="aborted"){R.return?.();const n=T(s,"Request was aborted");return n.stopReason="aborted",u?e.messages[e.messages.length-1]=n:(e.messages.push(n),r.push({type:"message_start",message:{...n}})),r.push({type:"message_end",message:n}),n}if(m.done)break;const h=m.value;switch(h.type){case"start":g=h.partial,e.messages.push(g),u=!0,r.push({type:"message_start",message:{...g}});break;case"text_start":case"text_delta":case"text_end":case"thinking_start":case"thinking_delta":case"thinking_end":case"toolcall_start":case"toolcall_delta":g&&(g=h.partial,e.messages[e.messages.length-1]=g,r.push({type:"message_update",assistantMessageEvent:h,message:{...g}}));break;case"toolcall_end":g&&(g=h.partial,e.messages[e.messages.length-1]=g,r.push({type:"message_update",assistantMessageEvent:h,message:{...g}}),_?.addTool(h.toolCall));break;case"done":case"error":{const n=h.type==="done"?h.message:h.error;return u?e.messages[e.messages.length-1]=n:e.messages.push(n),u||r.push({type:"message_start",message:{...n}}),r.push({type:"message_end",message:n}),n}}}const c=k.resultIfResolved()??T(s,"Provider stream ended without a final assistant message");return u?e.messages[e.messages.length-1]=c:(e.messages.push(c),r.push({type:"message_start",message:{...c}})),r.push({type:"message_end",message:c}),c}d(me,"streamAssistantResponse");function P(e,s,o){const r=T(o,"Request was aborted");return r.stopReason="aborted",e.messages.push(r),s.push({type:"message_start",message:{...r}}),s.push({type:"message_end",message:r}),r}d(P,"pushAbortedAssistantMessage");function H(e,s,o,r){const a=T(r.config,"Request was aborted");a.stopReason="aborted",s.messages.push(a),o.push(a),e.push({type:"message_start",message:{...a}}),e.push({type:"message_end",message:a}),e.push({type:"turn_end",message:a,toolResults:[]}),r.finalStopReason="aborted",r.finalErrorMessage=a.errorMessage,r.finalErrorSubtype="aborted",M(e,o,r)}d(H,"finishStructuredAdaptiveWithAbortedTurn");function T(e,s){return{role:"assistant",content:[{type:"text",text:""}],api:e.model.api,provider:e.model.provider,model:e.model.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"error",errorMessage:s,timestamp:Date.now()}}d(T,"createLoopLimitMessage");function B(e,s,o,r,a){const p=T(o,r instanceof Error?r.message:String(r));a?.aborted&&(p.stopReason="aborted"),s.push(p),e.push({type:"message_start",message:{...p}}),e.push({type:"message_end",message:p}),e.push({type:"turn_end",message:p,toolResults:[]});const _={config:o,turnCount:0,toolCallCount:0,transition:{reason:"start"},transitions:[],pendingMessages:[],pendingToolUseSummaries:[],stopHookActive:!1,stopHookContinuationCount:0,maxOutputTokensRecoveryCount:0,modelErrorRecoveryCount:0,tokenBudgetContinuationCount:0,hasAttemptedReactiveCompact:!1,startedAt:Date.now(),usage:K(),permissionDenials:[],finalStopReason:p.stopReason,finalErrorMessage:p.errorMessage,finalErrorSubtype:a?.aborted?"aborted":"loop_error"};M(e,s,_)}d(B,"endWithLoopError");function M(e,s,o){e.push({type:"agent_result",stopReason:o.finalStopReason??I(s),loopFramework:oe(o.config),loopPolicy:te(o.config),turnCount:o.turnCount,toolCallCount:o.toolCallCount,durationMs:Date.now()-o.startedAt,usage:o.usage,permissionDenialCount:o.permissionDenials.length,permissionDenials:o.permissionDenials,transitions:o.transitions.length>0?o.transitions:void 0,lastTransition:o.transition,errorMessage:o.finalErrorMessage,errorSubtype:o.finalErrorSubtype}),e.push({type:"agent_end",messages:s}),e.end(s)}d(M,"finish");function v(e,s){e.transition=s,e.transitions.push(s)}d(v,"recordTransition");function K(){return{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}}}d(K,"emptyUsage");function de(e,s){e.input+=s.input,e.output+=s.output,e.cacheRead+=s.cacheRead,e.cacheWrite+=s.cacheWrite,e.totalTokens+=s.totalTokens,e.cost.input+=s.cost.input,e.cost.output+=s.cost.output,e.cost.cacheRead+=s.cost.cacheRead,e.cost.cacheWrite+=s.cost.cacheWrite,e.cost.total+=s.cost.total}d(de,"addUsage");function I(e){for(let s=e.length-1;s>=0;s-=1){const o=e[s];if(o?.role==="assistant")return o.stopReason}return"stop"}d(I,"inferStopReason");export{Me as structuredAdaptiveAgentLoop,be as structuredAdaptiveAgentLoopContinue};
1
+ var N=Object.defineProperty;var c=(e,s)=>N(e,"name",{value:s,configurable:!0});import{EventStream as z}from"@pencil-agent/ai/events";import{isContextOverflow as X}from"@pencil-agent/ai/overflow";import{streamSimple as V}from"@pencil-agent/ai/stream";import{resolveMaxToolConcurrency as Y,runStructuredAdaptiveTools as j}from"./structured-adaptive-tool-orchestration.js";import{StructuredAdaptiveStreamingToolExecutor as G}from"./structured-adaptive-streaming-tool-executor.js";import{ValidationError as H}from"./errors.js";import{computeRecoveryMaxTokens as Q,createOutputTokenRecoveryMessage as J,createTokenBudgetContinuation as Z}from"./agent-loop-continuations.js";import{createInterruptedToolResults as ee,createSkippedToolCallLimitResults as se,enforceToolResultBatchSize as B}from"./agent-loop-tool-results.js";import{flushReadyToolUseSummaries as te,startToolUseSummary as oe}from"./agent-loop-tool-summaries.js";import{buildAgentRunPolicy as ae,resolveAgentRunLoopFramework as ne}from"./agent-run-result.js";import{waitForAbortableOperation as b,waitForAssistantStream as re,waitForAssistantStreamEvent as ue}from"./agent-loop-stream-events.js";const pe=256,le=512,ie=1,me=3,de=1;function O(e){if(process.env.NANOPENCIL_DEBUG==="1")try{const{appendFileSync:s}=require("fs"),{join:t}=require("path"),{homedir:r}=require("os");s(t(r(),".nanopencil","agent","nanopencil-debug.log"),`[${new Date().toISOString()}] [loop] ${e}
2
+ `)}catch{}}c(O,"_tlog");function be(e,s,t,r,a){const p=W();return(async()=>{const y=[...e],l={...s,messages:[...s.messages,...e]};try{p.push({type:"agent_start"}),p.push({type:"turn_start"});for(const R of e)p.push({type:"message_start",message:R}),p.push({type:"message_end",message:R});await q(l,y,t,r,p,a)}catch(R){I(p,y,t,R,r)}})(),p}c(be,"structuredAdaptiveAgentLoop");function Ee(e,s,t,r){if(e.messages.length===0)throw new H("Cannot continue: no messages in context");if(e.messages[e.messages.length-1].role==="assistant")throw new H("Cannot continue from message role: assistant");const a=W();return(async()=>{const p=[],y={...e};try{a.push({type:"agent_start"}),a.push({type:"turn_start"}),await q(y,p,s,t,a,r)}catch(l){I(a,p,s,l,t)}})(),a}c(Ee,"structuredAdaptiveAgentLoopContinue");function W(){return new z(e=>e.type==="agent_end",e=>e.type==="agent_end"?e.messages:[])}c(W,"createAgentStream");async function q(e,s,t,r,a,p){const y=t.maxTurnsPerPrompt??pe,l=t.maxToolCallsPerPrompt??le,R=t.maxOutputTokenRecoveryAttempts??ie,A=t.maxStopHookContinuations??me,E=t.maxModelErrorRecoveryAttempts??de,w=await b(t.getSteeringMessages?t.getSteeringMessages():[],r),D={loopStart:performance.now(),streamStart:0,firstTokenAt:0,turnCount:0};O("run_loop start (structured-adaptive)");const o={config:t,turnCount:0,toolCallCount:0,transition:{reason:"start"},transitions:[],pendingMessages:w.type==="resolved"?w.value||[]:[],pendingToolUseSummaries:[],stopHookActive:!1,stopHookContinuationCount:0,maxOutputTokensRecoveryCount:0,modelErrorRecoveryCount:0,tokenBudgetContinuationCount:0,hasAttemptedReactiveCompact:!1,startedAt:Date.now(),usage:K(),permissionDenials:[]};if(w.type==="aborted"){F(a,e,s,o);return}let U=!0;for(;;){if(U?U=!1:a.push({type:"turn_start"}),o.pendingToolUseSummaries=te(o.pendingToolUseSummaries,e.messages,s,a),o.pendingMessages.length>0){for(const n of o.pendingMessages)a.push({type:"message_start",message:n}),a.push({type:"message_end",message:n}),e.messages.push(n),s.push(n);o.pendingMessages=[]}if(o.turnCount+=1,o.turnCount>y){const n=C(t,`max_turns_reached: stopped after ${y} assistant turns to prevent a runaway agent loop.`);e.messages.push(n),s.push(n),a.push({type:"message_start",message:{...n}}),a.push({type:"message_end",message:n}),a.push({type:"turn_end",message:n,toolResults:[]}),S(o,{reason:"max_turns_reached",maxTurns:y,turnCount:o.turnCount}),o.finalStopReason="error",o.finalErrorMessage=n.errorMessage,o.finalErrorSubtype="max_turns_reached",M(a,s,o);return}const k=new G(e.tools,r,a,Y(t.maxToolConcurrency),t.canUseTool);D.turnCount++;const g=s.length,u=await ce(e,t,r,a,p,o.maxOutputTokensOverride,k,D);if(s.push(u),ge(o.usage,u.usage),o.maxOutputTokensOverride=void 0,u.stopReason==="error"||u.stopReason==="aborted"){const n=u.stopReason==="aborted"?"aborted":X(u,t.model.contextWindow)?"context_overflow":"model_error",d=k.size>0?await k.discardAndDrain(u.stopReason==="aborted"?"assistant stream aborted":"assistant stream error",u.stopReason==="aborted"?"cancel":"all"):{toolResults:[],contextMessages:[],permissionDenials:[]},T=B(d.toolResults,t.maxToolResultBatchSizeChars),x=ee(u,new Set(T.map(i=>i.toolCallId))),v=[...T,...x];for(const i of v)e.messages.push(i),s.push(i),a.push({type:"message_start",message:i}),a.push({type:"message_end",message:i});for(const i of d.contextMessages)e.messages.push(i),s.push(i),a.push({type:"message_start",message:i}),a.push({type:"message_end",message:i});if(u.stopReason==="error"&&t.recoverModelError&&o.modelErrorRecoveryCount<E){const i=o.modelErrorRecoveryCount+1,P=await t.recoverModelError({message:u,messages:e.messages,errorSubtype:n,attempt:i});if(P.action==="retry"){a.push({type:"turn_end",message:u,toolResults:v}),o.modelErrorRecoveryCount=i,s.splice(g),e.messages=P.messages,S(o,P.transition??{reason:"model_error_recovery",subtype:n,attempt:i});continue}}o.permissionDenials.push(...d.permissionDenials),a.push({type:"turn_end",message:u,toolResults:v}),o.finalStopReason=u.stopReason,o.finalErrorMessage=u.errorMessage,o.finalErrorSubtype=n,M(a,s,o);return}const f=u.content.filter(n=>n.type==="toolCall");if(f.length===0){if(a.push({type:"turn_end",message:u,toolResults:[]}),u.stopReason==="length"&&o.maxOutputTokensRecoveryCount<R){o.maxOutputTokensRecoveryCount+=1,o.maxOutputTokensOverride=Q(t,u),o.pendingMessages=[J(o.maxOutputTokensRecoveryCount)],S(o,{reason:"max_output_tokens_recovery",attempt:o.maxOutputTokensRecoveryCount});continue}if(t.runStopHooks&&!o.stopHookActive){o.stopHookActive=!0;const x=await b(t.runStopHooks({message:u,messages:e.messages}),r);if(o.stopHookActive=!1,x.type==="aborted"){F(a,e,s,o);return}const v=x.value;if(v.action==="continue"&&v.messages.length>0){if(o.stopHookContinuationCount>=A){const i=C(t,`stop_hook_limit_reached: stopped after ${A} stop-hook continuation turns.`);e.messages.push(i),s.push(i),a.push({type:"message_start",message:{...i}}),a.push({type:"message_end",message:i}),a.push({type:"turn_end",message:i,toolResults:[]}),S(o,{reason:"stop_hook_limit_reached",maxContinuations:A,continuationCount:o.stopHookContinuationCount}),o.finalStopReason="error",o.finalErrorMessage=i.errorMessage,o.finalErrorSubtype="stop_hook_limit_reached",M(a,s,o);return}o.stopHookContinuationCount+=1,o.pendingMessages=v.messages,S(o,{reason:"stop_hook_blocking",continuationCount:o.stopHookContinuationCount});continue}}const n=Z(t,o.usage.output,o.tokenBudgetContinuationCount);if(n){o.tokenBudgetContinuationCount+=1,o.pendingMessages=[n.message],S(o,{reason:"token_budget_continuation",continuationCount:o.tokenBudgetContinuationCount,outputTokens:n.outputTokens,targetTokens:n.targetTokens});continue}const d=await b(t.getFollowUpMessages?t.getFollowUpMessages():[],r);if(d.type==="aborted"){F(a,e,s,o);return}const T=d.value||[];if(T.length===0)break;o.pendingMessages=T,S(o,{reason:"follow_up"});continue}if(o.toolCallCount+f.length>l){const n=se(u,`Tool call skipped because this prompt reached the ${l} tool-call limit.`);for(const T of n)e.messages.push(T),s.push(T),a.push({type:"message_start",message:T}),a.push({type:"message_end",message:T});const d=C(t,`tool_call_limit_reached: stopped before executing ${f.length} tool call${f.length===1?"":"s"} because this prompt reached the ${l} tool-call limit.`);e.messages.push(d),s.push(d),a.push({type:"message_start",message:{...d}}),a.push({type:"message_end",message:d}),a.push({type:"turn_end",message:d,toolResults:n}),S(o,{reason:"tool_call_limit_reached",maxToolCalls:l,requestedToolCalls:f.length,toolCallCount:o.toolCallCount}),o.finalStopReason="error",o.finalErrorMessage=d.errorMessage,o.finalErrorSubtype="tool_call_limit_reached",M(a,s,o);return}o.toolCallCount+=f.length;const h=k.size>0?await k.drain():await j(f,e.tools,r,a,t.getSteeringMessages,t.maxToolConcurrency,t.canUseTool),m=B(h.toolResults,t.maxToolResultBatchSizeChars);o.permissionDenials.push(...h.permissionDenials);for(const n of m)e.messages.push(n),s.push(n),a.push({type:"message_start",message:n}),a.push({type:"message_end",message:n});for(const n of h.contextMessages)e.messages.push(n),s.push(n),a.push({type:"message_start",message:n}),a.push({type:"message_end",message:n});const _=oe(t,{assistantMessage:u,toolResults:m,contextMessages:h.contextMessages,messages:e.messages});_&&o.pendingToolUseSummaries.push(_),a.push({type:"turn_end",message:u,toolResults:m}),h.steeringMessages&&h.steeringMessages.length>0?o.pendingMessages=h.steeringMessages:o.pendingMessages=await t.getSteeringMessages?.()||[],S(o,{reason:"tool_result",toolCallCount:f.length})}o.finalStopReason=o.finalStopReason??L(s),M(a,s,o)}c(q,"runStructuredAdaptiveQueryLoop");async function ce(e,s,t,r,a,p,y,l){let R=e.messages;if(s.transformContext){const m=await b(s.transformContext(R,t),t);if(m.type==="aborted")return $(e,r,s);R=m.value}const A=await b(s.convertToLlm(R),t);if(A.type==="aborted")return $(e,r,s);const E=A.value,w={systemPrompt:e.systemPrompt,messages:E,tools:e.tools},D=a||V,o=await b(s.getApiKey?s.getApiKey(s.model.provider):void 0,t);if(o.type==="aborted")return $(e,r,s);const U=o.value||s.apiKey;l&&(l.streamStart=performance.now(),O(`stream_request_start model=${s.model.id} provider=${s.model.provider} msgCount=${E.length} maxTokens=${p??s.maxTokens} (+${(l.streamStart-l.loopStart).toFixed(0)}ms from loop_start)`)),r.push({type:"stream_request_start",model:s.model.id,provider:s.model.provider,api:s.model.api,messageCount:E.length,maxTokens:p??s.maxTokens});const k=await re(D(s.model,w,{...s,maxTokens:p??s.maxTokens,apiKey:U,signal:t}),t);if(k==="aborted"){const m=C(s,"Request was aborted");return m.stopReason="aborted",e.messages.push(m),r.push({type:"message_start",message:{...m}}),r.push({type:"message_end",message:m}),m}let g=null,u=!1;const f=k[Symbol.asyncIterator]();for(;;){let m;try{m=await ue(f,t)}catch(n){const d=C(s,n instanceof Error?n.message:String(n));return u?e.messages[e.messages.length-1]=d:(e.messages.push(d),r.push({type:"message_start",message:{...d}})),r.push({type:"message_end",message:d}),d}if(m==="aborted"){f.return?.();const n=C(s,"Request was aborted");return n.stopReason="aborted",u?e.messages[e.messages.length-1]=n:(e.messages.push(n),r.push({type:"message_start",message:{...n}})),r.push({type:"message_end",message:n}),n}if(m.done)break;const _=m.value;switch(l&&!l.firstTokenAt&&(l.firstTokenAt=performance.now(),O(`first_token ttft=${(l.firstTokenAt-l.streamStart).toFixed(0)}ms (+${(l.firstTokenAt-l.loopStart).toFixed(0)}ms from loop_start)`)),_.type){case"start":g=_.partial,e.messages.push(g),u=!0,r.push({type:"message_start",message:{...g}});break;case"text_start":case"text_delta":case"text_end":case"thinking_start":case"thinking_delta":case"thinking_end":case"toolcall_start":case"toolcall_delta":g&&(g=_.partial,e.messages[e.messages.length-1]=g,r.push({type:"message_update",assistantMessageEvent:_,message:{...g}}));break;case"toolcall_end":g&&(g=_.partial,e.messages[e.messages.length-1]=g,r.push({type:"message_update",assistantMessageEvent:_,message:{...g}}),y?.addTool(_.toolCall));break;case"done":case"error":{const n=_.type==="done"?_.message:_.error;return u?e.messages[e.messages.length-1]=n:e.messages.push(n),u||r.push({type:"message_start",message:{...n}}),r.push({type:"message_end",message:n}),n}}}if(l){const m=performance.now();O(`stream_end duration=${(m-l.streamStart).toFixed(0)}ms total=${(m-l.loopStart).toFixed(0)}ms`)}const h=k.resultIfResolved()??C(s,"Provider stream ended without a final assistant message");return u?e.messages[e.messages.length-1]=h:(e.messages.push(h),r.push({type:"message_start",message:{...h}})),r.push({type:"message_end",message:h}),h}c(ce,"streamAssistantResponse");function $(e,s,t){const r=C(t,"Request was aborted");return r.stopReason="aborted",e.messages.push(r),s.push({type:"message_start",message:{...r}}),s.push({type:"message_end",message:r}),r}c($,"pushAbortedAssistantMessage");function F(e,s,t,r){const a=C(r.config,"Request was aborted");a.stopReason="aborted",s.messages.push(a),t.push(a),e.push({type:"message_start",message:{...a}}),e.push({type:"message_end",message:a}),e.push({type:"turn_end",message:a,toolResults:[]}),r.finalStopReason="aborted",r.finalErrorMessage=a.errorMessage,r.finalErrorSubtype="aborted",M(e,t,r)}c(F,"finishStructuredAdaptiveWithAbortedTurn");function C(e,s){return{role:"assistant",content:[{type:"text",text:""}],api:e.model.api,provider:e.model.provider,model:e.model.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"error",errorMessage:s,timestamp:Date.now()}}c(C,"createLoopLimitMessage");function I(e,s,t,r,a){const p=C(t,r instanceof Error?r.message:String(r));a?.aborted&&(p.stopReason="aborted"),s.push(p),e.push({type:"message_start",message:{...p}}),e.push({type:"message_end",message:p}),e.push({type:"turn_end",message:p,toolResults:[]});const y={config:t,turnCount:0,toolCallCount:0,transition:{reason:"start"},transitions:[],pendingMessages:[],pendingToolUseSummaries:[],stopHookActive:!1,stopHookContinuationCount:0,maxOutputTokensRecoveryCount:0,modelErrorRecoveryCount:0,tokenBudgetContinuationCount:0,hasAttemptedReactiveCompact:!1,startedAt:Date.now(),usage:K(),permissionDenials:[],finalStopReason:p.stopReason,finalErrorMessage:p.errorMessage,finalErrorSubtype:a?.aborted?"aborted":"loop_error"};M(e,s,y)}c(I,"endWithLoopError");function M(e,s,t){e.push({type:"agent_result",stopReason:t.finalStopReason??L(s),loopFramework:ne(t.config),loopPolicy:ae(t.config),turnCount:t.turnCount,toolCallCount:t.toolCallCount,durationMs:Date.now()-t.startedAt,usage:t.usage,permissionDenialCount:t.permissionDenials.length,permissionDenials:t.permissionDenials,transitions:t.transitions.length>0?t.transitions:void 0,lastTransition:t.transition,errorMessage:t.finalErrorMessage,errorSubtype:t.finalErrorSubtype}),O(`loop_finished stopReason=${t.finalStopReason??L(s)} turns=${t.turnCount} tools=${t.toolCallCount} duration=${Date.now()-t.startedAt}ms`),e.push({type:"agent_end",messages:s}),e.end(s)}c(M,"finish");function S(e,s){e.transition=s,e.transitions.push(s)}c(S,"recordTransition");function K(){return{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}}}c(K,"emptyUsage");function ge(e,s){e.input+=s.input,e.output+=s.output,e.cacheRead+=s.cacheRead,e.cacheWrite+=s.cacheWrite,e.totalTokens+=s.totalTokens,e.cost.input+=s.cost.input,e.cost.output+=s.cost.output,e.cost.cacheRead+=s.cost.cacheRead,e.cost.cacheWrite+=s.cost.cacheWrite,e.cost.total+=s.cost.total}c(ge,"addUsage");function L(e){for(let s=e.length-1;s>=0;s-=1){const t=e[s];if(t?.role==="assistant")return t.stopReason}return"stop"}c(L,"inferStopReason");export{be as structuredAdaptiveAgentLoop,Ee as structuredAdaptiveAgentLoopContinue};
@@ -0,0 +1,20 @@
1
+ /**
2
+ * [WHO]: Provides ExtensionFlag, ExtensionFlagOptions, ExtensionFlagValue
3
+ * [FROM]: No dependencies — flags are portable extension metadata
4
+ * [TO]: Consumed by protocol ExtensionAPI and the host extension loader/runner
5
+ * [HERE]: packages/protocol/src/flags.ts - stable CLI/config flag declaration contract
6
+ */
7
+ /** Supported values for extension-declared flags. */
8
+ export type ExtensionFlagValue = boolean | string;
9
+ /** Options an extension passes to `api.registerFlag(...)`. */
10
+ export interface ExtensionFlagOptions {
11
+ description?: string;
12
+ type: "boolean" | "string";
13
+ default?: ExtensionFlagValue;
14
+ }
15
+ /** A runtime flag an extension declares (parsed from CLI/config by the host). */
16
+ export interface ExtensionFlag extends ExtensionFlagOptions {
17
+ name: string;
18
+ /** Absolute path of the declaring extension (filled by the host loader). */
19
+ extensionPath: string;
20
+ }
File without changes
@@ -0,0 +1,17 @@
1
+ /**
2
+ * [WHO]: Provides HookEventName and HookHandler — public lifecycle hook vocabulary
3
+ * [FROM]: No dependencies — context is generic so lifecycle/host can supply their own context type
4
+ * [TO]: Consumed by protocol ExtensionAPI and host extension event overloads
5
+ * [HERE]: packages/protocol/src/hooks.ts - stable hook-name contract without payload freezing
6
+ *
7
+ * Payload types intentionally stay out of protocol for now. The host keeps rich typed
8
+ * overloads; protocol only publishes the event-name vocabulary that external extensions
9
+ * may subscribe to.
10
+ */
11
+ /** Lifecycle hook names an extension may subscribe to via `api.on(...)`. */
12
+ export type HookEventName = "resources_discover" | "session_start" | "session_ready" | "session_before_switch" | "session_switch" | "session_before_fork" | "session_fork" | "session_before_compact" | "session_compact" | "session_shutdown" | "session_before_tree" | "session_tree" | "context" | "before_agent_start" | "agent_start" | "agent_result" | "agent_abort" | "agent_end" | "turn_start" | "turn_end" | "message_start" | "message_update" | "message_end" | "tool_execution_start" | "tool_execution_update" | "tool_execution_end" | "model_select" | "tool_call" | "tool_result" | "user_bash" | "input";
13
+ /**
14
+ * Hook callback. The event payload is intentionally `any` this round so host-agnostic
15
+ * extensions compile without per-event payload types; typed payloads remain host-owned.
16
+ */
17
+ export type HookHandler<TContext = unknown> = (event: any, ctx: TContext) => void | Promise<void>;
File without changes
@@ -1,13 +1,15 @@
1
1
  /**
2
2
  * [WHO]: Barrel for @pencil-agent/protocol — the stable protocol surface for extensions
3
- * [FROM]: Re-exports the per-protocol modules (tools + lifecycle + commands today; themes/hooks/permissions in later P3 checkpoints)
3
+ * [FROM]: Re-exports the per-protocol modules (tools + lifecycle + commands + hooks + flags today; themes/permissions in later P3 checkpoints)
4
4
  * [TO]: Consumed by third-party extensions, packages/mem-core, packages/soul-core, and the host (adopting these contracts)
5
5
  * [HERE]: packages/protocol/src/index.ts - protocol public entry
6
6
  *
7
7
  * Scope (this round / P3): tools (S1), lifecycle (ExtensionAPI/ExtensionContext/SessionManagerContract, S3),
8
- * commands, then themes/hooks/permissions. Explicitly NOT here (EVOLUTION-RESERVED): agent-profile,
8
+ * commands, hooks, flags, then themes/permissions. Explicitly NOT here (EVOLUTION-RESERVED): agent-profile,
9
9
  * host-adapter, tool-runtime, a2a-bridge, memory/soul providers — see evolution/PARP.md.
10
10
  */
11
11
  export * from "./tools.js";
12
12
  export * from "./lifecycle.js";
13
13
  export * from "./commands.js";
14
+ export * from "./hooks.js";
15
+ export * from "./flags.js";
@@ -1 +1 @@
1
- export*from"./tools.js";export*from"./lifecycle.js";export*from"./commands.js";
1
+ export*from"./tools.js";export*from"./lifecycle.js";export*from"./commands.js";export*from"./hooks.js";export*from"./flags.js";
@@ -1,17 +1,19 @@
1
1
  /**
2
2
  * [WHO]: Provides ExtensionAPI, ExtensionContext, ExtensionFactory, ExtensionUi,
3
- * SessionManagerContract, HookEventName, HookHandler — the extension lifecycle protocol
4
- * [FROM]: Depends on ./commands and ./tools for command/tool registration contracts
3
+ * SessionManagerContract — the extension lifecycle protocol
4
+ * [FROM]: Depends on ./commands, ./flags, ./hooks, and ./tools for registration contracts
5
5
  * [TO]: Consumed by packages/mem-core (extension adapter) and third-party extensions; the host's
6
6
  * richer ExtensionContext/ExtensionAPI satisfy these structurally (extensions load dynamically)
7
7
  * [HERE]: packages/protocol/src/lifecycle.ts - the stable extension entry contract
8
8
  *
9
- * Scope note: event payloads are intentionally loose (HookHandler's event is `unknown`) this round;
10
- * per-event typed payloads land in hooks.ts during P3.1. This file carries only the surface that
9
+ * Scope note: event payloads are intentionally loose (HookHandler's event is `any`) this round;
10
+ * per-event typed payloads remain host-owned. This file carries only the surface that
11
11
  * lets a host-agnostic extension (e.g. mem-core) compile against the SDK instead of the host package.
12
12
  */
13
13
  import type { TSchema } from "@sinclair/typebox";
14
14
  import type { ExtensionCommand } from "./commands.js";
15
+ import type { ExtensionFlagOptions, ExtensionFlagValue } from "./flags.js";
16
+ import type { HookEventName, HookHandler } from "./hooks.js";
15
17
  import type { ToolContract } from "./tools.js";
16
18
  /** Read-only session info an extension may consult via `ctx.sessionManager`. */
17
19
  export interface SessionManagerContract {
@@ -42,28 +44,16 @@ export interface ExtensionContext {
42
44
  /** User-facing UI affordances. */
43
45
  ui: ExtensionUi;
44
46
  }
45
- /** Lifecycle hook names an extension may subscribe to via `api.on(...)`. */
46
- export type HookEventName = "session_start" | "session_ready" | "session_shutdown" | "before_agent_start" | "agent_start" | "agent_end" | "agent_result" | "turn_start" | "turn_end" | "tool_execution_start" | "tool_execution_end";
47
- /**
48
- * Hook callback. The event payload is intentionally `any` this round so host-agnostic
49
- * extensions compile without per-event payload types; typed payloads land in hooks.ts (P3.1).
50
- */
51
- export type HookHandler = (event: any, ctx: ExtensionContext) => void | Promise<void>;
52
- /** A runtime flag an extension declares (parsed from CLI/config by the host). */
53
- export interface ExtensionFlag {
54
- name: string;
55
- description?: string;
56
- type: "boolean" | "string";
57
- default?: boolean | string;
58
- /** Absolute path of the declaring extension (filled by the host loader). */
59
- extensionPath: string;
60
- }
61
47
  /** The registration surface a host passes to an extension factory. */
62
48
  export interface ExtensionAPI {
63
49
  /** Subscribe to a lifecycle hook. */
64
- on(event: HookEventName, handler: HookHandler): void;
50
+ on(event: HookEventName, handler: HookHandler<ExtensionContext>): void;
65
51
  /** Register a slash command. */
66
52
  registerCommand(name: string, command: ExtensionCommand<ExtensionContext>): void;
53
+ /** Register a CLI/config flag declared by this extension. */
54
+ registerFlag(name: string, options: ExtensionFlagOptions): void;
55
+ /** Get the value of a registered CLI/config flag. */
56
+ getFlag(name: string): ExtensionFlagValue | undefined;
67
57
  /** Register a model-facing tool. Generic so each call infers its own parameter schema. */
68
58
  registerTool<TParams extends TSchema = TSchema, TDetails = unknown>(tool: ToolContract<TParams, TDetails>): void;
69
59
  }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * [WHO]: Public config subpath exports for auth, settings, resource, and package managers
3
+ * [FROM]: Re-exports selected core/platform config and package-manager modules
4
+ * [TO]: Consumed by advanced SDK users importing @pencil-agent/nano-pencil/config
5
+ * [HERE]: public-config.ts - package subpath entry for configuration APIs
6
+ */
7
+ export { type ApiKeyCredential, type AuthCredential, AuthStorage, type AuthStorageBackend, FileAuthStorageBackend, InMemoryAuthStorageBackend, type OAuthCredential, } from "./core/platform/config/auth-storage.js";
8
+ export { type CompactionSettings, type ImageSettings, type PackageSource, type RetrySettings, SettingsManager, } from "./core/platform/config/settings-manager.js";
9
+ export type { ResourceCollision, ResourceDiagnostic, ResourceLoader } from "./core/platform/config/resource-loader.js";
10
+ export { DefaultResourceLoader } from "./core/platform/config/resource-loader.js";
11
+ export type { PackageManager, PathMetadata, ProgressCallback, ProgressEvent, ResolvedPaths, ResolvedResource, } from "./core/package-manager.js";
12
+ export { DefaultPackageManager } from "./core/package-manager.js";
@@ -0,0 +1 @@
1
+ import{AuthStorage as a,FileAuthStorageBackend as o,InMemoryAuthStorageBackend as t}from"./core/platform/config/auth-storage.js";import{SettingsManager as f}from"./core/platform/config/settings-manager.js";import{DefaultResourceLoader as u}from"./core/platform/config/resource-loader.js";import{DefaultPackageManager as c}from"./core/package-manager.js";export{a as AuthStorage,c as DefaultPackageManager,u as DefaultResourceLoader,o as FileAuthStorageBackend,t as InMemoryAuthStorageBackend,f as SettingsManager};
@@ -0,0 +1,9 @@
1
+ /**
2
+ * [WHO]: Public runtime subpath exports for advanced AgentSession embedding
3
+ * [FROM]: Re-exports selected runtime/message modules
4
+ * [TO]: Consumed by advanced SDK users importing @pencil-agent/nano-pencil/runtime
5
+ * [HERE]: runtime.ts - package subpath entry for runtime APIs
6
+ */
7
+ export { AgentSession, type AgentSessionConfig, type AgentSessionEvent, type AgentSessionEventListener, type ModelCycleResult, type ParsedSkillBlock, parseSkillBlock, type PromptOptions, type SessionStats, } from "./core/runtime/agent-session.js";
8
+ export { createEventBus, type EventBus, type EventBusController } from "./core/runtime/event-bus.js";
9
+ export { convertToLlm } from "./core/messages.js";
@@ -0,0 +1 @@
1
+ import{AgentSession as r,parseSkillBlock as t}from"./core/runtime/agent-session.js";import{createEventBus as m}from"./core/runtime/event-bus.js";import{convertToLlm as p}from"./core/messages.js";export{r as AgentSession,p as convertToLlm,m as createEventBus,t as parseSkillBlock};
@@ -0,0 +1,7 @@
1
+ /**
2
+ * [WHO]: Public session/compaction subpath exports for context compaction helpers
3
+ * [FROM]: Re-exports core/session/compaction/index.js
4
+ * [TO]: Consumed by advanced SDK users importing @pencil-agent/nano-pencil/session/compaction
5
+ * [HERE]: session-compaction.ts - package subpath entry for compaction APIs
6
+ */
7
+ export * from "./core/session/compaction/index.js";
@@ -0,0 +1 @@
1
+ export*from"./core/session/compaction/index.js";
@@ -0,0 +1,7 @@
1
+ /**
2
+ * [WHO]: Public session subpath exports for session persistence and entry types
3
+ * [FROM]: Re-exports core/session/session-manager.js
4
+ * [TO]: Consumed by advanced SDK users importing @pencil-agent/nano-pencil/session
5
+ * [HERE]: session.ts - package subpath entry for session APIs
6
+ */
7
+ export { type BranchSummaryEntry, buildSessionContext, type CompactionEntry, CURRENT_SESSION_VERSION, type CustomEntry, type CustomMessageEntry, type FileEntry, getLatestCompactionEntry, type ModelChangeEntry, migrateSessionEntries, type NewSessionOptions, parseSessionEntries, type SessionContext, type SessionEntry, type SessionEntryBase, type SessionHeader, type SessionInfo, type SessionInfoEntry, SessionManager, type SessionMessageEntry, type ThinkingLevelChangeEntry, } from "./core/session/session-manager.js";
@@ -0,0 +1 @@
1
+ import{buildSessionContext as t,CURRENT_SESSION_VERSION as n,getLatestCompactionEntry as i,migrateSessionEntries as o,parseSessionEntries as r,SessionManager as S}from"./core/session/session-manager.js";export{n as CURRENT_SESSION_VERSION,S as SessionManager,t as buildSessionContext,i as getLatestCompactionEntry,o as migrateSessionEntries,r as parseSessionEntries};
@@ -0,0 +1,7 @@
1
+ /**
2
+ * [WHO]: Public skills subpath exports for skill discovery and prompt formatting
3
+ * [FROM]: Re-exports core/skills.js
4
+ * [TO]: Consumed by advanced SDK users importing @pencil-agent/nano-pencil/skills
5
+ * [HERE]: skills.ts - package subpath entry for skill APIs
6
+ */
7
+ export { formatSkillsForPrompt, type LoadSkillsFromDirOptions, type LoadSkillsResult, loadSkills, loadSkillsFromDir, type Skill, type SkillFrontmatter, } from "./core/skills.js";
package/dist/skills.js ADDED
@@ -0,0 +1 @@
1
+ import{formatSkillsForPrompt as r,loadSkills as i,loadSkillsFromDir as m}from"./core/skills.js";export{r as formatSkillsForPrompt,i as loadSkills,m as loadSkillsFromDir};
@@ -0,0 +1,7 @@
1
+ /**
2
+ * [WHO]: Public tools subpath exports for built-in tool implementations and types
3
+ * [FROM]: Re-exports core/tools/index.js
4
+ * [TO]: Consumed by advanced SDK users importing @pencil-agent/nano-pencil/tools
5
+ * [HERE]: tools.ts - package subpath entry for tool APIs
6
+ */
7
+ export * from "./core/tools/index.js";
package/dist/tools.js ADDED
@@ -0,0 +1 @@
1
+ export*from"./core/tools/index.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pencil-agent/nano-pencil",
3
- "version": "2.0.0-beta.9",
3
+ "version": "2.0.1",
4
4
  "description": "CLI writing agent with read, bash, edit, write tools and session management. Supports DashScope and Ali Token Plan. Soul enabled by default for AI personality evolution.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -10,6 +10,34 @@
10
10
  ".": {
11
11
  "import": "./dist/index.js",
12
12
  "types": "./dist/index.d.ts"
13
+ },
14
+ "./tools": {
15
+ "import": "./dist/tools.js",
16
+ "types": "./dist/tools.d.ts"
17
+ },
18
+ "./runtime": {
19
+ "import": "./dist/runtime.js",
20
+ "types": "./dist/runtime.d.ts"
21
+ },
22
+ "./session": {
23
+ "import": "./dist/session.js",
24
+ "types": "./dist/session.d.ts"
25
+ },
26
+ "./session/compaction": {
27
+ "import": "./dist/session-compaction.js",
28
+ "types": "./dist/session-compaction.d.ts"
29
+ },
30
+ "./config": {
31
+ "import": "./dist/public-config.js",
32
+ "types": "./dist/public-config.d.ts"
33
+ },
34
+ "./models": {
35
+ "import": "./dist/models.js",
36
+ "types": "./dist/models.d.ts"
37
+ },
38
+ "./skills": {
39
+ "import": "./dist/skills.js",
40
+ "types": "./dist/skills.d.ts"
13
41
  }
14
42
  },
15
43
  "files": [