@memo-code/memo 0.6.3 → 0.6.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -7
- package/README.zh.md +17 -16
- package/dist/index.js +63 -94
- package/dist/prompt.md +3 -0
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -166,15 +166,16 @@ pnpm run build # generates dist/index.js
|
|
|
166
166
|
### Test
|
|
167
167
|
|
|
168
168
|
```bash
|
|
169
|
-
pnpm test
|
|
170
|
-
pnpm test
|
|
171
|
-
pnpm test
|
|
169
|
+
pnpm test # all tests
|
|
170
|
+
pnpm run test:core # core package
|
|
171
|
+
pnpm run test:tools # tools package
|
|
172
|
+
pnpm run test:tui # tui package
|
|
172
173
|
```
|
|
173
174
|
|
|
174
175
|
### Format
|
|
175
176
|
|
|
176
177
|
```bash
|
|
177
|
-
npm run format # format
|
|
178
|
+
npm run format # format source/config files
|
|
178
179
|
npm run format:check # check format (CI)
|
|
179
180
|
```
|
|
180
181
|
|
|
@@ -185,7 +186,7 @@ memo-cli/
|
|
|
185
186
|
├── packages/
|
|
186
187
|
│ ├── core/ # core logic: Session, tool routing, config
|
|
187
188
|
│ ├── tools/ # built-in tool implementations
|
|
188
|
-
│ └──
|
|
189
|
+
│ └── tui/ # terminal runtime (CLI entry, interactive TUI, slash, MCP command)
|
|
189
190
|
├── docs/ # technical docs
|
|
190
191
|
└── dist/ # build output
|
|
191
192
|
```
|
|
@@ -195,7 +196,7 @@ memo-cli/
|
|
|
195
196
|
- `/help`: show help and shortcut guide.
|
|
196
197
|
- `/models`: list available Provider/Model entries and switch with Enter; also supports direct selection like `/models deepseek`.
|
|
197
198
|
- `/context`: open 80k/120k/150k/200k options and apply immediately.
|
|
198
|
-
-
|
|
199
|
+
- `/mcp`: show configured MCP servers in current session.
|
|
199
200
|
- `resume` history: type `resume` to list and load past sessions for current directory.
|
|
200
201
|
- Exit and clear: `exit` / `/exit`, `Ctrl+L` for new session, `Esc Esc` to cancel current run or clear input.
|
|
201
202
|
- **Tool approval**: risky operations open an approval dialog with `once`/`session`/`deny`.
|
|
@@ -212,8 +213,9 @@ memo-cli/
|
|
|
212
213
|
|
|
213
214
|
## Related Docs
|
|
214
215
|
|
|
215
|
-
- [User Guide](./docs/
|
|
216
|
+
- [User Guide](./web/content/docs/README.md) - User-facing docs by module
|
|
216
217
|
- [Core Architecture](./docs/core.md) - Core implementation details
|
|
218
|
+
- [TUI Rewrite Design](./docs/tui-rewrite-design.md) - Codex-aligned TUI architecture and migration notes
|
|
217
219
|
- [CLI Adaptation History](./docs/cli-update.md) - Historical migration notes (Tool Use API)
|
|
218
220
|
- [Contributing](./CONTRIBUTING.md) - Contribution guide
|
|
219
221
|
- [Project Guidelines](./AGENTS.md) - Coding conventions and development process
|
package/README.zh.md
CHANGED
|
@@ -106,15 +106,14 @@ memo mcp remove remote
|
|
|
106
106
|
|
|
107
107
|
## 内置工具
|
|
108
108
|
|
|
109
|
-
- `
|
|
110
|
-
- `
|
|
111
|
-
- `
|
|
112
|
-
- `
|
|
113
|
-
- `
|
|
114
|
-
- `grep`:搜索内容(正则匹配)
|
|
109
|
+
- `exec_command` / `write_stdin`:执行命令(默认执行工具族)
|
|
110
|
+
- `shell` / `shell_command`:兼容执行工具(按环境开关切换)
|
|
111
|
+
- `apply_patch`:结构化文件改动
|
|
112
|
+
- `read_file` / `list_dir` / `grep_files`:文件读取与检索
|
|
113
|
+
- `list_mcp_resources` / `list_mcp_resource_templates` / `read_mcp_resource`:MCP 资源访问
|
|
115
114
|
- `webfetch`:获取网页
|
|
116
|
-
- `
|
|
117
|
-
- `
|
|
115
|
+
- `update_plan`:更新当前会话内的计划状态
|
|
116
|
+
- `get_memory`:读取 `~/.memo/Agents.md`(或 `MEMO_HOME` 下)记忆内容
|
|
118
117
|
|
|
119
118
|
通过 MCP 协议可扩展更多工具。
|
|
120
119
|
|
|
@@ -122,8 +121,8 @@ memo mcp remove remote
|
|
|
122
121
|
|
|
123
122
|
新增工具审批机制,保护用户免受危险操作影响:
|
|
124
123
|
|
|
125
|
-
-
|
|
126
|
-
-
|
|
124
|
+
- **自动审批**:读类工具(如 `read_file`、`list_dir`、`grep_files`、`webfetch` 等)
|
|
125
|
+
- **手动审批**:高风险工具(如 `apply_patch`、`exec_command`、`write_stdin`)
|
|
127
126
|
- **审批选项**:
|
|
128
127
|
- `once`:仅批准当前操作
|
|
129
128
|
- `session`:批准本次会话中的所有同类操作
|
|
@@ -163,9 +162,10 @@ pnpm run build # 生成 dist/index.js
|
|
|
163
162
|
### 测试
|
|
164
163
|
|
|
165
164
|
```bash
|
|
166
|
-
pnpm test
|
|
167
|
-
pnpm test
|
|
168
|
-
pnpm test
|
|
165
|
+
pnpm test # 全量测试
|
|
166
|
+
pnpm run test:core # 测试 core 包
|
|
167
|
+
pnpm run test:tools # 测试 tools 包
|
|
168
|
+
pnpm run test:tui # 测试 tui 包
|
|
169
169
|
```
|
|
170
170
|
|
|
171
171
|
### 代码格式化
|
|
@@ -182,7 +182,7 @@ memo-cli/
|
|
|
182
182
|
├── packages/
|
|
183
183
|
│ ├── core/ # 核心逻辑:Session、工具路由、配置
|
|
184
184
|
│ ├── tools/ # 内置工具实现
|
|
185
|
-
│ └──
|
|
185
|
+
│ └── tui/ # 终端运行时(CLI 入口、交互 TUI、slash、MCP 子命令)
|
|
186
186
|
├── docs/ # 技术文档
|
|
187
187
|
└── dist/ # 构建输出
|
|
188
188
|
```
|
|
@@ -192,7 +192,7 @@ memo-cli/
|
|
|
192
192
|
- `/help`:显示帮助与快捷键说明。
|
|
193
193
|
- `/models`:列出现有 Provider/Model,回车切换;支持直接 `/models deepseek` 精确选择。
|
|
194
194
|
- `/context`:弹出 80k/120k/150k/200k 选项并立即设置上限。
|
|
195
|
-
-
|
|
195
|
+
- `/mcp`:查看当前会话加载的 MCP 服务器配置。
|
|
196
196
|
- `resume` 历史:输入 `resume` 查看并加载本目录的历史会话。
|
|
197
197
|
- 退出与清屏:`exit` / `/exit`,`Ctrl+L` 新会话,`Esc Esc` 取消运行或清空输入。
|
|
198
198
|
- **工具审批**:危险操作会弹出审批对话框,可选择 `once`/`session`/`deny`。
|
|
@@ -209,8 +209,9 @@ memo-cli/
|
|
|
209
209
|
|
|
210
210
|
## 相关文档
|
|
211
211
|
|
|
212
|
-
- [用户指南](./docs/
|
|
212
|
+
- [用户指南](./web/content/docs/README.md) - 面向使用者的分模块说明
|
|
213
213
|
- [Core 架构](./docs/core.md) - 核心实现详解
|
|
214
|
+
- [TUI 重构设计](./docs/tui-rewrite-design.md) - 对标 Codex 的 TUI 架构与迁移说明
|
|
214
215
|
- [CLI 适配更新](./docs/cli-update.md) - Tool Use API 迁移说明
|
|
215
216
|
- [开发指南](./CONTRIBUTING.md) - 贡献指南
|
|
216
217
|
- [项目约定](./AGENTS.md) - 代码规范和开发流程
|
package/dist/index.js
CHANGED
|
@@ -1,98 +1,70 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var
|
|
3
|
-
`,"utf8")}async flush(){return Promise.resolve()}};function
|
|
4
|
-
`)}function
|
|
5
|
-
[exec error] ${
|
|
6
|
-
`);if(e[0]!=="*** Begin Patch")throw new Error("patch must start with *** Begin Patch");let n=[],o=1;for(;o<e.length;){let
|
|
7
|
-
`),o=e.filter(
|
|
8
|
-
`);if(!n){if(!o)return t;if(!t)return o;let
|
|
2
|
+
var Rr=Object.create;var mn=Object.defineProperty;var Ir=Object.getOwnPropertyDescriptor;var Or=Object.getOwnPropertyNames;var Lr=Object.getPrototypeOf,$r=Object.prototype.hasOwnProperty;var Nr=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var Dr=(t,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of Or(e))!$r.call(t,s)&&s!==n&&mn(t,s,{get:()=>e[s],enumerable:!(o=Ir(e,s))||o.enumerable});return t};var Ur=(t,e,n)=>(n=t!=null?Rr(Lr(t)):{},Dr(e||!t||!t.__esModule?mn(n,"default",{value:t,enumerable:!0}):n,t));var Pn=Nr((su,Mn)=>{"use strict";function xn(t){return Array.isArray(t)?t:[t]}var $t="",Cn=" ",Ot="\\",ms=/^\s+$/,ds=/(?:[^\\]|^)\\$/,fs=/^\\!/,gs=/^\\#/,hs=/\r?\n/g,ys=/^\.*\/|^\.+$/,Lt="/",wn="node-ignore";typeof Symbol<"u"&&(wn=Symbol.for("node-ignore"));var En=wn,Ts=(t,e,n)=>Object.defineProperty(t,e,{value:n}),_s=/([0-z])-([0-z])/g,bn=()=>!1,Ss=t=>t.replace(_s,(e,n,o)=>n.charCodeAt(0)<=o.charCodeAt(0)?e:$t),vs=t=>{let{length:e}=t;return t.slice(0,e-e%2)},xs=[[/^\uFEFF/,()=>$t],[/((?:\\\\)*?)(\\?\s+)$/,(t,e,n)=>e+(n.indexOf("\\")===0?Cn:$t)],[/(\\+?)\s/g,(t,e)=>{let{length:n}=e;return e.slice(0,n-n%2)+Cn}],[/[\\$.|*+(){^]/g,t=>`\\${t}`],[/(?!\\)\?/g,()=>"[^/]"],[/^\//,()=>"^"],[/\//g,()=>"\\/"],[/^\^*\\\*\\\*\\\//,()=>"^(?:.*\\/)?"],[/^(?=[^^])/,function(){return/\/(?!$)/.test(this)?"^":"(?:^|\\/)"}],[/\\\/\\\*\\\*(?=\\\/|$)/g,(t,e,n)=>e+6<n.length?"(?:\\/[^\\/]+)*":"\\/.+"],[/(^|[^\\]+)(\\\*)+(?=.+)/g,(t,e,n)=>{let o=n.replace(/\\\*/g,"[^\\/]*");return e+o}],[/\\\\\\(?=[$.|*+(){^])/g,()=>Ot],[/\\\\/g,()=>Ot],[/(\\)?\[([^\]/]*?)(\\*)($|\])/g,(t,e,n,o,s)=>e===Ot?`\\[${n}${vs(o)}${s}`:s==="]"&&o.length%2===0?`[${Ss(n)}${o}]`:"[]"],[/(?:[^*])$/,t=>/\/$/.test(t)?`${t}$`:`${t}(?=$|\\/$)`],[/(\^|\\\/)?\\\*$/,(t,e)=>`${e?`${e}[^/]+`:"[^/]*"}(?=$|\\/$)`]],An=Object.create(null),Cs=(t,e)=>{let n=An[t];return n||(n=xs.reduce((o,[s,r])=>o.replace(s,r.bind(t)),t),An[t]=n),e?new RegExp(n,"i"):new RegExp(n)},Ut=t=>typeof t=="string",Es=t=>t&&Ut(t)&&!ms.test(t)&&!ds.test(t)&&t.indexOf("#")!==0,As=t=>t.split(hs),Nt=class{constructor(e,n,o,s){this.origin=e,this.pattern=n,this.negative=o,this.regex=s}},ws=(t,e)=>{let n=t,o=!1;t.indexOf("!")===0&&(o=!0,t=t.substr(1)),t=t.replace(fs,"!").replace(gs,"#");let s=Cs(t,e);return new Nt(n,t,o,s)},bs=(t,e)=>{throw new e(t)},ye=(t,e,n)=>Ut(t)?t?ye.isNotRelative(t)?n(`path should be a \`path.relative()\`d string, but got "${e}"`,RangeError):!0:n("path must not be empty",TypeError):n(`path must be a string, but got \`${e}\``,TypeError),kn=t=>ys.test(t);ye.isNotRelative=kn;ye.convert=t=>t;var Dt=class{constructor({ignorecase:e=!0,ignoreCase:n=e,allowRelativePaths:o=!1}={}){Ts(this,En,!0),this._rules=[],this._ignoreCase=n,this._allowRelativePaths=o,this._initCache()}_initCache(){this._ignoreCache=Object.create(null),this._testCache=Object.create(null)}_addPattern(e){if(e&&e[En]){this._rules=this._rules.concat(e._rules),this._added=!0;return}if(Es(e)){let n=ws(e,this._ignoreCase);this._added=!0,this._rules.push(n)}}add(e){return this._added=!1,xn(Ut(e)?As(e):e).forEach(this._addPattern,this),this._added&&this._initCache(),this}addPattern(e){return this.add(e)}_testOne(e,n){let o=!1,s=!1;return this._rules.forEach(r=>{let{negative:i}=r;if(s===i&&o!==s||i&&!o&&!s&&!n)return;r.regex.test(e)&&(o=!i,s=i)}),{ignored:o,unignored:s}}_test(e,n,o,s){let r=e&&ye.convert(e);return ye(r,e,this._allowRelativePaths?bn:bs),this._t(r,n,o,s)}_t(e,n,o,s){if(e in n)return n[e];if(s||(s=e.split(Lt)),s.pop(),!s.length)return n[e]=this._testOne(e,o);let r=this._t(s.join(Lt)+Lt,n,o,s);return n[e]=r.ignored?r:this._testOne(e,o)}ignores(e){return this._test(e,this._ignoreCache,!1).ignored}createFilter(){return e=>!this.ignores(e)}filter(e){return xn(e).filter(this.createFilter())}test(e){return this._test(e,this._testCache,!0)}},rt=t=>new Dt(t),ks=t=>ye(t&&ye.convert(t),t,bn);rt.isPathValid=ks;rt.default=rt;Mn.exports=rt;if(typeof process<"u"&&(process.env&&process.env.IGNORE_TEST_WIN32||process.platform==="win32")){let t=n=>/^\\\\\?\\/.test(n)||/["<>|\u0000-\u001F]+/u.test(n)?n:n.replace(/\\/g,"/");ye.convert=t;let e=/^[a-z]:\//i;ye.isNotRelative=n=>e.test(n)||kn(n)}});import{randomUUID as _r}from"crypto";import{createInterface as fc}from"readline/promises";import{stdin as gc,stdout as hc}from"process";import{render as yc}from"ink";import Hr from"os";import{readFile as Fr}from"fs/promises";import{join as jr,dirname as Br}from"path";import{fileURLToPath as Wr}from"url";var zr=/{{\s*([\w.-]+)\s*}}/g;function qr(t,e){return t.replace(zr,(n,o)=>e[o]??"")}function Kr(){try{return Hr.userInfo().username}catch{return process.env.USER??process.env.USERNAME??"unknown"}}async function dn(){let t=Br(Wr(import.meta.url)),e=jr(t,"prompt.md"),n=await Fr(e,"utf-8"),o={date:new Date().toISOString(),user:Kr(),pwd:process.cwd()};return qr(n,o)}import{appendFile as Vr,mkdir as Gr}from"fs/promises";import{dirname as Xr}from"path";var ot=class{constructor(e){this.filePath=e}ready=!1;async append(e){this.ready||(await Gr(Xr(this.filePath),{recursive:!0}),this.ready=!0),await Vr(this.filePath,`${JSON.stringify(e)}
|
|
3
|
+
`,"utf8")}async flush(){return Promise.resolve()}};function fn(t){return{ts:new Date().toISOString(),sessionId:t.sessionId,turn:t.turn,step:t.step,type:t.type,content:t.content,role:t.role,meta:t.meta}}import{z as ge}from"zod";function O(t){let{inputSchema:e,execute:n,...o}=t,s=e.toJSONSchema?.(),{$schema:r,...i}=s??{};return{...o,source:"native",inputSchema:i,validateInput:l=>{let a=e.safeParse(l);if(!a.success){let c=a.error.issues[0]?.message??"invalid input";return{ok:!1,error:`${t.name} invalid input: ${c}`}}return{ok:!0,data:a.data}},execute:n}}function p(t,e=!1){return{content:[{type:"text",text:t}],isError:e}}import{spawn as Jr}from"child_process";import{EventEmitter as Yr}from"events";import{resolve as Zr}from"path";var Qr=1e4,es=250,ts=2e3,gn=64;function ns(t){return Math.ceil(t.length/4)}function os(){return Math.random().toString(16).slice(2)||String(Date.now())}function rs(t){let e=t.login,n=t.shell?.trim();if(process.platform==="win32"){let s=n||"powershell.exe";return s.toLowerCase().includes("powershell")?{file:s,args:["-NoProfile","-Command",t.cmd]}:{file:s,args:[e?"-lc":"-c",t.cmd]}}return{file:n||process.env.SHELL||"/bin/bash",args:[e?"-lc":"-c",t.cmd]}}function ss(t,e){let o=(typeof e=="number"&&e>0?Math.floor(e):ts)*4,s=ns(t);return t.length<=o?{output:t,originalTokenCount:s}:{output:t.slice(0,o),originalTokenCount:s}}function is(t){let e=[];return e.push(`Chunk ID: ${t.chunkId}`),e.push(`Wall time: ${t.wallTimeSeconds.toFixed(4)} seconds`),t.exitCode!==null?e.push(`Process exited with code ${t.exitCode}`):e.push(`Process running with session ID ${t.sessionId}`),e.push(`Original token count: ${t.originalTokenCount}`),e.push("Output:"),e.push(t.output),e.join(`
|
|
4
|
+
`)}function hn(t,e){return typeof t!="number"||Number.isNaN(t)?e:t<0?0:Math.floor(t)}async function yn(t,e){e<=0||t.exited||await Promise.race([new Promise(n=>{let o=setTimeout(()=>{r(),n()},e),s=()=>{clearTimeout(o),r(),n()},r=()=>{t.eventBus.off("exit",s)};t.eventBus.on("exit",s)})])}var Pt=class{sessions=new Map;nextId=1;cleanupSessions(){if(this.sessions.size<=gn)return;let e=Array.from(this.sessions.values()).filter(n=>n.exited).sort((n,o)=>n.startedAtMs-o.startedAtMs);for(let n of e){if(this.sessions.size<=gn)break;this.sessions.delete(n.id)}}async start(e){let n=e.cmd.trim();if(!n)throw new Error("cmd must not be empty");let o=this.nextId++,s=Date.now(),r=rs({cmd:n,shell:e.shell,login:e.login!==!1}),i=e.workdir?.trim()?Zr(process.cwd(),e.workdir.trim()):process.cwd(),l=Jr(r.file,r.args,{cwd:i,env:process.env,stdio:["pipe","pipe","pipe"],shell:!1}),a={id:o,output:"",readOffset:0,startedAtMs:s,exited:!1,exitCode:null,eventBus:new Yr,proc:l},c=(m,d)=>{let h=typeof d=="string"?d:d.toString("utf8");a.output+=m?`${m}${h}`:h,a.eventBus.emit("output")};l.stdout?.on("data",m=>c("",m)),l.stderr?.on("data",m=>c("",m)),l.on("error",m=>{a.output+=`
|
|
5
|
+
[exec error] ${m.message}`,a.eventBus.emit("output")}),l.on("close",m=>{a.exited=!0,a.exitCode=typeof m=="number"?m:-1,a.eventBus.emit("exit")}),this.sessions.set(o,a),this.cleanupSessions();let u=hn(e.yield_time_ms,Qr);return await yn(a,u),this.buildResponseText(a,e.max_output_tokens)}async write(e){let n=this.sessions.get(e.session_id);if(!n)throw new Error(`session_id ${e.session_id} not found`);!n.exited&&e.chars&&e.chars.length>0&&n.proc.stdin?.write(e.chars);let o=hn(e.yield_time_ms,es);return await yn(n,o),this.buildResponseText(n,e.max_output_tokens)}buildResponseText(e,n){let o=e.output.slice(e.readOffset);e.readOffset=e.output.length;let s=ss(o,n),r={sessionId:e.id,chunkId:os(),wallTimeSeconds:(Date.now()-e.startedAtMs)/1e3,exitCode:e.exited?e.exitCode:null,output:s.output,originalTokenCount:s.originalTokenCount};return is(r)}},Tn=new Pt;async function Oe(t){return Tn.start(t)}async function _n(t){return Tn.write(t)}var as=ge.object({command:ge.array(ge.string().min(1)).min(1,"command \u4E0D\u80FD\u4E3A\u7A7A"),workdir:ge.string().optional(),timeout_ms:ge.number().int().positive().optional(),sandbox_permissions:ge.enum(["use_default","require_escalated"]).optional(),justification:ge.string().optional(),prefix_rule:ge.array(ge.string().min(1)).optional()}).strict();function ls(t){return t.map(e=>/^[A-Za-z0-9_./:@%+-]+$/.test(e)?e:JSON.stringify(e)).join(" ")}var Sn=O({name:"shell",description:"Runs a shell command (argv form) and returns output.",inputSchema:as,supportsParallelToolCalls:!0,isMutating:!0,execute:async({command:t,workdir:e,timeout_ms:n})=>{try{let o=await Oe({cmd:ls(t),workdir:e,login:!1,yield_time_ms:n});return p(o)}catch(o){return p(`shell failed: ${o.message}`,!0)}}});import{z as he}from"zod";var cs=he.object({command:he.string().min(1,"command \u4E0D\u80FD\u4E3A\u7A7A"),workdir:he.string().optional(),login:he.boolean().optional(),timeout_ms:he.number().int().positive().optional(),sandbox_permissions:he.enum(["use_default","require_escalated"]).optional(),justification:he.string().optional(),prefix_rule:he.array(he.string().min(1)).optional()}).strict(),vn=O({name:"shell_command",description:"Runs a shell command and returns its output. Always set workdir when possible.",inputSchema:cs,supportsParallelToolCalls:!0,isMutating:!0,execute:async({command:t,workdir:e,login:n,timeout_ms:o})=>{try{let s=await Oe({cmd:t,workdir:e,login:n,yield_time_ms:o});return p(s)}catch(s){return p(`shell_command failed: ${s.message}`,!0)}}});import{z as oe}from"zod";var us=oe.object({cmd:oe.string().min(1,"cmd \u4E0D\u80FD\u4E3A\u7A7A"),workdir:oe.string().optional(),shell:oe.string().optional(),login:oe.boolean().optional(),tty:oe.boolean().optional(),yield_time_ms:oe.number().int().nonnegative().optional(),max_output_tokens:oe.number().int().positive().optional(),sandbox_permissions:oe.enum(["use_default","require_escalated"]).optional(),justification:oe.string().optional(),prefix_rule:oe.array(oe.string().min(1)).optional()}).strict(),Rt=O({name:"exec_command",description:"Runs a command in a PTY-like managed session, returning output or a session ID for ongoing interaction.",inputSchema:us,supportsParallelToolCalls:!0,isMutating:!0,execute:async t=>{try{let e=await Oe(t);return p(e)}catch(e){return p(`exec_command failed: ${e.message}`,!0)}}});import{z as Be}from"zod";var ps=Be.object({session_id:Be.number().int().positive(),chars:Be.string().optional(),yield_time_ms:Be.number().int().nonnegative().optional(),max_output_tokens:Be.number().int().positive().optional()}).strict(),It=O({name:"write_stdin",description:"Writes characters to an existing unified exec session and returns recent output.",inputSchema:ps,supportsParallelToolCalls:!1,isMutating:!0,execute:async t=>{try{let e=await _n(t);return p(e)}catch(e){return p(`write_stdin failed: ${e.message}`,!0)}}});import{mkdir as On,readFile as Hs,rm as Ln,writeFile as Ht}from"fs/promises";import{dirname as $n}from"path";import{z as Nn}from"zod";var $s=Ur(Pn(),1);import{normalize as Ms,resolve as Ps,dirname as au,join as Rs,relative as Is,isAbsolute as Os}from"path";import{homedir as Ls}from"os";import{existsSync as uu,statSync as pu}from"fs";import{readFile as du}from"fs/promises";function re(t){return Ms(Ps(t))}function Ns(t,e){let n=Is(e,t);return n===""||!n.startsWith("..")&&!Os(n)}function Ds(){let t=process.env.MEMO_SANDBOX_WRITABLE_ROOTS?.trim();return t?t.split(",").map(e=>e.trim()).filter(Boolean).map(e=>re(e)):[]}function Rn(){let t=new Set;t.add(re(process.cwd()));let e=process.env.MEMO_HOME?.trim()||Rs(Ls(),".memo");t.add(re(e));for(let n of Ds())t.add(n);return Array.from(t)}function Us(t){return Rn().some(n=>Ns(t,n))}function In(t){if(Us(t))return null;let e=Rn();return`sandbox \u62D2\u7EDD\u5199\u5165: ${t} \u4E0D\u5728\u5141\u8BB8\u76EE\u5F55\u5185 (${e.join(", ")})`}var Fs=Nn.object({input:Nn.string().min(1,"patch input \u4E0D\u80FD\u4E3A\u7A7A")}).strict();function js(t){let e=t.replace(/\r/g,"").split(`
|
|
6
|
+
`);if(e[0]!=="*** Begin Patch")throw new Error("patch must start with *** Begin Patch");let n=[],o=1;for(;o<e.length;){let s=e[o]??"";if(s==="*** End Patch")break;if(!s){o+=1;continue}if(s.startsWith("*** Add File: ")){let r=s.slice(14).trim();if(!r)throw new Error("Add File requires a path");o+=1;let i=[];for(;o<e.length;){let l=e[o];if(l===void 0||l.startsWith("*** "))break;if(!l.startsWith("+"))throw new Error("Add File lines must start with +");i.push(l.slice(1)),o+=1}n.push({type:"add",file:r,lines:i});continue}if(s.startsWith("*** Delete File: ")){let r=s.slice(17).trim();if(!r)throw new Error("Delete File requires a path");n.push({type:"delete",file:r}),o+=1;continue}if(s.startsWith("*** Update File: ")){let r=s.slice(17).trim();if(!r)throw new Error("Update File requires a path");o+=1;let i,l=e[o];l&&l.startsWith("*** Move to: ")&&(i=l.slice(13).trim(),o+=1);let a=[],c=[];for(;o<e.length;){let u=e[o];if(u===void 0||u.startsWith("*** "))break;if(u.startsWith("@@")){c.length>0&&(a.push(c),c=[]),o+=1;continue}if(u==="*** End of File"){o+=1;continue}if(u.startsWith("+")||u.startsWith("-")||u.startsWith(" ")){c.push(u),o+=1;continue}throw new Error(`Unexpected patch line: ${u}`)}if(c.length>0&&a.push(c),a.length===0)throw new Error(`Update File ${r} has no hunks`);n.push({type:"update",file:r,moveTo:i,hunks:a});continue}throw new Error(`Unexpected patch marker: ${s}`)}if(n.length===0)throw new Error("patch contains no operations");return n}function Bs(t,e){let n=e.filter(r=>r.startsWith(" ")||r.startsWith("-")).map(r=>r.slice(1)).join(`
|
|
7
|
+
`),o=e.filter(r=>r.startsWith(" ")||r.startsWith("+")).map(r=>r.slice(1)).join(`
|
|
8
|
+
`);if(!n){if(!o)return t;if(!t)return o;let r=t.endsWith(`
|
|
9
9
|
`)?"":`
|
|
10
|
-
`;return`${t}${
|
|
11
|
-
`),"utf8");continue}if(n.type==="delete"){let
|
|
12
|
-
`)}function
|
|
13
|
-
`))}catch(i){return
|
|
14
|
-
`))}catch(
|
|
15
|
-
`).replace(
|
|
16
|
-
`).replace(
|
|
17
|
-
`).map(
|
|
18
|
-
`).trim()},
|
|
19
|
-
...[truncated]`}function
|
|
20
|
-
${
|
|
10
|
+
`;return`${t}${r}${o}`}let s=t.indexOf(n);if(s<0)throw new Error("patch hunk context not found in target file");return`${t.slice(0,s)}${o}${t.slice(s+n.length)}`}function st(t){let e=In(t);if(e)throw new Error(e)}var Dn=O({name:"apply_patch",description:"Apply a structured patch with Add/Update/Delete operations and hunk-based replacements.",inputSchema:Fs,supportsParallelToolCalls:!1,isMutating:!0,execute:async t=>{try{let e=js(t.input);for(let n of e){if(n.type==="add"){let r=re(n.file);st(r),await On($n(r),{recursive:!0}),await Ht(r,n.lines.join(`
|
|
11
|
+
`),"utf8");continue}if(n.type==="delete"){let r=re(n.file);st(r),await Ln(r);continue}let o=re(n.file);st(o);let s=await Hs(o,"utf8");for(let r of n.hunks)s=Bs(s,r);if(n.moveTo){let r=re(n.moveTo);st(r),await On($n(r),{recursive:!0}),await Ht(r,s,"utf8"),r!==o&&await Ln(o)}else await Ht(o,s,"utf8")}return p(`apply_patch succeeded (${e.length} operations)`)}catch(e){return p(`apply_patch failed: ${e.message}`,!0)}}});import{readFile as Ws}from"fs/promises";import{z as ae}from"zod";var Un=500,Hn=200,zs=ae.object({file_path:ae.string().min(1),offset:ae.number().int().positive().optional(),limit:ae.number().int().positive().optional(),mode:ae.enum(["slice","indentation"]).optional(),indentation:ae.object({anchor_line:ae.number().int().positive().optional(),max_levels:ae.number().int().nonnegative().optional(),include_siblings:ae.boolean().optional(),include_header:ae.boolean().optional(),max_lines:ae.number().int().positive().optional()}).strict().optional()}).strict();function qs(t){return t.length<=Un?t:t.slice(0,Un)}function Ks(t){let e=0;for(let n of t)if(n===" ")e+=1;else if(n===" ")e+=4;else break;return e}function Vs(t){return t.split(/\r?\n/).map((n,o)=>({line:o+1,text:qs(n),indent:Ks(n)}))}function Gs(t){return t.map(e=>`L${e.line}: ${e.text}`).join(`
|
|
12
|
+
`)}function Xs(t,e,n){let o=e-1;if(o>=t.length)throw new Error("offset exceeds file length");return t.slice(o,o+n)}function Js(t,e){let n=e.offset??1,o=e.limit??Hn,s=e.indentation,r=s?.anchor_line??n;if(r<=0||r>t.length)throw new Error("anchor_line exceeds file length");let i=t[r-1];if(!i)throw new Error("anchor_line exceeds file length");let l=s?.max_levels??0,a=s?.include_siblings??!0,c=s?.include_header??!0,u=s?.max_lines??o,m=Math.max(1,Math.min(o,u)),d=l===0?0:Math.max(0,i.indent-l*4),h=r-1,w=r-1;for(;h-1>=0;){let f=t[h-1];if(!f)break;let I=/^\s*(#|\/\/|--)/.test(f.text),S=f.text.trim().length===0;if(f.indent<d||!a&&f.indent===d&&!I&&!S||!c&&(I||S)&&f.indent<i.indent||(h-=1,w-h+1>=m))break}for(;w+1<t.length&&w-h+1<m;){let f=t[w+1];if(!f||f.indent<d||!a&&f.indent===d)break;w+=1}return t.slice(h,w+1)}var Fn=O({name:"read_file",description:"Reads a local file with 1-indexed line numbers, supporting slice and indentation-aware block modes.",inputSchema:zs,supportsParallelToolCalls:!0,isMutating:!1,execute:async t=>{let e=t.offset??1,n=t.limit??Hn;if(e<=0)return p("offset must be a 1-indexed line number",!0);if(n<=0)return p("limit must be greater than zero",!0);let o=t.file_path.trim();if(!o.startsWith("/"))return p("file_path must be an absolute path",!0);let s=re(o);try{let r=await Ws(s,"utf8"),i=Vs(r);if(i.length===0)return p("");let a=(t.mode??"slice")==="indentation"?Js(i,t):Xs(i,e,n);return p(Gs(a))}catch(r){return p(`read_file failed: ${r.message}`,!0)}}});import{readdir as Ys,lstat as Zs}from"fs/promises";import{join as Qs}from"path";import{z as We}from"zod";var ei=1,ti=25,ni=2,oi=We.object({dir_path:We.string().min(1),offset:We.number().int().positive().optional(),limit:We.number().int().positive().optional(),depth:We.number().int().positive().optional()}).strict();function ri(t){let e=" ".repeat(t.displayDepth*2),n="";t.kind==="dir"&&(n="/"),t.kind==="symlink"&&(n="@"),t.kind==="other"&&(n="?");let o=t.path.split("/"),s=o[o.length-1]??t.path;return`${e}${s}${n}`}var jn=O({name:"list_dir",description:"Lists entries in a local directory with 1-indexed entry numbers and simple type labels.",inputSchema:oi,supportsParallelToolCalls:!0,isMutating:!1,execute:async t=>{let e=t.offset??ei,n=t.limit??ti,o=t.depth??ni;if(e<=0)return p("offset must be a 1-indexed entry number",!0);if(n<=0)return p("limit must be greater than zero",!0);if(o<=0)return p("depth must be greater than zero",!0);let s=t.dir_path.trim();if(!s.startsWith("/"))return p("dir_path must be an absolute path",!0);let r=re(s);try{let i=[{absPath:r,depth:o,displayDepth:0}],l=[];for(;i.length>0;){let m=i.shift();if(!m)continue;let d=await Ys(m.absPath);d.sort((h,w)=>h.localeCompare(w));for(let h of d){let w=Qs(m.absPath,h),f=await Zs(w),I=f.isSymbolicLink()?"symlink":f.isDirectory()?"dir":f.isFile()?"file":"other";l.push({path:w,displayDepth:m.displayDepth,kind:I}),I==="dir"&&m.depth>1&&i.push({absPath:w,depth:m.depth-1,displayDepth:m.displayDepth+1})}}if(l.length===0)return p(`Absolute path: ${r}`);let a=e-1;if(a>=l.length)return p("offset exceeds directory entry count",!0);let c=l.slice(a,a+n),u=[`Absolute path: ${r}`,...c.map(ri)];return a+n<l.length&&u.push(`More than ${n} entries found`),p(u.join(`
|
|
13
|
+
`))}catch(i){return p(`list_dir failed: ${i.message}`,!0)}}});import{spawn as si}from"child_process";import{resolve as ii}from"path";import{z as ze}from"zod";var ai=100,li=2e3,ci=3e4,ui=ze.object({pattern:ze.string().min(1),include:ze.string().optional(),path:ze.string().optional(),limit:ze.number().int().positive().optional()}).strict();function pi(t){return new Promise((e,n)=>{let o=["--files-with-matches","--sortr=modified","--regexp",t.pattern,"--no-messages"];t.include?.trim()&&o.push("--glob",t.include.trim()),o.push("--",t.searchPath);let s=si("rg",o,{cwd:t.cwd,stdio:["ignore","pipe","pipe"]}),r=[],i=[];s.stdout?.setEncoding("utf8"),s.stderr?.setEncoding("utf8"),s.stdout?.on("data",a=>r.push(a)),s.stderr?.on("data",a=>i.push(a));let l=setTimeout(()=>{s.kill("SIGTERM"),n(new Error("rg timed out after 30 seconds"))},ci);s.on("error",a=>{clearTimeout(l),n(a)}),s.on("close",a=>{clearTimeout(l),e({exitCode:typeof a=="number"?a:-1,stdout:r.join(""),stderr:i.join("")})})})}var Bn=O({name:"grep_files",description:"Finds files whose contents match the pattern and lists them by modification time.",inputSchema:ui,supportsParallelToolCalls:!0,isMutating:!1,execute:async t=>{let e=t.pattern.trim();if(!e)return p("pattern must not be empty",!0);let n=Math.min(t.limit??ai,li),o=t.path?.trim()?ii(process.cwd(),t.path.trim()):process.cwd();try{let s=await pi({pattern:e,include:t.include,searchPath:o,cwd:process.cwd(),limit:n});if(s.exitCode===1)return p("No matches found.");if(s.exitCode!==0)return p(`rg failed: ${s.stderr||s.stdout}`,!0);let r=s.stdout.split(/\r?\n/).map(i=>i.trim()).filter(Boolean).slice(0,n);return r.length===0?p("No matches found."):p(r.join(`
|
|
14
|
+
`))}catch(s){return p(`grep_files failed: ${s.message}`,!0)}}});import{z as Te}from"zod";var Wn=null;function Ft(t){Wn=t}function zn(){return Wn}var mi=Te.object({server:Te.string().optional(),cursor:Te.string().optional()}).strict(),di=Te.object({server:Te.string().optional(),cursor:Te.string().optional()}).strict(),fi=Te.object({server:Te.string().min(1),uri:Te.string().min(1)}).strict();function jt(){let t=zn();if(!t)throw new Error("MCP pool is not initialized");return t}var qn=O({name:"list_mcp_resources",description:"Lists resources provided by MCP servers. Prefer resources over web search when possible.",inputSchema:mi,supportsParallelToolCalls:!0,isMutating:!1,execute:async({server:t,cursor:e})=>{try{let n=jt();if(t?.trim()){let r=n.get(t.trim());if(!r)return p(`MCP server not found: ${t}`,!0);let i=await r.client.listResources(e?{cursor:e}:void 0);return p(JSON.stringify({server:r.name,resources:i.resources,nextCursor:i.nextCursor},null,2))}if(e)return p("cursor is only supported when server is specified",!0);let o=n.getAll().sort((r,i)=>r.name.localeCompare(i.name)),s=[];for(let r of o){let i=await r.client.listResources();for(let l of i.resources)s.push({server:r.name,...l})}return p(JSON.stringify({resources:s},null,2))}catch(n){return p(`list_mcp_resources failed: ${n.message}`,!0)}}}),Kn=O({name:"list_mcp_resource_templates",description:"Lists resource templates provided by MCP servers. Prefer resource templates over web search when possible.",inputSchema:di,supportsParallelToolCalls:!0,isMutating:!1,execute:async({server:t,cursor:e})=>{try{let n=jt();if(t?.trim()){let r=n.get(t.trim());if(!r)return p(`MCP server not found: ${t}`,!0);let i=await r.client.listResourceTemplates(e?{cursor:e}:void 0);return p(JSON.stringify({server:r.name,resourceTemplates:i.resourceTemplates,nextCursor:i.nextCursor},null,2))}if(e)return p("cursor is only supported when server is specified",!0);let o=n.getAll().sort((r,i)=>r.name.localeCompare(i.name)),s=[];for(let r of o){let i=await r.client.listResourceTemplates();for(let l of i.resourceTemplates)s.push({server:r.name,...l})}return p(JSON.stringify({resourceTemplates:s},null,2))}catch(n){return p(`list_mcp_resource_templates failed: ${n.message}`,!0)}}}),Vn=O({name:"read_mcp_resource",description:"Read a specific resource from an MCP server given the server name and resource URI.",inputSchema:fi,supportsParallelToolCalls:!0,isMutating:!1,execute:async({server:t,uri:e})=>{try{let o=jt().get(t);if(!o)return p(`MCP server not found: ${t}`,!0);let s=await o.client.readResource({uri:e});return p(JSON.stringify({server:t,uri:e,...s},null,2))}catch(n){return p(`read_mcp_resource failed: ${n.message}`,!0)}}});import{z as Le}from"zod";var gi=Le.object({step:Le.string().min(1),status:Le.enum(["pending","in_progress","completed"])}).strict(),hi=Le.object({explanation:Le.string().optional(),plan:Le.array(gi).min(1)}).strict(),Gn=[],Xn=O({name:"update_plan",description:"Updates the task plan. At most one step can be in_progress at a time.",inputSchema:hi,supportsParallelToolCalls:!1,isMutating:!1,execute:async({explanation:t,plan:e})=>e.filter(o=>o.status==="in_progress").length>1?p("At most one step can be in_progress at a time",!0):(Gn=e,p(JSON.stringify({message:"Plan updated",explanation:t,plan:Gn},null,2)))});import{readFile as yi}from"fs/promises";import{homedir as Ti}from"os";import{join as Jn}from"path";import{z as Yn}from"zod";var _i=Yn.object({memory_id:Yn.string().min(1)}).strict();function Si(){let t=process.env.MEMO_HOME?.trim()||Jn(Ti(),".memo");return Jn(t,"Agents.md")}var Zn=O({name:"get_memory",description:"Loads the stored memory payload for a memory_id.",inputSchema:_i,supportsParallelToolCalls:!0,isMutating:!1,execute:async({memory_id:t})=>{try{let e=Si(),n=await yi(e,"utf8");return p(JSON.stringify({memory_id:t,memory_summary:n},null,2))}catch{return p(`memory not found for memory_id=${t}`,!0)}}});import{z as Qn}from"zod";var vi=Qn.object({url:Qn.string().min(1)}).strict(),eo=1e4,qe=512e3,Bt=4e3,xi=new Set(["http:","https:","data:"]),Ci=/<\/\s*(p|div|section|article|header|footer|aside|main|h[1-6]|li|tr|table|blockquote)\s*>/gi,Ei=/<\s*(br|hr)\s*\/?>/gi,Ai=/<\s*li[^>]*>/gi,wi=/<[^>]+>/g,bi=/<(script|style)[^>]*>[\s\S]*?<\/\s*\1>/gi,ki=t=>t.replace(/ /gi," ").replace(/</gi,"<").replace(/>/gi,">").replace(/&/gi,"&").replace(/"/gi,'"').replace(/'/g,"'").replace(/&#(x?[0-9a-fA-F]+);/g,(o,s)=>{try{let r=s.startsWith("x")||s.startsWith("X")?parseInt(s.slice(1),16):parseInt(s,10);return Number.isFinite(r)?String.fromCharCode(r):""}catch{return""}}),Mi=t=>{let o=t.replace(bi," ").replace(Ai,"- ").replace(Ei,`
|
|
15
|
+
`).replace(Ci,`
|
|
16
|
+
`).replace(wi," "),r=ki(o).replace(/\r/g,"").split(`
|
|
17
|
+
`).map(l=>l.trim().replace(/[ \t]{2,}/g," "));return r.filter((l,a)=>l.length>0||a>0&&(r[a-1]?.length??0)>0).join(`
|
|
18
|
+
`).trim()},Pi=t=>t.replace(/\s+/g," ").trim(),to=O({name:"webfetch",description:"HTTP GET \u8BF7\u6C42\uFF0C\u8FD4\u56DE\u5904\u7406\u540E\u7684\u7EAF\u6587\u672C\u6B63\u6587\uFF08\u81EA\u52A8\u5265\u79BB HTML \u6807\u7B7E\uFF09",inputSchema:vi,supportsParallelToolCalls:!0,isMutating:!1,execute:async t=>{let e;try{e=new URL(t.url)}catch{return p(`\u65E0\u6548 URL: ${t.url}`,!0)}if(!xi.has(e.protocol))return p(`\u4E0D\u652F\u6301\u7684\u534F\u8BAE: ${e.protocol}`,!0);let n=new AbortController,o=setTimeout(()=>n.abort(),eo);try{let s=await globalThis.fetch(e,{signal:n.signal}),r=s.headers.get("content-length"),i=r?Number(r):void 0;if(i&&i>qe)return p(`\u8BF7\u6C42\u88AB\u62D2\u7EDD: \u54CD\u5E94\u4F53\u8FC7\u5927\uFF08${i} bytes\uFF09`,!0);let l=0,a="";if(s.body&&s.body.getReader){let I=s.body.getReader(),S=[];for(;;){let{done:N,value:M}=await I.read();if(N)break;if(M){if(l+=M.byteLength,l>qe)return n.abort(),p(`\u8BF7\u6C42\u88AB\u4E2D\u6B62: \u54CD\u5E94\u4F53\u8D85\u8FC7 ${qe} bytes`,!0);S.push(M)}}let _=new Uint8Array(l),U=0;for(let N of S)_.set(N,U),U+=N.byteLength;a=new TextDecoder().decode(_)}else if(a=await s.text(),l=new TextEncoder().encode(a).byteLength,l>qe)return p(`\u8BF7\u6C42\u88AB\u62D2\u7EDD: \u54CD\u5E94\u4F53\u8D85\u8FC7 ${qe} bytes`,!0);let c=s.headers.get("content-type")||"",u=/text\/html/i.test(c)||/^\s*<!doctype html/i.test(a)||/^\s*<html[\s>]/i.test(a),m=u?Mi(a):a.trim(),d=Pi(m),h=d.length>Bt?`${d.slice(0,Bt)}...`:d,w=d.length>Bt?" text_truncated=true":"",f=u?" source=html_stripped":"";return p(`status=${s.status} bytes=${l} text_chars=${d.length} text="${h}"${w}${f}`)}catch(s){return s.name==="AbortError"?p(`\u8BF7\u6C42\u8D85\u65F6\u6216\u88AB\u4E2D\u6B62\uFF08${eo}ms\uFF09`,!0):p(`\u8BF7\u6C42\u5931\u8D25: ${s.message}`,!0)}finally{clearTimeout(o)}}});import{spawn as Ri}from"child_process";import{existsSync as Ii}from"fs";import{resolve as Oi}from"path";import{z as Y}from"zod";var Li=3e4,$i=1e4,Ni=3e5,no=4,Di=1500,oo=2e3,ve=new Map,Ui=Y.object({message:Y.string().min(1),agent_type:Y.string().optional()}).strict(),Hi=Y.object({id:Y.string().min(1),message:Y.string().min(1),interrupt:Y.boolean().optional()}).strict(),Fi=Y.object({id:Y.string().min(1)}).strict(),ji=Y.object({ids:Y.array(Y.string().min(1)).min(1),timeout_ms:Y.number().int().positive().optional()}).strict(),Bi=Y.object({id:Y.string().min(1)}).strict();function $e(){return new Date().toISOString()}function Wt(t){return p(`agent not found: ${t}`,!0)}function Wi(){let t=process.env.MEMO_SUBAGENT_MAX_AGENTS?.trim();if(!t)return no;let e=Number(t);return!Number.isFinite(e)||e<=0?no:Math.floor(e)}function zi(){let t=0;for(let e of ve.values())e.running&&(t+=1);return t}function qi(){let t=process.env.MEMO_SUBAGENT_COMMAND?.trim();if(t)return t;let e=Oi(process.cwd(),"dist/index.js");return Ii(e)?`node ${JSON.stringify(e)} --dangerous`:"memo --dangerous"}function Ki(t){return t!=="running"}function Vi(t){return new Promise(e=>{setTimeout(e,t)})}function Gi(t){return t===void 0?Li:t<=0?null:Math.max($i,Math.min(Ni,t))}function Xi(t){return t.length<=oo?t:`${t.slice(0,oo)}
|
|
19
|
+
...[truncated]`}function Ji(t,e){let n=[],o=t.trim(),s=e.trim();return o&&n.push(o),s&&n.push(`stderr:
|
|
20
|
+
${s}`),Xi(n.join(`
|
|
21
21
|
|
|
22
|
-
`))}async function
|
|
23
|
-
`)}catch{}try{
|
|
24
|
-
`)}function
|
|
22
|
+
`))}async function ro(t){let e=t.running;if(!e)return;e.interrupted=!0;let n=e.process;n.exitCode!==null||n.killed||await new Promise(o=>{let s=!1,r=()=>{s||(s=!0,clearTimeout(i),n.off("close",r),o())},i=setTimeout(()=>{if(n.exitCode===null)try{n.kill("SIGKILL")}catch{r()}},Di);n.on("close",r);try{n.kill("SIGTERM")}catch{r()}})}function Yi(t){let e=ve.get(t);return e?e.status:"not_found"}function Zi(t){let e=ve.get(t);return e?{status:e.status,last_message:e.lastMessage,last_output:e.lastOutput,last_error:e.lastError,last_submission_id:e.lastSubmissionId,updated_at:e.updatedAt}:{status:"not_found",last_message:null,last_output:null,last_error:null,last_submission_id:null,updated_at:null}}function Qi(t){return{agent_id:t.id,status:t.status,created_at:t.createdAt,updated_at:t.updatedAt,last_message:t.lastMessage,last_submission_id:t.lastSubmissionId,has_last_output:!!t.lastOutput,has_last_error:!!t.lastError}}function ea(t){let{record:e,submissionId:n,stdout:o,stderr:s,exitCode:r,interrupted:i}=t;if(!(!e.running||e.running.id!==n)&&(e.running=null,e.updatedAt=$e(),e.lastOutput=Ji(o,s)||null,e.lastError=null,e.status!=="closed")){if(i){e.status="errored",e.lastError="interrupted",e.statusBeforeClose="errored";return}if(r===0){e.status="completed",e.statusBeforeClose="completed";return}e.status="errored",e.lastError=`submission failed with exit code ${r}`,e.statusBeforeClose="errored"}}async function so(t,e){let n=Wi();if(zi()>=n)throw new Error(`subagent concurrency limit reached (${n})`);let o=crypto.randomUUID(),s=qi(),r=Ri(s,{cwd:process.cwd(),env:{...process.env},shell:!0,stdio:["pipe","pipe","pipe"]}),i=[],l=[];r.stdout?.setEncoding("utf8"),r.stderr?.setEncoding("utf8"),r.stdout?.on("data",a=>i.push(a)),r.stderr?.on("data",a=>l.push(a)),r.on("error",a=>{l.push(`[spawn error] ${a.message}`)}),t.running={id:o,message:e,process:r,startedAt:$e(),interrupted:!1},t.status="running",t.lastMessage=e,t.lastSubmissionId=o,t.updatedAt=$e(),r.on("close",a=>{let c=typeof a=="number"?a:-1,u=!!(t.running?.id===o&&t.running.interrupted);ea({record:t,submissionId:o,stdout:i.join(""),stderr:l.join(""),exitCode:c,interrupted:u})});try{r.stdin?.write(`${e.trim()}
|
|
23
|
+
`)}catch{}try{r.stdin?.end()}catch{}return o}var io=O({name:"spawn_agent",description:"Spawn a sub-agent for a well-scoped task and return the agent id.",inputSchema:Ui,supportsParallelToolCalls:!1,isMutating:!0,execute:async({message:t})=>{let e=t.trim();if(!e)return p("spawn_agent failed: message must not be empty",!0);let n=crypto.randomUUID(),o=$e(),s={id:n,createdAt:o,updatedAt:o,status:"running",statusBeforeClose:"completed",lastMessage:e,lastSubmissionId:null,lastOutput:null,lastError:null,running:null};ve.set(n,s);try{let r=await so(s,e);return p(JSON.stringify({...Qi(s),submission_id:r},null,2))}catch(r){return ve.delete(n),p(`spawn_agent failed: ${r.message}`,!0)}}}),ao=O({name:"send_input",description:"Send a message to an existing agent.",inputSchema:Hi,supportsParallelToolCalls:!1,isMutating:!0,execute:async({id:t,message:e,interrupt:n})=>{let o=ve.get(t);if(!o)return Wt(t);let s=e.trim();if(!s)return p("send_input failed: message must not be empty",!0);if(o.status==="closed")return p(`send_input failed: agent ${t} is closed; run resume_agent first`,!0);if(o.running){if(!n)return p(`send_input failed: agent ${t} is busy; set interrupt=true to cancel current submission`,!0);await ro(o)}try{let r=await so(o,s);return p(JSON.stringify({agent_id:o.id,status:o.status,submission_id:r},null,2))}catch(r){return p(`send_input failed: ${r.message}`,!0)}}}),lo=O({name:"resume_agent",description:"Resume a previously closed agent by id.",inputSchema:Fi,supportsParallelToolCalls:!1,isMutating:!0,execute:async({id:t})=>{let e=ve.get(t);return e?(e.status==="closed"&&(e.status=e.statusBeforeClose,e.updatedAt=$e()),p(JSON.stringify({agent_id:t,status:e.status},null,2))):Wt(t)}}),co=O({name:"wait",description:"Wait for agent statuses and return current snapshots.",inputSchema:ji,supportsParallelToolCalls:!1,isMutating:!1,execute:async({ids:t,timeout_ms:e})=>{let n=Gi(e);if(n===null)return p("wait failed: timeout_ms must be greater than zero",!0);let o=()=>{let i={},l={};for(let a of t){let c=Yi(a);Ki(c)&&(i[a]=c,l[a]=Zi(a))}return{status:i,details:l}},s=o();if(Object.keys(s.status).length>0)return p(JSON.stringify({status:s.status,details:s.details,timed_out:!1},null,2));let r=Date.now()+n;for(;Date.now()<r;)if(await Vi(100),s=o(),Object.keys(s.status).length>0)return p(JSON.stringify({status:s.status,details:s.details,timed_out:!1},null,2));return p(JSON.stringify({status:{},details:{},timed_out:!0},null,2))}}),uo=O({name:"close_agent",description:"Close an agent and return its last known status.",inputSchema:Bi,supportsParallelToolCalls:!1,isMutating:!0,execute:async({id:t})=>{let e=ve.get(t);return e?e.status==="closed"?p(JSON.stringify({agent_id:t,status:"closed"},null,2)):(e.statusBeforeClose=e.running?"completed":e.status,e.status="closed",e.updatedAt=$e(),await ro(e),p(JSON.stringify({agent_id:t,status:"closed"},null,2))):Wt(t)}});var zt={list_mcp_resources:"read",list_mcp_resource_templates:"read",read_mcp_resource:"read",update_plan:"read",get_memory:"read",webfetch:"read",read_file:"read",list_dir:"read",grep_files:"read",wait:"read",spawn_agent:"read",send_input:"read",resume_agent:"read",close_agent:"read",apply_patch:"write",shell:"execute",shell_command:"execute",exec_command:"execute",write_stdin:"execute"},po=new Set(["spawn_agent","send_input","resume_agent","wait","close_agent"]),it={read:0,write:1,execute:2},mo=["exec","run","shell","command","stdin"],fo=["write","patch","create","delete","modify","update"],go=["read","get","fetch","search","list","find"],ho=new Set(["write","execute"]);function Kt(t){let e={...zt,...t?.customLevels};return{getRiskLevel(n){if(n in e)return e[n];let o=n.toLowerCase();return qt(o,mo)?"execute":qt(o,fo)?"write":qt(o,go)?"read":"write"},compareRisk(n,o){return it[n]-it[o]},needsApproval(n,o){return o==="strict"?!0:ho.has(n)}}}function qt(t,e){return e.some(n=>t.includes(n))}import{createHash as ta}from"crypto";function at(t){return t===null||typeof t!="object"?JSON.stringify(t):Array.isArray(t)?"["+t.map(n=>at(n)).join(",")+"]":`{${Object.entries(t).sort(([n],[o])=>n.localeCompare(o)).map(([n,o])=>`${JSON.stringify(n)}:${at(o)}`).join(",")}}`}function Vt(t,e){let n=at(e),o=`${t}:${n}`;return ta("sha256").update(o).digest("hex").slice(0,16)}function na(t){return`Tool "${t}" requires approval.`}function Gt(t){let{mode:e="auto",dangerous:n=!1,toolRiskLevels:o}=t||{},s=e==="strict"?"strict":"auto";if(n)return{isDangerousMode:!0,getRiskLevel:()=>"read",check:()=>({needApproval:!1,decision:"auto-execute"}),recordDecision:()=>{},isGranted:()=>!0,clearOnceApprovals:()=>{},dispose:()=>{}};let r=Kt({customLevels:o}),i={session:new Set,once:new Set,denied:new Set};return{get isDangerousMode(){return!1},getRiskLevel(l){return r.getRiskLevel(l)},check(l,a){if(po.has(l))return{needApproval:!1,decision:"auto-execute"};let c=r.getRiskLevel(l);if(!r.needsApproval(c,s))return{needApproval:!1,decision:"auto-execute"};let u=Vt(l,a);return i.session.has(u)||i.once.has(u)?{needApproval:!1,decision:"auto-execute"}:i.denied.has(u)?{needApproval:!0,fingerprint:u,riskLevel:c,reason:"This request was previously denied.",toolName:l,params:a}:{needApproval:!0,fingerprint:u,riskLevel:c,reason:na(l),toolName:l,params:a}},recordDecision(l,a){switch(i.session.delete(l),i.once.delete(l),i.denied.delete(l),a){case"session":i.session.add(l);break;case"once":i.once.add(l);break;case"deny":i.denied.add(l);break}},isGranted(l){return i.session.has(l)||i.once.has(l)},clearOnceApprovals(){i.once.clear()},dispose(){i.session.clear(),i.once.clear(),i.denied.clear()}}}var yo=12e3;function oa(){let t=process.env.MEMO_TOOL_RESULT_MAX_CHARS?.trim();if(!t)return yo;let e=Number(t);return!Number.isFinite(e)||e<=0?yo:Math.floor(e)}function ra(t){return t.replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}function sa(t){let e=0;for(let n of t.content??[]){if(n.type==="text"){e+=n.text.length;continue}try{e+=JSON.stringify(n).length}catch{e+=100}}return e}function ia(t,e,n){return`<system_hint type="tool_output_omitted" tool="${ra(t)}" reason="too_long" actual_chars="${e}" max_chars="${n}">\u5DE5\u5177\u8FD4\u56DE\u5185\u5BB9\u8FC7\u957F\uFF0C\u5DF2\u81EA\u52A8\u7701\u7565\u3002\u8BF7\u7F29\u5C0F\u8303\u56F4\u6216\u589E\u52A0\u9650\u5236\u53C2\u6570\u540E\u91CD\u8BD5\u3002</system_hint>`}function aa(t,e){let n=oa(),o=sa(e);return o<=n?e:{content:[{type:"text",text:ia(t,o,n)}],isError:!1}}function la(t){return(t.content?.flatMap(n=>n.type==="text"?[n.text]:[])??[]).join(`
|
|
24
|
+
`)}function ca(t,e){let n=e;if(typeof e=="string"){let o=e.trim();if(o)try{n=JSON.parse(o)}catch{n=o}else n={}}return typeof n!="object"||n===null?{ok:!1,error:`${t.name} invalid input: expected object`}:typeof t.validateInput=="function"?t.validateInput(n):{ok:!0,data:n}}function ua(t){let e=t instanceof Error?t.message.toLowerCase():String(t).toLowerCase();return e.includes("sandbox")||e.includes("permission denied")||e.includes("operation not permitted")||e.includes("eacces")?"sandbox_denied":"execution_failed"}var Xt=class{constructor(e){this.config=e;this.approvalManager=Gt(e.approval)}approvalManager;async executeAction(e,n){let o=Date.now(),s=e.id??`${e.name}:${o}`,r=this.approvalManager.check(e.name,e.input);if(r.needApproval){let l={toolName:r.toolName,params:r.params,fingerprint:r.fingerprint,riskLevel:r.riskLevel,reason:r.reason};await n?.onApprovalRequest?.(l);let a=n?.requestApproval?await n.requestApproval(l):"deny";if(this.approvalManager.recordDecision(r.fingerprint,a),await n?.onApprovalResponse?.({fingerprint:r.fingerprint,decision:a}),a==="deny")return{actionId:s,tool:e.name,status:"approval_denied",errorType:"approval_denied",success:!1,observation:`\u7528\u6237\u62D2\u7EDD\u4E86\u5DE5\u5177\u6267\u884C: ${e.name}`,durationMs:Date.now()-o,rejected:!0}}let i=this.config.tools[e.name];if(!i)return{actionId:s,tool:e.name,status:"tool_not_found",errorType:"tool_not_found",success:!1,observation:`Unknown tool: ${e.name}`,durationMs:Date.now()-o};try{let l=ca(i,e.input);if(!l.ok)return{actionId:s,tool:e.name,status:"input_invalid",errorType:"input_invalid",success:!1,observation:l.error,durationMs:Date.now()-o};let a=await i.execute(l.data),c=aa(e.name,a);return{actionId:s,tool:e.name,status:"success",success:!0,observation:la(c)||"(no tool output)",durationMs:Date.now()-o}}catch(l){let a=ua(l);return{actionId:s,tool:e.name,status:a,errorType:a,success:!1,observation:`Tool execution failed: ${l.message}`,durationMs:Date.now()-o}}}async executeActions(e,n={}){let o=n.executionMode??"sequential",s=n.failurePolicy??(n.stopOnRejection===!1?"collect_all":"fail_fast"),r=[];if(o==="parallel"){let a=await Promise.all(e.map(c=>this.executeAction(c,n)));if(s==="fail_fast"){let c=a.findIndex(u=>u.rejected);r=c>=0?a.slice(0,c+1):a}else r=a}else for(let a of e){let c=await this.executeAction(a,n);if(r.push(c),c.rejected&&s==="fail_fast")break}let i=r.some(a=>a.rejected),l=r.map(a=>`[${a.tool}]: ${a.observation}`).join(`
|
|
25
25
|
|
|
26
|
-
`);return{results:
|
|
26
|
+
`);return{results:r,combinedObservation:l,hasRejection:i,executionMode:o,failurePolicy:s}}clearOnceApprovals(){this.approvalManager.clearOnceApprovals()}dispose(){this.approvalManager.dispose()}};function To(t){return new Xt(t)}var lt=class{tools=new Map;register(e){this.tools.set(e.name,e)}registerMany(e){for(let n of e)this.register(n)}get(e){return this.tools.get(e)}getAll(){return Array.from(this.tools.values())}toRegistry(){let e={};for(let[n,o]of this.tools)e[n]=o;return e}has(e){return this.tools.has(e)}get size(){return this.tools.size}};import{Client as pa}from"@modelcontextprotocol/sdk/client/index.js";import{StreamableHTTPClientTransport as ma}from"@modelcontextprotocol/sdk/client/streamableHttp.js";import{StdioClientTransport as da}from"@modelcontextprotocol/sdk/client/stdio.js";function fa(t){if(!t)return;let e={...process.env,...t},n=Object.entries(e).filter(o=>typeof o[1]=="string");return Object.fromEntries(n)}function _o(){return new pa({name:"memo-code-cli-client",version:"1.0.0"},{capabilities:{}})}function ga(t){if(!(!t||Object.keys(t).length===0))return{headers:t}}function ha(t){let e={...t.http_headers??t.headers??{}};if(t.bearer_token_env_var){let n=process.env[t.bearer_token_env_var];n&&!e.Authorization&&(e.Authorization=`Bearer ${n}`)}return e}async function ya(t){let e=new URL(t.url),n=ga(ha(t));try{let o=_o(),s=new ma(e,{requestInit:n});return await o.connect(s),{client:o,transport:s}}catch(o){let s=`Failed to connect via streamable_http (${o.message})`,r=new Error(s);throw r.cause=o,r}}async function Ta(t){if("url"in t)return ya(t);let e={command:t.command,args:t.args,env:fa(t.env),stderr:t.stderr??(process.stdout.isTTY&&process.stdin.isTTY?"ignore":void 0)},n=new da(e),o=_o();return await o.connect(n),{client:o,transport:n}}var ct=class{connections=new Map;async connect(e,n){let o=this.connections.get(e);if(o)return o;let{client:s,transport:r}=await Ta(n),i=await s.listTools(),l={name:e,client:s,transport:r,tools:(i.tools||[]).map(a=>({name:`${e}_${a.name}`,description:a.description||`Tool from ${e}: ${a.name}`,source:"mcp",serverName:e,originalName:a.name,inputSchema:a.inputSchema,execute:async()=>({content:[]})}))};return this.connections.set(e,l),l}get(e){return this.connections.get(e)}getAll(){return Array.from(this.connections.values())}getAllTools(){let e=[];for(let n of this.connections.values())for(let o of n.tools)e.push({name:o.name,description:o.description,serverName:o.serverName,originalName:o.originalName,inputSchema:o.inputSchema,client:n.client});return e}async closeAll(){let e=Array.from(this.connections.values()).map(async n=>{try{await n.client.close()}catch(o){console.error(`[MCP] Error closing client ${n.name}:`,o)}});await Promise.all(e),this.connections.clear()}get size(){return this.connections.size}};var ut=class{pool;tools=new Map;shouldLog;constructor(){this.pool=new ct,Ft(this.pool),this.shouldLog=process.env.MEMO_MCP_LOG==="1"||!(process.stdout.isTTY&&process.stdin.isTTY)}async loadServers(e){if(!e||Object.keys(e).length===0)return 0;let n=0;return await Promise.all(Object.entries(e).map(async([o,s])=>{try{let r=await this.pool.connect(o,s);for(let i of r.tools){let l={...i,execute:async a=>{let c=this.pool.get(i.serverName)?.client;if(!c)throw new Error(`MCP client for server '${i.serverName}' not found`);return c.callTool({name:i.originalName,arguments:a})}};this.tools.set(l.name,l)}n+=r.tools.length,this.shouldLog&&console.log(`[MCP] Connected to '${o}' with ${r.tools.length} tools`)}catch(r){this.shouldLog&&console.error(`[MCP] Failed to connect to server '${o}':`,r)}})),n}get(e){return this.tools.get(e)}getAll(){return Array.from(this.tools.values())}toRegistry(){let e={};for(let[n,o]of this.tools)e[n]=o;return e}has(e){return this.tools.has(e)}get size(){return this.tools.size}async dispose(){await this.pool.closeAll(),this.tools.clear(),Ft(null)}getPool(){return this.pool}};var pt=class{nativeRegistry;mcpRegistry;constructor(){this.nativeRegistry=new lt,this.mcpRegistry=new ut}registerNativeTool(e){this.nativeRegistry.register(e)}registerNativeTools(e){for(let n of e)this.registerNativeTool(n)}async loadMcpServers(e){return this.mcpRegistry.loadServers(e)}getTool(e){return this.nativeRegistry.get(e)??this.mcpRegistry.get(e)}getAllTools(){return[...this.nativeRegistry.getAll(),...this.mcpRegistry.getAll()]}toRegistry(){return{...this.nativeRegistry.toRegistry(),...this.mcpRegistry.toRegistry()}}hasTool(e){return this.nativeRegistry.has(e)||this.mcpRegistry.has(e)}getToolCount(){let e=this.nativeRegistry.size,n=this.mcpRegistry.size;return{native:e,mcp:n,total:e+n}}async execute(e,n){let o=this.getTool(e);if(!o)throw new Error(`Tool '${e}' not found`);return o.execute(n)}generateToolDefinitions(){return this.getAllTools().map(e=>({name:e.name,description:e.description,input_schema:e.inputSchema||{type:"object",properties:{}}}))}generateToolDescriptions(){let e=this.getAllTools();if(e.length===0)return"";let n=[];n.push("## Available Tools"),n.push("");let o=e.filter(r=>r.source==="native"),s=e.filter(r=>r.source==="mcp");if(o.length>0){n.push("### Built-in Tools"),n.push("");for(let r of o)n.push(this.formatToolDescription(r));n.push("")}if(s.length>0){n.push("### External MCP Tools"),n.push("");let r=this.groupByServer(s);for(let[i,l]of Object.entries(r)){n.push(`**Server: ${i}**`),n.push("");for(let a of l)n.push(this.formatToolDescription(a));n.push("")}}return n.join(`
|
|
27
27
|
`)}formatToolDescription(e){let n=[];return n.push(`#### ${e.name}`),n.push(`- **Description**: ${e.description}`),e.inputSchema&&Object.keys(e.inputSchema).length>0&&n.push(`- **Input Schema**: ${JSON.stringify(e.inputSchema)}`),n.join(`
|
|
28
|
-
`)}groupByServer(e){let n={};for(let o of e)if(o.source==="mcp"){let
|
|
28
|
+
`)}groupByServer(e){let n={};for(let o of e)if(o.source==="mcp"){let s=o.serverName;n[s]||(n[s]=[]),n[s].push(o)}return n}getToolDescriptions(){return this.getAllTools().map(e=>({name:e.name,description:e.description,source:e.source,serverName:e.source==="mcp"?e.serverName:void 0,inputSchema:e.inputSchema}))}async dispose(){await this.mcpRegistry.dispose()}};function _a(t){let e=process.env[t]?.trim();return e?new Set(e.split(",").map(n=>n.trim()).filter(Boolean)):new Set}function Sa(){let t=[],e=process.env.MEMO_SHELL_TOOL_TYPE?.trim()||"unified_exec",n=_a("MEMO_EXPERIMENTAL_TOOLS"),o=n.size===0,s=process.env.MEMO_ENABLE_COLLAB_TOOLS!=="0",r=process.env.MEMO_ENABLE_MEMORY_TOOL!=="0";return e==="shell"?t.push(Sn):e==="shell_command"?t.push(vn):e==="unified_exec"?t.push(Rt,It):e!=="disabled"&&t.push(Rt,It),t.push(qn,Kn,Vn),t.push(Xn),t.push(Dn),(o||n.has("grep_files"))&&t.push(Bn),(o||n.has("read_file"))&&t.push(Fn),(o||n.has("list_dir"))&&t.push(jn),r&&t.push(Zn),t.push(to),s&&t.push(io,ao,lo,co,uo),t}function va(t){let e={};for(let n of t)e[n.name]=n;return e}var xa=va(Sa()),Ca=Object.values(xa),So=Ca;import Ha from"openai";import{encoding_for_model as Ea,get_encoding as Aa}from"@dqbd/tiktoken";var vo="cl100k_base";function wa(t){let e=t?.trim()||vo;try{let n=()=>Ea(e);return n().free(),{model:e,factory:n}}catch{let n=vo,o=()=>Aa(n);return o().free(),{model:n,factory:o}}}function ba(t){return t.role==="assistant"&&t.tool_calls?.length?`${t.content}
|
|
29
29
|
${JSON.stringify(t.tool_calls)}`:t.role==="tool"?`${t.content}
|
|
30
30
|
${t.tool_call_id}
|
|
31
|
-
${t.name??""}`:t.content}function
|
|
31
|
+
${t.name??""}`:t.content}function xo(t){let{model:e,factory:n}=wa(t),o=n(),s=4,r=2,i=1,l=c=>c?o.encode(c).length:0;return{model:e,countText:l,countMessages:c=>{if(!c.length)return 0;let u=0;for(let m of c)u+=s,u+=l(ba(m)),m.name&&(u+=i);return u+=r,u},dispose:()=>o.free()}}import{mkdir as ka,writeFile as Ma,readFile as Pa,access as Ra}from"fs/promises";import{homedir as Co}from"os";import{dirname as Ia,join as Ve}from"path";import{randomUUID as pm}from"crypto";import{parse as Oa}from"toml";var La=Ve(Co(),".memo"),$a="sessions",Ke={current_provider:"deepseek",max_prompt_tokens:12e4,providers:[{name:"deepseek",env_api_key:"DEEPSEEK_API_KEY",model:"deepseek-chat",base_url:"https://api.deepseek.com"}],mcp_servers:{}};function Na(t){return/^[A-Za-z0-9_-]+$/.test(t)?t:JSON.stringify(t)}function Da(t){if(!t||typeof t!="object"||Array.isArray(t))return[];let e=[];for(let[n,o]of Object.entries(t)){if(!o)continue;let s=Array.isArray(o)?o:[o];for(let r of s){if(!r||typeof r!="object")continue;let i={...r};(typeof i.name!="string"||i.name.length===0)&&n&&(i.name=n),e.push(i)}}return e}function Eo(t){return t.startsWith("~")?Ve(Co(),t.slice(1)):t}function Ua(t){let e=t.providers.map(r=>{let i=typeof r?.name=="string"?r.name:"";if(!i)return"";let a=[`[[providers.${Na(i)}]]`,`name = ${JSON.stringify(i)}`,`env_api_key = ${JSON.stringify(String(r.env_api_key??""))}`,`model = ${JSON.stringify(String(r.model??""))}`];return r.base_url&&a.push(`base_url = ${JSON.stringify(String(r.base_url))}`),a.join(`
|
|
32
32
|
`)}).filter(Boolean).join(`
|
|
33
33
|
|
|
34
|
-
`),n="";t.mcp_servers&&Object.keys(t.mcp_servers).length>0&&(n=Object.entries(t.mcp_servers).map(([
|
|
35
|
-
`)}let
|
|
34
|
+
`),n="";t.mcp_servers&&Object.keys(t.mcp_servers).length>0&&(n=Object.entries(t.mcp_servers).map(([r,i])=>{if("url"in i){let h=[`[mcp_servers.${r}]`];h.push(`type = "${i.type??"streamable_http"}"`),h.push(`url = "${i.url}"`),i.bearer_token_env_var&&h.push(`bearer_token_env_var = ${JSON.stringify(i.bearer_token_env_var)}`);let w=i.http_headers??i.headers;if(w&&Object.keys(w).length>0){let f=Object.entries(w).map(([S,_])=>`${JSON.stringify(S)} = ${JSON.stringify(_)}`).join(", "),I=i.http_headers?"http_headers":"headers";h.push(`${I} = { ${f} }`)}return h.join(`
|
|
35
|
+
`)}let l=i.args?`args = ${JSON.stringify(i.args)}`:"",a=i.type?`type = "${i.type}"
|
|
36
36
|
`:"",c=i.stderr?`stderr = "${i.stderr}"
|
|
37
|
-
`:"",u=`[mcp_servers.${
|
|
38
|
-
${
|
|
39
|
-
${c}${
|
|
37
|
+
`:"",u=`[mcp_servers.${r}]
|
|
38
|
+
${a}command = "${i.command}"
|
|
39
|
+
${c}${l}`.trimEnd(),m=i.env?Object.entries(i.env):[];if(m.length===0)return u;let d=m.map(([h,w])=>`${JSON.stringify(h)} = ${JSON.stringify(w)}`).join(`
|
|
40
40
|
`);return`${u}
|
|
41
41
|
|
|
42
|
-
[mcp_servers.${
|
|
43
|
-
${
|
|
42
|
+
[mcp_servers.${r}.env]
|
|
43
|
+
${d}`}).join(`
|
|
44
44
|
|
|
45
45
|
`));let o=[`current_provider = "${t.current_provider}"`];return typeof t.max_prompt_tokens=="number"&&Number.isFinite(t.max_prompt_tokens)&&o.push(`max_prompt_tokens = ${Math.floor(t.max_prompt_tokens)}`),[o.join(`
|
|
46
46
|
`),e,n].filter(Boolean).join(`
|
|
47
47
|
|
|
48
|
-
`)}async function
|
|
48
|
+
`)}async function le(t,e){await ka(Ia(t),{recursive:!0}),await Ma(t,Ua(e),"utf-8")}async function Q(){let t=process.env.MEMO_HOME?Eo(process.env.MEMO_HOME):La,e=Ve(t,"config.toml");try{await Ra(e);let n=await Pa(e,"utf-8"),o=Oa(n),s=Da(o.providers),r=typeof o.max_prompt_tokens=="number"&&Number.isFinite(o.max_prompt_tokens)&&o.max_prompt_tokens>0?Math.floor(o.max_prompt_tokens):void 0,i={current_provider:o.current_provider??Ke.current_provider,max_prompt_tokens:r??Ke.max_prompt_tokens,providers:s,mcp_servers:o.mcp_servers??{}},l=!i.providers.length;return{config:l?Ke:i,home:t,configPath:e,needsSetup:l}}catch{return{config:Ke,home:t,configPath:e,needsSetup:!0}}}function be(t,e){let n=e||t.current_provider,o=t.providers.find(s=>s.name===n);return o||(t.providers?.[0]??Ke.providers[0])}function mt(t,e){let n=e.historyDir??Ve(t.home,$a);return Eo(n)}function Ao(t,e){let n=new Date,o=String(n.getFullYear()),s=String(n.getMonth()+1).padStart(2,"0"),r=String(n.getDate()).padStart(2,"0"),i=String(n.getHours()).padStart(2,"0"),l=String(n.getMinutes()).padStart(2,"0"),a=String(n.getSeconds()).padStart(2,"0"),c=`rollout-${o}-${s}-${r}T${i}-${l}-${a}-${e}.jsonl`;return Ve(t,o,s,r,c)}function Fa(t){try{return{ok:!0,data:JSON.parse(t)}}catch(e){return{ok:!1,raw:t,error:e.message}}}function ja(t){return t.role==="assistant"?{role:"assistant",content:t.content,tool_calls:t.tool_calls?.map(e=>({id:e.id,type:e.type,function:{name:e.function.name,arguments:e.function.arguments}}))}:t.role==="tool"?{role:"tool",content:t.content,tool_call_id:t.tool_call_id}:{role:t.role,content:t.content}}async function wo(t,e,n){let o=await Q(),s=o.config,r=new pt;if(r.registerNativeTools(So),await r.loadMcpServers(s.mcp_servers),t.tools)for(let[d,h]of Object.entries(t.tools))r.registerNativeTool({name:d,description:h.description,source:"native",inputSchema:{type:"object"},execute:h.execute});let i=r.toRegistry(),l=async()=>{let d=await(t.loadPrompt??dn)(),h=r.generateToolDescriptions();return h&&(d+=`
|
|
49
49
|
|
|
50
|
-
${
|
|
51
|
-
`),{thinkingParts:n,cleaned:o}=
|
|
50
|
+
${h}`),d},a=r.generateToolDefinitions(),c=mt(o,e),u=Ao(c,n),m=new ot(u);return{tools:i,dispose:async()=>{t.dispose&&await t.dispose(),await r.dispose()},callLLM:t.callLLM??(async(d,h,w)=>{let f=be(s,e.providerName),I=process.env[f.env_api_key]??process.env.OPENAI_API_KEY??process.env.DEEPSEEK_API_KEY;if(!I)throw new Error(`Missing env var ${f.env_api_key} (or OPENAI_API_KEY/DEEPSEEK_API_KEY)`);let S=new Ha({apiKey:I,baseURL:f.base_url}),_=d.map(ja),U=a.length>0?a.map(E=>({type:"function",function:{name:E.name,description:E.description,parameters:E.input_schema}})):void 0,N=await S.chat.completions.create({model:f.model,messages:_,tools:U,tool_choice:U?"auto":void 0},{signal:w?.signal}),M=N.choices?.[0]?.message;if(M?.tool_calls&&M.tool_calls.length>0){let E=[];M.content&&E.push({type:"text",text:M.content});for(let D of M.tool_calls)if(D.type==="function"){let ne=Fa(D.function.arguments);ne.ok?E.push({type:"tool_use",id:D.id,name:D.function.name,input:ne.data}):E.push({type:"text",text:`[tool_use parse error] ${ne.error}; raw: ${ne.raw}`})}let ie=E.some(D=>D.type==="tool_use");return{content:E,stop_reason:ie?"tool_use":"end_turn",usage:{prompt:N.usage?.prompt_tokens??void 0,completion:N.usage?.completion_tokens??void 0,total:N.usage?.total_tokens??void 0}}}let y=M?.content;if(typeof y!="string")throw new Error("OpenAI-compatible API returned empty content");return{content:[{type:"text",text:y}],stop_reason:"end_turn",usage:{prompt:N.usage?.prompt_tokens??void 0,completion:N.usage?.completion_tokens??void 0,total:N.usage?.total_tokens??void 0}}}),loadPrompt:l,historySinks:t.historySinks??[m],tokenCounter:t.tokenCounter??xo(e.tokenizerModel),historyFilePath:u}}function Ba(t){let e=[],n=/<\s*(think|thinking)\s*>([\s\S]*?)<\/\s*\1\s*>/gi,o=t.replace(n,(s,r,i)=>{let l=(i??"").trim();return l&&e.push(l),l});return{thinkingParts:e,cleaned:o.trim()}}function bo(t){if(t.length===0)return;let e=t.join(`
|
|
51
|
+
`),{thinkingParts:n,cleaned:o}=Ba(e);return n.length>0?n.join(`
|
|
52
52
|
|
|
53
|
-
`):o||void 0}import{randomUUID as
|
|
54
|
-
`),toolUseBlocks:n.map(o=>({id:o.id,name:o.name,input:o.input})),stopReason:t.stop_reason,usage:t.usage}}async function Fl(t,e){for(let n of e)try{await n.append(t)}catch(o){console.error(`Failed to write history event: ${o.message}`)}}function jl(t){return t instanceof Error&&t.name==="AbortError"}function at(t){return t===null||typeof t!="object"?JSON.stringify(t)??"null":Array.isArray(t)?`[${t.map(n=>at(n)).join(",")}]`:`{${Object.entries(t).sort(([n],[o])=>n.localeCompare(o)).map(([n,o])=>`${JSON.stringify(n)}:${at(o)}`).join(",")}}`}function Bl(t){return t.map(e=>({id:e.id,type:"function",function:{name:e.name,arguments:at(e.input)}}))}function Wl(t,e){let n=t.trim();if(!n)return null;let o=[n],r=n.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/i);r?.[1]&&o.push(r[1].trim());for(let s of o)if(!(!s.startsWith("{")||!s.endsWith("}")))try{let i=JSON.parse(s);if(!i||typeof i!="object"||Array.isArray(i))continue;let a=i,l=typeof a.tool=="string"?a.tool.trim():"";if(!l||!Object.prototype.hasOwnProperty.call(e,l))continue;return{tool:l,input:a.input??{}}}catch{}return null}var Tn=class{constructor(e,n,o,r,s){this.deps=e;this.options=n;this.id=n.sessionId||cr(),this.mode=n.mode||ur,this.history=[{role:"system",content:o}],this.tokenCounter=r,this.sinks=e.historySinks??[],this.hooks=ir(e),this.historyFilePath=s,this.toolOrchestrator=Xo({tools:e.tools,approval:{dangerous:n.dangerous??!1,mode:"auto"}})}id;mode;history;historyFilePath;turnIndex=0;tokenCounter;sinks;sessionUsage=ar();startedAt=Date.now();hooks;closed=!1;sessionStartEmitted=!1;currentAbortController=null;cancelling=!1;lastActionSignature=null;repeatedActionCount=0;toolOrchestrator;async init(){}resetActionRepetition(){this.lastActionSignature=null,this.repeatedActionCount=0}maybeWarnRepeatedAction(e,n){let o=`${e}:${at(n)}`;if(this.lastActionSignature===o?this.repeatedActionCount+=1:(this.lastActionSignature=o,this.repeatedActionCount=1),this.repeatedActionCount===3){let r=at(n).slice(0,200),s=`\u7CFB\u7EDF\u63D0\u9192\uFF1A\u4F60\u5DF2\u8FDE\u7EED3\u6B21\u8C03\u7528\u540C\u4E00\u5DE5\u5177\u300C${e}\u300D\u4E14\u53C2\u6570\u76F8\u540C\uFF08${r}${r.length>=200?"\u2026":""}\uFF09\u3002\u8BF7\u786E\u8BA4\u662F\u5426\u9677\u5165\u5FAA\u73AF\uFF0C\u5FC5\u8981\u65F6\u76F4\u63A5\u7ED9\u51FA\u6700\u7EC8\u56DE\u7B54\u6216\u8C03\u6574\u53C2\u6570\u3002`;this.history.push({role:"system",content:s})}}buildToolApprovalHooks(e,n){return{onApprovalRequest:async o=>{await Z(this.hooks,"onApprovalRequest",{sessionId:this.id,turn:e,step:n,request:o})},requestApproval:async o=>this.deps.requestApproval?this.deps.requestApproval(o):"deny",onApprovalResponse:async({fingerprint:o,decision:r})=>{await Z(this.hooks,"onApprovalResponse",{sessionId:this.id,turn:e,step:n,fingerprint:o,decision:r})}}}async executeToolAction(e,n,o,r,s){return this.toolOrchestrator.executeAction({id:e,name:n,input:o},this.buildToolApprovalHooks(r,s))}async runTurn(e){let n=new AbortController;this.currentAbortController=n,this.cancelling=!1,this.turnIndex+=1;let o=this.turnIndex,r=[],s=ar(),i=Date.now(),a=this.options.maxPromptTokens??Ul;this.sessionStartEmitted||(await this.emitEvent("session_start",{meta:{mode:this.mode,cwd:process.cwd(),tokenizer:this.tokenCounter.model,warnPromptTokens:this.options.warnPromptTokens,maxPromptTokens:a}}),this.sessionStartEmitted=!0),this.history.push({role:"user",content:e});try{let l=this.tokenCounter.countMessages(this.history);await this.emitEvent("turn_start",{turn:o,content:e,meta:{tokens:{prompt:l}}}),await Z(this.hooks,"onTurnStart",{sessionId:this.id,turn:o,input:e,promptTokens:l,history:Ge(this.history)});let c="",u="ok",p,T=0;for(let m=0;;m++){let S=this.tokenCounter.countMessages(this.history);if(S>a){let E=`Context tokens (${S}) exceed the limit. Please shorten the input or restart the session.`;this.history.push({role:"assistant",content:E}),u="prompt_limit",c=E,p=E,await this.emitEvent("final",{turn:o,step:m,content:E,role:"assistant",meta:{tokens:{prompt:S}}}),await Z(this.hooks,"onFinal",{sessionId:this.id,turn:o,step:m,finalText:E,status:u,errorMessage:p,turnUsage:{...s},steps:r});break}this.options.warnPromptTokens&&S>this.options.warnPromptTokens&&console.warn(`Prompt tokens are near the limit: ${S}`);let _="",v=[],N,R;try{let E=await this.deps.callLLM(this.history,z=>this.deps.onAssistantStep?.(z,m),{signal:n.signal}),A=Hl(E);_=A.textContent,v=A.toolUseBlocks,R=A.stopReason,N=A.usage}catch(E){if(this.cancelling&&jl(E)){u="cancelled",c="",p="Turn cancelled",await this.emitEvent("final",{turn:o,step:m,content:"",role:"assistant",meta:{cancelled:!0}}),await Z(this.hooks,"onFinal",{sessionId:this.id,turn:o,step:m,finalText:c,status:u,errorMessage:p,turnUsage:{...s},steps:r});break}let A=`LLM call failed: ${E.message}`;this.history.push({role:"assistant",content:A}),u="error",c=A,p=A,await this.emitEvent("final",{turn:o,content:A,role:"assistant"}),await Z(this.hooks,"onFinal",{sessionId:this.id,turn:o,step:m,finalText:c,status:u,errorMessage:p,turnUsage:{...s},steps:r});break}this.deps.onAssistantStep?.(_,m);let w=v.length===0&&_?Wl(_,this.deps.tools):null,y,k=null;if(v.length>0){let E=v[0];if(E){let A=_?rr([_]):void 0;y={action:{tool:E.name,input:E.input},thinking:A},k={role:"assistant",content:_,tool_calls:Bl(v)}}else y={}}else _?(y={final:_},k={role:"assistant",content:_}):y={};let K=this.tokenCounter.countText(_),D=N?.prompt??S,fe=N?.completion??K,H=N?.total??D+fe,I={prompt:D,completion:fe,total:H};if(lr(s,I),lr(this.sessionUsage,I),r.push({index:m,assistantText:_,parsed:y,tokenUsage:I}),await this.emitEvent("assistant",{turn:o,step:m,content:_,role:"assistant",meta:{tokens:I,protocol_violation:!!w,protocol_violation_count:w?T+1:T||void 0}}),w){T+=1;let E=`Model protocol error: returned plain-text tool JSON for "${w.tool}" ${T} times. Structured tool calls are required.`;u="error",c=E,p=E,this.history.push({role:"assistant",content:E}),await this.emitEvent("final",{turn:o,step:m,content:E,role:"assistant",meta:{error_type:"model_protocol_error",tool:w.tool,protocol_violation:!0,protocol_violation_count:T,tokens:I}}),await Z(this.hooks,"onFinal",{sessionId:this.id,turn:o,step:m,finalText:c,status:u,errorMessage:p,tokenUsage:I,turnUsage:{...s},steps:r});break}if(k&&this.history.push(k),v.length>1){for(let b of v)this.maybeWarnRepeatedAction(b.name,b.input);await this.emitEvent("action",{turn:o,step:m,meta:{tools:v.map(b=>b.name),action_ids:v.map(b=>b.id),action_id:v[0]?.id,parallel:!0,phase:"dispatch",thinking:y.thinking,toolBlocks:v.map(b=>({id:b.id,name:b.name,input:b.input}))}});let E=v[0];E&&await Z(this.hooks,"onAction",{sessionId:this.id,turn:o,step:m,action:{tool:E.name,input:E.input},parallelActions:v.map(b=>({tool:b.name,input:b.input})),thinking:y.thinking,history:Ge(this.history)});let A=v.every(b=>!!this.deps.tools[b.name]?.supportsParallelToolCalls),z=v.some(b=>!!this.deps.tools[b.name]?.isMutating),ie=A&&!z?"parallel":"sequential",Y=await this.toolOrchestrator.executeActions(v.map(b=>({id:b.id,name:b.name,input:b.input})),{...this.buildToolApprovalHooks(o,m),executionMode:ie,failurePolicy:"fail_fast"});for(let[b,V]of Y.results.entries())this.history.push({role:"tool",content:V.observation,tool_call_id:V.actionId,name:V.tool}),await this.emitEvent("observation",{turn:o,step:m,content:V.observation,meta:{tool:V.tool,index:b,action_id:V.actionId,phase:"result",status:V.status,error_type:V.errorType,duration_ms:V.durationMs,execution_mode:ie}});let Ce=Y.combinedObservation,xe=r[r.length-1];if(xe&&(xe.observation=Ce),await Z(this.hooks,"onObservation",{sessionId:this.id,turn:o,step:m,tool:v.map(b=>b.name).join(", "),observation:Ce,history:Ge(this.history)}),Y.hasRejection){let b=Y.results.find(V=>V.rejected);u="cancelled",c="\u7528\u6237\u62D2\u7EDD\u4E86\u5DE5\u5177\u6267\u884C\uFF0C\u5DF2\u505C\u6B62\u5F53\u524D\u64CD\u4F5C\u3002",await this.emitEvent("final",{turn:o,step:m,content:c,role:"assistant",meta:{rejected:!0,phase:"result",action_id:b?.actionId,error_type:b?.errorType??"approval_denied",duration_ms:b?.durationMs}}),await Z(this.hooks,"onFinal",{sessionId:this.id,turn:o,step:m,finalText:c,status:u,tokenUsage:I,turnUsage:{...s},steps:r});break}continue}else if(y.action){this.maybeWarnRepeatedAction(y.action.tool,y.action.input);let E=v[0]?.id??`${o}:${m}:single:${y.action.tool}`;await this.emitEvent("action",{turn:o,step:m,meta:{tool:y.action.tool,input:y.action.input,action_id:E,phase:"dispatch",thinking:y.thinking}}),await Z(this.hooks,"onAction",{sessionId:this.id,turn:o,step:m,action:y.action,thinking:y.thinking,history:Ge(this.history)});let A=await this.executeToolAction(E,y.action.tool,y.action.input,o,m);if(A.rejected){u="cancelled",c="\u7528\u6237\u62D2\u7EDD\u4E86\u5DE5\u5177\u6267\u884C\uFF0C\u5DF2\u505C\u6B62\u5F53\u524D\u64CD\u4F5C\u3002",await this.emitEvent("final",{turn:o,step:m,content:c,role:"assistant",meta:{rejected:!0,phase:"result",action_id:A.actionId,error_type:A.errorType??"approval_denied",duration_ms:A.durationMs}}),await Z(this.hooks,"onFinal",{sessionId:this.id,turn:o,step:m,finalText:c,status:u,tokenUsage:I,turnUsage:{...s},steps:r});break}let z=A.observation;this.history.push({role:"tool",content:z,tool_call_id:A.actionId,name:y.action.tool});let ie=r[r.length-1];ie&&(ie.observation=z),await this.emitEvent("observation",{turn:o,step:m,content:z,meta:{tool:y.action.tool,action_id:A.actionId,phase:"result",status:A.status,error_type:A.errorType,duration_ms:A.durationMs}}),await Z(this.hooks,"onObservation",{sessionId:this.id,turn:o,step:m,tool:y.action.tool,observation:z,history:Ge(this.history)});continue}if(R==="end_turn"||y.final){this.resetActionRepetition(),c=y.final||_,y.final&&(y.final=c),await this.emitEvent("final",{turn:o,step:m,content:c,role:"assistant",meta:{tokens:I}}),await Z(this.hooks,"onFinal",{sessionId:this.id,turn:o,step:m,finalText:c,status:u,tokenUsage:I,turnUsage:{...s},steps:r});break}this.resetActionRepetition();break}return!c&&u!=="cancelled"&&(u==="ok"&&(u="error"),c="Unable to produce a final answer. Please retry or adjust the request.",p=c,this.history.push({role:"assistant",content:c}),await this.emitEvent("final",{turn:o,content:c,role:"assistant"}),await Z(this.hooks,"onFinal",{sessionId:this.id,turn:o,finalText:c,status:u,errorMessage:p,turnUsage:{...s},steps:r})),await this.emitEvent("turn_end",{turn:o,meta:{status:u,stepCount:r.length,durationMs:Date.now()-i,tokens:s,protocol_violation_count:T||void 0}}),{finalText:c,steps:r,status:u,errorMessage:p,tokenUsage:s}}finally{this.currentAbortController=null,this.cancelling=!1,this.toolOrchestrator.clearOnceApprovals()}}cancelCurrentTurn(){this.currentAbortController&&(this.cancelling=!0,this.currentAbortController.abort())}async close(){if(this.closed)return;if(this.closed=!0,this.sessionStartEmitted||this.turnIndex>=0){await this.emitEvent("session_end",{meta:{durationMs:Date.now()-this.startedAt,tokens:this.sessionUsage}});for(let n of this.sinks)if(n.flush)try{await n.flush()}catch(o){console.error(`History flush failed: ${o.message}`)}}this.tokenCounter.dispose(),this.toolOrchestrator.dispose(),this.deps.dispose&&await this.deps.dispose()}async emitEvent(e,n){if(!this.sinks.length)return;let o=Xn({sessionId:this.id,type:e,turn:n.turn,step:n.step,content:n.content,role:n.role,meta:n.meta});await Fl(o,this.sinks)}};async function lt(t,e={}){let n=e.sessionId||cr(),o=await or(t,{...e,sessionId:n},n),r=await o.loadPrompt(),s=new Tn({...t,...o},{...e,sessionId:n,mode:e.mode??ur},r,o.tokenCounter,o.historyFilePath);return await s.init(),s}import{useCallback as X,useEffect as zt,useMemo as Dn,useRef as Tt,useState as J}from"react";import{readFile as Zu}from"fs/promises";import"path";import{randomUUID as _t}from"crypto";import{exec as Qu}from"child_process";import{promisify as ep}from"util";import{Box as ms,useApp as tp,Text as np}from"ink";import{Box as pr,Text as Vl}from"ink";import{memo as zl}from"react";import{jsx as mr,jsxs as Gl}from"react/jsx-runtime";var dr=zl(function({contextPercent:e=0}){let n=e>0?` ${e.toFixed(1)}%`:" 0.0%";return mr(pr,{justifyContent:"flex-end",children:mr(pr,{marginTop:8,children:Gl(Vl,{color:"gray",children:["context:",n]})})})});import{Box as Se,Static as Tc,Text as ue}from"ink";import{memo as _c}from"react";import xc from"os";import{Box as Kl,Text as fr}from"ink";import{memo as ql}from"react";import{jsx as Xl,jsxs as gr}from"react/jsx-runtime";var hr=ql(function({message:e}){return gr(Kl,{flexDirection:"column",gap:0,children:[gr(fr,{color:"cyan",children:["\u25CF ",e.title]}),Xl(fr,{color:"gray",children:e.content})]})});import{Box as fc,Text as gc}from"ink";import{memo as hc}from"react";import{Box as ct,Text as ce}from"ink";import{memo as ic}from"react";import{Box as _n,Text as G}from"ink";import{marked as Jl}from"marked";import{useMemo as yr,memo as Yl}from"react";import{jsx as oe,jsxs as Ke}from"react/jsx-runtime";var Zl="#2b2b2b";function $t(t){return t?[{type:"text",raw:t,text:t}]:[]}function Ql(t,e,n){switch(t.type){case"text":return t.tokens&&t.tokens.length>0?Ae(t.tokens,e,`${n}-text`):t.text;case"escape":return t.text;case"strong":return oe(G,{bold:!0,children:Ae(t.tokens,e,`${n}-strong`)},n);case"em":return oe(G,{italic:!0,children:Ae(t.tokens,e,`${n}-em`)},n);case"codespan":return oe(G,{color:e.codeColor,backgroundColor:Zl,children:t.text},n);case"del":return oe(G,{strikethrough:!0,children:Ae(t.tokens,e,`${n}-del`)},n);case"link":{let o=t.tokens&&t.tokens.length>0?Ae(t.tokens,e,`${n}-link`):t.text,r=t.href&&t.text&&t.text!==t.href?` (${t.href})`:"";return Ke(G,{underline:!0,color:e.linkColor,children:[o,r]},n)}case"image":{let o=t.text||"image";return Ke(G,{color:e.linkColor,children:["[",o,"](",t.href,")"]},n)}case"br":return`
|
|
55
|
-
|
|
56
|
-
`).map(e=>e.length>0?` ${e}`:"").join(`
|
|
57
|
-
`).trimEnd()}function nc(t){let e=t.header.map(r=>r.text).join(" | "),n=t.header.map(()=>"---").join(" | "),o=t.rows.map(r=>r.map(s=>s.text).join(" | "));return[e,n,...o].join(`
|
|
58
|
-
`)}function oc(t){return t.type==="table"&&"header"in t&&"rows"in t&&"align"in t}function rc(t,e,n){switch(t.type){case"space":case"def":return null;case"heading":return oe(G,{bold:!0,color:e.textColor,children:Ae(t.tokens,e,`${n}-heading`)},n);case"paragraph":{let o=t.tokens??$t(t.text);return oe(G,{color:e.textColor,children:Ae(o,e,`${n}-para`)},n)}case"text":{let o=t.tokens??$t(t.text);return oe(G,{color:e.textColor,children:Ae(o,e,`${n}-text`)},n)}case"code":{let o=tc(t.text);return oe(G,{color:e.codeColor,children:o},n)}case"list":{let o=typeof t.start=="number"?t.start:1;return oe(_n,{flexDirection:"column",children:t.items.map((r,s)=>{let i=t.ordered?`${o+s}.`:"-",a=r.task?r.checked?"[x] ":"[ ] ":"",l=ec(r);return Ke(_n,{children:[Ke(G,{color:e.textColor,children:[i," "]}),Ke(G,{color:e.textColor,children:[a,Ae(l,e,`${n}-item-${s}`)]})]},`${n}-item-${s}`)})},n)}case"blockquote":return Ke(G,{color:"gray",dimColor:!0,children:["> ",t.text.trim()]},n);case"hr":return oe(G,{color:"gray",children:"---"},n);case"table":return oc(t)?oe(G,{color:e.textColor,children:nc(t)},n):oe(G,{color:e.textColor,children:"text"in t?t.text:t.raw},n);case"html":return oe(G,{color:e.textColor,children:t.text},n);default:return oe(G,{color:e.textColor,children:"text"in t?t.text:t.raw},n)}}function sc(t,e,n){return t.flatMap((o,r)=>{let s=rc(o,e,`${n}-${r}`);return s?[s]:[]})}var qe=Yl(function({text:e,tone:n="normal"}){let o=yr(()=>({textColor:n==="muted"?"gray":void 0,codeColor:n==="muted"?"gray":"cyan",linkColor:n==="muted"?"gray":"blue",muted:n==="muted"}),[n]),r=yr(()=>{let s=Jl.lexer(e,{gfm:!0,breaks:!0});return sc(s,o,"markdown")},[e,o]);return oe(_n,{flexDirection:"column",gap:1,children:r})});import{Fragment as xn,jsx as Q,jsxs as Xe}from"react/jsx-runtime";function Tr(t){if(!t)return;if(typeof t=="string")return t.length>50?t.slice(0,47)+"...":t;if(typeof t!="object"||Array.isArray(t))return;let e=t,n=["cmd","dir_path","file_path","path","file","filename","url","command","pattern","include","query","content","cwd","dir"];for(let o of n)if(e[o]){let r=String(e[o]);return r.length>50?r.slice(0,47)+"...":r}for(let[o,r]of Object.entries(e))if(typeof r=="string"&&o!=="description")return r.length>50?r.slice(0,47)+"...":r}function ac(t,e){let n=t.step,o=e.step;return!(n.index!==o.index||n.assistantText!==o.assistantText||n.thinking!==o.thinking||n.action?.tool!==o.action?.tool||JSON.stringify(n.action?.input)!==JSON.stringify(o.action?.input)||JSON.stringify(n.parallelActions)!==JSON.stringify(o.parallelActions)||n.toolStatus!==o.toolStatus)}var _r=ic(function({step:e}){let n=e.action?.tool,o=e.action?.input,r=Tr(o),s=e.parallelActions??[],i=s.length>1;return Xe(ct,{flexDirection:"column",gap:0,children:[e.thinking&&Xe(ct,{children:[Q(ce,{color:"gray",children:"\u25CF "}),Q(ct,{flexDirection:"column",flexGrow:1,children:Q(qe,{text:e.thinking,tone:"muted"})})]}),i&&Q(xn,{children:s.map((a,l)=>{let c=Tr(a.input);return Xe(ct,{children:[Q(ce,{color:"green",children:"\u25CF "}),Q(ce,{color:"gray",children:"Used "}),Q(ce,{color:"cyan",children:a.tool}),c&&Xe(xn,{children:[Q(ce,{color:"gray",children:" ("}),Q(ce,{color:"cyan",children:c}),Q(ce,{color:"gray",children:")"})]})]},l)})}),!i&&n&&Xe(ct,{children:[Q(ce,{color:"green",children:"\u25CF "}),Q(ce,{color:"gray",children:"Used "}),Q(ce,{color:"cyan",children:n}),r&&Xe(xn,{children:[Q(ce,{color:"gray",children:" ("}),Q(ce,{color:"cyan",children:r}),Q(ce,{color:"gray",children:")"})]})]})]})},ac);import{Box as lc,Text as xr}from"ink";import{memo as cc}from"react";import{jsx as Sr,jsxs as uc}from"react/jsx-runtime";var vr=cc(function({text:e}){return uc(lc,{paddingY:1,children:[Sr(xr,{color:"gray",children:"\u203A "}),Sr(xr,{color:"white",children:e})]})});import{Box as ut,Text as He}from"ink";import{memo as Sn,useMemo as pc}from"react";import{Fragment as dc,jsx as de,jsxs as Lt}from"react/jsx-runtime";function mc(t){let e=/<\s*(think|thinking)\s*>([\s\S]*?)<\/\s*\1\s*>/gi,n=[],o,r=0,s=[];for(;(o=e.exec(t))!==null;){s.push({start:o.index,end:e.lastIndex});let a=o[2]?.trim();a&&n.push(a)}if(s.length===0)return{content:t,thinking:null};let i="";r=0;for(let{start:a,end:l}of s)i+=t.slice(r,a),r=l;return i+=t.slice(r),i=i.replace(/\n{3,}/g,`
|
|
53
|
+
`):o||void 0}import{randomUUID as Oo}from"crypto";function Wa(){return{onTurnStart:[],onAction:[],onObservation:[],onFinal:[],onApprovalRequest:[],onApprovalResponse:[]}}function ko(t,e){e&&(e.onTurnStart&&t.onTurnStart.push(e.onTurnStart),e.onAction&&t.onAction.push(e.onAction),e.onObservation&&t.onObservation.push(e.onObservation),e.onFinal&&t.onFinal.push(e.onFinal),e.onApprovalRequest&&t.onApprovalRequest.push(e.onApprovalRequest),e.onApprovalResponse&&t.onApprovalResponse.push(e.onApprovalResponse))}function Mo(t){let e=Wa();if(ko(e,t.hooks),Array.isArray(t.middlewares))for(let n of t.middlewares)ko(e,n);return e}async function J(t,e,n){let o=t[e];if(o.length)for(let s of o)try{await s(n)}catch(r){console.warn(`Hook ${e} failed: ${r.message}`)}}function Ne(t){return t.map(e=>e.role==="assistant"&&e.tool_calls?.length?{...e,tool_calls:e.tool_calls.map(n=>({...n,function:{...n.function}}))}:{...e})}var Lo="interactive",za=12e4,Po="success";function Ro(){return{prompt:0,completion:0,total:0}}function Io(t,e){if(!e)return;let n=e.prompt??0,o=e.completion??0,s=e.total??n+o;t.prompt+=n,t.completion+=o,t.total+=s}function qa(t){let e=t.content.filter(o=>o.type==="text"),n=t.content.filter(o=>o.type==="tool_use");return{textContent:e.map(o=>o.text).join(`
|
|
54
|
+
`),toolUseBlocks:n.map(o=>({id:o.id,name:o.name,input:o.input})),stopReason:t.stop_reason,usage:t.usage}}async function Ka(t,e){for(let n of e)try{await n.append(t)}catch(o){console.error(`Failed to write history event: ${o.message}`)}}function Va(t){return t instanceof Error&&t.name==="AbortError"}function Ge(t){return t===null||typeof t!="object"?JSON.stringify(t)??"null":Array.isArray(t)?`[${t.map(n=>Ge(n)).join(",")}]`:`{${Object.entries(t).sort(([n],[o])=>n.localeCompare(o)).map(([n,o])=>`${JSON.stringify(n)}:${Ge(o)}`).join(",")}}`}function Ga(t){return t.map(e=>({id:e.id,type:"function",function:{name:e.name,arguments:Ge(e.input)}}))}function Xa(t,e){let n=t.trim();if(!n)return null;let o=[n],s=n.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/i);s?.[1]&&o.push(s[1].trim());for(let r of o)if(!(!r.startsWith("{")||!r.endsWith("}")))try{let i=JSON.parse(r);if(!i||typeof i!="object"||Array.isArray(i))continue;let l=i,a=typeof l.tool=="string"?l.tool.trim():"";if(!a||!Object.prototype.hasOwnProperty.call(e,a))continue;return{tool:a,input:l.input??{}}}catch{}return null}var Jt=class{constructor(e,n,o,s,r){this.deps=e;this.options=n;this.id=n.sessionId||Oo(),this.mode=n.mode||Lo,this.history=[{role:"system",content:o}],this.tokenCounter=s,this.sinks=e.historySinks??[],this.hooks=Mo(e),this.historyFilePath=r,this.toolOrchestrator=To({tools:e.tools,approval:{dangerous:n.dangerous??!1,mode:"auto"}})}id;mode;history;historyFilePath;turnIndex=0;tokenCounter;sinks;sessionUsage=Ro();startedAt=Date.now();hooks;closed=!1;sessionStartEmitted=!1;currentAbortController=null;cancelling=!1;lastActionSignature=null;repeatedActionCount=0;toolOrchestrator;async init(){}resetActionRepetition(){this.lastActionSignature=null,this.repeatedActionCount=0}maybeWarnRepeatedAction(e,n){let o=`${e}:${Ge(n)}`;if(this.lastActionSignature===o?this.repeatedActionCount+=1:(this.lastActionSignature=o,this.repeatedActionCount=1),this.repeatedActionCount===3){let s=Ge(n).slice(0,200),r=`\u7CFB\u7EDF\u63D0\u9192\uFF1A\u4F60\u5DF2\u8FDE\u7EED3\u6B21\u8C03\u7528\u540C\u4E00\u5DE5\u5177\u300C${e}\u300D\u4E14\u53C2\u6570\u76F8\u540C\uFF08${s}${s.length>=200?"\u2026":""}\uFF09\u3002\u8BF7\u786E\u8BA4\u662F\u5426\u9677\u5165\u5FAA\u73AF\uFF0C\u5FC5\u8981\u65F6\u76F4\u63A5\u7ED9\u51FA\u6700\u7EC8\u56DE\u7B54\u6216\u8C03\u6574\u53C2\u6570\u3002`;this.history.push({role:"system",content:r})}}buildToolApprovalHooks(e,n){return{onApprovalRequest:async o=>{await J(this.hooks,"onApprovalRequest",{sessionId:this.id,turn:e,step:n,request:o})},requestApproval:async o=>this.deps.requestApproval?this.deps.requestApproval(o):"deny",onApprovalResponse:async({fingerprint:o,decision:s})=>{await J(this.hooks,"onApprovalResponse",{sessionId:this.id,turn:e,step:n,fingerprint:o,decision:s})}}}async executeToolAction(e,n,o,s,r){return this.toolOrchestrator.executeAction({id:e,name:n,input:o},this.buildToolApprovalHooks(s,r))}async runTurn(e){let n=new AbortController;this.currentAbortController=n,this.cancelling=!1,this.turnIndex+=1;let o=this.turnIndex,s=[],r=Ro(),i=Date.now(),l=this.options.maxPromptTokens??za;if(!this.sessionStartEmitted){let a=this.history[0]?.role==="system"?this.history[0].content:void 0;await this.emitEvent("session_start",{content:a,role:a?"system":void 0,meta:{mode:this.mode,cwd:process.cwd(),tokenizer:this.tokenCounter.model,warnPromptTokens:this.options.warnPromptTokens,maxPromptTokens:l}}),this.sessionStartEmitted=!0}this.history.push({role:"user",content:e});try{let a=this.tokenCounter.countMessages(this.history);await this.emitEvent("turn_start",{turn:o,content:e,meta:{tokens:{prompt:a}}}),await J(this.hooks,"onTurnStart",{sessionId:this.id,turn:o,input:e,promptTokens:a,history:Ne(this.history)});let c="",u="ok",m,d=0,h=null,w=-1;for(let f=0;;f++){let I=this.tokenCounter.countMessages(this.history);if(I>l){let b=`Context tokens (${I}) exceed the limit. Please shorten the input or restart the session.`;this.history.push({role:"assistant",content:b}),u="prompt_limit",c=b,m=b,await this.emitEvent("final",{turn:o,step:f,content:b,role:"assistant",meta:{tokens:{prompt:I}}}),await J(this.hooks,"onFinal",{sessionId:this.id,turn:o,step:f,finalText:b,status:u,errorMessage:m,turnUsage:{...r},steps:s});break}this.options.warnPromptTokens&&I>this.options.warnPromptTokens&&console.warn(`Prompt tokens are near the limit: ${I}`);let S="",_=[],U,N;try{let b=await this.deps.callLLM(this.history,V=>this.deps.onAssistantStep?.(V,f),{signal:n.signal}),R=qa(b);S=R.textContent,_=R.toolUseBlocks,N=R.stopReason,U=R.usage,S.trim().length>0&&(h=S,w=f)}catch(b){if(this.cancelling&&Va(b)){u="cancelled",c="",m="Turn cancelled",await this.emitEvent("final",{turn:o,step:f,content:"",role:"assistant",meta:{cancelled:!0}}),await J(this.hooks,"onFinal",{sessionId:this.id,turn:o,step:f,finalText:c,status:u,errorMessage:m,turnUsage:{...r},steps:s});break}let R=`LLM call failed: ${b.message}`;this.history.push({role:"assistant",content:R}),u="error",c=R,m=R,await this.emitEvent("final",{turn:o,content:R,role:"assistant"}),await J(this.hooks,"onFinal",{sessionId:this.id,turn:o,step:f,finalText:c,status:u,errorMessage:m,turnUsage:{...r},steps:s});break}this.deps.onAssistantStep?.(S,f);let M=_.length===0&&S?Xa(S,this.deps.tools):null,y,E=null;if(_.length>0){let b=_[0];if(b){let R=S?bo([S]):void 0;y={action:{tool:b.name,input:b.input},thinking:R},E={role:"assistant",content:S,tool_calls:Ga(_)}}else y={}}else S?(y={final:S},E={role:"assistant",content:S}):y={};let ie=this.tokenCounter.countText(S),D=U?.prompt??I,ne=U?.completion??ie,q=U?.total??D+ne,B={prompt:D,completion:ne,total:q};if(Io(r,B),Io(this.sessionUsage,B),s.push({index:f,assistantText:S,parsed:y,tokenUsage:B}),await this.emitEvent("assistant",{turn:o,step:f,content:S,role:"assistant",meta:{tokens:B,protocol_violation:!!M,protocol_violation_count:M?d+1:d||void 0}}),M){d+=1;let b=`Model protocol error: returned plain-text tool JSON for "${M.tool}" ${d} times. Structured tool calls are required.`;u="error",c=b,m=b,this.history.push({role:"assistant",content:b}),await this.emitEvent("final",{turn:o,step:f,content:b,role:"assistant",meta:{error_type:"model_protocol_error",tool:M.tool,protocol_violation:!0,protocol_violation_count:d,tokens:B}}),await J(this.hooks,"onFinal",{sessionId:this.id,turn:o,step:f,finalText:c,status:u,errorMessage:m,tokenUsage:B,turnUsage:{...r},steps:s});break}if(E&&this.history.push(E),_.length>1){for(let A of _)this.maybeWarnRepeatedAction(A.name,A.input);await this.emitEvent("action",{turn:o,step:f,meta:{tools:_.map(A=>A.name),action_ids:_.map(A=>A.id),action_id:_[0]?.id,parallel:!0,phase:"dispatch",thinking:y.thinking,toolBlocks:_.map(A=>({id:A.id,name:A.name,input:A.input}))}});let b=_[0];b&&await J(this.hooks,"onAction",{sessionId:this.id,turn:o,step:f,action:{tool:b.name,input:b.input},parallelActions:_.map(A=>({tool:A.name,input:A.input})),thinking:y.thinking,history:Ne(this.history)});let R=_.every(A=>!!this.deps.tools[A.name]?.supportsParallelToolCalls),V=_.some(A=>!!this.deps.tools[A.name]?.isMutating),X=R&&!V?"parallel":"sequential",K=await this.toolOrchestrator.executeActions(_.map(A=>({id:A.id,name:A.name,input:A.input})),{...this.buildToolApprovalHooks(o,f),executionMode:X,failurePolicy:"fail_fast"});for(let[A,H]of K.results.entries())this.history.push({role:"tool",content:H.observation,tool_call_id:H.actionId,name:H.tool}),await this.emitEvent("observation",{turn:o,step:f,content:H.observation,meta:{tool:H.tool,index:A,action_id:H.actionId,phase:"result",status:H.status,error_type:H.errorType,duration_ms:H.durationMs,execution_mode:X}});let Re=K.combinedObservation,de=K.results.map(A=>A.status),Ie=de.find(A=>A!==Po)??Po,W=s[s.length-1];if(W&&(W.observation=Re),await J(this.hooks,"onObservation",{sessionId:this.id,turn:o,step:f,tool:_.map(A=>A.name).join(", "),observation:Re,resultStatus:Ie,parallelResultStatuses:de,history:Ne(this.history)}),K.hasRejection){let A=K.results.find(H=>H.rejected);u="cancelled",c="\u7528\u6237\u62D2\u7EDD\u4E86\u5DE5\u5177\u6267\u884C\uFF0C\u5DF2\u505C\u6B62\u5F53\u524D\u64CD\u4F5C\u3002",await this.emitEvent("final",{turn:o,step:f,content:c,role:"assistant",meta:{rejected:!0,phase:"result",action_id:A?.actionId,error_type:A?.errorType??"approval_denied",duration_ms:A?.durationMs}}),await J(this.hooks,"onFinal",{sessionId:this.id,turn:o,step:f,finalText:c,status:u,tokenUsage:B,turnUsage:{...r},steps:s});break}continue}else if(y.action){this.maybeWarnRepeatedAction(y.action.tool,y.action.input);let b=_[0]?.id??`${o}:${f}:single:${y.action.tool}`;await this.emitEvent("action",{turn:o,step:f,meta:{tool:y.action.tool,input:y.action.input,action_id:b,phase:"dispatch",thinking:y.thinking}}),await J(this.hooks,"onAction",{sessionId:this.id,turn:o,step:f,action:y.action,thinking:y.thinking,history:Ne(this.history)});let R=await this.executeToolAction(b,y.action.tool,y.action.input,o,f);if(R.rejected){u="cancelled",c="\u7528\u6237\u62D2\u7EDD\u4E86\u5DE5\u5177\u6267\u884C\uFF0C\u5DF2\u505C\u6B62\u5F53\u524D\u64CD\u4F5C\u3002",await this.emitEvent("final",{turn:o,step:f,content:c,role:"assistant",meta:{rejected:!0,phase:"result",action_id:R.actionId,error_type:R.errorType??"approval_denied",duration_ms:R.durationMs}}),await J(this.hooks,"onFinal",{sessionId:this.id,turn:o,step:f,finalText:c,status:u,tokenUsage:B,turnUsage:{...r},steps:s});break}let V=R.observation;this.history.push({role:"tool",content:V,tool_call_id:R.actionId,name:y.action.tool});let X=s[s.length-1];X&&(X.observation=V),await this.emitEvent("observation",{turn:o,step:f,content:V,meta:{tool:y.action.tool,action_id:R.actionId,phase:"result",status:R.status,error_type:R.errorType,duration_ms:R.durationMs}}),await J(this.hooks,"onObservation",{sessionId:this.id,turn:o,step:f,tool:y.action.tool,observation:V,resultStatus:R.status,history:Ne(this.history)});continue}if(N==="end_turn"||y.final){this.resetActionRepetition();let b=N==="end_turn"&&!y.final&&S.trim().length===0&&!!h&&w===f-1;c=b?h??"":y.final||S,y.final&&(y.final=c),await this.emitEvent("final",{turn:o,step:f,content:c,role:"assistant",meta:{tokens:B,fallback_from_previous_text:b||void 0}}),await J(this.hooks,"onFinal",{sessionId:this.id,turn:o,step:f,finalText:c,status:u,tokenUsage:B,turnUsage:{...r},steps:s});break}this.resetActionRepetition();break}return!c&&u!=="cancelled"&&(u==="ok"&&(u="error"),c="Unable to produce a final answer. Please retry or adjust the request.",m=c,this.history.push({role:"assistant",content:c}),await this.emitEvent("final",{turn:o,content:c,role:"assistant"}),await J(this.hooks,"onFinal",{sessionId:this.id,turn:o,finalText:c,status:u,errorMessage:m,turnUsage:{...r},steps:s})),await this.emitEvent("turn_end",{turn:o,meta:{status:u,stepCount:s.length,durationMs:Date.now()-i,tokens:r,protocol_violation_count:d||void 0}}),{finalText:c,steps:s,status:u,errorMessage:m,tokenUsage:r}}finally{this.currentAbortController=null,this.cancelling=!1,this.toolOrchestrator.clearOnceApprovals()}}cancelCurrentTurn(){this.currentAbortController&&(this.cancelling=!0,this.currentAbortController.abort())}async close(){if(this.closed)return;if(this.closed=!0,this.sessionStartEmitted||this.turnIndex>=0){await this.emitEvent("session_end",{meta:{durationMs:Date.now()-this.startedAt,tokens:this.sessionUsage}});for(let n of this.sinks)if(n.flush)try{await n.flush()}catch(o){console.error(`History flush failed: ${o.message}`)}}this.tokenCounter.dispose(),this.toolOrchestrator.dispose(),this.deps.dispose&&await this.deps.dispose()}async emitEvent(e,n){if(!this.sinks.length)return;let o=fn({sessionId:this.id,type:e,turn:n.turn,step:n.step,content:n.content,role:n.role,meta:n.meta});await Ka(o,this.sinks)}};async function dt(t,e={}){let n=e.sessionId||Oo(),o=await wo(t,{...e,sessionId:n},n),s=await o.loadPrompt(),r=new Jt({...t,...o},{...e,sessionId:n,mode:e.mode??Lo},s,o.tokenCounter,o.historyFilePath);return await r.init(),r}import{randomUUID as nt}from"crypto";import{readFile as sc}from"fs/promises";import{useCallback as Z,useEffect as kt,useMemo as fr,useReducer as ic,useRef as Mt,useState as te}from"react";import{Box as gr,Text as ac,useApp as lc}from"ink";import{memo as Za,useMemo as Qa}from"react";import{Box as jo,Static as el,Text as gt}from"ink";import{Box as xe,Text as G}from"ink";var _e={PENDING:"pending",EXECUTING:"executing",SUCCESS:"success",ERROR:"error"};var Ja="success";function Yt(t){return t?t===Ja?_e.SUCCESS:_e.ERROR:_e.SUCCESS}function $o(t){if(t?.length)return t.map(e=>Yt(e))}function No(t,e){return!e||e<=0||!t||t<=0?0:Math.min(100,t/e*100)}function Do(t){return t?`tokens: ${t.total} (prompt ${t.prompt} / completion ${t.completion})`:""}function Xe(t,e=80){return t.length<=e?t:`${t.slice(0,Math.max(0,e-3))}...`}function Uo(t){if(typeof t=="string")return t;try{return JSON.stringify(t)??String(t)}catch{return String(t)}}import{jsx as ee,jsxs as se}from"react/jsx-runtime";function Ho(t){return t===_e.ERROR?"red":t===_e.EXECUTING?"yellow":"green"}function ft(t){if(t==null)return null;if(typeof t=="string")return Xe(t,70);if(typeof t!="object"||Array.isArray(t))return Xe(String(t),70);let e=t,n=["cmd","path","file_path","dir_path","query","pattern","url","content"];for(let o of n){let s=e[o];if(!(s==null||s===""))return Xe(String(s),70)}return Xe(Uo(e),70)}function Fo({message:t}){let e=t.tone==="error"?"red":t.tone==="warning"?"yellow":"cyan";return se(xe,{flexDirection:"column",children:[se(G,{color:e,children:["\u25CF ",t.title]}),ee(G,{color:"gray",children:t.content})]})}function Ya({step:t}){let e=!!(t.parallelActions&&t.parallelActions.length>1);return se(xe,{flexDirection:"column",children:[t.thinking?se(xe,{children:[ee(G,{color:"gray",children:"\u25CF "}),ee(G,{color:"gray",children:t.thinking})]}):null,e?t.parallelActions?.map((n,o)=>se(xe,{children:[se(G,{color:Ho(t.parallelToolStatuses?.[o]??t.toolStatus),children:["\u25CF"," "]}),ee(G,{color:"gray",children:"Used "}),ee(G,{color:"cyan",children:n.tool}),ft(n.input)?se(G,{color:"gray",children:[" (",ft(n.input),")"]}):null]},`${n.tool}-${o}`)):null,!e&&t.action?se(xe,{children:[ee(G,{color:Ho(t.toolStatus),children:"\u25CF "}),ee(G,{color:"gray",children:"Used "}),ee(G,{color:"cyan",children:t.action.tool}),ft(t.action.input)?se(G,{color:"gray",children:[" (",ft(t.action.input),")"]}):null]}):null]})}function Zt({turn:t}){return se(xe,{flexDirection:"column",children:[se(xe,{children:[ee(G,{color:"gray",children:"\u203A "}),ee(G,{children:t.userInput})]}),t.steps.map(e=>ee(Ya,{step:e},`${t.index}-${e.index}`)),t.finalText?ee(xe,{marginTop:0,children:ee(G,{children:t.finalText})}):null,t.status&&t.status!=="ok"?se(G,{color:"red",children:["Status: ",t.status]}):null,t.errorMessage?ee(G,{color:"red",children:t.errorMessage}):null]})}import{jsx as Je,jsxs as Ye}from"react/jsx-runtime";var Bo=Za(function({header:e,systemMessages:n,turns:o,historicalTurns:s}){let r=Qa(()=>[...s,...o],[s,o]),i=r.length>0?r[r.length-1]:void 0,l=i&&!!(i.finalText||i.status&&i.status!=="ok"),a=l?r:r.slice(0,-1),c=l?void 0:i,u=[{type:"header",data:e}],m=[...n.map(d=>({type:"system",sequence:d.sequence,data:d})),...a.map(d=>({type:"turn",sequence:d.sequence??0,data:d}))].sort((d,h)=>d.sequence-h.sequence);for(let d of m)u.push(d);return Ye(jo,{flexDirection:"column",children:[Je(el,{items:u,children:d=>d.type==="header"?Ye(jo,{borderStyle:"round",borderColor:"blue",paddingX:1,flexDirection:"column",children:[Je(gt,{bold:!0,children:"Memo CLI"}),Ye(gt,{color:"gray",children:[d.data.providerName," / ",d.data.model," \u2022 v",d.data.version]}),Ye(gt,{color:"gray",children:["cwd: ",d.data.cwd]}),Ye(gt,{color:"gray",children:["mcp: ",d.data.mcpNames.join(", ")||"none"]})]},"header"):d.type==="system"?Je(Fo,{message:d.data},d.data.id):Je(Zt,{turn:d.data},`turn-${d.data.index}`)}),c?Je(Zt,{turn:c}):null]})});import{useCallback as Yo,useEffect as Qt,useMemo as Zo,useRef as en,useState as Ce}from"react";import{Box as xt,Text as Ue,useInput as Ml}from"ink";var De=[8e4,12e4,15e4,2e5],Wo=De[1],$={HELP:"help",EXIT:"exit",NEW:"new",RESUME:"resume",MODELS:"models",CONTEXT:"context",MCP:"mcp",INIT:"init"};function ce(t){return`/${t}`}var zo="exit";var ht=[{name:$.HELP,description:"Show command and shortcut help"},{name:$.EXIT,description:"Exit current session"},{name:$.NEW,description:"Start a fresh session"},{name:$.RESUME,description:"List and load session history"},{name:$.MODELS,description:"List or switch configured models"},{name:$.CONTEXT,description:"Set context window (80k/120k/150k/200k)"},{name:$.MCP,description:"Show configured MCP servers"},{name:$.INIT,description:"Generate AGENTS.md with agent instructions"}];function tl(){let t=ht.reduce((n,o)=>Math.max(n,o.name.length),0);return["Available commands:",...ht.map(n=>` ${ce(n.name).padEnd(t+3)} ${n.description}`)," exit Exit session (without slash)","","Shortcuts:"," Enter Send message"," Shift+Enter New line"," Up/Down Browse local input history"," Tab Accept active suggestion"," Ctrl+L Clear screen and start new session"," Esc Esc Interrupt running turn / clear input"].join(`
|
|
55
|
+
`)}function nl(t){if(!t)return null;let n=t.toLowerCase().replace(/,/g,"").match(/^(\d+)(k)?$/);if(!n)return null;let o=Number(n[1]);return Number.isFinite(o)?o*(n[2]?1e3:1):null}function qo(t,e){let[n,...o]=t.trim().slice(1).split(/\s+/);switch((n??"").toLowerCase()){case $.HELP:return{kind:"message",title:"Help",content:tl()};case $.EXIT:return{kind:"exit"};case $.NEW:return{kind:"new"};case $.RESUME:return{kind:"message",title:"Resume",content:'Type "resume" followed by keywords to load local session history.'};case $.MODELS:{if(!e.providers.length)return{kind:"message",title:"Models",content:`No providers configured. Check ${e.configPath}`};let r=o.join(" ").trim(),i=e.providers.find(c=>c.name===r)??e.providers.find(c=>c.model===r);if(i)return{kind:"switch_model",provider:i};let l=e.providers.map(c=>{let u=c.name===e.providerName&&c.model===e.model?" (current)":"",m=c.base_url?` @ ${c.base_url}`:"";return`- ${c.name}: ${c.model}${m}${u}`});return{kind:"message",title:"Models",content:`${r?`Not found: ${r}
|
|
59
56
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
`):null}}var Cr=Sn(function({text:e,isThinking:n=!1}){let{content:o,thinking:r}=pc(()=>mc(e),[e]);return n?de(ut,{flexDirection:"column",flexGrow:1,children:de(qe,{text:e,tone:"muted"})}):Lt(ut,{flexDirection:"column",flexGrow:1,gap:1,children:[r&&de(ut,{flexDirection:"column",paddingLeft:2,children:de(qe,{text:r,tone:"muted"})}),de(qe,{text:o,tone:"normal"})]})}),pg=Sn(function({text:e}){return de(ut,{children:Lt(He,{color:"gray",children:["\u2022 ",e]})})}),mg=Sn(function({toolName:e,fileName:n}){return Lt(ut,{children:[de(He,{color:"green",children:"\u25CF "}),de(He,{color:"gray",children:"Used "}),de(He,{color:"cyan",children:e}),n&&Lt(dc,{children:[de(He,{color:"gray",children:" ("}),de(He,{color:"cyan",children:n}),de(He,{color:"gray",children:")"})]})]})});import{jsx as vn,jsxs as wr}from"react/jsx-runtime";function yc(t,e){let n=t.turn,o=e.turn;if(n.index!==o.index||n.userInput!==o.userInput||n.finalText!==o.finalText||n.status!==o.status||n.steps.length!==o.steps.length||n.tokenUsage?.total!==o.tokenUsage?.total)return!1;for(let r=0;r<n.steps.length;r++){let s=n.steps[r],i=o.steps[r];if(!s||!i||s.assistantText!==i.assistantText||s.thinking!==i.thinking||s.action?.tool!==i.action?.tool)return!1}return!0}var Cn=hc(function({turn:e}){let n=e.finalText?.trim()??"",o=n.length>0;return wr(fc,{flexDirection:"column",children:[vn(vr,{text:e.userInput}),e.steps.map(r=>vn(_r,{step:r},`step-${e.index}-${r.index}`)),o?vn(Cr,{text:n,isThinking:!1}):null,e.status&&e.status!=="ok"?wr(gc,{color:"red",children:["Status: ",e.status]}):null]})},yc);import{jsx as ee,jsxs as _e}from"react/jsx-runtime";function Sc(t){let e=xc.homedir();return e&&t.startsWith(e)?`~${t.slice(e.length)}`:t}function vc(t){return t.length>16?`${t.slice(0,8)}...${t.slice(-4)}`:t}function Cc(t,e){if(t.headerInfo?.sessionId!==e.headerInfo?.sessionId||t.headerInfo?.model!==e.headerInfo?.model||t.headerInfo?.providerName!==e.headerInfo?.providerName||t.headerInfo?.cwd!==e.headerInfo?.cwd||t.headerInfo?.version!==e.headerInfo?.version||t.headerInfo?.mcpNames?.length!==e.headerInfo?.mcpNames?.length)return!1;if(t.headerInfo?.mcpNames&&e.headerInfo?.mcpNames){let n=t.headerInfo.mcpNames,o=e.headerInfo.mcpNames;for(let r=0;r<n.length;r++)if(n[r]!==o[r])return!1}if(t.systemMessages.length!==e.systemMessages.length)return!1;for(let n=0;n<t.systemMessages.length;n++)if(t.systemMessages[n]?.id!==e.systemMessages[n]?.id)return!1;if(t.turns.length!==e.turns.length)return!1;for(let n=0;n<t.turns.length;n++)if(t.turns[n]!==e.turns[n])return!1;return!0}var Er=_c(function({systemMessages:e,turns:n,headerInfo:o}){let r=n.length>0?n[n.length-1]:void 0,s=r&&(r.finalText||r.status&&r.status!=="ok"),i=s?n:n.slice(0,-1),a=s?void 0:r,l=[];o&&l.push({type:"header",data:o});let c=[];for(let u of e)c.push({sequence:u.sequence,item:{type:"system",data:u}});for(let u of i){let p=u.sequence??0;c.push({sequence:p,item:{type:"turn",data:u}})}c.sort((u,p)=>u.sequence-p.sequence);for(let u of c)l.push(u.item);return _e(Se,{flexDirection:"column",gap:0,children:[ee(Tc,{items:l,children:u=>{if(u.type==="header"&&u.data){let p=u.data;return _e(Se,{borderStyle:"round",borderColor:"blueBright",paddingX:2,paddingY:1,flexDirection:"column",gap:1,children:[ee(Se,{gap:1,alignItems:"center",children:_e(Se,{flexDirection:"column",children:[ee(ue,{bold:!0,children:"Welcome to Memo Code CLI!"}),ee(ue,{color:"gray",children:"Send /help for help information."})]})}),_e(Se,{flexDirection:"column",gap:0,children:[_e(Se,{children:[ee(ue,{color:"gray",children:"Directory: "}),ee(ue,{color:"cyan",children:Sc(p.cwd)})]}),_e(Se,{children:[ee(ue,{color:"gray",children:"Session: "}),ee(ue,{color:"cyan",children:vc(p.sessionId)})]}),_e(Se,{children:[ee(ue,{color:"gray",children:"Model: "}),ee(ue,{color:"cyan",children:p.model}),_e(ue,{color:"gray",children:[" ","(powered by ",p.providerName,")"]})]}),_e(Se,{children:[ee(ue,{color:"gray",children:"Version: "}),_e(ue,{color:"cyan",children:["v",p.version]})]}),_e(Se,{children:[ee(ue,{color:"gray",children:"MCP: "}),ee(ue,{color:"cyan",children:p.mcpNames.length>0?p.mcpNames.join(", "):"none"})]})]})]},"header")}return u.type==="system"?ee(hr,{message:u.data},u.data.id):u.type==="turn"?ee(Cn,{turn:u.data},`turn-${u.data.index}`):null}}),a&&ee(Cn,{turn:a},`turn-live-${a.index}`)]})},Cc);import{useCallback as Yr,useEffect as In,useMemo as mu,useRef as $n,useState as Le}from"react";import{readFile as du,readdir as fu,stat as gu}from"fs/promises";import{basename as hu,join as jt,resolve as ft}from"path";import{Box as Bt,Text as Fe,useInput as yu}from"ink";var Nr=Kn(Lr(),1);import{readFile as Vc,readdir as zc}from"fs/promises";import{join as Or,relative as Gc,sep as Kc}from"path";var qc=6,Xc=2500,Dr=25,Jc=[".git",".svn",".hg","node_modules","dist","build",".next",".turbo",".cache",".output","coverage","tmp","temp","logs","*.log"],Ut=new Map;function Yc(t){return t.split(Kc).join("/")}function Zc(t,e){return JSON.stringify({maxDepth:t.maxDepth,maxEntries:t.maxEntries,respectGitIgnore:t.respectGitIgnore,ignoreGlobs:t.ignoreGlobs,gitignore:e})}function Qc(t){return{maxDepth:typeof t.maxDepth=="number"?Math.max(1,t.maxDepth):qc,maxEntries:typeof t.maxEntries=="number"?Math.max(100,t.maxEntries):Xc,limit:typeof t.limit=="number"?Math.max(1,t.limit):Dr,respectGitIgnore:t.respectGitIgnore!==!1,ignoreGlobs:t.ignoreGlobs?.length?t.ignoreGlobs:[]}}async function eu(t,e){if(!e)return"";try{return await Vc(Or(t,".gitignore"),"utf8")}catch{}return""}async function tu(t,e){let n=await eu(e,t.respectGitIgnore),o=(0,Nr.default)();o.add(Jc),t.ignoreGlobs.length&&o.add(t.ignoreGlobs),n.trim()&&o.add(n);let r=Zc(t,n);return Object.assign(o,{__memoSignature:r})}async function nu(t,e,n){let o=[],r=e.maxEntries,s=async(i,a)=>{if(o.length>=r)return;let l;try{l=await zc(i,{withFileTypes:!0})}catch{return}for(let c of l){if(o.length>=r)break;if(c.isSymbolicLink())continue;let u=Or(i,c.name),p=Gc(t,u);if(!p)continue;let T=Yc(p);if(n.ignores(T))continue;let m=T.split("/").filter(Boolean),S=m.map(v=>v.toLowerCase()),_=c.isDirectory();if(o.push({path:T,pathLower:T.toLowerCase(),segments:m,segmentsLower:S,depth:a,isDir:_}),o.length>=r)break;_&&a<e.maxDepth&&await s(u,a+1)}};return await s(t,0),o.sort((i,a)=>i.path.localeCompare(a.path)),{entries:o,signature:n.__memoSignature}}async function ou(t,e){let n=Qc(e),o=await tu(n,t),r=o.__memoSignature,s=Ut.get(t);if(s&&s.signature===r)return s.pending?s.pending:s.entries;let i=nu(t,n,o).then(a=>(Ut.set(t,{entries:a.entries,signature:a.signature}),a.entries)).catch(a=>{throw Ut.delete(t),a});return Ut.set(t,{entries:[],signature:r,pending:i}),i}function ru(t){return t.depth+(t.isDir?-.2:.2)}function su(t,e){if(!e.length)return ru(t);let n=t.depth,o=0;for(let r of e){let s=-1;for(let i=o;i<t.segmentsLower.length;i++){let a=t.segmentsLower[i];if(a.startsWith(r)){s=i,n+=(i-o)*1.5,n+=a.length-r.length;break}let l=a.indexOf(r);if(l!==-1){s=i,n+=(i-o)*2+l+2;break}}if(s===-1)return null;o=s+1}return t.isDir&&(n-=.5),n}function iu(t,e,n){let s=e.trim().replace(/\\/g,"/").split("/").filter(Boolean).map(a=>a.toLowerCase()),i=[];for(let a of t){let l=su(a,s);l!==null&&i.push({entry:a,score:l})}return i.sort((a,l)=>{let c=a.score-l.score;return c!==0?c:a.entry.path.localeCompare(l.entry.path)}),i.slice(0,n).map(({entry:a})=>({id:a.path,path:a.path,name:a.segments[a.segments.length-1]??a.path,parent:a.segments.length>1?a.segments.slice(0,-1).join("/"):void 0,isDir:a.isDir}))}async function Ur(t){let e=await ou(t.cwd,t),n=typeof t.limit=="number"?Math.max(1,t.limit):Dr;return iu(e,t.query,n)}import{mkdir as Lg,readFile as Og,writeFile as Ng}from"fs/promises";import{dirname as Ug}from"path";import{randomUUID as Fg}from"crypto";import{Box as mt,Text as Ze}from"ink";import{jsx as Pe,jsxs as Fr}from"react/jsx-runtime";var au="#3a3a3a",Ht="#2b2b2b",Hr="#888888",lu="#666666";function jr({items:t,activeIndex:e,loading:n}){return n?Pe(mt,{flexDirection:"column",paddingX:1,backgroundColor:Ht,children:Pe(Ze,{color:"gray",children:"Loading..."})}):t.length?Pe(mt,{flexDirection:"column",backgroundColor:Ht,children:t.map((o,r)=>{let s=r===e,i=s?au:Ht;return o.kind==="slash"?Fr(mt,{flexDirection:"row",gap:2,paddingX:1,backgroundColor:i,children:[Pe(Ze,{color:s?"cyan":"white",bold:s,children:o.title}),o.subtitle?Pe(Ze,{color:Hr,children:o.subtitle}):null]},o.id):Fr(mt,{flexDirection:"row",gap:1,paddingX:1,backgroundColor:i,children:[Pe(Ze,{color:s?"cyan":"white",bold:s,children:o.title}),o.subtitle?Pe(Ze,{color:Hr,children:o.subtitle}):null]},o.id)})}):Pe(mt,{flexDirection:"column",paddingX:1,backgroundColor:Ht,children:Pe(Ze,{color:lu,children:"No matches"})})}var Pn=[{name:"help",description:"Show help and shortcuts"},{name:"exit",description:"Exit the session"},{name:"new",description:"Start a new session"},{name:"resume",description:"Resume session history"},{name:"models",description:"Select a model (from configured providers)"},{name:"context",description:"Set context length limit (80k/120k/150k/200k) (starts new session)"},{name:"mcp",description:"Show configured MCP servers"},{name:"init",description:"Generate AGENTS.md for current project"}],cu=Object.fromEntries(Pn.map(t=>[t.name,t.description]));function te(t){return cu[t]}function Br(){let t=Pn.reduce((e,n)=>Math.max(e,n.name.length),0);return Pn.map(e=>` /${e.name.padEnd(t)} ${e.description}`)}var Wr={name:"new",description:te("new"),run:({closeSuggestions:t,setInputValue:e,clearScreen:n,showSystemMessage:o,newSession:r})=>{t(),e(""),n(),o("New Session","Starting a new session..."),r?.()}};var Vr={name:"exit",description:te("exit"),run:({closeSuggestions:t,exitApp:e})=>{t(),e()}};var zr={name:"resume",description:te("resume"),run:({closeSuggestions:t,setInputValue:e,showSystemMessage:n})=>{t(!1),e("resume "),n("Resume",'Type "resume" followed by keywords to filter and select from session history.')}};var Gr={name:"models",description:te("models"),run:({closeSuggestions:t,setInputValue:e,showSystemMessage:n,data:o})=>{t(!1);let{providers:r,providerName:s,model:i}=o;if(!r.length){n("Models",`No providers configured. Check ${o.configPath}`),e("");return}let a=r.map(l=>{let c=l.name===s&&l.model===i?" (current)":"",u=l.base_url?` @ ${l.base_url}`:"";return`- ${l.name}: ${l.model}${u}${c}`});e("/models "),n("Models",`Available models:
|
|
63
|
-
${a.join(`
|
|
64
|
-
`)}
|
|
65
|
-
|
|
66
|
-
${
|
|
67
|
-
|
|
68
|
-
$
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
Enter Send message
|
|
72
|
-
Shift+Enter New line in input
|
|
73
|
-
Up/Down Browse input history
|
|
74
|
-
Tab Accept suggestion
|
|
75
|
-
Ctrl+L Start a new session
|
|
76
|
-
Ctrl+C Exit
|
|
77
|
-
exit Type in input to exit
|
|
78
|
-
Esc Esc Cancel / Clear input`;var Kr={name:"help",description:te("help"),run:({closeSuggestions:t,setInputValue:e,showSystemMessage:n})=>{t(),e(""),n("Help",Ft)}};var qr={name:"context",description:te("context"),run:({closeSuggestions:t,setInputValue:e})=>{t(!1),e("/context ")}};function pu(t,e){let n=[];if(n.push(`- **${t}**`),"url"in e){n.push(` - Type: ${e.type??"streamable_http"}`),n.push(` - URL: ${e.url}`),e.bearer_token_env_var&&n.push(` - Bearer token env: ${e.bearer_token_env_var}`);let o=e.http_headers??e.headers;if(o&&Object.keys(o).length>0){let r=Object.entries(o).map(([s,i])=>`${s}=${i}`).join(", ");n.push(` - Headers: ${r}`)}}else if(n.push(` - Type: ${e.type??"stdio"}`),n.push(` - Command: ${e.command}`),e.args&&e.args.length>0&&n.push(` - Args: ${e.args.join(" ")}`),e.env&&Object.keys(e.env).length>0){let o=Object.entries(e.env).map(([r,s])=>`${r}=${s}`).join(", ");n.push(` - Env: ${o}`)}return n.join(`
|
|
79
|
-
`)}var Xr={name:"mcp",description:te("mcp"),run:({closeSuggestions:t,setInputValue:e,showSystemMessage:n,data:o})=>{t();let{mcpServers:r,configPath:s}=o,i=Object.keys(r);if(i.length===0){n("MCP Servers",`No MCP servers configured.
|
|
80
|
-
|
|
81
|
-
Add servers to ${s}`),e("");return}let a=[];a.push(`Total: ${i.length} server(s)
|
|
82
|
-
`);for(let[l,c]of Object.entries(r))a.push(pu(l,c)),a.push("");e(""),n("MCP Servers",a.join(`
|
|
83
|
-
`))}};var Jr={name:"init",description:te("init"),run:({closeSuggestions:t,setInputValue:e})=>{t(!1),e("/init")}};var Rn=[Kr,Vr,Wr,zr,Gr,qr,Xr,Jr];import{Fragment as $u,jsx as Oe,jsxs as dt}from"react/jsx-runtime";var Tu=400;function Qr({disabled:t,onSubmit:e,onExit:n,onClear:o,onNewSession:r,onCancelRun:s,onModelSelect:i,onSystemMessage:a,onSetContextLimit:l,history:c,cwd:u,sessionsDir:p,currentSessionFile:T,onHistorySelect:m,providers:S,configPath:_,providerName:v,model:N,contextLimit:R,mcpServers:w}){let[y,k]=Le(""),[K,D]=Le(null),[fe,H]=Le(""),[I,E]=Le("none"),[A,z]=Le([]),[ie,Y]=Le(0),[Ce,xe]=Le(!1),[b,V]=Le(!1),ge=$n(0),ae=$n(0),j=$n(""),Gt="\u203A ";In(()=>{j.current=y,V(!1)},[y]);let B=mu(()=>b||t?null:Eu(y),[t,b,y]),q=Yr(($=!0)=>{$&&V(!0),E("none"),z([]),Y(0),xe(!1)},[]);In(()=>{t&&q(!1)},[t,q]),In(()=>{if(!B){E("none"),z([]),Y(0),xe(!1);return}let $=!1,F=++ge.current;return xe(!0),(async()=>{try{if(B.type==="file"){let M=await Ur({cwd:u,query:B.query,limit:8});if($||F!==ge.current)return;let U=M.map(h=>{let C=h.isDir?`${h.path}/`:h.path;return{id:h.id,title:C,kind:"file",value:C,meta:{isDir:h.isDir}}});E("file"),z(U),Y(h=>U.length?Math.min(h,U.length-1):0);return}if(B.type==="history"){let M=await _u({sessionsDir:p,cwd:u,keyword:B.keyword,activeSessionFile:T});if($||F!==ge.current)return;let U=M.map(Ru);E("history"),z(U),Y(h=>U.length?Math.min(h,U.length-1):0);return}if(B.type==="models"){let M=B.keyword.toLowerCase(),h=(S??[]).filter(C=>{let re=C.name?.toLowerCase()??"",he=C.model?.toLowerCase()??"";return M?re.includes(M)||he.includes(M):!0}).map(C=>({id:C.name,title:`${C.name}: ${C.model}`,subtitle:C.base_url??C.env_api_key??"",kind:"model",value:`/models ${C.name}`,meta:{provider:C}}));E("model"),z(h),Y(C=>h.length?Math.min(C,h.length-1):0);return}if(B.type==="context"){let U=[8e4,12e4,15e4,2e5].map(h=>({id:`${h}`,title:`${(h/1e3).toFixed(0)}k tokens`,subtitle:h===R?"Current":void 0,kind:"context",value:`/context ${(h/1e3).toFixed(0)}k`,meta:{contextValue:h}}));E("context"),z(U),Y(h=>U.length?Math.min(h,U.length-1):0);return}if(B.type==="slash"){let M=B.keyword.toLowerCase(),h=(M?Rn.filter(C=>C.matches?C.matches(M):C.name.startsWith(M)):Rn).map(C=>({id:C.name,title:`/${C.name}`,subtitle:C.description,kind:"slash",value:`/${C.name} `,meta:{slashCommand:C}}));E("slash"),z(h),Y(C=>h.length?Math.min(C,h.length-1):0);return}}catch{!$&&F===ge.current&&z([])}finally{!$&&F===ge.current&&xe(!1)}})(),()=>{$=!0}},[B,u,p,T,S,R]);let xt=Yr($=>{if($){if(I==="file"&&B?.type==="file"){let F=y.slice(0,B.tokenStart),M=y.slice(B.tokenStart+B.query.length),U=`${F}${$.value}${M}`;j.current=U,k(U),D(null),H(""),$.meta?.isDir||q();return}if(I==="history"){$.meta?.historyEntry&&m?.($.meta.historyEntry),j.current=$.value,k($.value),D(null),H(""),q();return}if(I==="model"&&$.meta?.provider){i?.($.meta.provider),j.current="",k(""),D(null),H(""),q();return}if(I==="slash"&&$.meta?.slashCommand){$.meta.slashCommand.run({setInputValue:M=>{j.current=M,k(M),D(null),H("")},closeSuggestions:q,clearScreen:()=>{o()},newSession:()=>{r?.()},exitApp:()=>{n()},showSystemMessage:(M,U)=>{a?.(M,U)},switchModel:M=>{i?.(M)},setContextLimit:M=>{l?.(M)},loadHistory:M=>{m?.(M)},data:{configPath:_,providerName:v,model:N,contextLimit:R,providers:S,mcpServers:w}});return}if(I==="context"&&$.meta?.contextValue){let F=$.meta.contextValue;l?.(F),a?.("Context",`Context limit set to ${(F/1e3).toFixed(0)}k tokens`),j.current="",k(""),D(null),H(""),q();return}}},[q,o,n,i,a,l,m,I,B,y,_,v,N,R,S,w]);yu(($,F)=>{if(F.ctrl&&$==="l"){j.current="",k(""),D(null),H(""),q(),o(),r?.();return}let M=I!=="none",U=M&&A.length>0;if(F.escape){let h=Date.now();if(h-ae.current<=Tu){ae.current=0,t?s():(j.current="",k(""),D(null),H(""),q());return}ae.current=h,M&&q();return}if(!t){if(F.upArrow){if(U){Y(re=>re<=0?A.length-1:re-1);return}if(!c.length)return;if(K===null){H(j.current);let re=c.length-1;D(re);let he=c[re]??"";j.current=he,k(he);return}let h=Math.max(0,K-1);D(h);let C=c[h]??"";j.current=C,k(C);return}if(F.downArrow){if(U){Y(re=>(re+1)%A.length);return}if(K===null)return;let h=K+1;if(h>=c.length){D(null),j.current=fe,k(fe),H("");return}D(h);let C=c[h]??"";j.current=C,k(C);return}if(F.tab&&U){xt(A[ie]);return}if(F.return){if(U){xt(A[ie]);return}if(F.shift){let C=j.current+`
|
|
84
|
-
`;j.current=C,k(C);return}let h=j.current.trim();h&&(e(h),j.current="",k(""),D(null),H(""),q(!1));return}if(F.backspace||F.delete){let h=j.current.slice(0,Math.max(0,j.current.length-1));j.current=h,k(h);return}if($){let h=j.current+$;j.current=h,k(h)}}});let et=y,St=t?" ":"\u258A",De=et.split(`
|
|
85
|
-
`),Ie=2,Kt=A.map(({value:$,meta:F,...M})=>M);return dt(Bt,{flexDirection:"column",gap:1,children:[dt(Bt,{flexDirection:"column",paddingY:1,children:[dt(Bt,{children:[Oe(Fe,{color:"gray",children:Gt}),t?Oe(Fe,{color:"gray",children:De[0]}):dt($u,{children:[Oe(Fe,{color:"white",children:De[0]}),De.length===1&&Oe(Fe,{color:"cyan",children:St})]})]}),De.slice(1).map(($,F)=>dt(Bt,{children:[Oe(Fe,{color:"gray",children:" ".repeat(Ie)}),Oe(Fe,{color:"white",children:$}),F===De.length-2&&Oe(Fe,{color:"cyan",children:St})]},`line-${F}`))]}),I!=="none"?Oe(jr,{items:Kt,activeIndex:ie,loading:Ce}):null]})}async function _u(t){let e=t.activeSessionFile?ft(t.activeSessionFile):null,r=(await wu(t.sessionsDir)).filter(l=>!e||ft(l.path)!==e).filter((l,c,u)=>u.findIndex(p=>ft(p.path)===ft(l.path))===c).sort((l,c)=>c.mtimeMs-l.mtimeMs),s=t.limit??10,i=t.keyword?.trim().toLowerCase(),a=[];for(let l of r){if(a.length>=s)break;let c=await xu(l.path,t.cwd,l.mtimeMs);if(c&&!(i&&!c.input.toLowerCase().includes(i))&&(a.push(c),a.length>=s))break}return a}async function xu(t,e,n){try{let o=await du(t,"utf8"),{firstPrompt:r,sessionCwd:s}=Su(o);if(!Cu(e,s))return null;let i=r?.trim()||vu(t);return{id:t,cwd:e,input:i,ts:n,sessionFile:t}}catch{return null}}function Su(t){let e=null,n=null;for(let o of t.split(`
|
|
86
|
-
`)){let r=o.trim();if(!r)continue;let s;try{s=JSON.parse(r)}catch{continue}if(!(!s||typeof s!="object")){if(s.type==="session_start"&&!n){let i=s.meta?.cwd;typeof i=="string"&&i.trim()&&(n=i);continue}if(s.type==="turn_start"&&!e){let i=typeof s.content=="string"?s.content.trim():"";i&&(e=i)}}}return{firstPrompt:e,sessionCwd:n}}function vu(t){return hu(t).replace(/\.jsonl$/i,"")}function Zr(t){let e=ft(t);return process.platform==="win32"?e.toLowerCase():e}function Cu(t,e){return e?Zr(t)===Zr(e):!1}async function wu(t){let e=async s=>{try{return await fu(s,{withFileTypes:!0})}catch{return[]}},n=(await e(t)).filter(s=>s.isDirectory()&&/^\d{4}$/.test(s.name)),o=[];for(let s of n){let i=jt(t,s.name),a=(await e(i)).filter(l=>l.isDirectory()&&/^\d{2}$/.test(l.name));for(let l of a){let c=jt(i,l.name),u=(await e(c)).filter(p=>p.isDirectory()&&/^\d{2}$/.test(p.name));for(let p of u){let T=jt(c,p.name),m=(await e(T)).filter(S=>S.isFile()&&S.name.endsWith(".jsonl"));for(let S of m)o.push(jt(T,S.name))}}}return(await Promise.all(o.map(async s=>{try{let i=await gu(s);return{path:s,mtimeMs:i.mtimeMs}}catch{return null}}))).filter(s=>!!s)}function Eu(t){let e=Mu(t);if(e)return e;let n=Au(t);if(n)return n;let o=Pu(t);if(o)return o;let r=ku(t);return r||bu(t)}function ku(t){let e=t.lastIndexOf("@");if(e===-1)return null;if(e>0){let o=t[e-1];if(o&&!/\s/.test(o))return null}let n=t.slice(e+1);return/\s/.test(n)?null:{type:"file",query:n,tokenStart:e+1}}function bu(t){let e=t.trimStart(),n=t.length-e.length;if(e.length===0)return null;let o=e;if(o.startsWith("/")&&(o=o.slice(1)),!o.toLowerCase().startsWith("resume")||t.slice(0,n).trim().length>0)return null;let s=o.slice(6);return s&&!s.startsWith(" ")?null:{type:"history",keyword:s.trim()}}function Au(t){let e=t.trimStart();if(!e.startsWith("/models"))return null;let n=e.slice(7);return n&&!n.startsWith(" ")?null:{type:"models",keyword:n.trim()}}function Mu(t){let e=t.trimStart();if(!e.startsWith("/context"))return null;let n=e.slice(8);return n&&!n.startsWith(" ")?null:{type:"context"}}function Pu(t){let e=t.trimStart();if(!e.startsWith("/"))return null;let n=e.slice(1);return n.includes(" ")?null:/^[a-zA-Z]*$/.test(n)?{type:"slash",keyword:n.toLowerCase()}:n.length===0?{type:"slash",keyword:""}:null}function Ru(t){return{id:t.id,title:t.input,subtitle:Iu(t.ts),kind:"history",badge:"HIS",value:t.input,meta:{historyEntry:t}}}function Iu(t){if(!t)return"";let e=new Date(t);if(Number.isNaN(e.getTime()))return"";let n=String(e.getFullYear()),o=String(e.getMonth()+1).padStart(2,"0"),r=String(e.getDate()).padStart(2,"0"),s=String(e.getHours()).padStart(2,"0"),i=String(e.getMinutes()).padStart(2,"0");return`${n}-${o}-${r} ${s}:${i}`}import{Box as gt,Text as Ln,useInput as Lu}from"ink";import{useState as Ou,useCallback as Nu}from"react";import{jsx as ht,jsxs as On}from"react/jsx-runtime";function Du(t){if(typeof t!="object"||t===null)return String(t);let e=Object.entries(t);if(e.length===0)return"";let[n,o]=e[0],r=typeof o=="string"?o:JSON.stringify(o);return`${r.slice(0,40)}${r.length>40?"...":""}`}function es({request:t,onDecision:e}){let n=[{label:"Allow once",decision:"once"},{label:"Allow all session",decision:"session"},{label:"Reject this time",decision:"deny"}],[o,r]=Ou(0);Lu(Nu((i,a)=>{a.upArrow?r(l=>l>0?l-1:n.length-1):a.downArrow?r(l=>l<n.length-1?l+1:0):a.return&&e(n[o].decision)},[o,e,n]));let s=Du(t.params);return On(gt,{borderStyle:"single",borderColor:"gray",paddingX:2,flexDirection:"column",children:[ht(gt,{children:ht(Ln,{bold:!0,children:"Tool Approval:"})}),ht(gt,{marginTop:1,children:On(Ln,{color:"cyan",children:[t.toolName,s?` (${s})`:""]})}),ht(gt,{flexDirection:"column",marginTop:1,children:n.map((i,a)=>ht(gt,{children:On(Ln,{color:o===a?"green":"gray",children:[o===a?"> ":" ",i.label]})},i.decision))})]})}import Hh from"string-width";function ns(t){if(!t)return"success";let e=t.toLowerCase();return e.includes("error")||e.includes("unknown")||e.includes("failed")?"error":"success"}var ts={"gpt-4o-mini":128e3,"gpt-4o":128e3,"gpt-4":8192,"gpt-3.5":16384,"claude-3":2e5,claude:2e5,"deepseek-coder":64e3,"deepseek-chat":64e3,deepseek:64e3,"kimi-k2":2e5,kimi:2e5,default:12e4};function Uu(t){let e=t.toLowerCase(),n=Object.entries(ts).filter(([o])=>o!=="default");for(let[o,r]of n.sort((s,i)=>i[0].length-s[0].length))if(e.includes(o))return r;return ts.default}function os(t,e){if(t==null)return 0;let n=typeof t=="number"?t:t.prompt??t.total??0;if(n<=0)return 0;let o=e&&e>0?e:Uu("");return Math.min(100,n/o*100)}function rs(t){return t?`${t.total} tokens`:""}function ss(t,e){let[n,...o]=t.trim().slice(1).split(/\s+/),r=(n??"").toLowerCase(),s=[8e4,12e4,15e4,2e5],i=a=>{if(!a)return null;let c=a.toLowerCase().replace(/,/g,"").match(/^(\d+)(k)?$/);if(!c)return null;let u=Number(c[1])*(c[2]?1e3:1);return Number.isFinite(u)?u:null};switch(r){case"exit":return{kind:"exit"};case"new":return{kind:"new"};case"help":return{kind:"message",title:"Help",content:Ft};case"config":return{kind:"message",title:"Config",content:`Config file: ${e.configPath}
|
|
87
|
-
Current provider: ${e.providerName}
|
|
88
|
-
Current model: ${e.model}`};case"resume":return{kind:"message",title:"Resume",content:'Type "resume" to filter and select from session history.'};case"context":{let p=i(o[0]),T=s.map(m=>`${m/1e3}k`).join(", ");return p===null?{kind:"message",title:"Context",content:`Current: ${(e.contextLimit/1e3).toFixed(0)}k
|
|
89
|
-
Usage: /context <length> (starts new session)
|
|
90
|
-
Choices: ${T}`}:s.includes(p)?{kind:"set_context_limit",limit:p}:{kind:"message",title:"Context",content:`Unsupported length: ${p}. Pick one of: ${T}`}}case"init":return{kind:"init_agents_md"};case"$":{let p=o.join(" ").trim();return p?{kind:"shell_command",command:p}:{kind:"message",title:"Shell Command",content:"Usage: $ <command> (e.g. $ git status)"}}case"models":if(!e.providers.length)return{kind:"message",title:"Models",content:`No providers configured. Check ${e.configPath}`};let a=o.join(" ").trim(),l=e.providers.find(p=>p.name===a)??e.providers.find(p=>p.model===a);if(l)return{kind:"switch_model",provider:l};let c=e.providers.map(p=>{let T=p.base_url?` @ ${p.base_url}`:"";return`- ${p.name}: ${p.model}${T}`});return{kind:"message",title:"Models",content:`${a?`Not found: ${a}, `:""}Available models:
|
|
91
|
-
${c.join(`
|
|
92
|
-
`)}`};default:return{kind:"message",title:"Unknown",content:`Unknown command: ${t}
|
|
93
|
-
Type /help for available commands.`}}}import{dirname as Wt,join as as,resolve as Hu}from"path";import{statSync as Fu,existsSync as ls,readFileSync as ju}from"fs";import{readFile as Bu}from"fs/promises";import{get as Wu}from"https";import{fileURLToPath as Vu}from"url";function is(t){let e=t.trim().replace(/^v/i,""),[n="",o]=e.split("-",2),r=n.split(".").map(s=>Number(s));return r.length<3||r.some(s=>!Number.isFinite(s))?null:{major:r[0]??0,minor:r[1]??0,patch:r[2]??0,prerelease:o??null}}function zu(t,e){let n=is(t),o=is(e);return!n||!o?!1:n.major!==o.major?n.major>o.major:n.minor!==o.minor?n.minor>o.minor:n.patch!==o.patch?n.patch>o.patch:n.prerelease&&!o.prerelease?!1:!n.prerelease&&o.prerelease?!0:n.prerelease&&o.prerelease?n.prerelease>o.prerelease:!1}function cs(){try{let e=Vu(import.meta.url);return Wt(e)}catch{}let t=Hu(process.argv[1]??process.cwd());try{return Fu(t).isFile()?Wt(t):t}catch{return process.cwd()}}async function Gu(t){let e=as(t,"package.json");if(!ls(e))return null;let n=await Bu(e,"utf8"),o=JSON.parse(n);return!o.name||!o.version?null:{name:o.name,version:o.version}}function Ku(t){let e=as(t,"package.json");if(!ls(e))return null;try{let n=ju(e,"utf8"),o=JSON.parse(n);return!o.name||!o.version?null:{name:o.name,version:o.version}}catch{return null}}async function qu(){let t=cs();for(;;){let e=await Gu(t);if(e&&e.name==="@memo-code/memo")return e;let n=Wt(t);if(n===t)break;t=n}return null}function Vt(){let t=cs();for(;;){let e=Ku(t);if(e&&e.name==="@memo-code/memo")return e;let n=Wt(t);if(n===t)break;t=n}return null}async function Xu(t,e=1500){let o=`https://registry.npmjs.org/${encodeURIComponent(t)}/latest`;return new Promise(r=>{let s=Wu(o,{timeout:e},i=>{if(i.statusCode&&i.statusCode>=400){i.resume(),r(null);return}let a=[];i.on("data",l=>a.push(l)),i.on("end",()=>{try{let l=JSON.parse(Buffer.concat(a).toString("utf8"));r(l.version??null)}catch{r(null)}})});s.on("timeout",()=>{s.destroy(),r(null)}),s.on("error",()=>r(null))})}async function us(){let t=await qu();if(!t)return null;let e=await Xu(t.name);return!e||!zu(e,t.version)?null:{current:t.version,latest:e}}import{Box as Qe,Text as ve,useInput as Ju}from"ink";import{useCallback as Nn,useMemo as Yu,useState as yt}from"react";import{jsx as Re,jsxs as je}from"react/jsx-runtime";var Ne=[{key:"name",label:"Provider name",hint:"Used in /model and config",defaultValue:"deepseek"},{key:"envKey",label:"API key env var",hint:"Memo reads this env var at runtime",defaultValue:"DEEPSEEK_API_KEY"},{key:"model",label:"Model name",hint:"Provider model ID",defaultValue:"deepseek-chat"},{key:"baseUrl",label:"Base URL",hint:"Leave default unless you have a custom endpoint",defaultValue:"https://api.deepseek.com"}];function ps({configPath:t,onComplete:e,onExit:n}){let[o,r]=yt(0),[s,i]=yt(""),[a,l]=yt({}),[c,u]=yt(!1),[p,T]=yt(null),m=Ne[o]??Ne[0],S=s||a[m.key]||"",_=Nn(async R=>{u(!0),T(null);try{let w=R.name||Ne[0].defaultValue,y=R.envKey||Ne[1].defaultValue,k=R.model||Ne[2].defaultValue,K=R.baseUrl||Ne[3].defaultValue;await Te(t,{current_provider:w,providers:[{name:w,env_api_key:y,model:k,base_url:K||void 0}]}),e()}catch(w){T(w.message),u(!1)}},[t,e]),v=Nn(async()=>{let w=s.trim()||m.defaultValue,y={...a,[m.key]:w};if(l(y),i(""),o<Ne.length-1){r(o+1);return}await _(y)},[m.defaultValue,m.key,o,s,a,_]);Ju(Nn((R,w)=>{if(!c){if(w.ctrl&&R==="c"){n();return}if(w.return){v();return}if(w.backspace||w.delete){i(y=>y.slice(0,-1));return}R&&i(y=>y+R)}},[v,n,c]));let N=Yu(()=>`Step ${o+1}/${Ne.length}`,[o]);return je(Qe,{flexDirection:"column",children:[je(Qe,{flexDirection:"column",marginBottom:1,children:[Re(ve,{bold:!0,children:"Memo setup"}),Re(ve,{color:"gray",children:"No provider config found. Create one to continue."}),je(ve,{color:"gray",children:["Config path: ",t]})]}),je(Qe,{flexDirection:"column",marginBottom:1,children:[Re(ve,{color:"cyan",children:N}),je(ve,{children:[m.label," (default: ",m.defaultValue,")"]}),m.hint?Re(ve,{color:"gray",children:m.hint}):null]}),je(Qe,{children:[Re(ve,{children:"> "}),Re(ve,{children:S})]}),Re(Qe,{marginTop:1,children:Re(ve,{color:"gray",children:"Press Enter to continue. Ctrl+C to exit."})}),p?Re(Qe,{marginTop:1,children:je(ve,{color:"red",children:["Failed to write config: ",p]})}):null]})}import{jsx as Be,jsxs as ip}from"react/jsx-runtime";var op=ep(Qu);function rp(t){return{index:t,userInput:"",steps:[]}}function ds({sessionOptions:t,providerName:e,model:n,configPath:o,mcpServers:r,cwd:s,sessionsDir:i,providers:a,dangerous:l=!1,needsSetup:c=!1}){let{exit:u}=tp(),[p,T]=J(e),[m,S]=J(n),[_,v]=J(a),[N,R]=J({...t,providerName:e}),[w,y]=J(null),[k,K]=J([]),[D,fe]=J([]),[H,I]=J(!1),E=Tt(null),A=Tt(null),[z,ie]=J([]),[Y,Ce]=J(null),[xe,b]=J([]),[V,ge]=J(null),ae=Tt(null),[j,Gt]=J(null),B=Tt(0),[q,xt]=J(t.maxPromptTokens??12e4),[et,St]=J(c),[De,Ie]=J(0),Kt=Dn(()=>Vt(),[]),[$,F]=J(null),M=Tt(null),U=X(()=>(B.current+=1,B.current),[]),h=X((f,g)=>{let x=`${Date.now()}-${Math.random().toString(16).slice(2)}`,P=U();fe(O=>[...O,{id:x,title:f,content:g,sequence:P}])},[U]),C=X((f,g)=>{K(x=>{let P=[...x],O=P.findIndex(le=>le.index===f);O===-1&&(P.push(rp(f)),O=P.length-1);let W=P[O];return W&&(P[O]=g(W)),P})},[]),re=Dn(()=>({onAssistantStep:(f,g)=>{let x=E.current;x&&C(x,P=>{let O=P.steps.slice();for(;O.length<=g;)O.push({index:O.length,assistantText:""});let W=O[g];if(!W)return P;let le={...W,assistantText:W.assistantText+f};return O[g]=le,{...P,steps:O}})},requestApproval:l?void 0:f=>new Promise(g=>{F(f),M.current=g}),hooks:{onTurnStart:({turn:f,input:g,promptTokens:x})=>{E.current=f;let P=A.current;P&&(A.current=null);let O=P??g;x&&x>0&&Ie(x),C(f,W=>({...W,index:f,userInput:O,steps:[],startedAt:Date.now(),contextPromptTokens:x??W.contextPromptTokens}))},onAction:({turn:f,step:g,action:x,thinking:P,parallelActions:O})=>{C(f,W=>{let le=W.steps.slice();for(;le.length<=g;)le.push({index:le.length,assistantText:""});let vt=le[g];return vt?(le[g]={...vt,action:x,thinking:P,toolStatus:"executing",parallelActions:O&&O.length>1?O:void 0},{...W,steps:le}):W})},onObservation:({turn:f,step:g,observation:x})=>{C(f,P=>{let O=P.steps.slice();for(;O.length<=g;)O.push({index:O.length,assistantText:""});let W=O[g];return W?(O[g]={...W,observation:x,toolStatus:ns(x)},{...P,steps:O}):P})},onFinal:({turn:f,finalText:g,status:x,turnUsage:P,tokenUsage:O})=>{C(f,W=>{let le=W.startedAt??Date.now(),vt=Math.max(0,Date.now()-le),ks=O?.prompt??W.contextPromptTokens,bs=W.sequence??U();return{...W,finalText:g,status:x,tokenUsage:P,contextPromptTokens:ks,startedAt:le,durationMs:vt,sequence:bs}}),I(!1)}}}),[C,l,U]);zt(()=>{let f=!1;return(async()=>{if(et)return;let g=ae.current;g&&await g.close();let x=await lt(re,N);if(f){await x.close();return}ae.current=x,y(x),Ce(x.historyFilePath??null)})(),()=>{f=!0}},[re,N,et]),zt(()=>{let f=!1;return(async()=>{let g=await us();f||!g||h("Update",`Update available: v${g.latest}. Run: npm install -g @memo-code/memo@latest`)})(),()=>{f=!0}},[h]),zt(()=>()=>{ae.current&&ae.current.close()},[]);let he=X(async()=>{ae.current&&await ae.current.close(),Gt("Bye!"),setTimeout(()=>{u()},300)},[u]),Fn=X(()=>{K([]),fe([]),b([]),ge(null),Ie(0),B.current=0},[]),jn=X(async()=>{K([]),fe([]),b([]),ge(null),Ie(0),B.current=0;let f=_t(),g={...N,sessionId:f};ae.current&&await ae.current.close();let x=await lt(re,g);ae.current=x,y(x),Ce(x.historyFilePath??null),R(g),h("New Session","Started a new session with fresh context.")},[re,N,h]),Bn=X(async f=>{try{let g=await se(),x={...g.config,max_prompt_tokens:f};await Te(g.configPath,x)}catch(g){h("Failed to save config",`Failed to save context limit: ${g.message}`)}},[h]),qt=X(f=>{xt(f),Ie(0),R(g=>({...g,maxPromptTokens:f,sessionId:_t()})),h("Context length",`Context limit set to ${(f/1e3).toFixed(0)}k tokens (new session started)`),Bn(f)},[h,Bn]),Ts=X(async f=>{if(!f.sessionFile){h("History","This entry has no context file to load.");return}try{let g=await Zu(f.sessionFile,"utf8"),x=sp(g);b(x.turns),ge(x.messages),I(!1),K([]),y(null),Ce(null),Ie(0),E.current=null,B.current=Math.max(B.current,x.maxSequence),R(P=>({...P,sessionId:_t()})),h("History loaded",x.summary||f.input)}catch(g){h("Failed to load history",`Unable to read ${f.sessionFile}: ${g.message}`)}},[h]),Wn=X(async f=>{try{let g=await se(),x={...g.config,current_provider:f};await Te(g.configPath,x)}catch(g){h("Failed to save config",`Failed to save model selection: ${g.message}`)}},[h]),_s=X(()=>{H&&w?.cancelCurrentTurn?.()},[H,w]),Xt=X(async f=>{if(f.name===p&&f.model===m){h("Model switch",`Already using ${f.name} (${f.model})`);return}if(H){h("Model switch","Currently running. Press Esc Esc to cancel before switching models.");return}K([]),b([]),ge(null),Ie(0),E.current=null,y(null),Ce(null),T(f.name),S(f.model),R(g=>({...g,sessionId:_t(),providerName:f.name})),await Wn(f.name),h("Model switch",`Switched to ${f.name} (${f.model})`)},[h,H,m,p,Wn]),Jt=X(async f=>{if(!f.trim()){h("Shell Command","Usage: $ <command> (e.g. $ git status)");return}I(!0);try{let{stdout:g,stderr:x}=await op(f,{cwd:s,maxBuffer:5242880}),P=[g?.trim(),x?.trim()].filter(Boolean).join(`
|
|
94
|
-
`);h("Shell Result",P||"(no output)")}catch(g){let x=g,O=[x.stdout?.trim(),x.stderr?.trim(),x.message].filter(Boolean).join(`
|
|
95
|
-
`);h("Shell Error",O||"Command failed")}finally{I(!1)}},[h,s]),Vn=X(async f=>{let g=ss(f,{configPath:o,providerName:p,model:m,mcpServers:r,providers:_,contextLimit:q});if(g.kind==="exit"){await he();return}if(g.kind==="new"){await jn();return}if(g.kind==="switch_model"){await Xt(g.provider);return}if(g.kind==="set_context_limit"){qt(g.limit);return}if(g.kind==="init_agents_md"){h("Init","Analyzing project structure and generating AGENTS.md...");let x=`Please analyze the current project and create an AGENTS.md file at the project root.
|
|
57
|
+
`:""}${l.join(`
|
|
58
|
+
`)}`}}case $.CONTEXT:{let r=nl(o[0]),i=De.map(l=>`${Math.floor(l/1e3)}k`).join(", ");return r===null?{kind:"message",title:"Context",content:`Current: ${(e.contextLimit/1e3).toFixed(0)}k
|
|
59
|
+
Usage: ${ce($.CONTEXT)} <length>
|
|
60
|
+
Choices: ${i}`}:De.includes(r)?{kind:"set_context_limit",limit:r}:{kind:"message",title:"Context",content:`Unsupported value: ${r}. Choose one of ${i}`}}case $.MCP:{let r=Object.keys(e.mcpServers);if(!r.length)return{kind:"message",title:"MCP Servers",content:"No MCP servers configured in current config."};let i=[];i.push(`Total: ${r.length}`),i.push("");for(let[l,a]of Object.entries(e.mcpServers))i.push(`- ${l}`),"url"in a?(i.push(` type: ${a.type??"streamable_http"}`),i.push(` url: ${a.url}`),a.bearer_token_env_var&&i.push(` bearer: ${a.bearer_token_env_var}`)):(i.push(` type: ${a.type??"stdio"}`),i.push(` command: ${a.command}`),a.args?.length&&i.push(` args: ${a.args.join(" ")}`)),i.push("");return{kind:"message",title:"MCP Servers",content:i.join(`
|
|
61
|
+
`)}}case $.INIT:return{kind:"init_agents_md"};default:return{kind:"message",title:"Unknown",content:`Unknown command: ${t}
|
|
62
|
+
Type ${ce($.HELP)} for available commands.`}}}import{readdir as ol}from"fs/promises";import{join as rl,relative as sl,sep as il}from"path";var al=6,ll=2500,Ko=25,cl=new Set([".git",".svn",".hg","node_modules","dist","build",".next",".turbo",".cache",".output","coverage","tmp","temp","logs"]),yt=new Map;function ul(t){return t.split(il).join("/")}function pl(t){return{maxDepth:typeof t.maxDepth=="number"?Math.max(1,t.maxDepth):al,maxEntries:typeof t.maxEntries=="number"?Math.max(100,t.maxEntries):ll,limit:typeof t.limit=="number"?Math.max(1,t.limit):Ko,ignoreGlobs:t.ignoreGlobs?.length?t.ignoreGlobs:[]}}function ml(t,e){let n=t.split("/").filter(Boolean),o=n[n.length-1]??"";return n.some(s=>cl.has(s))||o.endsWith(".log")?!0:e.ignoreGlobs.length?e.ignoreGlobs.some(s=>{let r=s.replace(/\\/g,"/").trim();if(!r)return!1;if(r.endsWith("/**")){let i=r.slice(0,-3);return t.startsWith(i)}if(r.startsWith("*")){let i=r.slice(1);return t.endsWith(i)}return t.includes(r)}):!1}function dl(t){return JSON.stringify({maxDepth:t.maxDepth,maxEntries:t.maxEntries,ignoreGlobs:t.ignoreGlobs})}async function fl(t,e){let n=[],o=async(s,r)=>{if(n.length>=e.maxEntries)return;let i;try{i=await ol(s,{withFileTypes:!0})}catch{return}for(let l of i){if(n.length>=e.maxEntries)break;if(l.isSymbolicLink())continue;let a=rl(s,l.name),c=sl(t,a);if(!c)continue;let u=ul(c);if(ml(u,e))continue;let m=u.split("/").filter(Boolean),d=l.isDirectory();n.push({path:u,pathLower:u.toLowerCase(),segments:m,segmentsLower:m.map(h=>h.toLowerCase()),depth:r,isDir:d}),d&&r<e.maxDepth&&await o(a,r+1)}};return await o(t,0),n.sort((s,r)=>s.path.localeCompare(r.path)),n}async function gl(t,e){let n=pl(e),o=dl(n),s=yt.get(t);if(s&&s.signature===o)return s.pending?s.pending:s.entries;let r=fl(t,n).then(i=>(yt.set(t,{entries:i,signature:o}),i)).catch(i=>{throw yt.delete(t),i});return yt.set(t,{entries:[],signature:o,pending:r}),r}function hl(t,e){if(!e.length)return t.depth+(t.isDir?-.2:.2);let n=t.depth,o=0;for(let s of e){let r=-1;for(let i=o;i<t.segmentsLower.length;i++){let l=t.segmentsLower[i];if(l.startsWith(s)){r=i,n+=(i-o)*1.2,n+=l.length-s.length;break}let a=l.indexOf(s);if(a!==-1){r=i,n+=(i-o)*2+a+2;break}}if(r===-1)return null;o=r+1}return t.isDir&&(n-=.5),n}function yl(t,e,n){let s=e.trim().replace(/\\/g,"/").split("/").filter(Boolean).map(i=>i.toLowerCase()),r=[];for(let i of t){let l=hl(i,s);l!==null&&r.push({entry:i,score:l})}return r.sort((i,l)=>{let a=i.score-l.score;return a!==0?a:i.entry.path.localeCompare(l.entry.path)}),r.slice(0,n).map(({entry:i})=>({id:i.path,path:i.path,name:i.segments[i.segments.length-1]??i.path,parent:i.segments.length>1?i.segments.slice(0,-1).join("/"):void 0,isDir:i.isDir}))}async function Vo(t){let e=await gl(t.cwd,t),n=typeof t.limit=="number"?Math.max(1,t.limit):Ko;return yl(e,t.query,n)}import{readdir as Tl,readFile as _l,stat as Sl}from"fs/promises";import{basename as vl,join as Tt,resolve as Ze}from"path";function Go(t){let e=Ze(t);return process.platform==="win32"?e.toLowerCase():e}function xl(t,e){return e?Go(t)===Go(e):!1}function Cl(t){return vl(t).replace(/\.jsonl$/i,"")}function El(t){let e=null,n=null;for(let o of t.split(`
|
|
63
|
+
`)){let s=o.trim();if(!s)continue;let r;try{r=JSON.parse(s)}catch{continue}if(!(!r||typeof r!="object")){if(r.type==="session_start"&&!n){let i=r.meta?.cwd;typeof i=="string"&&i.trim()&&(n=i);continue}if(r.type==="turn_start"&&!e){let i=typeof r.content=="string"?r.content.trim():"";i&&(e=i)}}}return{firstPrompt:e,sessionCwd:n}}async function Al(t,e,n){try{let o=await _l(t,"utf8"),{firstPrompt:s,sessionCwd:r}=El(o);return xl(e,r)?{id:t,cwd:e,input:s?.trim()||Cl(t),ts:n,sessionFile:t}:null}catch{return null}}async function wl(t){let e=async r=>{try{return await Tl(r,{withFileTypes:!0})}catch{return[]}},n=(await e(t)).filter(r=>r.isDirectory()&&/^\d{4}$/.test(r.name)),o=[];for(let r of n){let i=Tt(t,r.name),l=(await e(i)).filter(a=>a.isDirectory()&&/^\d{2}$/.test(a.name));for(let a of l){let c=Tt(i,a.name),u=(await e(c)).filter(m=>m.isDirectory()&&/^\d{2}$/.test(m.name));for(let m of u){let d=Tt(c,m.name),h=(await e(d)).filter(w=>w.isFile()&&w.name.endsWith(".jsonl"));for(let w of h)o.push(Tt(d,w.name))}}}return(await Promise.all(o.map(async r=>{try{let i=await Sl(r);return{path:r,mtimeMs:i.mtimeMs}}catch{return null}}))).filter(r=>!!r)}async function Xo(t){let e=t.activeSessionFile?Ze(t.activeSessionFile):null,o=(await wl(t.sessionsDir)).filter(l=>!e||Ze(l.path)!==e).filter((l,a,c)=>c.findIndex(u=>Ze(u.path)===Ze(l.path))===a).sort((l,a)=>a.mtimeMs-l.mtimeMs),s=t.keyword?.trim().toLowerCase(),r=t.limit??10,i=[];for(let l of o){if(i.length>=r)break;let a=await Al(l.path,t.cwd,l.mtimeMs);a&&(s&&!a.input.toLowerCase().includes(s)||i.push(a))}return i}import{Box as _t,Text as St}from"ink";import{jsx as ke,jsxs as kl}from"react/jsx-runtime";var bl="#3a3a3a",vt="#262626";function Jo({items:t,activeIndex:e,loading:n}){return n?ke(_t,{paddingX:1,backgroundColor:vt,children:ke(St,{color:"gray",children:"Loading..."})}):t.length?ke(_t,{flexDirection:"column",backgroundColor:vt,children:t.map((o,s)=>{let r=s===e;return kl(_t,{paddingX:1,gap:2,backgroundColor:r?bl:vt,children:[ke(St,{color:r?"cyan":"white",bold:r,children:o.title}),o.subtitle?ke(St,{color:"gray",children:o.subtitle}):null]},o.id)})}):ke(_t,{paddingX:1,backgroundColor:vt,children:ke(St,{color:"gray",children:"No matches"})})}import{jsx as Me,jsxs as Ct}from"react/jsx-runtime";var Pl=400,tn=ce($.MODELS),nn=ce($.CONTEXT),Rl=ce($.INIT);function Il(t){let e=t.lastIndexOf("@");if(e===-1)return null;if(e>0){let o=t[e-1];if(o&&!/\s/.test(o))return null}let n=t.slice(e+1);return/\s/.test(n)?null:{type:"file",query:n,tokenStart:e+1}}function Ol(t){let e=t.trimStart(),n=t.length-e.length;if(!e.length)return null;let o=e;if(o.startsWith("/")&&(o=o.slice(1)),!o.toLowerCase().startsWith($.RESUME)||t.slice(0,n).trim().length>0)return null;let r=o.slice($.RESUME.length);return r&&!r.startsWith(" ")?null:{type:"history",keyword:r.trim()}}function Ll(t){let e=t.trimStart();if(!e.startsWith("/"))return null;let n=e.slice(1);return n.includes(" ")?null:n.length?/^[a-zA-Z-]+$/.test(n)?{type:"slash",keyword:n.toLowerCase()}:null:{type:"slash",keyword:""}}function $l(t){let e=t.trimStart();if(!e.startsWith(tn))return null;let n=e.slice(tn.length);return n&&!n.startsWith(" ")?null:{type:"models",keyword:n.trim().toLowerCase()}}function Nl(t){let e=t.trimStart();if(!e.startsWith(nn))return null;let n=e.slice(nn.length);return n&&!n.startsWith(" ")?null:{type:"context"}}function Dl(t){return Nl(t)??$l(t)??Ll(t)??Il(t)??Ol(t)}function Ul(t){let e=new Date(t);if(Number.isNaN(e.getTime()))return"";let n=String(e.getFullYear()),o=String(e.getMonth()+1).padStart(2,"0"),s=String(e.getDate()).padStart(2,"0"),r=String(e.getHours()).padStart(2,"0"),i=String(e.getMinutes()).padStart(2,"0");return`${n}-${o}-${s} ${r}:${i}`}function Qo({disabled:t,busy:e,history:n,cwd:o,sessionsDir:s,currentSessionFile:r,providers:i,configPath:l,providerName:a,model:c,contextLimit:u,mcpServers:m,onSubmit:d,onExit:h,onClear:w,onNewSession:f,onCancelRun:I,onHistorySelect:S,onModelSelect:_,onSetContextLimit:U,onSystemMessage:N}){let[M,y]=Ce(""),E=en(""),[ie,D]=Ce(null),[ne,q]=Ce(""),[B,b]=Ce("none"),[R,V]=Ce([]),[X,K]=Ce(0),[Re,de]=Ce(!1),[Ie,W]=Ce(!1),A=en(0),H=en(0);Qt(()=>{E.current=M,W(!1)},[M]);let Ae=Zo(()=>({configPath:l,providerName:a,model:c,mcpServers:m,providers:i,contextLimit:u}),[l,a,c,m,i,u]),j=Zo(()=>t||Ie?null:Dl(M),[t,Ie,M]),z=Yo((P=!0)=>{P&&W(!0),b("none"),V([]),K(0),de(!1)},[]);Qt(()=>{t&&z(!1)},[t,z]),Qt(()=>{if(!j){z(!1);return}let P=!1,k=++A.current;return de(!0),(async()=>{try{if(j.type==="file"){let C=await Vo({cwd:o,query:j.query,limit:8});if(P||k!==A.current)return;let v=C.map(x=>({id:x.id,title:x.isDir?`${x.path}/`:x.path,kind:"file",value:x.isDir?`${x.path}/`:x.path,meta:{type:"file",isDir:x.isDir}}));b("file"),V(v),K(x=>v.length?Math.min(x,v.length-1):0);return}if(j.type==="history"){let C=await Xo({sessionsDir:s,cwd:o,keyword:j.keyword,activeSessionFile:r});if(P||k!==A.current)return;let v=C.map(x=>({id:x.id,title:x.input,subtitle:Ul(x.ts),kind:"history",value:x.input,meta:{type:"history",entry:x}}));b("history"),V(v),K(x=>v.length?Math.min(x,v.length-1):0);return}if(j.type==="models"){let C=i.filter(v=>{if(!j.keyword)return!0;let x=v.name.toLowerCase(),F=v.model.toLowerCase();return x.includes(j.keyword)||F.includes(j.keyword)}).map(v=>({id:v.name,title:`${v.name}: ${v.model}`,subtitle:v.base_url,kind:"model",value:`${tn} ${v.name}`,meta:{type:"model",provider:v}}));b("model"),V(C),K(v=>C.length?Math.min(v,C.length-1):0);return}if(j.type==="context"){let C=De.map(v=>({id:`${v}`,title:`${Math.floor(v/1e3)}k tokens`,subtitle:v===u?"Current":void 0,kind:"context",value:`${nn} ${Math.floor(v/1e3)}k`,meta:{type:"context",value:v}}));b("context"),V(C),K(v=>C.length?Math.min(v,C.length-1):0);return}if(j.type==="slash"){let C=ht.filter(v=>v.name.startsWith(j.keyword)).map(v=>({id:v.name,title:`/${v.name}`,subtitle:v.description,kind:"slash",value:`/${v.name}`,meta:{type:"slash"}}));b("slash"),V(C),K(v=>C.length?Math.min(v,C.length-1):0)}}finally{!P&&k===A.current&&de(!1)}})(),()=>{P=!0}},[j,o,s,r,i,u,z]);let Fe=Yo(P=>{if(P){if(B==="file"&&j?.type==="file"){let k=M.slice(0,j.tokenStart),C=M.slice(j.tokenStart+j.query.length),v=`${k}${P.value}${C}`;E.current=v,y(v),D(null),q(""),P.meta?.type==="file"&&P.meta.isDir||z();return}if(P.meta?.type==="history"){S(P.meta.entry),E.current=P.value,y(P.value),D(null),q(""),z();return}if(P.meta?.type==="model"){_(P.meta.provider),E.current="",y(""),D(null),q(""),z();return}if(P.meta?.type==="context"){U(P.meta.value),N("Context",`Context limit set to ${Math.floor(P.meta.value/1e3)}k`),E.current="",y(""),D(null),q(""),z();return}if(P.meta?.type==="slash"){E.current=`${P.value} `,y(`${P.value} `),D(null),q(""),z(!1);return}E.current=P.value,y(P.value),D(null),q(""),z()}},[B,j,M,z,S,_,U,N]);Ml((P,k)=>{if(k.ctrl&&P==="c"){h();return}if(k.ctrl&&P==="l"){E.current="",y(""),D(null),q(""),z(),w(),f();return}let C=B!=="none",v=C&&R.length>0;if(k.escape){let x=Date.now();if(x-H.current<=Pl){H.current=0,e?I():(E.current="",y(""),D(null),q(""),z());return}H.current=x,C&&z();return}if(!t){if(k.upArrow){if(v){K(fe=>fe<=0?R.length-1:fe-1);return}if(!n.length)return;if(ie===null){q(E.current);let fe=n.length-1;D(fe);let je=n[fe]??"";E.current=je,y(je);return}let x=Math.max(0,ie-1);D(x);let F=n[x]??"";E.current=F,y(F);return}if(k.downArrow){if(v){K(fe=>(fe+1)%R.length);return}if(ie===null)return;let x=ie+1;if(x>=n.length){D(null),E.current=ne,y(ne),q("");return}D(x);let F=n[x]??"";E.current=F,y(F);return}if(k.tab&&v){Fe(R[X]);return}if(k.return){if(v){Fe(R[X]);return}if(k.shift){let F=`${E.current}
|
|
64
|
+
`;E.current=F,y(F);return}let x=E.current.trim();if(!x)return;if(x.startsWith("/")){let F=qo(x,Ae);F.kind==="message"?N(F.title,F.content):F.kind==="new"?f():F.kind==="exit"?h():F.kind==="switch_model"?_(F.provider):F.kind==="set_context_limit"?U(F.limit):F.kind==="init_agents_md"&&d(Rl),E.current="",y(""),D(null),q(""),z(!1);return}d(x),E.current="",y(""),D(null),q(""),z(!1);return}if(k.backspace||k.delete){let x=E.current.slice(0,Math.max(0,E.current.length-1));E.current=x,y(x);return}if(P){let x=`${E.current}${P}`;E.current=x,y(x)}}});let Se=M.split(`
|
|
65
|
+
`);return Ct(xt,{flexDirection:"column",gap:1,children:[Ct(xt,{flexDirection:"column",paddingY:1,children:[Ct(xt,{children:[Me(Ue,{color:"gray",children:"\u203A "}),Me(Ue,{children:Se[0]??""}),!t&&Se.length===1?Me(Ue,{color:"cyan",children:"\u258A"}):null]}),Se.slice(1).map((P,k)=>Ct(xt,{children:[Me(Ue,{color:"gray",children:" "}),Me(Ue,{children:P}),k===Se.length-2&&!t?Me(Ue,{color:"cyan",children:"\u258A"}):null]},`line-${k}`))]}),B!=="none"?Me(Jo,{items:R.map(({value:P,meta:k,...C})=>C),activeIndex:X,loading:Re}):null]})}import{Box as Hl,Text as er}from"ink";import{jsx as Fl,jsxs as tr}from"react/jsx-runtime";function nr({busy:t,contextPercent:e,tokenLine:n}){let o=`${e.toFixed(1)}%`;return tr(Hl,{justifyContent:"space-between",children:[Fl(er,{color:"gray",children:t?"Working... Esc Esc to interrupt":"Enter send \u2022 Shift+Enter newline \u2022 /help"}),tr(er,{color:"gray",children:[n?`${n} \u2022 `:"","context: ",o]})]})}import{useState as jl}from"react";import{Box as or,Text as Et,useInput as Bl}from"ink";import{jsx as on,jsxs as rn}from"react/jsx-runtime";var At=[{label:"Allow once",decision:"once"},{label:"Allow for this session",decision:"session"},{label:"Deny",decision:"deny"}];function Wl(t){if(!t)return"";if(typeof t!="object")return String(t);let e=Object.entries(t);if(!e.length)return"";let[n,o]=e[0]??[];if(!n)return"";let s=typeof o=="string"?o:JSON.stringify(o);return`${n}=${s?.slice(0,60)??""}${s&&s.length>60?"...":""}`}function rr({request:t,onDecision:e}){let[n,o]=jl(0);Bl((r,i)=>{if(i.upArrow){o(l=>l<=0?At.length-1:l-1);return}if(i.downArrow){o(l=>(l+1)%At.length);return}if(i.return){let l=At[n];l&&e(l.decision);return}(i.escape||i.ctrl&&r==="c")&&e("deny")});let s=Wl(t.params);return rn(or,{flexDirection:"column",borderStyle:"single",borderColor:"yellow",paddingX:1,children:[on(Et,{bold:!0,color:"yellow",children:"Tool Approval Required"}),rn(Et,{children:[t.toolName,s?` (${s})`:""]}),on(Et,{color:"gray",children:t.reason}),on(or,{marginTop:1,flexDirection:"column",children:At.map((r,i)=>rn(Et,{color:n===i?"green":"gray",children:[n===i?"> ":" ",r.label]},r.decision))})]})}import{Box as Qe,Text as ue,useInput as zl}from"ink";import{useCallback as sr,useMemo as ql,useState as et}from"react";import{jsx as me,jsxs as He}from"react/jsx-runtime";var Ee=[{key:"name",label:"Provider name",hint:"Used for /models switching",defaultValue:"deepseek"},{key:"envKey",label:"API key env var",hint:"Read at runtime from environment variables",defaultValue:"DEEPSEEK_API_KEY"},{key:"model",label:"Model name",defaultValue:"deepseek-chat"},{key:"baseUrl",label:"Base URL",defaultValue:"https://api.deepseek.com"}];function ir({configPath:t,onComplete:e,onExit:n}){let[o,s]=et(0),[r,i]=et(""),[l,a]=et({}),[c,u]=et(!1),[m,d]=et(null),h=Ee[o]??Ee[0],w=sr(async S=>{u(!0),d(null);try{let _={current_provider:S.name,providers:[{name:S.name,env_api_key:S.envKey,model:S.model,base_url:S.baseUrl||void 0}]};await le(t,_),e()}catch(_){d(_.message),u(!1)}},[t,e]),f=sr(async()=>{if(!h)return;let S=r.trim()||h.defaultValue,_={...l,[h.key]:S};if(a(_),i(""),o<Ee.length-1){s(o+1);return}let U={name:_.name||Ee[0].defaultValue,envKey:_.envKey||Ee[1].defaultValue,model:_.model||Ee[2].defaultValue,baseUrl:_.baseUrl||Ee[3].defaultValue};await w(U)},[r,w,h,o,l]);zl((S,_)=>{if(!c){if(_.ctrl&&S==="c"){n();return}if(_.return){f();return}if(_.backspace||_.delete){i(U=>U.slice(0,-1));return}S&&i(U=>U+S)}});let I=ql(()=>`Step ${o+1}/${Ee.length}`,[o]);return h?He(Qe,{flexDirection:"column",children:[me(ue,{bold:!0,children:"Memo setup"}),me(ue,{color:"gray",children:"No provider config found. Complete setup to continue."}),He(ue,{color:"gray",children:["Config path: ",t]}),He(Qe,{marginTop:1,flexDirection:"column",children:[me(ue,{color:"cyan",children:I}),me(ue,{children:h.label}),He(ue,{color:"gray",children:["Default: ",h.defaultValue]}),h.hint?me(ue,{color:"gray",children:h.hint}):null]}),He(Qe,{marginTop:1,children:[me(ue,{children:"> "}),me(ue,{children:r})]}),me(Qe,{marginTop:1,children:me(ue,{color:"gray",children:"Enter to continue, Ctrl+C to exit."})}),m?me(Qe,{marginTop:1,children:He(ue,{color:"red",children:["Failed to save config: ",m]})}):null]}):null}function ar(t){let e=[],n=[],o=[],s=t.split(`
|
|
66
|
+
`).map(a=>a.trim()).filter(Boolean),r=null,i=0,l=0;for(let a of s){let c;try{c=JSON.parse(a)}catch{continue}if(!(!c||typeof c!="object")){if(c.type==="turn_start"){let u=typeof c.content=="string"?c.content:"";r={index:-(i+1),userInput:u,steps:[],status:"ok",sequence:l+=1},n.push(r),u&&(e.push({role:"user",content:u}),o.push(`User: ${u}`)),i+=1;continue}if(c.type==="assistant"){let u=typeof c.content=="string"?c.content:"";if(u&&(e.push({role:"assistant",content:u}),o.push(`Assistant: ${u}`),r)){let m={index:r.steps.length,assistantText:u};r.steps=[...r.steps,m],r.finalText=u}continue}if(c.type==="action"&&r){let u=c.meta;if(u&&typeof u=="object"){let m=typeof u.tool=="string"?u.tool:"",d=u.input,h=typeof u.thinking=="string"?u.thinking:"",f=(Array.isArray(u.toolBlocks)?u.toolBlocks:[]).map(S=>{let _=typeof S?.name=="string"?S.name:"";return _?{tool:_,input:S?.input}:null}).filter(Boolean),I=r.steps[r.steps.length-1];I&&(f.length>1?(I.action=f[0],I.parallelActions=f):m&&(I.action={tool:m,input:d}),h&&(I.thinking=h))}continue}if(c.type==="observation"&&r){let u=typeof c.content=="string"?c.content:"",m=r.steps[r.steps.length-1];m&&(m.observation=u);continue}}}return{summary:o.join(`
|
|
67
|
+
`),messages:e,turns:n,maxSequence:l}}function an(){return{turns:[],historicalTurns:[],systemMessages:[],sequence:0}}function Kl(t,e){return{index:t,userInput:"",steps:[],sequence:e}}function sn(t,e){let n=t.slice();for(;n.length<=e;)n.push({index:n.length,assistantText:""});return n}function tt(t,e,n){let o=t.turns.slice(),s=o.findIndex(i=>i.index===e);if(s===-1){let i=t.sequence+1;return o.push(n(Kl(e,i))),{turns:o,sequence:i}}let r=o[s];return r?(o[s]=n(r),{turns:o,sequence:t.sequence}):{turns:o,sequence:t.sequence}}function Vl(t){return{id:`${Date.now()}-${Math.random().toString(16).slice(2)}`,title:t.title,content:t.content,tone:t.tone??"info",sequence:t.sequence}}function lr(t,e){switch(e.type){case"append_system_message":{let n=t.sequence+1;return{...t,sequence:n,systemMessages:[...t.systemMessages,Vl({title:e.title,content:e.content,tone:e.tone,sequence:n})]}}case"turn_start":{let n=tt(t,e.turn,o=>({...o,index:e.turn,userInput:e.input,steps:[],finalText:void 0,status:void 0,errorMessage:void 0,tokenUsage:void 0,startedAt:Date.now(),durationMs:void 0,contextPromptTokens:e.promptTokens??o.contextPromptTokens}));return{...t,turns:n.turns,sequence:n.sequence}}case"assistant_chunk":{let n=tt(t,e.turn,o=>{let s=sn(o.steps,e.step),r=s[e.step];return r?(s[e.step]={...r,assistantText:`${r.assistantText}${e.chunk}`},{...o,steps:s}):o});return{...t,turns:n.turns,sequence:n.sequence}}case"tool_action":{let n=tt(t,e.turn,o=>{let s=sn(o.steps,e.step),r=s[e.step];return r?(s[e.step]={...r,action:e.action,thinking:e.thinking,parallelActions:e.parallelActions&&e.parallelActions.length>1?e.parallelActions:void 0,toolStatus:_e.EXECUTING},{...o,steps:s}):o});return{...t,turns:n.turns,sequence:n.sequence}}case"tool_observation":{let n=tt(t,e.turn,o=>{let s=sn(o.steps,e.step),r=s[e.step];return r?(s[e.step]={...r,observation:e.observation,toolStatus:e.toolStatus,parallelToolStatuses:e.parallelToolStatuses},{...o,steps:s}):o});return{...t,turns:n.turns,sequence:n.sequence}}case"turn_final":{let n=tt(t,e.turn,o=>{let s=o.startedAt??Date.now(),r=Math.max(0,Date.now()-s),i=e.tokenUsage?.prompt??o.contextPromptTokens;return{...o,finalText:e.finalText,status:e.status,errorMessage:e.errorMessage,tokenUsage:e.turnUsage,contextPromptTokens:i,startedAt:s,durationMs:r}});return{...t,turns:n.turns,sequence:n.sequence}}case"replace_history":return{...t,historicalTurns:e.turns,sequence:Math.max(t.sequence,e.maxSequence)};case"clear_current_timeline":return{...t,turns:[],systemMessages:[]};case"reset_all":return an();default:return t}}import{dirname as wt,join as ur,resolve as Gl}from"path";import{statSync as Xl,existsSync as pr,readFileSync as Jl}from"fs";import{readFile as Yl}from"fs/promises";import{get as Zl}from"https";import{fileURLToPath as Ql}from"url";function cr(t){let e=t.trim().replace(/^v/i,""),[n="",o]=e.split("-",2),s=n.split(".").map(r=>Number(r));return s.length<3||s.some(r=>!Number.isFinite(r))?null:{major:s[0]??0,minor:s[1]??0,patch:s[2]??0,prerelease:o??null}}function ec(t,e){let n=cr(t),o=cr(e);return!n||!o?!1:n.major!==o.major?n.major>o.major:n.minor!==o.minor?n.minor>o.minor:n.patch!==o.patch?n.patch>o.patch:n.prerelease&&!o.prerelease?!1:!n.prerelease&&o.prerelease?!0:n.prerelease&&o.prerelease?n.prerelease>o.prerelease:!1}function mr(){try{let e=Ql(import.meta.url);return wt(e)}catch{}let t=Gl(process.argv[1]??process.cwd());try{return Xl(t).isFile()?wt(t):t}catch{return process.cwd()}}async function tc(t){let e=ur(t,"package.json");if(!pr(e))return null;let n=await Yl(e,"utf8"),o=JSON.parse(n);return!o.name||!o.version?null:{name:o.name,version:o.version}}function nc(t){let e=ur(t,"package.json");if(!pr(e))return null;try{let n=Jl(e,"utf8"),o=JSON.parse(n);return!o.name||!o.version?null:{name:o.name,version:o.version}}catch{return null}}async function oc(){let t=mr();for(;;){let e=await tc(t);if(e&&e.name==="@memo-code/memo")return e;let n=wt(t);if(n===t)break;t=n}return null}function bt(){let t=mr();for(;;){let e=nc(t);if(e&&e.name==="@memo-code/memo")return e;let n=wt(t);if(n===t)break;t=n}return null}async function rc(t,e=1500){let o=`https://registry.npmjs.org/${encodeURIComponent(t)}/latest`;return new Promise(s=>{let r=Zl(o,{timeout:e},i=>{if(i.statusCode&&i.statusCode>=400){i.resume(),s(null);return}let l=[];i.on("data",a=>l.push(a)),i.on("end",()=>{try{let a=JSON.parse(Buffer.concat(l).toString("utf8"));s(a.version??null)}catch{s(null)}})});r.on("timeout",()=>{r.destroy(),s(null)}),r.on("error",()=>s(null))})}async function dr(){let t=await oc();if(!t)return null;let e=await rc(t.name);return!e||!ec(e,t.version)?null:{current:t.version,latest:e}}import{jsx as Pe,jsxs as cc}from"react/jsx-runtime";function hr({sessionOptions:t,providerName:e,model:n,configPath:o,mcpServers:s,cwd:r,sessionsDir:i,providers:l,dangerous:a=!1,needsSetup:c=!1}){let{exit:u}=lc(),[m,d]=ic(lr,void 0,an),[h,w]=te(e),[f,I]=te(n),[S,_]=te(l),[U,N]=te({...t,providerName:e}),[M,y]=te(!1),[E,ie]=te([]),[D,ne]=te(null),[q,B]=te(null),[b,R]=te(t.maxPromptTokens??Wo),[V,X]=te(0),[K,Re]=te(c),[de,Ie]=te(null),[W,A]=te(null),H=Mt(null),Ae=Mt(null),j=Mt(null),[z,Fe]=te(null),Se=Mt(null),P=fr(()=>bt(),[]),k=Z(g=>{d(g)},[]),C=Z((g,T,L="info")=>{k({type:"append_system_message",title:g,content:T,tone:L})},[k]),v=fr(()=>({onAssistantStep:(g,T)=>{let L=Ae.current;L&&k({type:"assistant_chunk",turn:L,step:T,chunk:g})},requestApproval:a?void 0:g=>new Promise(T=>{Fe(g),Se.current=T}),hooks:{onTurnStart:({turn:g,input:T,promptTokens:L})=>{Ae.current=g;let pe=j.current;pe&&(j.current=null);let we=pe??T;L&&L>0&&X(L),k({type:"turn_start",turn:g,input:we,promptTokens:L})},onAction:({turn:g,step:T,action:L,thinking:pe,parallelActions:we})=>{k({type:"tool_action",turn:g,step:T,action:L,thinking:pe,parallelActions:we})},onObservation:({turn:g,step:T,observation:L,resultStatus:pe,parallelResultStatuses:we})=>{k({type:"tool_observation",turn:g,step:T,observation:L,toolStatus:Yt(pe),parallelToolStatuses:$o(we)})},onFinal:({turn:g,finalText:T,status:L,errorMessage:pe,turnUsage:we,tokenUsage:Pr})=>{k({type:"turn_final",turn:g,finalText:T,status:L,errorMessage:pe,turnUsage:we,tokenUsage:Pr}),y(!1)}}}),[k,a]);kt(()=>{let g=!1;return(async()=>{if(K)return;let T=H.current;T&&await T.close();let L=await dt(v,U);if(g){await L.close();return}H.current=L,A(L),ne(L.historyFilePath??null)})(),()=>{g=!0}},[v,U,K]),kt(()=>{let g=!1;return(async()=>{let T=await dr();g||!T||C("Update",`Update available: v${T.latest}. Run: npm install -g @memo-code/memo@latest`)})(),()=>{g=!0}},[C]),kt(()=>()=>{H.current&&H.current.close()},[]);let x=Z(async()=>{H.current&&await H.current.close(),Ie("Bye!"),setTimeout(()=>u(),250)},[u]),F=Z(()=>{k({type:"clear_current_timeline"}),B(null),X(0)},[k]),fe=Z(()=>{k({type:"reset_all"}),B(null),X(0),Ae.current=null,N(g=>({...g,sessionId:nt()})),C("New Session","Started a fresh session.")},[C,k]),je=Z(async g=>{try{let T=await Q();await le(T.configPath,{...T.config,current_provider:g})}catch(T){C("Config",`Failed to persist provider: ${T.message}`,"warning")}},[C]),vr=Z(async g=>{if(M){C("Model switch","Cancel current run before switching models.","warning");return}if(g.name===h&&g.model===f){C("Model switch",`Already using ${g.name} (${g.model}).`);return}k({type:"reset_all"}),X(0),Ae.current=null,w(g.name),I(g.model),N(T=>({...T,sessionId:nt(),providerName:g.name})),await je(g.name),C("Model switch",`Switched to ${g.name} (${g.model}).`)},[C,M,f,h,k,je]),un=Z(async g=>{try{let T=await Q();await le(T.configPath,{...T.config,max_prompt_tokens:g})}catch(T){C("Context",`Failed to persist context limit: ${T.message}`,"warning")}},[C]),xr=Z(g=>{R(g),X(0),N(T=>({...T,maxPromptTokens:g,sessionId:nt()})),C("Context",`Context window set to ${Math.floor(g/1e3)}k.`),un(g)},[C,un]),Cr=Z(async g=>{try{let T=await sc(g.sessionFile,"utf8"),L=ar(T);k({type:"clear_current_timeline"}),k({type:"replace_history",turns:L.turns,maxSequence:L.maxSequence}),B(L.messages),y(!1),A(null),ne(null),X(0),Ae.current=null,N(pe=>({...pe,sessionId:nt()})),C("History",L.summary||g.input)}catch(T){C("History",`Failed to load ${g.sessionFile}: ${T.message}`,"error")}},[C,k]),Er=Z(()=>{M&&W?.cancelCurrentTurn?.()},[M,W]),pn=Z(async()=>{if(!W||M)return;let g=`Please analyze the current project and create an AGENTS.md file at the project root.
|
|
96
68
|
|
|
97
69
|
The AGENTS.md should include:
|
|
98
70
|
1. Project name and brief description
|
|
@@ -103,15 +75,12 @@ The AGENTS.md should include:
|
|
|
103
75
|
6. Any project-specific notes for AI assistants
|
|
104
76
|
|
|
105
77
|
Steps:
|
|
106
|
-
1.
|
|
107
|
-
2. Read key configuration files
|
|
108
|
-
3. Understand
|
|
109
|
-
4. Create
|
|
78
|
+
1. Explore project structure using list_dir and exec_command tools
|
|
79
|
+
2. Read key configuration files
|
|
80
|
+
3. Understand stack and conventions
|
|
81
|
+
4. Create AGENTS.md using apply_patch
|
|
110
82
|
|
|
111
|
-
|
|
112
|
-
`);return Be(ms,{flexDirection:"column",children:f.map((g,x)=>Be(np,{color:"green",children:g},x))})}return et?Be(ps,{configPath:o,onComplete:xs,onExit:he}):ip(ms,{flexDirection:"column",children:[Be(Er,{systemMessages:D,turns:ws,headerInfo:{providerName:p,model:m,cwd:s,sessionId:N.sessionId??"unknown",mcpNames:Object.keys(r??{}).sort(),version:Kt?.version??"unknown"}}),Be(Qr,{disabled:!w||H||!!$,onSubmit:Ss,onExit:he,onClear:Fn,onNewSession:jn,onCancelRun:_s,onHistorySelect:Ts,onModelSelect:Xt,onSystemMessage:h,onSetContextLimit:f=>{qt(f)},history:z,cwd:s,sessionsDir:i,currentSessionFile:Y??void 0,providers:_,configPath:o,providerName:p,model:m,contextLimit:q,mcpServers:r}),$&&Be(es,{request:$,onDecision:Es}),Be(dr,{contextPercent:Cs})]})}function sp(t){let e=[],n=[],o=[],r=t.split(`
|
|
113
|
-
`).map(l=>l.trim()).filter(Boolean),s=null,i=0,a=0;for(let l of r){let c;try{c=JSON.parse(l)}catch{continue}if(!(!c||typeof c!="object")){if(c.type==="turn_start"){let u=typeof c.content=="string"?c.content:"";s={index:-(i+1),userInput:u,steps:[],status:"ok",sequence:a+=1},n.push(s),u&&(e.push({role:"user",content:u}),o.push(`User: ${u}`)),i+=1;continue}if(c.type==="assistant"){let u=typeof c.content=="string"?c.content:"";if(u&&(e.push({role:"assistant",content:u}),o.push(`Assistant: ${u}`),s)){let p={index:s.steps.length,assistantText:u};s.steps=[...s.steps,p],s.finalText=u}continue}if(c.type==="action"&&s){let u=c.meta;if(u&&typeof u=="object"){let p=typeof u.tool=="string"?u.tool:"",T=u.input,m=typeof u.thinking=="string"?u.thinking:"",_=(Array.isArray(u.toolBlocks)?u.toolBlocks:[]).map(N=>{let R=typeof N?.name=="string"?N.name:"";return R?{tool:R,input:N?.input}:null}).filter(Boolean),v=s.steps[s.steps.length-1];v&&(_.length>1?(v.action=_[0],v.parallelActions=_):p&&(v.action={tool:p,input:T}),m&&(v.thinking=m))}continue}if(c.type==="observation"&&s){let u=typeof c.content=="string"?c.content:"",p=s.steps[s.steps.length-1];p&&(p.observation=u);continue}}}return{summary:o.join(`
|
|
114
|
-
`),messages:e,turns:n,maxSequence:a}}var ap=`
|
|
83
|
+
Keep the result concise and actionable.`,T=ce($.INIT);ie(L=>[...L,T]),y(!0);try{j.current=T,await W.runTurn(g)}catch{y(!1)}},[M,W]),Ar=Z(async g=>{let T=g.trim();if(T){if(T.toLowerCase()===zo){await x();return}if(T===ce($.INIT)){await pn();return}if(!(!W||M)){ie(L=>[...L,T]),y(!0);try{await W.runTurn(T)}catch{y(!1)}}}},[M,x,pn,W]),wr=Z(async()=>{try{let g=await Q(),T=be(g.config);_(g.config.providers),w(T.name),I(T.model),N(L=>({...L,sessionId:nt(),providerName:T.name})),Re(!1),C("Setup",`Config saved to ${g.configPath}`)}catch(g){C("Setup",`Failed to reload config: ${g.message}`,"error")}},[C]);kt(()=>{if(!W||!q?.length)return;let g=W.history[0];g&&(W.history.splice(0,W.history.length,g,...q),B(null))},[q,W]);let br=Z(g=>{let T=Se.current;T&&(T(g),Se.current=null),Fe(null)},[]),kr=Do(m.turns[m.turns.length-1]?.tokenUsage),Mr=No(V,b);return de?Pe(gr,{children:Pe(ac,{color:"green",children:de})}):K?Pe(ir,{configPath:o,onComplete:wr,onExit:x}):cc(gr,{flexDirection:"column",children:[Pe(Bo,{header:{providerName:h,model:f,cwd:r,sessionId:U.sessionId??"unknown",mcpNames:Object.keys(s??{}).sort(),version:P?.version??"unknown"},systemMessages:m.systemMessages,turns:m.turns,historicalTurns:m.historicalTurns}),Pe(Qo,{disabled:!W||!!z,busy:M,history:E,cwd:r,sessionsDir:i,currentSessionFile:D??void 0,providers:S,configPath:o,providerName:h,model:f,contextLimit:b,mcpServers:s,onSubmit:g=>{Ar(g)},onExit:()=>{x()},onClear:F,onNewSession:fe,onCancelRun:Er,onHistorySelect:g=>{Cr(g)},onModelSelect:g=>{vr(g)},onSetContextLimit:xr,onSystemMessage:C}),z?Pe(rr,{request:z,onDecision:br}):null,Pe(nr,{busy:M,contextPercent:Mr,tokenLine:kr})]})}var uc=`
|
|
115
84
|
Usage:
|
|
116
85
|
memo mcp list [--json]
|
|
117
86
|
memo mcp get <name> [--json]
|
|
@@ -120,14 +89,14 @@ Usage:
|
|
|
120
89
|
memo mcp remove <name>
|
|
121
90
|
memo mcp login <name> [--scopes scope1,scope2]
|
|
122
91
|
memo mcp logout <name>
|
|
123
|
-
`;function
|
|
124
|
-
`)}function
|
|
125
|
-
`),{...e,config:
|
|
126
|
-
[approval required] ${
|
|
127
|
-
[tool] ${
|
|
128
|
-
`);let
|
|
129
|
-
${
|
|
130
|
-
[tokens] prompt=${
|
|
131
|
-
provider=${n.name} model=${n.model}`)}catch(
|
|
132
|
-
`)),await
|
|
92
|
+
`;function ln(){console.log(uc.trim())}function pc(t){let e=t.indexOf("=");if(e<=0)return null;let n=t.slice(0,e).trim(),o=t.slice(e+1);return n?{key:n,value:o}:null}function yr(t,e){let n=[];if(n.push(`${t}`),"url"in e){n.push(` type: ${e.type??"streamable_http"}`),n.push(` url: ${e.url}`),e.bearer_token_env_var&&n.push(` bearer_token_env_var: ${e.bearer_token_env_var}`);let o=e.http_headers??e.headers;o&&Object.keys(o).length>0&&n.push(` headers: ${Object.entries(o).map(([s,r])=>`${s}=${r}`).join(", ")}`)}else n.push(` type: ${e.type??"stdio"}`),n.push(` command: ${e.command}`),e.args&&e.args.length>0&&n.push(` args: ${e.args.join(" ")}`),e.env&&Object.keys(e.env).length>0&&n.push(` env: ${Object.entries(e.env).map(([o,s])=>`${o}=${s}`).join(", ")}`);return n.join(`
|
|
93
|
+
`)}function mc(t){let e=t.shift();if(!e)return{error:"Missing server name."};let n,o,s={},r=[];for(let i=0;i<t.length;i+=1){let l=t[i];if(l){if(l==="--"){r=t.slice(i+1);break}if(l==="--url"){let a=t[i+1];if(!a)return{error:"Missing value for --url."};n=a,i+=1;continue}if(l==="--bearer-token-env-var"){let a=t[i+1];if(!a)return{error:"Missing value for --bearer-token-env-var."};o=a,i+=1;continue}if(l==="--env"){let a=t[i+1];if(!a)return{error:"Missing value for --env (KEY=VALUE)."};let c=pc(a);if(!c)return{error:"Invalid --env format. Use KEY=VALUE."};s[c.key]=c.value,i+=1;continue}return l==="--help"||l==="-h"?{error:""}:{error:`Unknown option: ${l}`}}}return n?r.length>0?{error:"Use either --url or a stdio command, not both."}:Object.keys(s).length>0?{error:"--env is only supported with stdio servers."}:{options:{name:e,url:n,bearerTokenEnvVar:o}}:o?{error:"--bearer-token-env-var is only supported with HTTP servers."}:r.length===0?{error:"Missing stdio command. Use `-- <command...>`."}:{options:{name:e,command:r[0],args:r.slice(1),env:Object.keys(s).length>0?s:void 0}}}function dc(t){let[e,...n]=t;return!e||e==="--help"||e==="-h"||e==="help"?{command:"help",rest:[]}:{command:e,rest:n}}function cn(t,e=[]){let n=new Set(e);for(let o=0;o<t.length;o+=1){let s=t[o];if(s){if(s.startsWith("--")){n.has(s)&&(o+=1);continue}return s}}return null}async function Tr(t){let{command:e,rest:n}=dc(t);if(e==="help"){ln();return}if(e==="list"){let o=n.includes("--json"),r=(await Q()).config.mcp_servers??{};if(o){console.log(JSON.stringify(r,null,2));return}let i=Object.keys(r);if(i.length===0){console.log('No MCP servers configured. Add one with "memo mcp add".');return}console.log(`MCP servers (${i.length}):`);for(let l of i){let a=r[l];a&&console.log(yr(l,a))}return}if(e==="get"){let o=n.includes("--json"),s=cn(n);if(!s){console.error("Missing server name."),process.exitCode=1;return}let i=(await Q()).config.mcp_servers?.[s];if(!i){console.error(`Unknown MCP server "${s}".`),process.exitCode=1;return}if(o){console.log(JSON.stringify(i,null,2));return}console.log(yr(s,i));return}if(e==="add"){let o=mc(n);if(o.error!==void 0){o.error&&(console.error(o.error),process.exitCode=1),ln();return}let s=o.options;if(!s)return;if(s.url)try{new URL(s.url)}catch{console.error("Invalid URL."),process.exitCode=1;return}let r=await Q(),i={...r.config.mcp_servers??{}};if(i[s.name]){console.error(`MCP server "${s.name}" already exists.`),process.exitCode=1;return}let l;s.url?l={type:"streamable_http",url:s.url,...s.bearerTokenEnvVar?{bearer_token_env_var:s.bearerTokenEnvVar}:{}}:l={command:s.command,args:s.args&&s.args.length>0?s.args:void 0,env:s.env},i[s.name]=l,await le(r.configPath,{...r.config,mcp_servers:i}),console.log(`Added MCP server "${s.name}".`);return}if(e==="remove"){let o=cn(n);if(!o){console.error("Missing server name."),process.exitCode=1;return}let s=await Q(),r={...s.config.mcp_servers??{}};if(!r[o]){console.error(`Unknown MCP server "${o}".`),process.exitCode=1;return}delete r[o],await le(s.configPath,{...s.config,mcp_servers:r}),console.log(`Removed MCP server "${o}".`);return}if(e==="login"||e==="logout"){let o=cn(n,["--scopes"]);if(!o){console.error("Missing server name."),process.exitCode=1;return}let r=(await Q()).config.mcp_servers?.[o];if(!r){console.error(`Unknown MCP server "${o}".`),process.exitCode=1;return}if(!("url"in r)){console.error("OAuth login/logout only applies to streamable HTTP servers."),process.exitCode=1;return}console.error("OAuth login/logout is not supported in memo yet. Configure a bearer token env var instead."),process.exitCode=1;return}console.error(`Unknown subcommand: ${e}`),ln(),process.exitCode=1}import{jsx as Cc}from"react/jsx-runtime";function Tc(t){let e={dangerous:!1,showVersion:!1,removedOnceFlag:!1},n=[];for(let o=0;o<t.length;o++){let s=t[o];if(s!==void 0){if(s==="--version"||s==="-v"){e.showVersion=!0;continue}if(s==="--once"){e.removedOnceFlag=!0;continue}if(s==="--dangerous"||s==="-d"){e.dangerous=!0;continue}n.push(s)}}return{question:n.join(" "),options:e}}async function Sr(t){let e=await Q();if(!e.needsSetup)return e;let n=e.config.providers[0],s=[n?.env_api_key,"OPENAI_API_KEY","DEEPSEEK_API_KEY"].filter(Boolean).some(l=>!!process.env[l]);if(n&&s)return await le(e.configPath,e.config),console.log(`Detected API key in env. Wrote default provider (${n.name}) to ${e.configPath}`),{...e,needsSetup:!1};if(t==="tui")return e;let r=fc({input:gc,output:hc}),i=async(l,a)=>(await r.question(l)).trim()||a;try{console.log("No provider config found. Please answer the prompts:");let l=await i("Provider name [deepseek]: ","deepseek"),a=await i("API key env var [DEEPSEEK_API_KEY]: ","DEEPSEEK_API_KEY"),c=await i("Model name [deepseek-chat]: ","deepseek-chat"),u=await i("Base URL [https://api.deepseek.com]: ","https://api.deepseek.com"),m={current_provider:l,providers:[{name:l,env_api_key:a,model:c,base_url:u||void 0}]};return await le(e.configPath,m),console.log(`Config written to ${e.configPath}
|
|
94
|
+
`),{...e,config:m,needsSetup:!1}}finally{r.close()}}async function _c(t){let e=await Sr("plain"),n=be(e.config),s={sessionId:_r(),mode:"interactive",maxPromptTokens:e.config.max_prompt_tokens,dangerous:t.options.dangerous};t.options.dangerous&&console.log("\u26A0\uFE0F DANGEROUS MODE: All tool approvals are bypassed!");let r={requestApproval:t.options.dangerous?void 0:a=>(console.log(`
|
|
95
|
+
[approval required] ${a.toolName}: ${a.reason}`),console.log("[approval] Run with --dangerous to bypass approval"),Promise.resolve("deny")),hooks:{onAction:({action:a})=>{console.log(`
|
|
96
|
+
[tool] ${a.tool}`),a.input!==void 0&&console.log(`[input] ${JSON.stringify(a.input)}`)},onObservation:()=>{}}},i=await dt(r,s),l=t.question;if(!l&&!process.stdin.isTTY&&(l=await xc()),!l){console.error("No input provided. Pass a question or use stdin."),await i.close();return}try{console.log(`User: ${l}
|
|
97
|
+
`);let a=await i.runTurn(l);console.log(`
|
|
98
|
+
${a.finalText}`),console.log(`
|
|
99
|
+
[tokens] prompt=${a.tokenUsage.prompt} completion=${a.tokenUsage.completion} total=${a.tokenUsage.total}`),console.log(`
|
|
100
|
+
provider=${n.name} model=${n.model}`)}catch(a){console.error(`Run failed: ${a.message}`)}finally{await i.close()}}async function Sc(t){let e=await Sr("tui"),n=be(e.config),s={sessionId:_r(),mode:"interactive",maxPromptTokens:e.config.max_prompt_tokens,dangerous:t.options.dangerous},r=mt(e,s);t.options.dangerous&&(console.log("\u26A0\uFE0F DANGEROUS MODE: All tool approvals are bypassed!"),console.log(` Use with caution.
|
|
101
|
+
`)),await yc(Cc(hr,{sessionOptions:s,providerName:n.name,model:n.model,configPath:e.configPath,mcpServers:e.config.mcp_servers??{},cwd:process.cwd(),sessionsDir:r,providers:e.config.providers,dangerous:t.options.dangerous,needsSetup:e.needsSetup}),{exitOnCtrlC:!1,patchConsole:!1}).waitUntilExit()}async function vc(){let t=process.argv.slice(2);if(t[0]==="mcp"||t[0]==="--"&&t[1]==="mcp"){let o=t[0]==="--"?2:1;await Tr(t.slice(o));return}let e=Tc(t);if(e.options.removedOnceFlag){console.error("`--once` has been removed. Use `memo` (interactive) or pipe input to `memo`."),process.exitCode=1;return}if(e.options.showVersion){let s=bt()?.version??"unknown";console.log(s);return}if(!(process.stdin.isTTY&&process.stdout.isTTY)){await _c(e);return}await Sc(e)}vc();async function xc(){return new Promise(t=>{let e="";process.stdin.setEncoding("utf8"),process.stdin.on("data",n=>{e+=n}),process.stdin.on("end",()=>{t(e.trim())}),process.stdin.resume()})}
|
|
133
102
|
//# sourceMappingURL=index.js.map
|
package/dist/prompt.md
CHANGED
|
@@ -108,6 +108,9 @@ assistant: [Makes ONE message with list_dir + grep_files tool calls in parallel]
|
|
|
108
108
|
|
|
109
109
|
- Use structured tool/function calls provided by the runtime instead of emitting tool JSON in plain text.
|
|
110
110
|
- Keep tool arguments valid and minimal; for shell commands prefer a single-line string unless multiline is required.
|
|
111
|
+
- Final answer MUST be the last step in a turn.
|
|
112
|
+
- Do NOT call any tool after you have already produced the user-facing final answer.
|
|
113
|
+
- If you need `update_plan`, run it before the final answer, not after.
|
|
111
114
|
|
|
112
115
|
---
|
|
113
116
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memo-code/memo",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.32",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "A lightweight coding agent that runs in your terminal",
|
|
@@ -41,18 +41,18 @@
|
|
|
41
41
|
"zod-to-json-schema": "^3.25.1"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
|
-
"start": "tsx packages/
|
|
44
|
+
"start": "tsx packages/tui/src/cli.tsx",
|
|
45
45
|
"build": "tsup",
|
|
46
46
|
"dev": "tsup --watch",
|
|
47
47
|
"web:dev": "pnpm --filter @memo-code/web dev",
|
|
48
48
|
"web:build": "pnpm --filter @memo-code/web build",
|
|
49
49
|
"web:start": "pnpm --filter @memo-code/web start",
|
|
50
|
-
"format": "prettier --write .",
|
|
51
|
-
"format:check": "prettier --check .",
|
|
50
|
+
"format": "prettier --write \"{packages,web}/**/*.{ts,tsx,js,jsx,mjs,cjs,json,css,mdx}\" \"{package.json,pnpm-workspace.yaml,tsconfig.json,tsup.config.ts,vitest.config.ts,vitest.setup.ts,.prettierrc}\"",
|
|
51
|
+
"format:check": "prettier --check \"{packages,web}/**/*.{ts,tsx,js,jsx,mjs,cjs,json,css,mdx}\" \"{package.json,pnpm-workspace.yaml,tsconfig.json,tsup.config.ts,vitest.config.ts,vitest.setup.ts,.prettierrc}\"",
|
|
52
52
|
"test": "vitest run",
|
|
53
53
|
"test:core": "vitest run packages/core",
|
|
54
54
|
"test:tools": "vitest run packages/tools",
|
|
55
|
-
"test:
|
|
55
|
+
"test:tui": "vitest run packages/tui",
|
|
56
56
|
"ci": "pnpm run format:check && pnpm run test:core && pnpm run test:tools && pnpm run build",
|
|
57
57
|
"release:patch": "npm version patch && npm publish",
|
|
58
58
|
"release:minor": "npm version minor && npm publish",
|