agent-termo 1.0.3 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +96 -85
- package/dist/cli.js.map +3 -3
- package/dist/main.js +81 -70
- package/dist/main.js.map +3 -3
- package/package.json +1 -1
- package/src/agents/index.ts +3 -2
- package/src/cli.ts +1 -1
- package/src/llm/client.ts +63 -20
- package/src/llm/tools.ts +21 -7
- package/src/main.ts +91 -85
- package/src/memory/index.ts +49 -13
- package/src/tools/index.ts +22 -2
- package/src/types/index.ts +2 -0
package/dist/main.js
CHANGED
|
@@ -1,19 +1,29 @@
|
|
|
1
|
-
import
|
|
2
|
-
`)){let r=n.trim();if(!r||r.startsWith("#"))continue;let o=r.indexOf("=");if(o===-1||o===r.length-1)continue;let i=r.slice(0,o).trim(),
|
|
3
|
-
`,{encoding:"utf-8",mode:384}),process.platform!=="win32"&&
|
|
1
|
+
import mt from"openai";var Te=[{id:"stepfun-ai/step-3.7-flash",note:"default"},{id:"meta/llama-3.1-8b-instruct",note:"fast, low cost"},{id:"meta/llama-3.1-70b-instruct",note:"balanced"},{id:"meta/llama-3.3-70b-instruct",note:"balanced"},{id:"meta/llama-3.1-405b-instruct",note:"highest quality Llama"},{id:"nvidia/llama-3.1-nemotron-70b-instruct",note:"NVIDIA tuned"},{id:"qwen/qwen2.5-coder-32b-instruct",note:"coding"},{id:"deepseek-ai/deepseek-r1",note:"reasoning"},{id:"moonshotai/kimi-k2-instruct",note:"agentic / tool use"},{id:"openai/gpt-oss-120b",note:"open-weight GPT"}],ut=/embed|rerank|retriev|reward|guard|safety|parse|clip|vila|neva|fuyu|kosmos|paligemma|deplot|riva|asr|tts|whisper|diffusion|sdxl|flux|cosmos|segment|bge-|e5-|gliner|pii|streampetr|ocdrnet|bevformer/i;function dt(e){return!ut.test(e)}function X(e){if(!e)return[...Te];let t=new Set(e),n=Te.filter(i=>t.has(i.id)),r=new Set(n.map(i=>i.id)),o=e.filter(i=>!r.has(i)&&dt(i)).sort((i,a)=>i.localeCompare(a)).map(i=>({id:i}));return[...n,...o]}var Ce={"file:read":"file_read","file:write":"file_write","file:edit":"file_edit","file:delete":"file_delete","file:glob":"file_glob","bash:execute":"bash_execute","git:status":"git_status","git:commit":"git_commit","git:push":"git_push","git:log":"git_log"};function ee(e){return Ce[e]??e.replace(/:/g,"_")}function U(e){return Object.entries(Ce).find(([,t])=>t===e)?.[0]??e}var G=class{client;model;constructor(t){let n=process.env.NIM_API_KEY??"",r=process.env.NIM_BASE_URL??"https://integrate.api.nvidia.com/v1";this.model=process.env.NIM_MODEL??"stepfun-ai/step-3.7-flash";let o=parseInt(process.env.LLM_TIMEOUT??"120000",10);this.client=new mt({apiKey:n,baseURL:r,timeout:o,defaultHeaders:{"User-Agent":"agent-termo/1.0"}})}buildToolDefs(t){return t.map(n=>({type:"function",function:{name:ee(n.name),description:n.description,parameters:n.parameters}}))}getModel(){return this.model}setModel(t){this.model=t}async listModels(){try{let n=(await this.client.models.list({timeout:1e4})).data.map(r=>r.id);if(n.length===0)throw new Error("empty model list");return{models:X(n),live:!0}}catch(t){return{models:X(null),live:!1,error:t instanceof Error?t.message:String(t)}}}async*streamComplete(t,n,r){let o=[],i=new Map,a=await this.client.chat.completions.create({model:this.model,messages:t.map(p=>p.role==="tool"?{role:"tool",content:p.content,tool_call_id:p.id}:p.role==="assistant"&&p.toolCalls?.length?{role:"assistant",content:p.content||null,tool_calls:p.toolCalls.map(u=>({id:u.id,type:"function",function:{name:ee(u.name),arguments:JSON.stringify(u.arguments)}}))}:{role:p.role,content:p.content}),tools:n,temperature:.3,max_tokens:8192,stream:!0});for await(let p of a){let u=p.choices[0]?.delta;if(!u)continue;let g=u.content??"";if(!(g==="null"||g==="undefined")&&g&&(o.push(g),r?.(g)),u.tool_calls)for(let y of u.tool_calls){let w=y.index??0,f=i.get(w);f?(f.arguments+=y.function?.arguments??"",y.id&&!f.id&&(f.id=y.id)):i.set(w,{id:y.id??crypto.randomUUID(),name:y.function?.name??"",arguments:y.function?.arguments??""})}}let c=o.join(""),s=Array.from(i.values()).map(p=>{let u={};try{u=JSON.parse(p.arguments)}catch{u={_raw:p.arguments}}return{id:p.id,name:U(p.name),arguments:u}});yield{content:c,toolCalls:s}}async complete(t,n){let o=(await this.client.chat.completions.create({model:this.model,messages:t.map(c=>c.role==="tool"?{role:"tool",content:c.content,tool_call_id:c.id}:c.role==="assistant"&&c.toolCalls?.length?{role:"assistant",content:c.content||null,tool_calls:c.toolCalls.map(s=>({id:s.id,type:"function",function:{name:ee(s.name),arguments:JSON.stringify(s.arguments)}}))}:{role:c.role,content:c.content}),tools:n,temperature:.3,max_tokens:8192,stream:!1})).choices[0]?.message,i=o?.content?.replace(/\[ Reasoning[^\]]*\][^\[]*\[\/ Reasoning\][^\n]*/gi,"").trim()??"",a=(o?.tool_calls??[]).map(c=>{let s={};try{s=JSON.parse(c.function.arguments??"{}")}catch{s={_raw:c.function.arguments}}return{id:c.id,name:U(c.function.name),arguments:s}});if(a.length===0&&i.includes('"tool_calls"'))try{let c=JSON.parse(i);if(c.tool_calls?.length){a.push(...c.tool_calls.map(p=>({id:p.id??crypto.randomUUID(),name:U(p.function?.name??p.name??""),arguments:typeof p.function?.arguments=="string"?JSON.parse(p.function.arguments):p.function?.arguments??{}})));let s=i.indexOf('{"tool_calls"');s!==-1&&(i=i.slice(0,s).trim())}}catch{}return{content:i,toolCalls:a}}};var te=[{name:"file:read",description:"Read the complete contents of a file. Use for examining existing code, config, or documentation.",parameters:{type:"object",properties:{path:{type:"string",description:"File path (absolute or relative to project root)"},limit:{type:"number",description:"Maximum number of lines to read (0 = all)",default:0},offset:{type:"number",description:"Line offset to start reading from (0 = start)",default:0}},required:["path"]}},{name:"file:write",description:"Write or overwrite a complete file. Use this to create new files or replace existing ones entirely.",parameters:{type:"object",properties:{path:{type:"string",description:"File path to write (relative to project root)"},content:{type:"string",description:"Complete file content to write"}},required:["path","content"]}},{name:"file:edit",description:"Edit an existing file by replacing an exact section. The old_string must appear verbatim in the file.",parameters:{type:"object",properties:{path:{type:"string",description:"File to edit"},old_string:{type:"string",description:"Exact text to find and replace (must be unique in file)"},new_string:{type:"string",description:"Replacement text"}},required:["path","old_string","new_string"]}},{name:"file:delete",description:"Delete a file from the project. Use only when the user explicitly asks to remove it.",parameters:{type:"object",properties:{path:{type:"string",description:"File path to delete (relative to project root)"}},required:["path"]}},{name:"file:glob",description:"Find all files matching a glob pattern. Use to discover project structure.",parameters:{type:"object",properties:{pattern:{type:"string",description:'Glob pattern (e.g. "src/**/*.ts", "**/*.json")'},cwd:{type:"string",description:"Root directory to search in (defaults to project root)"}},required:["pattern"]}},{name:"grep",description:"Search for text or regex patterns inside files. Use to find function definitions, imports, etc.",parameters:{type:"object",properties:{pattern:{type:"string",description:"Text or regex pattern to search for"},path:{type:"string",description:"File or directory to search in"},glob:{type:"string",description:"Only search files matching this glob pattern"},case_sensitive:{type:"boolean",description:"Case sensitive search (default true)",default:!0}},required:["pattern","path"]}},{name:"bash:execute",description:"Execute a shell command and return its stdout/stderr output. Destructive commands (rm, dd) require user confirmation.",parameters:{type:"object",properties:{command:{type:"string",description:"Shell command to execute"},cwd:{type:"string",description:"Working directory (defaults to project root)"},timeout:{type:"number",description:"Timeout in milliseconds (default 300000)",default:3e5}},required:["command"]}},{name:"git:status",description:"Show the git working tree status (modified, staged, untracked files).",parameters:{type:"object",properties:{cwd:{type:"string",description:"Repository root (default: project root)"}}}},{name:"git:commit",description:"Stage and commit all changes with a conventional commit message.",parameters:{type:"object",properties:{message:{type:"string",description:'Conventional commit message (e.g. "feat: add login page")'},cwd:{type:"string",description:"Repository root (default: project root)"}},required:["message"]}},{name:"git:push",description:"Push the current branch to the remote repository.",parameters:{type:"object",properties:{cwd:{type:"string",description:"Repository root (default: project root)"}}}},{name:"git:log",description:"Show recent git commit history.",parameters:{type:"object",properties:{cwd:{type:"string",description:"Repository root (default: project root)"},limit:{type:"number",description:"Number of commits to show (default: 20)",default:20}}}}];import{readFile as oe,writeFile as Tt,unlink as Ct}from"node:fs/promises";import{resolve as ie,isAbsolute as V,relative as St}from"node:path";import{exec as It}from"node:child_process";import{promisify as _e}from"node:util";import{default as At}from"glob";import{simpleGit as z}from"simple-git";import{statSync as Et,existsSync as W,mkdirSync as Pt}from"node:fs";import{chmodSync as pt,mkdirSync as ft,readFileSync as Ie,writeFileSync as gt}from"node:fs";import{resolve as O,dirname as Se}from"node:path";import{fileURLToPath as ht}from"node:url";function wt(){try{let e=ht(import.meta.url);return Se(Se(e))}catch{return process.cwd()}}function ne(e){try{let t=Ie(e,"utf-8");for(let n of t.split(`
|
|
2
|
+
`)){let r=n.trim();if(!r||r.startsWith("#"))continue;let o=r.indexOf("=");if(o===-1||o===r.length-1)continue;let i=r.slice(0,o).trim(),a=r.slice(o+1).trim().replace(/^["']|["']$/g,"");process.env[i]||(process.env[i]=a)}}catch{}}var Ae=wt();ne(O(Ae,".env"));ne(O(".env"));function Ee(){let e=process.env.AGENT_TERMO_DIR;return e?O(process.env.HOME||process.env.USERPROFILE||".",e):O(process.env.HOME||process.env.USERPROFILE||".",".agent-termo")}function re(){try{let e=JSON.parse(Ie(O(Ee(),"config.json"),"utf-8"));if(e&&typeof e=="object"&&!Array.isArray(e))return e}catch{}return{}}function yt(e){let t=Ee(),n=O(t,"config.json"),r={...re(),...e};ft(t,{recursive:!0,mode:448}),gt(n,`${JSON.stringify(r,null,2)}
|
|
3
|
+
`,{encoding:"utf-8",mode:384}),process.platform!=="win32"&&pt(n,384)}function bt(){if(process.env.NIM_API_KEY)return;let{nimApiKey:e}=re();typeof e=="string"&&e.trim()&&(process.env.NIM_API_KEY=e)}function xt(){let{nimModel:e}=re();typeof e=="string"&&e.trim()&&(process.env.NIM_MODEL=e)}function Pe(e){yt({nimModel:e})}bt();xt();function ke(e){return ne(O(e,".env")),{nimApiKey:process.env.NIM_API_KEY??"",nimBaseUrl:process.env.NIM_BASE_URL??"https://integrate.api.nvidia.com/v1",nimModel:process.env.NIM_MODEL??"stepfun-ai/step-3.7-flash",agentTermoDir:process.env.AGENT_TERMO_DIR??".claude",logLevel:process.env.LOG_LEVEL||"info",confirmDestructive:process.env.CONFIRM_DESTRUCTIVE!=="false",allowedCommands:(process.env.ALLOWED_COMMANDS??"git,npm,node,pnpm,yarn,tsx,tsc,npx").split(","),llmTimeout:parseInt(process.env.LLM_TIMEOUT??"120000",10),bashTimeout:parseInt(process.env.BASH_TIMEOUT??"300000",10)}}function De(e){return e||Ae}function Oe(e,t){let n=e.split(`
|
|
4
4
|
`),r=t.split(`
|
|
5
|
-
`);if(n.length===1&&n[0]==="")return{file:"",lines:r.map((f,v)=>({type:"add",lineNumber:v+1,content:f})),additions:r.length,deletions:0};if(e===t)return{file:"",lines:[],additions:0,deletions:0};let o=n.length,i=r.length,
|
|
6
|
-
`).length,y=
|
|
7
|
-
`),p=
|
|
5
|
+
`);if(n.length===1&&n[0]==="")return{file:"",lines:r.map((f,v)=>({type:"add",lineNumber:v+1,content:f})),additions:r.length,deletions:0};if(e===t)return{file:"",lines:[],additions:0,deletions:0};let o=n.length,i=r.length,a=i+1,c=new Int32Array((o+1)*(i+1)),s=(w,f)=>c[w*a+f],p=(w,f,v)=>{c[w*a+f]=v};for(let w=1;w<=o;w++)for(let f=1;f<=i;f++)n[w-1]===r[f-1]?p(w,f,s(w-1,f-1)+1):p(w,f,Math.max(s(w-1,f),s(w,f-1)));let u=vt(s,n,r),g=Mt(u),m=0,y=0;for(let w of g)w.type==="add"&&m++,w.type==="remove"&&y++;return{file:"",lines:g,additions:m,deletions:y}}function vt(e,t,n){let r=[],o=t.length,i=n.length,a=o,c=i;for(;a>0||c>0;)a>0&&c>0&&t[a-1]===n[c-1]?(r.unshift({type:"same",originalIndex:a,proposedIndex:c,originalLine:t[a-1],proposedLine:n[c-1]}),a--,c--):c>0&&(a===0||e(a,c-1)>=e(a-1,c))?(r.unshift({type:"add",proposedIndex:c,originalIndex:a,proposedLine:n[c-1]}),c--):(r.unshift({type:"remove",originalIndex:a,proposedIndex:c,originalLine:t[a-1]}),a--);return r}function Mt(e){let t=[],n=0,r=0;for(let o of e)switch(o.type){case"same":{n++,r++,t.push({type:"context",lineNumber:n,content:o.originalLine??""});break}case"remove":{n++,t.push({type:"remove",lineNumber:n,content:o.originalLine??""});break}case"add":{r++,t.push({type:"add",lineNumber:r,content:o.proposedLine??""});break}}return t}var Re=_e(It),kt=_e(At),Dt={"file:read":Ot,"file:write":_t,"file:edit":Rt,"file:delete":Nt,"file:glob":Lt,grep:jt,"bash:execute":$t,"git:status":Ut,"git:commit":Wt,"git:push":qt,"git:log":Ht};async function Ne(e,t,n){let r=Date.now(),o=crypto.randomUUID();try{let i=Dt[e];return i?await i(t,n):{id:o,name:e,success:!1,error:"Unknown tool: "+e,durationMs:Date.now()-r}}catch(i){return{id:o,name:e,success:!1,error:String(i instanceof Error?i.message:i),durationMs:Date.now()-r}}}function j(e,t){return V(e)?e:ie(t,e)}function F(e,t){try{let n=j(e,t),r=St(t,n);return!r.startsWith("..")&&!V(r)}catch{return!1}}function se(e,t,n,r,o){let i=j(e,n),a=o??"",c=!W(i),s=t===""&&r==="write",u=Oe(c?"":a,t),g={path:e,originalContent:a,proposedContent:t,diff:{...u,file:e},isNewFile:c,isDeletion:s},m=t.split(`
|
|
6
|
+
`).length,y=s?`Delete ${e} (${m} lines removed)`:c?`Create ${e} (${m} lines)`:`${r==="edit"?"Edit":"Overwrite"} ${e} (${m} lines, +${u.additions}/-${u.deletions})`,w={id:"",name:`${r}:${e}`,success:!0,output:JSON.stringify({message:y,needsApproval:!0,proposedChange:g}),durationMs:0};return{change:g,result:w}}async function Le(e,t){let n=Date.now(),r=j(e.path,t);try{if(e.isDeletion)W(r)&&await Ct(r);else{let o=ie(r,"..");W(o)||Pt(o,{recursive:!0}),await Tt(r,e.proposedContent,"utf-8")}return{id:"",name:"file:write",success:!0,output:`Applied: ${e.path}`,durationMs:Date.now()-n}}catch(o){return{id:"",name:"file:write",success:!1,error:"Cannot apply "+e.path+": "+(o instanceof Error?o.message:String(o)),durationMs:Date.now()-n}}}async function Ot(e,t){let n=String(e.path??"");if(!n)return{id:"",name:"file:read",success:!1,error:"path is required",durationMs:0};if(!F(n,t))return{id:"",name:"file:read",success:!1,error:"Access denied: "+n,durationMs:0};let r=j(n,t),o=Number(e.limit??0),i=Number(e.offset??0);try{if(Et(r).isDirectory())return{id:"",name:"file:read",success:!1,error:'Path "'+n+'" is a directory',durationMs:0};let s=(await oe(r,"utf-8")).split(`
|
|
7
|
+
`),p=s.slice(i,o>0?i+o:void 0),u=o>0?"[Showing lines "+(i+1)+"-"+(i+p.length)+" of "+s.length+"]":"";return{id:"",name:"file:read",success:!0,output:(u?u+`
|
|
8
8
|
`:"")+p.join(`
|
|
9
|
-
`),durationMs:0}}catch(
|
|
10
|
-
`):"(no files matched)",durationMs:0}}catch(o){return{id:"",name:"file:glob",success:!1,error:"glob error: "+(o instanceof Error?o.message:String(o)),durationMs:0}}}async function
|
|
11
|
-
`)||"(no output)",durationMs:0}}catch(i){let
|
|
12
|
-
`).slice(0,500)||
|
|
13
|
-
`),durationMs:0}}catch(r){return{id:"",name:"git:status",success:!1,error:r instanceof Error?r.message:String(r),durationMs:0}}}async function
|
|
14
|
-
`),durationMs:0}}catch(o){return{id:"",name:"git:log",success:!1,error:o instanceof Error?o.message:String(o),durationMs:0}}}import{readFileSync as
|
|
15
|
-
- [`+new Date().toISOString().replace("T"," ").slice(0,16)+"] "+e;try{
|
|
16
|
-
|
|
9
|
+
`),durationMs:0}}catch(a){return{id:"",name:"file:read",success:!1,error:"Cannot read "+n+": "+(a instanceof Error?a.message:String(a)),durationMs:0}}}async function _t(e,t){let n=String(e.path??""),r=String(e.content??"");if(!n)return{id:"",name:"file:write",success:!1,error:"path is required",durationMs:0};if(!F(n,t))return{id:"",name:"file:write",success:!1,error:"Access denied: "+n,durationMs:0};let{result:o}=se(n,r,t,"write");return o}async function Rt(e,t){let n=String(e.path??""),r=String(e.old_string??""),o=String(e.new_string??"");if(!n||!r)return{id:"",name:"file:edit",success:!1,error:"path and old_string are required",durationMs:0};if(!F(n,t))return{id:"",name:"file:edit",success:!1,error:"Access denied: "+n,durationMs:0};let i=j(n,t);try{let a=W(i)?await oe(i,"utf-8"):"";if(!a.includes(r))return{id:"",name:"file:edit",success:!1,error:"old_string not found in "+n+". Check whitespace.",durationMs:0};let c=a.replace(r,o),{result:s}=se(n,c,t,"edit",a);return s}catch(a){return{id:"",name:"file:edit",success:!1,error:"Cannot edit "+n+": "+(a instanceof Error?a.message:String(a)),durationMs:0}}}async function Nt(e,t){let n=String(e.path??"");if(!n)return{id:"",name:"file:delete",success:!1,error:"path is required",durationMs:0};if(!F(n,t))return{id:"",name:"file:delete",success:!1,error:"Access denied: "+n,durationMs:0};let r=j(n,t);try{if(!W(r))return{id:"",name:"file:delete",success:!1,error:"File not found: "+n,durationMs:0};let o=await oe(r,"utf-8");return se(n,"",t,"write",o).result}catch(o){return{id:"",name:"file:delete",success:!1,error:"Cannot delete "+n+": "+(o instanceof Error?o.message:String(o)),durationMs:0}}}async function Lt(e,t){let n=String(e.pattern??"");if(!n)return{id:"",name:"file:glob",success:!1,error:"pattern is required",durationMs:0};let r=e.cwd?String(e.cwd):t;if(!F(r,t))return{id:"",name:"file:glob",success:!1,error:"Access denied",durationMs:0};try{let o=await kt(n,{cwd:r,absolute:!1});return{id:"",name:"file:glob",success:!0,output:o.length>0?o.join(`
|
|
10
|
+
`):"(no files matched)",durationMs:0}}catch(o){return{id:"",name:"file:glob",success:!1,error:"glob error: "+(o instanceof Error?o.message:String(o)),durationMs:0}}}async function jt(e,t){let n=String(e.pattern??""),r=e.path?String(e.path):".",o=e.case_sensitive!==!1;if(!n||!r)return{id:"",name:"grep",success:!1,error:"pattern and path are required",durationMs:0};if(V(r)&&!F(r,t))return{id:"",name:"grep",success:!1,error:"Access denied",durationMs:0};let i=V(r)?r:ie(t,r),a=o?"":"-i",c=e.glob?["--include="+String(e.glob)]:[];try{let s=["grep",a,"-rn","--color=never",n,i,...c].join(" "),{stdout:p,stderr:u}=await Re(s,{timeout:3e4});return{id:"",name:"grep",success:!0,output:(p||u).trim()||"(no matches found)",durationMs:0}}catch(s){return s.code===1?{id:"",name:"grep",success:!0,output:"(no matches found)",durationMs:0}:{id:"",name:"grep",success:!1,error:"grep error: "+(s instanceof Error?s.message:String(s)),durationMs:0}}}var Ft=[/rm\s+-rf\s+['"]?\//i,/dd\s+if=/i,/>\s*\/dev\/sda/i,/mkfs\./i,/:\s*\(\)\s*\{\s*:\|:&?\s*\};?\s*:/i];async function $t(e,t){let n=String(e.command??""),r=e.cwd?String(e.cwd):t,o=Number(e.timeout??ke(t).bashTimeout);if(!n)return{id:"",name:"bash:execute",success:!1,error:"command is required",durationMs:0};for(let i of Ft)if(i.test(n))return{id:"",name:"bash:execute",success:!1,error:"Dangerous command blocked: "+n.slice(0,50),durationMs:0};try{let{stdout:i,stderr:a}=await Re(n,{cwd:r,timeout:o});return{id:"",name:"bash:execute",success:!0,output:[i,a].filter(Boolean).join(`
|
|
11
|
+
`)||"(no output)",durationMs:0}}catch(i){let a=i;return{id:"",name:"bash:execute",success:!1,error:[a.stdout,a.stderr].filter(Boolean).join(`
|
|
12
|
+
`).slice(0,500)||a.message,durationMs:0}}}async function Ut(e,t){let n=e.cwd?String(e.cwd):t;try{let o=await z(n).status(),i=o.tracking;return{id:"",name:"git:status",success:!0,output:["Current branch: "+(o.current??"unknown"),i?"tracking: "+i:"","","Modified: "+(o.modified.length>0?o.modified.join(", "):"(none)"),"Created: "+(o.created.length>0?o.created.join(", "):"(none)"),"Deleted: "+(o.deleted.length>0?o.deleted.join(", "):"(none)"),"","Not staged: "+(o.not_added.length>0?o.not_added.join(", "):"(none)"),"","Untracked: "+(o.files.length>0?o.files.join(", "):"(none)")].filter(Boolean).join(`
|
|
13
|
+
`),durationMs:0}}catch(r){return{id:"",name:"git:status",success:!1,error:r instanceof Error?r.message:String(r),durationMs:0}}}async function Wt(e,t){let n=String(e.message??""),r=e.cwd?String(e.cwd):t;if(!n)return{id:"",name:"git:commit",success:!1,error:"message is required",durationMs:0};try{let o=z(r);return await o.add("."),{id:"",name:"git:commit",success:!0,output:"Committed "+(await o.commit(n)).commit+" \u2014 "+n,durationMs:0}}catch(o){return{id:"",name:"git:commit",success:!1,error:o instanceof Error?o.message:String(o),durationMs:0}}}async function qt(e,t){let n=e.cwd?String(e.cwd):t;try{return await z(n).push(),{id:"",name:"git:push",success:!0,output:"Pushed to remote.",durationMs:0}}catch(r){return{id:"",name:"git:push",success:!1,error:r instanceof Error?r.message:String(r),durationMs:0}}}async function Ht(e,t){let n=e.cwd?String(e.cwd):t,r=Number(e.limit??20);try{return{id:"",name:"git:log",success:!0,output:(await z(n).log({maxCount:r})).all.map(c=>c.hash.slice(0,7)+" | "+c.date.slice(0,10)+" | "+c.message+" ("+c.author_name+")").join(`
|
|
14
|
+
`),durationMs:0}}catch(o){return{id:"",name:"git:log",success:!1,error:o instanceof Error?o.message:String(o),durationMs:0}}}import{readFileSync as ce,appendFileSync as $e,writeFileSync as je,existsSync as $,mkdirSync as Ue}from"node:fs";import{resolve as _}from"node:path";function We(){let e=_(process.env.HOME||process.env.USERPROFILE||".",".agent-termo");try{$(e)||Ue(e,{recursive:!0})}catch{}return e}var Fe=_(We(),"memory.md");function qe(){if(!$(Fe))return"";try{return ce(Fe,"utf-8")}catch{return""}}var ae=_(We(),"timeline.md");function He(){if(!$(ae))return"";try{return ce(ae,"utf-8")}catch{return""}}function q(e){let n=`
|
|
15
|
+
- [`+new Date().toISOString().replace("T"," ").slice(0,16)+"] "+e;try{$e(ae,n,"utf-8")}catch{}}async function Ke(e){let t=_(e,"docs","MEMORY.md");if(!$(t))return"";try{return ce(t,"utf-8")}catch{return""}}var Kt=`# Project Timeline
|
|
16
|
+
|
|
17
|
+
This document tracks the complete chronological history of the project.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
`,Yt=`# Project Memory
|
|
22
|
+
|
|
23
|
+
## Project Context
|
|
24
|
+
(Add project context here)
|
|
25
|
+
`;function Bt(e){let t=_(e,"docs"),n=_(t,"MEMORY.md"),r=_(t,"TIMELINE.md");return Ue(t,{recursive:!0}),$(n)||je(n,Yt,"utf-8"),$(r)||je(r,Kt,"utf-8"),{memoryPath:n,timelinePath:r}}async function H(e,t){let n;try{n=Bt(e).timelinePath}catch{return}let r=new Date().toISOString().replace("T"," ").slice(0,16);try{$e(n,`
|
|
26
|
+
- [`+r+"] "+t,"utf-8")}catch{}}import{readdirSync as Jt,readFileSync as Gt}from"node:fs";import{resolve as Ye}from"node:path";function Vt(e){let t=e.match(/^description:\s*(.+)$/m),r=e.match(/^tools:\s*\[(.+)\]/m)?.[1]??"",o=r?r.split(",").map(i=>i.trim().replace(/^["']|["']$/g,"")):["file:read","file:write","file:edit","file:delete","file:glob","grep","bash:execute","git:status","git:commit","git:push","git:log"];return{description:t?.[1]?.trim()??"",tools:o}}function Be(e){let t=Ye(e,"agents");try{return Jt(t).filter(o=>o.endsWith(".md")).map(o=>{let i=o.replace(/\.md$/,""),a=Gt(Ye(t,o),"utf-8"),c=Vt(a),s=a.replace(/^---[\s\S]+?---\n/,"").trim();return{name:i,description:c.description,systemPrompt:s,tools:c.tools}}).sort((o,i)=>o.name.localeCompare(i.name))}catch{return[]}}var zt=`You are Agent-Termo, a helpful AI assistant in a terminal.
|
|
17
27
|
|
|
18
28
|
RESPONSE RULES (follow these strictly):
|
|
19
29
|
- Be concise and direct. 1-3 sentences for simple questions.
|
|
@@ -33,6 +43,7 @@ Available functions:
|
|
|
33
43
|
- file:read(path) \u2192 read a file
|
|
34
44
|
- file:write(path, content) \u2192 overwrite a file completely
|
|
35
45
|
- file:edit(path, old_string, new_string) \u2192 edit a specific line section
|
|
46
|
+
- file:delete(path) \u2192 delete a file after explicit user instruction
|
|
36
47
|
- file:glob(pattern) \u2192 list files matching a glob (e.g. "src/**/*.ts")
|
|
37
48
|
- grep(pattern, path, glob?) \u2192 search for text in files
|
|
38
49
|
- bash:execute(command) \u2192 run a shell command
|
|
@@ -42,83 +53,83 @@ When done, say "Done: <brief summary>."
|
|
|
42
53
|
|
|
43
54
|
AVAILABLE FILES:
|
|
44
55
|
- docs/MEMORY.md \u2014 project context
|
|
45
|
-
- docs/TIMELINE.md \u2014 recent activity log`;function
|
|
56
|
+
- docs/TIMELINE.md \u2014 recent activity log`;function Je(e,t,n){let r=zt;return e&&(r+=`
|
|
46
57
|
|
|
47
58
|
## Project Memory
|
|
48
59
|
`+e),t&&(r+=`
|
|
49
60
|
|
|
50
61
|
## Recent Timeline (last entries)
|
|
51
|
-
`+t.slice(-1500)),r}import
|
|
52
|
-
`).join("");x.write((m?"":`${b}${o}A\r`)+y)};return new Promise(m=>{let y=!1,
|
|
53
|
-
`),
|
|
54
|
-
`),
|
|
55
|
-
`),
|
|
56
|
-
`),
|
|
57
|
-
`),
|
|
58
|
-
`),
|
|
59
|
-
`),
|
|
60
|
-
`),
|
|
61
|
-
`),
|
|
62
|
+
`+t.slice(-1500)),r}import gn from"chalk";import Zt from"chalk";import{createInterface as Qt}from"node:readline";var T=Zt,x=process.stdout,b="\x1B[",le="\x1B7",ue="\x1B8",de=4,Xt=12,en=40,tn="Ask anything\u2026 or type / for commands",d={active:!1,editing:!1,savedValid:!0,rows:0,model:"",project:"",commands:[],buffer:"",cursor:0,offset:0};function Ve(e){d.commands=e}function R(){return{rows:x.rows||24,cols:x.columns||80}}function S(){return x.columns||80}function M(e,t){return t<=0?"":e.length<=t?e:e.slice(0,Math.max(0,t-1))+"\u2026"}function nn(e){let t=process.env.HOME||process.env.USERPROFILE||"";return t&&e.startsWith(t)?"~"+e.slice(t.length):e}function rn(){return!!(x.isTTY&&process.stdin.isTTY&&(x.rows??0)>=Xt&&(x.columns??0)>=en)}function on(e){if(d.editing&&d.buffer.startsWith("/")&&!d.buffer.includes(" ")){let c=d.buffer.toLowerCase(),s=d.commands.filter(u=>u.name.startsWith(c)),p=s[0];if(s.length===1&&p)return" "+T.cyan(p.name)+T.dim(M(" \u2014 "+p.description,e-p.name.length-1));if(s.length>1)return T.cyan(M(" "+s.map(u=>u.name).join(" "),e))}let t="/help \xB7 /model \xB7 ctrl+c to exit",n=M(" "+d.model,e),r=e-n.length-t.length-2,o=r>=15,i=M(" \xB7 "+nn(d.project),o?r:Math.max(0,e-n.length)),a=Math.max(1,e-n.length-i.length-t.length);return T.cyan(n)+T.dim(i+(o?" ".repeat(a)+t:""))}function K(){let{rows:e,cols:t}=R(),n=Math.max(1,t-6);d.offset=Math.min(d.offset,Math.max(0,d.buffer.length-n+1)),d.cursor<d.offset&&(d.offset=d.cursor),d.cursor>d.offset+n-1&&(d.offset=d.cursor-n+1);let r=d.editing?T.magenta:T.dim,o=d.buffer?d.buffer.slice(d.offset,d.offset+n).padEnd(n):T.dim(M(tn,n).padEnd(n)),i=e-3,a=(c,s)=>`${b}${c};1H${b}2K${s}`;return[a(i,r("\u256D"+"\u2500".repeat(t-2)+"\u256E")),a(i+1,r("\u2502")+" "+T.magenta.bold("\u276F")+" "+o+" "+r("\u2502")),a(i+2,r("\u2570"+"\u2500".repeat(t-2)+"\u256F")),a(e,on(t-1))].join("")}function sn(){let{rows:e}=R();return`${b}${e-2};${5+d.cursor-d.offset}H`}function E(){d.active&&(d.editing?x.write(b+"?25l"+K()+sn()+b+"?25h"):x.write(le+K()+ue))}function me(){return Math.max(1,R().rows-de)}function pe(){x.write(`${b}1;${me()}r`)}function an(){let{rows:e}=R();if(e===d.rows){E();return}d.rows=e,d.savedValid=!1,x.write(`${b}2J${b}H`),pe(),x.write(K()+`${b}${me()};1H`),d.editing&&E()}function fe(e){d.model=e.model,d.project=e.project,!(d.active||!rn())&&(d.active=!0,d.rows=R().rows,x.write(`${b}2J${b}H`),pe(),x.write(K()+`${b}1;1H`),x.on("resize",an),process.on("exit",cn))}function ge(e){e.model!==void 0&&(d.model=e.model),e.project!==void 0&&(d.project=e.project),E()}function ze(){x.write(`${b}2J${b}H`),d.active&&(pe(),x.write(K()+`${b}1;1H`))}function cn(){if(!d.active)return;d.active=!1;let{rows:e}=R(),t=Math.max(1,e-de+1),n="";for(let i=t;i<=e;i++)n+=`${b}${i};1H${b}2K`;let r=d.editing?"":le,o=d.editing&&!d.savedValid?`${b}${t};1H`:ue;x.write(r+b+"r"+n+o+b+"?25h"+b+"?2004l")}var ln=/\x1b\[200~|\x1b\[201~|\x1b\[[0-9;?]*[ -/]*[@-~]|\x1bO[A-Za-z]|\x1b[\s\S]|[\s\S]/gu,un={"\r":"enter","\n":"enter","":"ctrl+c","":"ctrl+d","\x7F":"backspace","\b":"backspace"," ":"tab","\x1B":"escape","":"home","":"end","":"ctrl+u","\v":"ctrl+k","":"ctrl+w","\f":"ctrl+l","\x1B[A":"up","\x1BOA":"up","\x1B[B":"down","\x1BOB":"down","\x1B[C":"right","\x1BOC":"right","\x1B[D":"left","\x1BOD":"left","\x1B[H":"home","\x1BOH":"home","\x1B[1~":"home","\x1B[F":"end","\x1BOF":"end","\x1B[4~":"end","\x1B[3~":"delete","\x1B[5~":"pageup","\x1B[6~":"pagedown","\x1B[1;5D":"word-left","\x1B[1;3D":"word-left","\x1Bb":"word-left","\x1B[1;5C":"word-right","\x1B[1;3C":"word-right","\x1Bf":"word-right","\x1B\x7F":"ctrl+w"};function dn(e,t){let n=[],r="",o=()=>{r&&n.push({name:"text",text:r}),r=""};for(let i of e.match(ln)??[]){if(i==="\x1B[200~"){o(),t.paste="";continue}if(i==="\x1B[201~"){o(),t.paste!==null&&n.push({name:"paste",text:t.paste}),t.paste=null;continue}if(t.paste!==null){t.paste+=i;continue}let a=un[i];a?(o(),n.push({name:a})):(i.codePointAt(0)??0)>=32&&!i.startsWith("\x1B")&&i!=="\x7F"?r+=i:(o(),n.push({name:"unknown"}))}return o(),n}function Z(e){let t=process.stdin,n={paste:null},r=o=>{for(let i of dn(o.toString(),n))e(i)};return t.setRawMode?.(!0),t.resume(),t.setEncoding("utf8"),x.isTTY&&x.write(`${b}?2004h`),t.on("data",r),()=>{t.off("data",r),x.isTTY&&x.write(`${b}?2004l`),t.setRawMode?.(!1),t.pause()}}function Ge(e,t){let n=t;for(;n>0&&e[n-1]===" ";)n--;for(;n>0&&e[n-1]!==" ";)n--;return n}function mn(e,t){let n=t;for(;n<e.length&&e[n]===" ";)n++;for(;n<e.length&&e[n]!==" ";)n++;return n}function Ze(e){return[...e.replace(/\r\n|\r|\n/g," ").replace(/\t/g," ")].filter(t=>(t.codePointAt(0)??0)>=32&&t!=="\x7F").join("")}function pn(){if(!d.buffer.startsWith("/")||d.buffer.includes(" "))return;let e=d.buffer.toLowerCase(),t=d.commands.map(o=>o.name).filter(o=>o.startsWith(e)),n=t[0];if(!n)return;let r=n;for(let o of t)for(;!o.startsWith(r);)r=r.slice(0,-1);d.buffer=r,d.cursor=r.length}function fn(){return new Promise(e=>{let t=Qt({input:process.stdin,output:process.stdout});t.once("close",()=>e("/exit")),t.question("> ",n=>{t.removeAllListeners("close"),t.close(),e(n.trim())})})}function he(){let e=[],t=null;return{question(){return d.active?new Promise(n=>{let r=-1,o="",i=!1;d.editing=!0,d.savedValid=!0,d.buffer="",d.cursor=0,d.offset=0,x.write(le),E();let a=()=>{i=!0,t?.(),t=null,d.editing=!1,d.buffer="",d.cursor=0,d.offset=0,x.write(d.savedValid?ue:`${b}${me()};1H`),E()},c=()=>{a(),process.emit("SIGINT"),process.exit(0)},s=(p,u)=>{d.buffer=p,d.cursor=u,E()};t=Z(p=>{if(i)return;let{buffer:u,cursor:g}=d;switch(p.name){case"enter":{let m=u.trim();m&&e[0]!==m&&e.unshift(m),e.length>100&&e.pop(),a(),n(m);return}case"ctrl+c":u?(r=-1,s("",0)):c();return;case"ctrl+d":u?s(u.slice(0,g)+u.slice(g+1),g):c();return;case"backspace":g>0&&s(u.slice(0,g-1)+u.slice(g),g-1);return;case"delete":s(u.slice(0,g)+u.slice(g+1),g);return;case"left":s(u,Math.max(0,g-1));return;case"right":s(u,Math.min(u.length,g+1));return;case"home":s(u,0);return;case"end":s(u,u.length);return;case"word-left":s(u,Ge(u,g));return;case"word-right":s(u,mn(u,g));return;case"ctrl+u":s(u.slice(g),0);return;case"ctrl+k":s(u.slice(0,g),g);return;case"ctrl+w":{let m=Ge(u,g);s(u.slice(0,m)+u.slice(g),m);return}case"ctrl+l":E();return;case"tab":pn(),E();return;case"up":if(r<e.length-1){r===-1&&(o=u),r++;let m=e[r]??"";s(m,m.length)}return;case"down":if(r>=0){r--;let m=r===-1?o:e[r]??"";s(m,m.length)}return;case"text":case"paste":{let m=p.name==="paste"?Ze(p.text??""):p.text??"";m&&s(u.slice(0,g)+m+u.slice(g),g+m.length);return}default:return}})}):fn()},close(){t?.(),t=null},showPrompt(){E()}}}function we(e){if(!process.stdin.isTTY||!x.isTTY)return Promise.resolve(null);let{rows:t,cols:n}=R(),r=Math.max(3,Math.min(10,t-(d.active?de:0)-5)),o=r+3,i=n-1,a="",c=0,s=Math.max(0,e.items.findIndex(m=>m.value===e.current)),p=()=>{let m=a.toLowerCase().split(/\s+/).filter(Boolean),y=e.items.filter(f=>{let v=(f.label+" "+(f.hint??"")).toLowerCase();return m.every(A=>v.includes(A))}),w=a.trim();return e.allowCustom&&w.includes("/")&&!e.items.some(f=>f.value===w)&&y.push({value:w,label:w,hint:"use as typed"}),y},u=()=>{let m=p();s=Math.min(s,Math.max(0,m.length-1)),s<c&&(c=s),s>=c+r&&(c=s-r+1);let y=[T.bold(M(e.title,i-16))+T.dim(` ${m.length} of ${e.items.length}`),T.dim(" search \u203A ")+M(a,i-14)+T.dim("\u258F")];for(let w=0;w<r;w++){let f=m[c+w];if(!f){y.push(w===0&&m.length===0?T.dim(" no matches"):"");continue}let v=c+w===s,A=f.value===e.current,D=M(f.label,i-6),Me=i-3-D.length-(A?2:0)-2,lt=f.hint&&Me>8?" "+M(f.hint,Me):"";y.push((v?T.magenta(" \u203A "):" ")+(v?T.magenta.bold(D):D)+(A?T.green(" \u2713"):"")+T.dim(lt))}return y.push(T.dim(M(" \u2191\u2193 move \xB7 enter select \xB7 esc cancel \xB7 type to filter",i))),y},g=m=>{let y=u().map(w=>`${b}2K${w}
|
|
63
|
+
`).join("");x.write((m?"":`${b}${o}A\r`)+y)};return new Promise(m=>{let y=!1,w=()=>{},f=v=>{y=!0,w(),x.write(`${b}${o}A\r${b}${o}M${b}?25h`),m(v)};x.write(b+"?25l"),g(!0),w=Z(v=>{if(y)return;let A=p(),D=()=>{s=0,c=0};switch(v.name){case"up":s=Math.max(0,s-1);break;case"down":s=Math.min(Math.max(0,A.length-1),s+1);break;case"pageup":s=Math.max(0,s-r);break;case"pagedown":s=Math.min(Math.max(0,A.length-1),s+r);break;case"home":s=0;break;case"end":s=Math.max(0,A.length-1);break;case"backspace":a=a.slice(0,-1),D();break;case"ctrl+u":a="",D();break;case"text":case"paste":a+=Ze(v.text??""),D();break;case"enter":f(A[s]?.value??null);return;case"escape":case"ctrl+c":f(null);return;default:return}g(!1)})})}var l=gn,h=process.stdout,Xe=[{name:"/help",description:"show all commands"},{name:"/clear",description:"clear conversation & screen"},{name:"/memory",description:"view Agent-Termo memory"},{name:"/timeline",description:"view recent activity"},{name:"/model",description:"switch NVIDIA NIM model (or /model <id>)"},{name:"/agents",description:"list all agents"},{name:"/history",description:"show message count"},{name:"/exit",description:"quit"}];Ve(Xe);var hn=/\x1b\[[0-9;?]*[A-Za-z]/g,wn=e=>e.replace(hn,"").length,N=()=>l.dim("\u2500".repeat(Math.max(10,Math.min(S()-2,100))));function ye(e,t){let r=Math.max(40,Math.min(S()-2,64))-2,o=r-2,i=c=>" "+l.magenta("\u2502")+" "+c+" ".repeat(Math.max(0,o-wn(c)))+" "+l.magenta("\u2502"),a=(c,s)=>l.dim(c.padEnd(7))+l.cyan(M(s,o-7));h.write(`
|
|
64
|
+
`),h.write(" "+l.magenta("\u256D"+"\u2500".repeat(r)+"\u256E")+`
|
|
65
|
+
`),h.write(i(l.magenta.bold("\u273B Agent-Termo"))+`
|
|
66
|
+
`),h.write(i(l.dim(M("AI coding agent for your terminal",o)))+`
|
|
67
|
+
`),h.write(i("")+`
|
|
68
|
+
`),h.write(i(a("model",t))+`
|
|
69
|
+
`),h.write(i(a("cwd",e))+`
|
|
70
|
+
`),h.write(" "+l.magenta("\u2570"+"\u2500".repeat(r)+"\u256F")+`
|
|
71
|
+
`),h.write(`
|
|
72
|
+
`),h.write(l.dim(" ")+l.cyan("/help")+l.dim(" commands \xB7 ")+l.cyan("/model")+l.dim(" switch NIM model \xB7 ")+l.cyan("Tab")+l.dim(" completes")+`
|
|
62
73
|
|
|
63
|
-
`)}function
|
|
74
|
+
`)}function Y(e){return e.split(/(`[^`]+`)/).map(t=>t.length>1&&t.startsWith("`")&&t.endsWith("`")?l.cyan(t.slice(1,-1)):t.replace(/\*\*(.+?)\*\*/g,(n,r)=>l.bold(r))).join("")}var B=class{constructor(t){this.beforeFirstOutput=t}pending="";inCode=!1;first=!0;lastBlank=!1;push(t){this.pending+=t;let n=this.pending.indexOf(`
|
|
64
75
|
`);for(;n!==-1;){let r=this.pending.slice(0,n).replace(/\r$/,"");this.pending=this.pending.slice(n+1),this.emit(r),n=this.pending.indexOf(`
|
|
65
|
-
`)}}end(){this.pending&&this.emit(this.pending.replace(/\r$/,"")),this.pending=""}get printed(){return!this.first}emit(t){let n=t.trim()==="";if(!this.inCode&&n&&(this.first||this.lastBlank))return;this.lastBlank=n&&!this.inCode,this.first&&(this.beforeFirstOutput?.(),
|
|
66
|
-
`));let r=this.first?l.magenta("\u25CF "):" ";this.first=!1,
|
|
76
|
+
`)}}end(){this.pending&&this.emit(this.pending.replace(/\r$/,"")),this.pending=""}get printed(){return!this.first}emit(t){let n=t.trim()==="";if(!this.inCode&&n&&(this.first||this.lastBlank))return;this.lastBlank=n&&!this.inCode,this.first&&(this.beforeFirstOutput?.(),h.write(`
|
|
77
|
+
`));let r=this.first?l.magenta("\u25CF "):" ";this.first=!1,h.write(n&&!this.inCode?`
|
|
67
78
|
`:r+this.render(t)+`
|
|
68
|
-
`)}render(t){let n=/^\s*```\s*([\w+-]*)/.exec(t);if(n)return this.inCode=!this.inCode,this.inCode?l.dim("\u250C\u2500 "+(n[1]||"code")):l.dim("\u2514\u2500");if(this.inCode)return l.dim("\u2502 ")+l.cyan(t.replace(/\t/g," "));let r=/^#{1,6}\s+(.*)$/.exec(t);if(r)return l.bold.magenta(
|
|
69
|
-
`);
|
|
79
|
+
`)}render(t){let n=/^\s*```\s*([\w+-]*)/.exec(t);if(n)return this.inCode=!this.inCode,this.inCode?l.dim("\u250C\u2500 "+(n[1]||"code")):l.dim("\u2514\u2500");if(this.inCode)return l.dim("\u2502 ")+l.cyan(t.replace(/\t/g," "));let r=/^#{1,6}\s+(.*)$/.exec(t);if(r)return l.bold.magenta(Y(r[1]??""));if(/^\s*([-*_])\1{2,}\s*$/.test(t))return l.dim("\u2500".repeat(Math.min(40,S()-4)));let o=/^(\s*)[-*+]\s+(.*)$/.exec(t);if(o)return(o[1]??"")+l.magenta("\u2022")+" "+Y(o[2]??"");let i=/^(\s*)(\d+)[.)]\s+(.*)$/.exec(t);if(i)return(i[1]??"")+l.magenta(i[2]+".")+" "+Y(i[3]??"");let a=/^>\s?(.*)$/.exec(t);return a?l.dim("\u258E ")+l.italic(Y(a[1]??"")):Y(t)}};function be(e){let t=e.split(`
|
|
80
|
+
`);h.write(`
|
|
70
81
|
`+l.green.bold("\u276F ")+l.bold(t[0]??"")+`
|
|
71
|
-
`);for(let n of t.slice(1))
|
|
72
|
-
`)}function
|
|
82
|
+
`);for(let n of t.slice(1))h.write(" "+l.bold(n)+`
|
|
83
|
+
`)}function P(e){let t=new B;t.push(e),t.end()}function et(e,t){let n=Object.entries(t).map(([o,i])=>{let a=typeof i=="string"?i:JSON.stringify(i);return o+"="+M(String(a??"").replace(/\s+/g," "),40)}).join(", "),r=S()-e.length-6;h.write(`
|
|
73
84
|
`+l.blue("\u25CF ")+l.bold(e)+l.dim("("+M(n,r)+")")+`
|
|
74
|
-
`)}function
|
|
75
|
-
`).filter(
|
|
85
|
+
`)}function xe(e,t,n){if(n?.needsApproval&&n.proposedChange){yn(n.proposedChange);return}let r=S()-8;if(t.success){let o=(t.output??"").split(`
|
|
86
|
+
`).filter(a=>a.trim()!==""),i=o.length>1?`${o.length} lines`:M((o[0]??"").trim()||"done",r);h.write(l.dim(" \u23BF ")+l.green("\u2713 ")+i+`
|
|
76
87
|
`)}else{let o=(t.error??"unknown error").split(`
|
|
77
|
-
`)[0]??"unknown error";
|
|
78
|
-
`)}}function
|
|
88
|
+
`)[0]??"unknown error";h.write(l.dim(" \u23BF ")+l.red("\u2717 "+M(`${e}: ${o}`,r))+`
|
|
89
|
+
`)}}function yn(e){let t=e.diff,n=Math.max(20,S()-14),r=e.isDeletion?l.red("DELETE"):e.isNewFile?l.green("NEW"):l.blue("MODIFY");h.write(`
|
|
79
90
|
`+l.bold.cyan(t.file)+" "+r+" "+l.green("+"+t.additions)+" "+l.red("-"+t.deletions)+`
|
|
80
|
-
`),
|
|
81
|
-
`);for(let o of t.lines){let i=o.type==="add"?"+":o.type==="remove"?"-":" ",
|
|
82
|
-
`)}
|
|
83
|
-
`)}function
|
|
84
|
-
`+l.yellow("? ")+l.bold(e)+l.dim(" [")+l.green("Y")+l.dim("/")+l.red("n")+l.dim("] ")),new Promise(t=>{let n=!1,r=()=>{},o=i=>{n=!0,r(),
|
|
91
|
+
`),h.write(" "+l.dim("\u2500".repeat(Math.max(10,Math.min(S()-4,100))))+`
|
|
92
|
+
`);for(let o of t.lines){let i=o.type==="add"?"+":o.type==="remove"?"-":" ",a=o.type==="add"?l.green:o.type==="remove"?l.red:l.dim,c=o.lineNumber>0?String(o.lineNumber).padStart(4):" ",s=M(o.content.replace(/\t/g," "),n);h.write(" "+a(i+c+" \u2502 "+s)+`
|
|
93
|
+
`)}h.write(`
|
|
94
|
+
`)}function tt(e="Accept this change?"){return h.write(`
|
|
95
|
+
`+l.yellow("? ")+l.bold(e)+l.dim(" [")+l.green("Y")+l.dim("/")+l.red("n")+l.dim("] ")),new Promise(t=>{let n=!1,r=()=>{},o=i=>{n=!0,r(),h.write(i===!0?l.green("yes")+`
|
|
85
96
|
`:i===!1?l.red("no")+`
|
|
86
97
|
`:l.red("cancelled")+`
|
|
87
|
-
`),t(i===!0?"accept":"reject")};r=Z(i=>{if(n)return;let
|
|
98
|
+
`),t(i===!0?"accept":"reject")};r=Z(i=>{if(n)return;let a=i.text?.[0]?.toLowerCase();i.name==="enter"||a==="y"?o(!0):i.name==="escape"||a==="n"?o(!1):i.name==="ctrl+c"&&o("cancelled")})})}function L(e,t){h.write(`
|
|
88
99
|
`+l.red("\u2717 "+e)+`
|
|
89
|
-
`),t&&
|
|
90
|
-
`)}function
|
|
91
|
-
`)}function
|
|
92
|
-
`)}async function
|
|
100
|
+
`),t&&h.write(l.dim(" Hint: "+t)+`
|
|
101
|
+
`)}function J(e){h.write(l.green("\u2713 "+e)+`
|
|
102
|
+
`)}function I(e){h.write(l.blue("\u2139 ")+e+`
|
|
103
|
+
`)}async function nt(){let e=qe();if(!e){I("Agent-Termo memory is empty. (Normal for new sessions.)");return}h.write(`
|
|
93
104
|
`+l.bold("Agent-Termo memory")+`
|
|
94
|
-
`+
|
|
105
|
+
`+N()+`
|
|
95
106
|
`+e+`
|
|
96
|
-
`+
|
|
107
|
+
`+N()+`
|
|
97
108
|
|
|
98
|
-
`)}async function
|
|
99
|
-
`),n=Math.min(40,t.length);
|
|
109
|
+
`)}async function rt(){let e=He();if(!e||e.trim().length===0){I("Timeline is empty.");return}let t=e.split(`
|
|
110
|
+
`),n=Math.min(40,t.length);h.write(`
|
|
100
111
|
`+l.bold("Agent-Termo timeline")+l.dim(" (recent entries)")+`
|
|
101
|
-
`+
|
|
102
|
-
`),
|
|
112
|
+
`+N()+`
|
|
113
|
+
`),h.write(t.slice(-n).join(`
|
|
103
114
|
`)+`
|
|
104
|
-
`+
|
|
105
|
-
`),t.length>n&&
|
|
106
|
-
`),
|
|
107
|
-
`)}function
|
|
115
|
+
`+N()+`
|
|
116
|
+
`),t.length>n&&h.write(l.dim("\u2026 "+(t.length-n)+" earlier entries hidden")+`
|
|
117
|
+
`),h.write(`
|
|
118
|
+
`)}function ot(){h.write(`
|
|
108
119
|
`+l.bold("Commands")+`
|
|
109
|
-
`+
|
|
110
|
-
`);for(let t of
|
|
111
|
-
`);
|
|
120
|
+
`+N()+`
|
|
121
|
+
`);for(let t of Xe)h.write(" "+l.cyan(t.name.padEnd(11))+l.dim(t.description)+`
|
|
122
|
+
`);h.write(`
|
|
112
123
|
`+l.bold("Keys")+`
|
|
113
|
-
`+
|
|
114
|
-
`);let e=[["\u2191 / \u2193","input history"],["Tab","complete a /command"],["Ctrl+A / Ctrl+E","start / end of line"],["Ctrl+W / Ctrl+U","delete word / to line start"],["Ctrl+C","clear the line, or quit when empty"]];for(let[t,n]of e)
|
|
115
|
-
`);
|
|
116
|
-
`)}function
|
|
124
|
+
`+N()+`
|
|
125
|
+
`);let e=[["\u2191 / \u2193","input history"],["Tab","complete a /command"],["Ctrl+A / Ctrl+E","start / end of line"],["Ctrl+W / Ctrl+U","delete word / to line start"],["Ctrl+C","clear the line, or quit when empty"]];for(let[t,n]of e)h.write(" "+l.cyan(t.padEnd(17))+l.dim(n)+`
|
|
126
|
+
`);h.write(`
|
|
127
|
+
`)}function it(e){h.write(`
|
|
117
128
|
`+l.bold("Available agents")+`
|
|
118
|
-
`+
|
|
119
|
-
`);let t=Math.max(10,
|
|
120
|
-
`);
|
|
121
|
-
`)}var
|
|
122
|
-
`);return}let t=Date.now(),n=0,r=M(e,Math.max(10,
|
|
123
|
-
`),console.log("Session complete. "+Math.round((Date.now()-o.startedAt.getTime())/6e4)+" minutes."),process.exit(0)};process.on("SIGINT",c);e:for(;;)try{let
|
|
129
|
+
`+N()+`
|
|
130
|
+
`);let t=Math.max(10,S()-34);for(let n of e)h.write(" "+l.cyan(n.name.padEnd(30))+l.dim(M(n.description.replace(/\s+/g," "),t))+`
|
|
131
|
+
`);h.write(`
|
|
132
|
+
`)}var Qe=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],Q=null;function k(e){if(C(),!h.isTTY){h.write(l.dim(e+"\u2026")+`
|
|
133
|
+
`);return}let t=Date.now(),n=0,r=M(e,Math.max(10,S()-14)),o=()=>{let i=Math.floor((Date.now()-t)/1e3);h.write("\r\x1B[2K"+l.magenta(Qe[n++%Qe.length]??"\u280B")+" "+l.dim(`${r}\u2026 ${i}s`))};h.write("\x1B[?25l"),o(),Q=setInterval(o,80)}function C(e){Q&&(clearInterval(Q),Q=null,h.write("\r\x1B[2K\x1B[?25h"))}function st(){ze()}var bn=["build","create","write","edit","modify","file","code","function","class","component","debug","fix","git","commit","push","install","npm","run","bash","shell","command","read","grep","check","show","implement","configure","setup","src","package","app","project","api","deploy","test","compile","typescript","javascript","python","node","add","delete"];function xn(e){let t=e.toLowerCase();return bn.some(n=>t.includes(n))}function ve(e){let t=new Set;return e.filter(n=>t.has(n.id)?!1:(t.add(n.id),!0))}async function vn(e,t){k("Thinking");let n=new B(()=>C());try{await t.streamComplete(e,void 0,o=>n.push(o)).next(),n.end(),C();return}catch{n.end(),C()}k("Retrying");try{let r=await t.complete(e,void 0);C();let o=(r.content??"").trim();o&&(e.push({id:crypto.randomUUID(),role:"assistant",content:o,timestamp:new Date}),P(o))}catch(r){C(),L("LLM error: "+(r instanceof Error?r.message:String(r)))}}function ct(e){let t=(e??"").trim();t=t.replace(/^```(?:json)?\s*/i,"").replace(/```\s*$/i,"").trim();let n;try{n=JSON.parse(t)}catch{let o=t.indexOf("{"),i=t.lastIndexOf("}");if(o===-1||i===-1||i<=o)return[];try{n=JSON.parse(t.slice(o,i+1))}catch{return[]}}return(Array.isArray(n.tool_calls)?n.tool_calls:[]).map(o=>({id:o.id??crypto.randomUUID(),name:U(o.name??o.function?.name??""),arguments:typeof o.function?.arguments=="string"?(()=>{try{return JSON.parse(o.function.arguments)}catch{return{_raw:o.function.arguments}}})():o.function?.arguments??{}}))}function Mn(e,t){if(e==="file:write"||e==="file:edit"||e==="file:delete")try{let r=JSON.parse(t);if(r?.needsApproval&&r?.proposedChange)return r.proposedChange}catch{}}async function Tn(e){try{let{exec:t}=await import("node:child_process"),{promisify:n}=await import("node:util"),{mkdtemp:r,writeFile:o}=await import("node:fs/promises"),{basename:i}=await import("node:path"),{tmpdir:a}=await import("node:os"),c=n(t),s=e.path,p=await r(a()+"/agent-termo-diff-"),u=p+"/"+i(s);if(await o(u,e.proposedContent,"utf-8"),!e.isNewFile&&e.originalContent.length>0){let g=p+"/original-"+i(s);await o(g,e.originalContent,"utf-8"),c(`code --diff "${g}" "${u}" --wait`).catch(()=>{})}else c(`code "${u}" --wait`).catch(()=>{})}catch{}}async function Cn(e,t,n,r){et(e,t),k("Running "+e);let o=await Ne(e,t,n);C(o.success);let i=Mn(e,o.output??"");if(i){r.close(),xe(e,{success:o.success,output:o.output,error:o.error},{needsApproval:!0,proposedChange:i}),Tn(i);let a=await tt("Accept this change?");if(r.showPrompt(),a==="accept"){k("Writing to disk");let c=await Le(i,n);return C(c.success),c.success?(J(c.output??"Change applied"),{toolResult:c,change:i,applied:!0}):(L(c.error??"Failed to apply change"),{toolResult:c,change:i,applied:!1})}else return I("Change rejected \u2014 file was not modified"),{toolResult:o,change:i,applied:!1}}return xe(e,o),{toolResult:o,applied:!1}}async function at(e,t,n,r,o){let i=n,a="";for(;i.length>0;){e.push({id:crypto.randomUUID(),role:"assistant",content:a||"",toolCalls:i,timestamp:new Date});for(let s of i){let p=await Cn(s.name,s.arguments,t,r),u=p.toolResult,g=u.success?"OK":"ERR: "+(u.error?u.error.slice(0,80):"unknown error"),m=p.change?p.applied?" (applied)":" (rejected)":"";e.push({id:s.id,role:"tool",content:(u.success?"Result: ":"Error: ")+(u.success?u.output??"":u.error)+m,timestamp:new Date}),H(t,"Tool: "+s.name+" -- "+g+m),q("Tool: "+s.name+" -- "+g+m)}k("Working");let c;try{let s=o.buildToolDefs(te);c=await o.complete(e,s)}catch{try{let s=await o.complete(e,void 0);c={content:s.content,toolCalls:ct(s.content)}}catch(s){C(),L("LLM error: "+(s instanceof Error?s.message:String(s)));break}}C(),a=c.content,i=ve(c.toolCalls),a&&a.trim()&&a.trim()!=="null"&&(i.length===0&&e.push({id:crypto.randomUUID(),role:"assistant",content:a.trim(),timestamp:new Date}),i.length>0&&P(a.trim()))}return a}async function Sn(e,t,n){let r=e||null;if(!r){k("Fetching NVIDIA NIM models");let{models:o,live:i,error:a}=await t.listModels();if(C(),i||I("Could not fetch the live model list ("+(a??"unknown error")+"). Showing built-in suggestions; you can type any model ID."),r=await we({title:"Select a model",items:o.map(c=>({value:c.id,label:c.id,hint:c.note})),current:t.getModel(),allowCustom:!0}),!r){I("Model unchanged: "+t.getModel());return}}if(r===t.getModel()){I("Already using "+r);return}t.setModel(r),ge({model:r}),q("Model switched to "+r),H(n,"Model switched to "+r);try{Pe(r),J("Model set to "+r+" (saved as your default)")}catch{J("Model set to "+r+" for this session"),I("Could not save it as your default.")}}async function fr(e){e=De(e);let t=await Ke(e),n=new G(e),r=Je(t,"",e),o={id:crypto.randomUUID(),projectRoot:e,startedAt:new Date},i=[{id:crypto.randomUUID(),role:"system",content:r,timestamp:new Date}];fe({model:n.getModel(),project:e}),ye(e,n.getModel()),q("Agent-Termo session started. Model: "+n.getModel()),H(e,"Agent-Termo session started. Model: "+n.getModel()),q("Commands: /help /clear /memory /timeline /model /agents /history"),H(e,"Commands: /help /clear /memory /timeline /model /agents /history");let a=he(),c=()=>{a.close(),process.stdout.write(`
|
|
134
|
+
`),console.log("Session complete. "+Math.round((Date.now()-o.startedAt.getTime())/6e4)+" minutes."),process.exit(0)};process.on("SIGINT",c);e:for(;;)try{let s=await a.question("");if(!s)continue;if(s==="exit"||s==="quit"){c();break}if(s.startsWith("/")){let m=s.toLowerCase().trim();if(be(s),m==="/help"||m==="/"){ot();continue e}if(m==="/clear"||m==="/cls"){i.length=1,st(),ye(e,n.getModel()),J("Conversation cleared.");continue e}if(m==="/memory"){await nt();continue e}if(m==="/timeline"||m==="/tl"){await rt();continue e}if(m==="/model"||m.startsWith("/model ")){await Sn(s.trim().slice(6).trim(),n,e);continue e}if(m==="/agents"){let y=Be(process.env.AGENT_TERMO_DIR||".claude");it(y);continue e}if(m==="/history"||m==="/hist"){I("Conversation (excluding system): "+(i.length-1)+" messages");continue e}if(m==="/exit"||m==="/quit"){c();break}L("Unknown command: "+m,"Type /help for available commands.");continue e}let p={id:crypto.randomUUID(),role:"user",content:s,timestamp:new Date};i.push(p),be(s);let u=xn(s),g=u?n.buildToolDefs(te):void 0;if(u){k("Working");try{let m=await n.complete(i,g),y=m.content,w=ve(m.toolCalls);if(C(),w.length===0){let f=(y??"").trim().replace(/^null$/,"").trim();f&&(i.push({id:crypto.randomUUID(),role:"assistant",content:f,timestamp:new Date}),P(f))}else{let f=(y??"").trim().replace(/^null$/,"").trim();f&&P(f);let v=await at(i,e,w,a,n);v&&v.trim()&&v.trim()!=="null"&&P(v.trim())}}catch{C(),I("Tool calls not supported by this model \u2014 retrying without tools.");try{let y=await n.complete(i,void 0),w=ve(y.toolCalls.length>0?y.toolCalls:ct(y.content));if(w.length>0){let f=(y.content??"").trim().replace(/^null$/,"").trim();f&&!f.includes('"tool_calls"')&&P(f);let v=await at(i,e,w,a,n);v&&v.trim()&&v.trim()!=="null"&&P(v.trim())}else{let f=(y.content??"").trim().replace(/^null$/,"").trim();f&&(i.push({id:crypto.randomUUID(),role:"assistant",content:f,timestamp:new Date}),P(f))}}catch(y){L("LLM error: "+(y instanceof Error?y.message:String(y))),i.pop();continue e}}}else await vn(i,n);i.length>42&&i.splice(1,i.length-42)}catch(s){C(),L("Session error: "+(s instanceof Error?s.message:String(s)))}}export{fr as runRepl};
|
|
124
135
|
//# sourceMappingURL=main.js.map
|