@pencil-agent/nano-pencil 2.0.2 → 2.0.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.
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "2.0.2",
3
- "commitHash": "b357171",
2
+ "version": "2.0.3",
3
+ "commitHash": "7dacd59",
4
4
  "branch": "main",
5
- "builtAt": "2026-06-13T02:06:38.896Z"
5
+ "builtAt": "2026-06-13T02:34:03.864Z"
6
6
  }
@@ -1,4 +1,4 @@
1
- var D=Object.defineProperty;var c=(a,e)=>D(a,"name",{value:e,configurable:!0});import{Box as C,Container as E,Spacer as $,Text as P}from"@pencil-agent/tui";import{collectSystemInfo as h,collectModelInfo as y,collectSessionInfo as b,collectConfigInfo as I,collectGitInfo as O,collectAgentState as M,collectPreferencesInfo as U,sanitizeForLLM as _,formatDiagnosticData as L}from"./collectors.js";const S="debug",v="[DEBUG:",A="[DEBUG]",j=`You are a diagnostic analyst for nanoPencil (a terminal-native AI coding agent).
1
+ var D=Object.defineProperty;var c=(r,e)=>D(r,"name",{value:e,configurable:!0});import{Box as C,Container as E,Spacer as $,Text as P}from"@pencil-agent/tui";import{collectSystemInfo as h,collectModelInfo as y,collectSessionInfo as b,collectConfigInfo as I,collectGitInfo as O,collectAgentState as M,collectPreferencesInfo as U,sanitizeForLLM as _,formatDiagnosticData as L}from"./collectors.js";const S="debug",v="[DEBUG:",A="[DEBUG]",j=`You are a diagnostic analyst for nanoPencil (a terminal-native AI coding agent).
2
2
  Analyze the provided system state and produce a structured three-layer diagnostic report.
3
3
 
4
4
  Output format (use these exact section headers):
@@ -28,22 +28,22 @@ Rules:
28
28
  - If no specific issue, perform a general health assessment
29
29
  - Use concise language; prefer tables and bullet lists over prose
30
30
  - If a diagnostic collection failed, treat that failure itself as a diagnostic signal
31
- - Do NOT use any tools \u2014 this is a pure analysis task`;let p;function z(a){return a.startsWith(v)}c(z,"isDebugPrompt");const k=[{value:"env",label:"env",description:"Show terminal and system details"},{value:"session",label:"session",description:"Show current conversation state"},{value:"model",label:"model",description:"Show active model and provider details"},{value:"preferences",label:"preferences",description:"Show saved preferences"}],N=[{value:"zh",label:"zh",description:"Use Chinese for future replies"},{value:"en",label:"en",description:"Use English for future replies"}];function w(a){const e=a.trim().toLowerCase();return e==="env"?{subcommand:"env"}:e==="session"?{subcommand:"session"}:e==="model"?{subcommand:"model"}:e==="preferences"?{subcommand:"preferences"}:{subcommand:"full",issueDescription:a.trim()||void 0}}c(w,"parseDebugArgs");async function R(a,e,r){const t=w(a);e.ui.setStatus("debug","Collecting diagnostics...");try{const[n,s,o,i,u,l]=await Promise.allSettled([h(),y(e),b(e),I(e),O(e.cwd),M(e)]),m={system:n.status==="fulfilled"?n.value:{data:null,error:String(n.reason)},model:s.status==="fulfilled"?s.value:{data:null,error:String(s.reason)},session:o.status==="fulfilled"?o.value:{data:null,error:String(o.reason)},config:i.status==="fulfilled"?i.value:{data:null,error:String(i.reason)},git:u.status==="fulfilled"?u.value:{data:null,error:String(u.reason)},agent:l.status==="fulfilled"?l.value:{data:null,error:String(l.reason)}},g=_(m);e.ui.setStatus("debug",void 0);const d=[];d.push(`${A} Perform a three-layer diagnostic analysis.`),t.issueDescription&&d.push(`
31
+ - Do NOT use any tools \u2014 this is a pure analysis task`;let p;function k(r){return r.startsWith(v)}c(k,"isDebugPrompt");const z=[{value:"env",label:"env",description:"Show terminal and system details"},{value:"session",label:"session",description:"Show current conversation state"},{value:"model",label:"model",description:"Show active model and provider details"},{value:"preferences",label:"preferences",description:"Show saved preferences"}],N=[{value:"zh",label:"zh",description:"Use Chinese for future replies"},{value:"en",label:"en",description:"Use English for future replies"}];function w(r){const e=r.trim().toLowerCase();return e==="env"?{subcommand:"env"}:e==="session"?{subcommand:"session"}:e==="model"?{subcommand:"model"}:e==="preferences"?{subcommand:"preferences"}:{subcommand:"full",issueDescription:r.trim()||void 0}}c(w,"parseDebugArgs");async function R(r,e,o){const t=w(r);e.ui.setStatus("debug","Collecting diagnostics...");try{const[n,s,a,i,u,l]=await Promise.allSettled([h(),y(e),b(e),I(e),O(e.cwd),M(e)]),m={system:n.status==="fulfilled"?n.value:{data:null,error:String(n.reason)},model:s.status==="fulfilled"?s.value:{data:null,error:String(s.reason)},session:a.status==="fulfilled"?a.value:{data:null,error:String(a.reason)},config:i.status==="fulfilled"?i.value:{data:null,error:String(i.reason)},git:u.status==="fulfilled"?u.value:{data:null,error:String(u.reason)},agent:l.status==="fulfilled"?l.value:{data:null,error:String(l.reason)}},g=_(m);e.ui.setStatus("debug",void 0);const d=[];d.push(`${A} Perform a three-layer diagnostic analysis.`),t.issueDescription&&d.push(`
32
32
  User-Reported Issue: ${t.issueDescription}`),d.push(`
33
33
  Collected Diagnostics:
34
34
  `),d.push(L(g));const f=`${v}${Date.now()}]
35
35
  ${d.join(`
36
- `)}`;p=f,r.sendUserMessage(f,{deliverAs:"followUp"})}catch(n){e.ui.setStatus("debug",void 0);const s=n instanceof Error?n.message:String(n);e.ui.notify(`Debug error: ${s}`,"error")}}c(R,"handleFullDiagnostic");async function T(a,e,r){let t;switch(a){case"env":{const n=await h();t=n.data?`| System | |
36
+ `)}`;p=f,o.sendUserMessage(f,{deliverAs:"followUp"})}catch(n){e.ui.setStatus("debug",void 0);const s=n instanceof Error?n.message:String(n);e.ui.notify(`Debug error: ${s}`,"error")}}c(R,"handleFullDiagnostic");async function T(r,e,o){let t;switch(r){case"env":{const n=await h();t=n.data?`| System | |
37
37
  |---|---|
38
- ${Object.entries(n.data).map(([s,o])=>`| ${s} | ${o} |`).join(`
38
+ ${Object.entries(n.data).map(([s,a])=>`| ${s} | ${a} |`).join(`
39
39
  `)}`:`> Collection failed: ${n.error}`;break}case"session":{const n=await b(e);t=n.data?`| Session | |
40
40
  |---|---|
41
- ${Object.entries(n.data).map(([s,o])=>`| ${s} | ${o} |`).join(`
41
+ ${Object.entries(n.data).map(([s,a])=>`| ${s} | ${a} |`).join(`
42
42
  `)}`:`> Collection failed: ${n.error}`;break}case"model":{const n=await y(e);t=n.data?`| Model | |
43
43
  |---|---|
44
- ${Object.entries(n.data).map(([s,o])=>`| ${s} | ${o} |`).join(`
44
+ ${Object.entries(n.data).map(([s,a])=>`| ${s} | ${a} |`).join(`
45
45
  `)}`:`> Collection failed: ${n.error}`;break}case"preferences":{const n=await U(e);t=n.data?`| Preferences | |
46
46
  |---|---|
47
- ${Object.entries(n.data).map(([s,o])=>`| ${s} | ${typeof o=="string"?o:JSON.stringify(o)} |`).join(`
48
- `)}`:`> Collection failed: ${n.error}`;break}}r.sendMessage({customType:S,content:t,display:!0})}c(T,"handleQuickSub");async function B(a,e,r){const t=w(a);t.subcommand!=="full"?await T(t.subcommand,e,r):await R(a,e,r)}c(B,"handleDebugCommand");async function G(a){a.registerMessageRenderer(S,(e,r,t)=>{const n=typeof e.content=="string"?e.content:e.content.filter(i=>i.type==="text").map(i=>i.text).join(`
49
- `),s=new C(1,1,i=>t.bg("customMessageBg",i));s.addChild(new P(t.fg("dim",n),0,0));const o=new E;return o.addChild(new $(1)),o.addChild(s),o}),a.on("before_agent_start",e=>{if(!(!z(e.prompt)||e.prompt!==p))return{appendSystemPrompt:j}}),a.on("agent_end",()=>{p&&(p=void 0)}),a.registerCommand("debug",{description:"Check NanoPencil health or investigate an issue. Usage: /debug [env|session|model|preferences|<issue>]",getArgumentCompletions:c((e,r)=>{if(r&&r.tokenIndex>0)return null;const t=e.trim().toLowerCase(),n=k.filter(s=>s.value.startsWith(t));return n.length>0?n:null},"getArgumentCompletions"),handler:c((e,r)=>B(e,r,a),"handler")}),a.registerCommand("set-locale",{description:"Set language preference (/set-locale zh|en)",getArgumentCompletions:c((e,r)=>{if(r&&r.tokenIndex>0)return null;const t=e.trim().toLowerCase(),n=N.filter(s=>s.value.startsWith(t));return n.length>0?n:null},"getArgumentCompletions"),handler:c(async(e,r)=>{const t=e.trim().toLowerCase();if(t!=="zh"&&t!=="en"){r.ui.notify("Usage: /set-locale zh or /set-locale en","info");return}const n=await import("node:os"),s=await import("node:fs"),o=await import("node:path"),i=process.env.NANOMEM_MEMORY_DIR||o.join(n.homedir(),".nanopencil","agent","memory"),u=o.join(i,"preferences.json");try{let l=[];s.existsSync(u)&&(l=JSON.parse(s.readFileSync(u,"utf-8")));const m=l.findIndex(d=>{const f=d.name||"";return f.includes("\u7528\u6237\u504F\u597D")||f.includes("language preference")||f.includes("locale")}),g={id:`set-locale-${Date.now()}`,type:"preference",name:t==="zh"?"\u7528\u6237\u504F\u597D\u4E2D\u6587":"Language Preference (English)",summary:t==="zh"?"\u7528\u6237\u5E0C\u671B\u6211\u7528\u4E2D\u6587\u56DE\u590D":"User prefers English",detail:t==="zh"?"\u7528\u6237\u901A\u8FC7 /set-locale \u547D\u4EE4\u660E\u786E\u8BBE\u7F6E\u8BED\u8A00\u4E3A\u4E2D\u6587":"User explicitly set language to English via /set-locale command",content:t==="zh"?"\u7528\u6237\u5E0C\u671B\u7528\u4E2D\u6587\u56DE\u590D":"User prefers English responses",tags:["locale","language",t==="zh"?"\u4E2D\u6587":"english"],importance:10,strength:1e3,created:new Date().toISOString(),eventTime:new Date().toISOString(),accessCount:0,retention:"core",salience:10,stability:"stable",relations:[]};m>=0?l[m]=g:l.push(g),s.writeFileSync(u,JSON.stringify(l,null,2)),r.ui.notify(`Locale set to ${t==="zh"?"\u4E2D\u6587":"English"}. Restart or run /debug preferences to verify.`,"info")}catch(l){r.ui.notify(`Failed to set locale: ${l}`,"error")}},"handler")})}c(G,"debugExtension");export{G as default};
47
+ ${Object.entries(n.data).map(([s,a])=>`| ${s} | ${typeof a=="string"?a:JSON.stringify(a)} |`).join(`
48
+ `)}`:`> Collection failed: ${n.error}`;break}}o.sendMessage({customType:S,content:t,display:!0})}c(T,"handleQuickSub");async function B(r,e,o){const t=w(r);t.subcommand!=="full"?await T(t.subcommand,e,o):await R(r,e,o)}c(B,"handleDebugCommand");async function G(r){r.registerMessageRenderer(S,(e,o,t)=>{const n=typeof e.content=="string"?e.content:e.content.filter(i=>i.type==="text").map(i=>i.text).join(`
49
+ `),s=new C(1,1,i=>t.bg("customMessageBg",i));s.addChild(new P(t.fg("dim",n),0,0));const a=new E;return a.addChild(new $(1)),a.addChild(s),a}),r.on("before_agent_start",e=>{if(!(!k(e.prompt)||e.prompt!==p))return{appendSystemPrompt:j}}),r.on("agent_end",()=>{p&&(p=void 0)}),r.registerCommand("debug",{description:"Check NanoPencil health or investigate an issue. Usage: /debug [env|session|model|preferences|<issue>]",getArgumentCompletions:c((e,o)=>{if(o&&o.tokenIndex>0)return null;const t=e.trim().toLowerCase(),n=z.filter(s=>s.value.startsWith(t));return n.length>0?n:null},"getArgumentCompletions"),handler:c((e,o)=>B(e,o,r),"handler")}),r.registerCommand("set-locale",{description:"Set language preference (/set-locale zh|en)",getArgumentCompletions:c((e,o)=>{if(o&&o.tokenIndex>0)return null;const t=e.trim().toLowerCase(),n=N.filter(s=>s.value.startsWith(t));return n.length>0?n:null},"getArgumentCompletions"),handler:c(async(e,o)=>{const t=e.trim().toLowerCase();if(t!=="zh"&&t!=="en"){o.ui.notify("Usage: /set-locale zh or /set-locale en","info");return}const n=await import("node:os"),s=await import("node:fs"),a=await import("node:path"),i=process.env.NANOMEM_MEMORY_DIR||a.join(n.homedir(),".nanopencil","agent","memory"),u=a.join(i,"preferences.json");try{let l=[];s.existsSync(u)&&(l=JSON.parse(s.readFileSync(u,"utf-8")));const m=l.findIndex(d=>{const f=d.name||"";return f.includes("\u7528\u6237\u504F\u597D")||f.includes("language preference")||f.includes("locale")}),g={id:`set-locale-${Date.now()}`,type:"preference",name:t==="zh"?"\u7528\u6237\u504F\u597D\u4E2D\u6587":"Language Preference (English)",summary:t==="zh"?"\u7528\u6237\u5E0C\u671B\u6211\u7528\u4E2D\u6587\u56DE\u590D":"User prefers English",detail:t==="zh"?"\u7528\u6237\u901A\u8FC7 /set-locale \u547D\u4EE4\u660E\u786E\u8BBE\u7F6E\u8BED\u8A00\u4E3A\u4E2D\u6587":"User explicitly set language to English via /set-locale command",content:t==="zh"?"\u7528\u6237\u5E0C\u671B\u7528\u4E2D\u6587\u56DE\u590D":"User prefers English responses",tags:["locale","language",t==="zh"?"\u4E2D\u6587":"english"],importance:10,strength:1e3,created:new Date().toISOString(),eventTime:new Date().toISOString(),accessCount:0,retention:"core",salience:10,stability:"stable",relations:[]};m>=0?l[m]=g:l.push(g),s.mkdirSync(i,{recursive:!0}),s.writeFileSync(u,JSON.stringify(l,null,2)),o.ui.notify(`Locale set to ${t==="zh"?"\u4E2D\u6587":"English"}. Restart or run /debug preferences to verify.`,"info")}catch(l){o.ui.notify(`Failed to set locale: ${l}`,"error")}},"handler")})}c(G,"debugExtension");export{G as default};
@@ -1,10 +1,10 @@
1
- var U=Object.defineProperty;var i=(t,r)=>U(t,"name",{value:r,configurable:!0});import*as B from"node:fs";import*as F from"node:os";import*as O from"node:path";import{Box as N,Container as j,Spacer as D,Text as K}from"@pencil-agent/tui";import{runGoalCommand as H}from"./goal-command.js";import{GoalController as J}from"./goal-controller.js";import{getGoalArgumentCompletions as Q}from"./goal-parser.js";import{buildAllGoalTools as X,setGoalToolHost as q}from"./goal-tools.js";import{goalStatusIndicator as G,goalSummaryLines as z,goalUsageSummary as W}from"./goal-format.js";import{isActiveStatus as C}from"./goal-types.js";const y="goal",Y="weak-model-compatible",V=O.join(F.homedir(),".nanopencil","agent","nanopencil-debug.log");function g(t){B.appendFileSync(V,`[${new Date().toISOString()}] [goal] ${t}
2
- `)}i(g,"dbg");function w(t,r){return t.length>r?t.slice(0,r)+"\u2026":t}i(w,"truncate");function Z(t){const r=t.content;if(typeof r=="string")return w(r,150);if(Array.isArray(r)){const c=r.filter(u=>u.type==="text"&&typeof u.text=="string").map(u=>u.text);if(c.length>0)return w(c.join(" "),150);const m=r.filter(u=>u.type==="tool_use").map(u=>`[tool_use:${u.name??"?"}]`);if(m.length>0)return m.join(" ")}return"(empty)"}i(Z,"extractContentPreview");const h=new Map;let k=null,S=null,_=null,$=null;function tt(t,r){const c=r.sessionManager.getSessionId();if(!c)return null;const m=`${r.agentDir}/${c}`;k=m;let u=h.get(m);return u||(u=new J(t,c),h.set(m,u)),S=u,u}i(tt,"resolveController");const et={getController(t,r){const c=`${t}/${r}`;return h.get(c)??null}};function nt(t){return"normal"}i(nt,"detectRunKind");function ot(t){return!!t.getSettings().plan}i(ot,"isPlanMode");function st(t){let r=0;for(const c of t){if(c.role!=="assistant")continue;const u=c.usage;u&&typeof u.totalTokens=="number"&&(r+=u.totalTokens)}return r}i(st,"getRunningTotalTokens");async function rt(t){q(et);const r=i(o=>{const s=tt(t,o);return s&&(S=s),s},"ensureController"),[c,m,u]=X();t.registerTool(c),t.registerTool(m),t.registerTool(u),t.registerMessageRenderer(y,(o,s,e)=>{const l=typeof o.content=="string"?o.content:Array.isArray(o.content)?o.content.filter(a=>a.type==="text").map(a=>a.text).join(`
3
- `):JSON.stringify(o.content??""),d=new N(1,1,a=>e.bg("customMessageBg",a));d.addChild(new K(e.fg("dim",l),0,0));const n=new j;return n.addChild(new D(1)),n.addChild(d),n}),t.registerCommand("goal",{description:"Set, show, edit, pause, resume, or clear the thread goal.",getArgumentCompletions:Q,handler:i(async(o,s)=>{g(`/goal command invoked: args="${o}"`);const e=r(s);await H(o,s,e),_=null,$=null,g("/goal command done, reportedTerminalGoalId reset")},"handler")}),t.on("session_start",(o,s)=>{g("session_start"),r(s)?.resetIdleContinuationFlag(),_=null,$=null}),t.on("session_shutdown",()=>{k&&h.delete(k),k=null,S=null});const E=i((o,s)=>{g(`turn_start index=${o.turnIndex} timestamp=${o.timestamp}`);const e=r(s);if(!e)return;const l=ot(s)?"plan":"normal";e.on_turn_start(`turn-${o.turnIndex}-${o.timestamp}`,l,0)},"onTurnStart");t.on("turn_start",E);const I=i((o,s)=>{r(s);const e=o.message;g(`message_start role=${e.role??"?"}`)},"onMessageStart");t.on("message_start",I);const A=i((o,s)=>{const e=r(s);if(!e)return;const l=o.message,d=Z(l);if(g(`message_end role=${l.role??"?"} tokens=${l.usage?.totalTokens??"?"} content=${d}`),l.role!=="assistant")return;const n=l.usage?.totalTokens;if(typeof n!="number")return;const a=e.on_token_usage(n);if(a.crossed&&a.goal){const f=e.maybe_build_budget_limit_steering();f&&t.sendMessage({customType:y,content:f,display:!0,details:{kind:"budget_limit",goal:a.goal}})}},"onMessageEnd");t.on("message_end",A);const M=i((o,s)=>{g(`tool_execution_end name=${o.toolName} isError=${o.isError} result=${w(JSON.stringify(o.result??""),200)}`);const e=r(s);e&&(o.isError||e.on_tool_finish(o.toolName))},"onToolExecutionEnd");t.on("tool_execution_end",M);const P=i(async(o,s)=>{try{const e=r(s);if(!e)return;const l=e.currentTurnSnapshot(),d=l?((Date.now()-l.turnStartedAt)/1e3).toFixed(1):"?";g(`turn_end BEGIN index=${o.turnIndex} duration=${d}s tokens=${l?.tokensNow??"?"}`);const n=await e.on_turn_end();if(g(`turn_end RESULT: reason=${n.reason} goalId=${n.goal?.goal_id} goalStatus=${n.goal?.status} reportedTerminalGoalId=${_}`),n.reason!=="not_active_status"||!n.goal)return;const a=n.goal.status;if(a==="complete"||a==="blocked"||a==="budget_limited"||a==="paused"){g(`turn_end \u2192 clearing followUp queue (goal is ${a})`);try{t.clearFollowUpQueue()}catch(R){g(`turn_end \u2192 clearFollowUpQueue FAILED: ${R}`)}}const f=n.goal.goal_id,T=n.goal.status;if(_===f&&$===T)return;const p=G(n.goal,null);(p.type==="Complete"||p.type==="BudgetLimited")&&(_=f,$=T,g(`turn_end \u2192 sending terminal message: ${p.type} for goal ${f}`),t.sendMessage({customType:y,content:`Goal ${p.type==="Complete"?"complete":"budget_limited"}.
1
+ var R=Object.defineProperty;var i=(t,r)=>R(t,"name",{value:r,configurable:!0});import*as E from"node:fs";import*as F from"node:os";import*as G from"node:path";import{Box as j,Container as D,Spacer as K,Text as H}from"@pencil-agent/tui";import{runGoalCommand as J}from"./goal-command.js";import{GoalController as Q}from"./goal-controller.js";import{getGoalArgumentCompletions as X}from"./goal-parser.js";import{buildAllGoalTools as q,setGoalToolHost as z}from"./goal-tools.js";import{goalStatusIndicator as C,goalSummaryLines as W,goalUsageSummary as Y}from"./goal-format.js";import{isActiveStatus as I}from"./goal-types.js";const y="goal",V="weak-model-compatible",Z=process.env.NANOPENCIL_DEBUG==="1",A=G.join(F.homedir(),".nanopencil","agent","nanopencil-debug.log");function g(t){if(Z)try{E.mkdirSync(G.dirname(A),{recursive:!0}),E.appendFileSync(A,`[${new Date().toISOString()}] [goal] ${t}
2
+ `)}catch{}}i(g,"dbg");function w(t,r){return t.length>r?t.slice(0,r)+"\u2026":t}i(w,"truncate");function tt(t){const r=t.content;if(typeof r=="string")return w(r,150);if(Array.isArray(r)){const c=r.filter(u=>u.type==="text"&&typeof u.text=="string").map(u=>u.text);if(c.length>0)return w(c.join(" "),150);const m=r.filter(u=>u.type==="tool_use").map(u=>`[tool_use:${u.name??"?"}]`);if(m.length>0)return m.join(" ")}return"(empty)"}i(tt,"extractContentPreview");const h=new Map;let k=null,S=null,_=null,$=null;function et(t,r){const c=r.sessionManager.getSessionId();if(!c)return null;const m=`${r.agentDir}/${c}`;k=m;let u=h.get(m);return u||(u=new Q(t,c),h.set(m,u)),S=u,u}i(et,"resolveController");const nt={getController(t,r){const c=`${t}/${r}`;return h.get(c)??null}};function ot(t){return"normal"}i(ot,"detectRunKind");function st(t){return!!t.getSettings().plan}i(st,"isPlanMode");function rt(t){let r=0;for(const c of t){if(c.role!=="assistant")continue;const u=c.usage;u&&typeof u.totalTokens=="number"&&(r+=u.totalTokens)}return r}i(rt,"getRunningTotalTokens");async function at(t){z(nt);const r=i(o=>{const s=et(t,o);return s&&(S=s),s},"ensureController"),[c,m,u]=q();t.registerTool(c),t.registerTool(m),t.registerTool(u),t.registerMessageRenderer(y,(o,s,e)=>{const l=typeof o.content=="string"?o.content:Array.isArray(o.content)?o.content.filter(a=>a.type==="text").map(a=>a.text).join(`
3
+ `):JSON.stringify(o.content??""),d=new j(1,1,a=>e.bg("customMessageBg",a));d.addChild(new H(e.fg("dim",l),0,0));const n=new D;return n.addChild(new K(1)),n.addChild(d),n}),t.registerCommand("goal",{description:"Set, show, edit, pause, resume, or clear the thread goal.",getArgumentCompletions:X,handler:i(async(o,s)=>{g(`/goal command invoked: args="${o}"`);const e=r(s);await J(o,s,e),_=null,$=null,g("/goal command done, reportedTerminalGoalId reset")},"handler")}),t.on("session_start",(o,s)=>{g("session_start"),r(s)?.resetIdleContinuationFlag(),_=null,$=null}),t.on("session_shutdown",()=>{k&&h.delete(k),k=null,S=null});const P=i((o,s)=>{g(`turn_start index=${o.turnIndex} timestamp=${o.timestamp}`);const e=r(s);if(!e)return;const l=st(s)?"plan":"normal";e.on_turn_start(`turn-${o.turnIndex}-${o.timestamp}`,l,0)},"onTurnStart");t.on("turn_start",P);const M=i((o,s)=>{r(s);const e=o.message;g(`message_start role=${e.role??"?"}`)},"onMessageStart");t.on("message_start",M);const v=i((o,s)=>{const e=r(s);if(!e)return;const l=o.message,d=tt(l);if(g(`message_end role=${l.role??"?"} tokens=${l.usage?.totalTokens??"?"} content=${d}`),l.role!=="assistant")return;const n=l.usage?.totalTokens;if(typeof n!="number")return;const a=e.on_token_usage(n);if(a.crossed&&a.goal){const f=e.maybe_build_budget_limit_steering();f&&t.sendMessage({customType:y,content:f,display:!0,details:{kind:"budget_limit",goal:a.goal}})}},"onMessageEnd");t.on("message_end",v);const L=i((o,s)=>{g(`tool_execution_end name=${o.toolName} isError=${o.isError} result=${w(JSON.stringify(o.result??""),200)}`);const e=r(s);e&&(o.isError||e.on_tool_finish(o.toolName))},"onToolExecutionEnd");t.on("tool_execution_end",L);const N=i(async(o,s)=>{try{const e=r(s);if(!e)return;const l=e.currentTurnSnapshot(),d=l?((Date.now()-l.turnStartedAt)/1e3).toFixed(1):"?";g(`turn_end BEGIN index=${o.turnIndex} duration=${d}s tokens=${l?.tokensNow??"?"}`);const n=await e.on_turn_end();if(g(`turn_end RESULT: reason=${n.reason} goalId=${n.goal?.goal_id} goalStatus=${n.goal?.status} reportedTerminalGoalId=${_}`),n.reason!=="not_active_status"||!n.goal)return;const a=n.goal.status;if(a==="complete"||a==="blocked"||a==="budget_limited"||a==="paused"){g(`turn_end \u2192 clearing followUp queue (goal is ${a})`);try{t.clearFollowUpQueue()}catch(O){g(`turn_end \u2192 clearFollowUpQueue FAILED: ${O}`)}}const f=n.goal.goal_id,T=n.goal.status;if(_===f&&$===T)return;const p=C(n.goal,null);(p.type==="Complete"||p.type==="BudgetLimited")&&(_=f,$=T,g(`turn_end \u2192 sending terminal message: ${p.type} for goal ${f}`),t.sendMessage({customType:y,content:`Goal ${p.type==="Complete"?"complete":"budget_limited"}.
4
4
  ${b(n.goal)}`,display:!0,details:{kind:p.type.toLowerCase(),goal:n.goal}},{triggerTurn:!1}))}catch(e){g(`turn_end EXCEPTION: ${e instanceof Error?e.message:String(e)}
5
- ${e instanceof Error?e.stack:""}`)}},"onTurnEnd");t.on("turn_end",P);const L=i(async(o,s)=>{try{const e=r(s);if(!e)return;const l=st(o.messages);e.on_token_usage(l);const d=e.runStopReason;if(g(`agent_end stopReason=${d??"unknown"}`),d==="aborted")return;if(d==="error"){const a=e.on_turn_error();a&&a.status==="blocked"&&(g(`agent_end \u2192 goal ${a.goal_id} blocked after run error`),t.sendMessage({customType:y,content:`Goal blocked: the run ended with an error. Use /goal resume to continue.
5
+ ${e instanceof Error?e.stack:""}`)}},"onTurnEnd");t.on("turn_end",N);const U=i(async(o,s)=>{try{const e=r(s);if(!e)return;const l=rt(o.messages);e.on_token_usage(l);const d=e.runStopReason;if(g(`agent_end stopReason=${d??"unknown"}`),d==="aborted")return;if(d==="error"){const a=e.on_turn_error();a&&a.status==="blocked"&&(g(`agent_end \u2192 goal ${a.goal_id} blocked after run error`),t.sendMessage({customType:y,content:`Goal blocked: the run ended with an error. Use /goal resume to continue.
6
6
  ${b(a)}`,display:!0,details:{kind:"blocked_on_error",goal:a}},{triggerTurn:!1}));return}const n=e.maybe_dispatch_continuation({hasPendingMessages:s.hasPendingMessages()});if(g(`agent_end DISPATCH: dispatched=${n.dispatched} reason=${n.reason} goalStatus=${n.goal?.status}`),n.dispatched)t.sendMessage({customType:y,content:`Goal continuation dispatched.
7
7
  ${b(n.goal)}`,display:!0,details:{kind:"continuation",goal:n.goal}},{triggerTurn:!1});else if(n.goal&&n.reason==="continuation_limit_reached")s.hasUI&&s.ui.setStatus("goal","Continuation limit \u2014 /goal resume to continue");else if(n.goal&&n.reason==="total_continuation_limit_reached"){if(_===n.goal.goal_id&&$==="paused")return;_=n.goal.goal_id,$="paused",t.sendMessage({customType:y,content:`Goal auto-paused after ${n.consecutiveContinuations??"?"} continuation turns. Use /goal resume to continue.
8
8
  ${b(n.goal)}`,display:!0,details:{kind:"total_continuation_limit",goal:n.goal}},{triggerTurn:!1})}}catch(e){g(`agent_end EXCEPTION: ${e instanceof Error?e.message:String(e)}
9
- ${e instanceof Error?e.stack:""}`)}},"onAgentEnd");t.on("agent_end",L);const v=i((o,s)=>{const e=r(s);if(!e)return;e.note_run_stop_reason(o.stopReason);const l=o.usage;l&&typeof l.totalTokens=="number"&&e.on_token_usage(l.totalTokens);const d=o.loopFramework;nt(d)},"onAgentResult");t.on("agent_result",v);const x=i(async(o,s)=>{const e=r(s);if(!e)return;const l=await e.get_goal();!l||!C(l.status)||(g(`agent_abort \u2192 pausing goal ${l.goal_id}`),await e.set_status("paused"),_=null,$=null,s.hasUI&&s.ui.notify("Goal paused (agent aborted).","info"))},"onAgentAbort");t.on("agent_abort",x),t.on("session_start",(o,s)=>{if(!s.hasUI)return;const l=setInterval(i(()=>{const n=S;n&&n.get_goal().then(a=>{if(!a||!C(a.status)&&a.status!=="budget_limited"&&a.status!=="complete"){s.ui.setStatus("goal",void 0);return}const f=n.currentTurnSnapshot()?.turnStartedAt??null,T=G(a,f),p=at(T);s.ui.setStatus("goal",p)}).catch(()=>{})},"tick"),200),d=i(()=>clearInterval(l),"cleanup");t.on("session_shutdown",()=>d())})}i(rt,"goalExtension");function at(t){switch(t.type){case"Active":return`Pursuing goal (${t.usage})`;case"Paused":return"Goal paused (/goal resume)";case"Blocked":return"Goal blocked (/goal resume)";case"UsageLimited":return"Goal hit usage limits (/goal resume)";case"BudgetLimited":return t.usage?`Goal unmet (${t.usage})`:"Goal abandoned";case"Complete":return`Goal achieved (${t.usage})`}}i(at,"indicatorLabel");function b(t){if(!t)return"";const r=z(t),c=W(t);return[` Status: ${t.status}`,` Objective: ${t.objective}`,` Time used: ${c.elapsed}`,` Tokens used: ${c.tokensLabel}${c.hasBudget?" tokens":""}`].join(`
10
- `)}i(b,"summarizeGoalStatus");export{rt as default};
9
+ ${e instanceof Error?e.stack:""}`)}},"onAgentEnd");t.on("agent_end",U);const x=i((o,s)=>{const e=r(s);if(!e)return;e.note_run_stop_reason(o.stopReason);const l=o.usage;l&&typeof l.totalTokens=="number"&&e.on_token_usage(l.totalTokens);const d=o.loopFramework;ot(d)},"onAgentResult");t.on("agent_result",x);const B=i(async(o,s)=>{const e=r(s);if(!e)return;const l=await e.get_goal();!l||!I(l.status)||(g(`agent_abort \u2192 pausing goal ${l.goal_id}`),await e.set_status("paused"),_=null,$=null,s.hasUI&&s.ui.notify("Goal paused (agent aborted).","info"))},"onAgentAbort");t.on("agent_abort",B),t.on("session_start",(o,s)=>{if(!s.hasUI)return;const l=setInterval(i(()=>{const n=S;n&&n.get_goal().then(a=>{if(!a||!I(a.status)&&a.status!=="budget_limited"&&a.status!=="complete"){s.ui.setStatus("goal",void 0);return}const f=n.currentTurnSnapshot()?.turnStartedAt??null,T=C(a,f),p=lt(T);s.ui.setStatus("goal",p)}).catch(()=>{})},"tick"),200),d=i(()=>clearInterval(l),"cleanup");t.on("session_shutdown",()=>d())})}i(at,"goalExtension");function lt(t){switch(t.type){case"Active":return`Pursuing goal (${t.usage})`;case"Paused":return"Goal paused (/goal resume)";case"Blocked":return"Goal blocked (/goal resume)";case"UsageLimited":return"Goal hit usage limits (/goal resume)";case"BudgetLimited":return t.usage?`Goal unmet (${t.usage})`:"Goal abandoned";case"Complete":return`Goal achieved (${t.usage})`}}i(lt,"indicatorLabel");function b(t){if(!t)return"";const r=W(t),c=Y(t);return[` Status: ${t.status}`,` Objective: ${t.objective}`,` Time used: ${c.elapsed}`,` Tokens used: ${c.tokensLabel}${c.hasBudget?" tokens":""}`].join(`
10
+ `)}i(b,"summarizeGoalStatus");export{at as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pencil-agent/nano-pencil",
3
- "version": "2.0.2",
3
+ "version": "2.0.3",
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": {