agentpager-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/LICENSE +14 -0
  2. package/README.md +44 -0
  3. package/dist/cli.js +31 -0
  4. package/package.json +59 -0
package/LICENSE ADDED
@@ -0,0 +1,14 @@
1
+ Copyright (c) 2026 AgentPager (agentpaper.io@gmail.com). All rights reserved.
2
+
3
+ Permission is granted to install and use this software ("AgentPager daemon")
4
+ free of charge for personal and internal business purposes, solely in
5
+ conjunction with the AgentPager service.
6
+
7
+ You may NOT, without prior written permission:
8
+ - redistribute, sublicense, or sell copies of this software;
9
+ - modify, decompile, reverse engineer, or create derivative works of it,
10
+ except to the extent such restriction is prohibited by applicable law.
11
+
12
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13
+ IMPLIED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
14
+ OTHER LIABILITY ARISING FROM THE USE OF THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,44 @@
1
+ # AgentPager
2
+
3
+ 手机遥控你电脑上的编程 Agent。
4
+
5
+ 在微信小程序里实时查看 Claude Code / Codex / Gemini CLI 等 7 家编程 Agent 的会话,随时随地续聊、语音输入、发图片——就像给你的 Agent 配了一台传呼机。
6
+
7
+ ## 快速开始
8
+
9
+ 电脑上(macOS / Linux):
10
+
11
+ ```bash
12
+ npm install -g agentpager-cli
13
+ agentpager pair # 出配对码
14
+ ```
15
+
16
+ 手机上:微信搜索小程序「AgentPager」(或扫体验码)→ 配对页输入/扫描电脑上的配对码 → 完成。
17
+
18
+ 配对后启动守护进程:
19
+
20
+ ```bash
21
+ agentpager start
22
+ ```
23
+
24
+ ## 它能做什么
25
+
26
+ - **全历史聚合**:电脑上所有 Agent 会话(Claude Code、Codex、Gemini、Qwen、CodeBuddy、Cursor、OpenCode)一个列表看完
27
+ - **续聊**:点开任意会话接着聊,多轮上下文不丢
28
+ - **实时渲染**:工具调用、diff、推理过程结构化展示,和桌面端一致
29
+ - **语音输入**:说话转文字直接发给 Agent
30
+ - **发图片**:截图/照片直接发给 Agent 分析
31
+ - **端到端加密**:配对密钥仅存于你的手机和电脑,中继服务器只透传密文,无法解读内容
32
+
33
+ ## 命令
34
+
35
+ ```
36
+ agentpager pair 配对(电脑出码,手机扫码或手输)
37
+ agentpager start 启动守护进程
38
+ agentpager status 查看配对与 agent 状态
39
+ agentpager doctor 环境自检
40
+ ```
41
+
42
+ ## 隐私
43
+
44
+ 会话数据只在你的设备之间端到端加密传输;中继不落盘、不解密。详见小程序内隐私说明。
package/dist/cli.js ADDED
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env node
2
+ var Gs=Object.defineProperty;var T=(s,e,t)=>()=>{if(t)throw t[0];try{return s&&(e=s(s=0)),e}catch(r){throw t=[r],r}};var G=(s,e)=>{for(var t in e)Gs(s,t,{get:e[t],enumerable:!0})};var ht={};G(ht,{detect:()=>he,registerDefaults:()=>_e,versionsFor:()=>Zs});import{execSync as Fs,execFile as Js}from"node:child_process";import{promisify as Ks}from"node:util";import{homedir as Ws}from"node:os";import{randomUUID as Hs}from"node:crypto";function q(s){try{return Fs(`command -v ${s}`,{stdio:"ignore"}),!0}catch{return!1}}function he(){let s=[];return(q(process.env.AGENTPAGER_CLAUDE_BIN||"claude")||q("claude"))&&s.push("claude"),q("codex")&&s.push("codex"),q("codebuddy")&&s.push("codebuddy"),q("qwen")&&s.push("qwen"),q("opencode")&&s.push("opencode"),q("gemini")&&s.push("gemini"),(q("cursor-agent")||q(`${process.env.HOME}/.local/bin/cursor-agent`))&&s.push("cursor"),s}function _e(s){if(s.agents.length)return s;let e=Ws();for(let t of he())s.agents.push({agent_id:"agent_"+Hs().slice(0,8),agent_version:1,provider:t,workdir:e,name:`${t} @ home`});return s}function zs(s){let e=String(s||"").trim().split(`
3
+ `)[0],t=e.match(Vs);return t?t[0]:e.slice(0,24)}async function Qs(s){if(Be.has(s))return Be.get(s);let e=Ys[s]||s,t="";try{let{stdout:r}=await Xs(e,["--version"],{timeout:3e3});t=zs(r)}catch{}return Be.set(s,t),t}async function Zs(s){let e=[...new Set(s)],t=await Promise.all(e.map(async r=>[r,await Qs(r)]));return Object.fromEntries(t)}var Xs,Ys,Vs,Be,Ue=T(()=>{Xs=Ks(Js);Ys={claude:process.env.AGENTPAGER_CLAUDE_BIN||"claude",codex:"codex",codebuddy:"codebuddy",qwen:"qwen",opencode:"opencode",gemini:"gemini",cursor:"cursor-agent"},Vs=/\d+\.\d+(?:\.\d+)?/;Be=new Map});function Fe(s){if(!s||typeof s!="object")return null;if(s.kind)return s;switch(s.type){case"delta":return{kind:"chat.assistant_delta",text:s.text};case"tool_use":return{kind:"chat.tool_use",tool:s.tool.name,target:s.tool.title||""};case"done":return{kind:"chat.assistant_done"};default:return null}}function Rt(s){if(typeof s!="string")return"";let e=s.match(/^(?:\/usr\/bin\/|\/bin\/)?(?:ba)?sh\s+-l?c\s+(['"])([\s\S]*)\1\s*$/);return e?e[2]:s}function B({commandActions:s,name:e}={}){let t=Array.isArray(s)&&s[0]?s[0].type:null;if(t==="listFiles"||t==="readFile"||t==="read")return"read";if(t==="search"||t==="grep")return"search";if(t)return"bash";let r=String(e||"").toLowerCase();return/edit|write|patch|apply|replace/.test(r)?"edit":/read|cat|view|list|^ls/.test(r)?"read":/search|grep|glob|find/.test(r)?"search":/bash|exec|shell|run|command|terminal/.test(r)?"bash":"other"}function jt(s){return typeof s!="string"?{output:void 0,output_truncated:!1}:s.length<=Nt?{output:s,output_truncated:!1}:{output:s.slice(0,Nt),output_truncated:!0}}function Gt(s,e){let r={add:"added",delete:"deleted",update:"edited",edit:"edited",move:"edited"}[s?.kind?.type]||"edited",n=ur(s?.path||"",e),i=typeof s?.diff=="string"?s.diff:"";if(r==="added"&&!/^@@|^---|^diff --git/m.test(i)){let o=i.replace(/\n$/,"").split(`
4
+ `).map((a,l)=>({sign:"+",n:l+1,text:a}));return{path:n,verb:r,add:o.length,del:0,hunks:[{lines:o}]}}return{path:n,verb:r,...Je(i)}}function Lt(s,e){let t=String(e||"").replace(/\n$/,"").split(`
5
+ `).map((r,n)=>({sign:"+",n:n+1,text:r}));return{path:s,verb:"added",add:t.length,del:0,hunks:[{lines:t}]}}function Dt(s,e,t){let r=String(e||"").replace(/\n$/,"").split(`
6
+ `),n=String(t||"").replace(/\n$/,"").split(`
7
+ `),i=r.map(o=>({sign:"-",text:o})).concat(n.map(o=>({sign:"+",text:o})));return{path:s,verb:"edited",add:n.length,del:r.length,hunks:[{lines:i}]}}function Je(s){let e=[],t=null,r=0,n=0,i=0,o=0;for(let a of String(s||"").split(`
8
+ `)){if(a.startsWith("diff --git")||a.startsWith("index ")||a.startsWith("--- ")||a.startsWith("+++ ")||a.startsWith("new file")||a.startsWith("deleted file")||a.startsWith("rename "))continue;let l=a.match(/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/);if(l){t={lines:[]},e.push(t),i=+l[1],o=+l[2];continue}t&&(a.startsWith("+")?(t.lines.push({sign:"+",n:o++,text:a.slice(1)}),r++):a.startsWith("-")?(t.lines.push({sign:"-",n:i++,text:a.slice(1)}),n++):a.startsWith(" ")&&(t.lines.push({sign:" ",n:o,text:a.slice(1)}),i++,o++))}return{add:r,del:n,hunks:e}}function ur(s,e){if(e&&s.startsWith(e))return s.slice(e.length).replace(/^\//,"")||s;let t=s.lastIndexOf("/");return t>=0?s.slice(t+1):s}var Nt,b,lr,Ot,Pt,U=T(()=>{Nt=Number(process.env.AGENTPAGER_OUTPUT_PREVIEW_MAX||4e3),b={sessionBound:s=>({type:"session_bound",sdk_session_id:s}),user:(s,e)=>({type:"user",text:s,...e&&e.length?{images:e}:{}}),delta:(s,e,t)=>({type:"delta",text:s,...e?{item_id:e}:{},...t?{phase:t}:{}}),reasoning:(s,e="")=>({type:"reasoning",elapsed_ms:s,text:e}),toolUse:s=>({type:"tool_use",tool:s}),toolResult:s=>({type:"tool_result",result:s}),boundary:s=>({type:"boundary",kind:s}),threadTitle:s=>({type:"thread_title",title:s}),error:s=>({type:"error",message:s}),done:(s="completed")=>({type:"done",reason:s})},lr=0,Ot=()=>`t${++lr}`;Pt={read:"Read",edit:"Edit",bash:"Bash",search:"Search",mcp:"Call",other:"Tool"}});function $(){let s=new Map;function e(t){if(!t||!t.type)return[];let r=[];if(t.type==="assistant"){let n=t.message?.id;for(let i of t.message?.content||[])i.type==="text"&&i.text?r.push(b.delta(i.text,n)):i.type==="thinking"&&(i.thinking||i.text)?r.push(b.reasoning(0,i.thinking||i.text)):i.type==="tool_use"&&(s.set(i.id,{name:i.name,input:i.input||{}}),r.push(b.toolUse({tool_use_id:i.id,name:i.name,kind:B({name:i.name}),title:dr(i.input),input:i.input})))}else if(t.type==="user")for(let n of t.message?.content||[]){if(n.type!=="tool_result")continue;let i=s.get(n.tool_use_id)||{},o={tool_use_id:n.tool_use_id,status:n.is_error?"error":"ok",output:fr(n.content)},a=pr(i.name,i.input);a&&(o.diff=[a]),r.push(b.toolResult(o))}else t.type==="result"&&r.push(b.done(t.subtype==="success"&&!t.is_error?"completed":"error"));return r}return{onMessage:e}}function Ke(s){let e=String(s||"").lastIndexOf("/");return e>=0?s.slice(e+1):s}function dr(s){s=s||{};let e=s.command||s.file_path&&Ke(s.file_path)||s.pattern||"";return String(e).replace(/\s+/g," ").trim().slice(0,60)}function fr(s){return typeof s=="string"?s:Array.isArray(s)?s.map(e=>typeof e=="string"?e:e?.text||"").join(""):""}function pr(s,e){if(!s||!e)return null;let t=String(s).toLowerCase();return(/^write$/.test(t)||/write_file/.test(t))&&e.content!=null?Lt(Ke(e.file_path),e.content):(/^(edit|multiedit)$/.test(t)||/^replace$/.test(t))&&e.old_string!=null?Dt(Ke(e.file_path),e.old_string,e.new_string):null}var le=T(()=>{U()});function qt({repoRoot:s}={}){let e=new Map,t=new Map;function r(o){if(!o||!o.method)return[];let a=o.params||{};switch(o.method){case"item/agentMessage/delta":{let l=e.get(a.itemId);return a.delta?[b.delta(a.delta,a.itemId,l)]:[]}case"item/started":return n(a.item,a);case"item/completed":return i(a.item,a);case"turn/completed":return[b.done("completed")];case"thread/closed":return[b.done("error")];case"thread/realtime/error":return[b.error(a.message||"realtime error"),b.done("error")];default:return[]}}function n(o,a){if(!o)return[];switch(o.type){case"agentMessage":return e.set(o.id,o.phase||"commentary"),[b.boundary("assistant_segment")];case"reasoning":return t.set(o.id,a.startedAtMs||0),[];case"commandExecution":{let l=Rt(o.command);return[b.toolUse({tool_use_id:o.id,name:Pt[B({commandActions:o.commandActions})]||"Bash",kind:B({commandActions:o.commandActions}),title:l,input:{command:l,cwd:o.cwd}})]}case"fileChange":return[b.toolUse({tool_use_id:o.id,name:"Edit",kind:"edit",title:(o.changes||[]).map(l=>hr(l.path)).join(", "),input:{changes:o.changes}})];default:return[]}}function i(o,a){if(!o)return[];switch(o.type){case"reasoning":{let l=t.get(o.id)||0,d=l&&a.completedAtMs?a.completedAtMs-l:0,p=mr(o);return[b.reasoning(d,p)]}case"commandExecution":return[b.toolResult({tool_use_id:o.id,status:o.exitCode===0?"ok":"error",exit_code:typeof o.exitCode=="number"?o.exitCode:void 0,duration_ms:typeof o.durationMs=="number"?o.durationMs:void 0,output:o.aggregatedOutput||""})];case"fileChange":return[b.toolResult({tool_use_id:o.id,status:o.status==="failed"?"error":"ok",diff:(o.changes||[]).map(l=>Gt(l,s))})];case"agentMessage":return[];default:return[]}}return{onMessage:r}}function mr(s){let e=[];for(let t of[s.summary,s.content])for(let r of t||[])e.push(typeof r=="string"?r:r&&(r.text||r.content)||"");return e.filter(Boolean).join(`
9
+ `)}function hr(s){let e=String(s||"").lastIndexOf("/");return e>=0?s.slice(e+1):s}var Bt=T(()=>{U()});var $t={};G($t,{CodexSession:()=>We});import{spawn as _r}from"node:child_process";import{existsSync as gr}from"node:fs";var yr,Ut,We,Ft=T(()=>{Bt();yr=()=>{if(process.env.AGENTPAGER_CODEX_BIN)return process.env.AGENTPAGER_CODEX_BIN;let s=process.env.HOME+"/.npm-global/bin/codex";return gr(s)?s:"codex"},Ut=process.env.AGENTPAGER_CODEX_SANDBOX||"workspace-write",We=class{constructor({workdir:e,resumeSessionId:t,onSessionId:r,model:n}){this.onSessionId=r,this._workdir=e,this._model=n&&n!=="default"?n:null,this._id=0,this._pending=new Map,this._buf="",this._active=null,this._threadId=null,this._turnId=null,this._closed=!1,this._ready=this._boot({workdir:e,resumeSessionId:t})}_rpc(e,t){let r=++this._id;return this.child.stdin.write(JSON.stringify({jsonrpc:"2.0",id:r,method:e,params:t})+`
10
+ `),new Promise((n,i)=>this._pending.set(r,{resolve:n,reject:i}))}_respond(e,t){this.child.stdin.write(JSON.stringify({jsonrpc:"2.0",id:e,result:t})+`
11
+ `)}async _boot({workdir:e,resumeSessionId:t}){if(this.child=_r(yr(),["app-server","--listen","stdio://"],{stdio:["pipe","pipe","ignore"]}),this.child.stdout.on("data",r=>this._onData(r)),this.child.on("exit",()=>{this._closed=!0;let r=this._active;this._active=null,r?.resolve?.({done:!0,error:"codex_exited"})}),await this._rpc("initialize",{clientInfo:{name:"agentpager",version:"0.0.1"},capabilities:null}),t){let r=await this._rpc("thread/resume",{threadId:t,sandbox:Ut});this._threadId=r?.thread?.id||t}else{let r=await this._rpc("thread/start",{cwd:e,sandbox:Ut,approvalPolicy:"on-request"});this._threadId=r?.thread?.id}return this._threadId&&this.onSessionId?.(this._threadId),this._threadId}_onData(e){this._buf+=e.toString();let t;for(;(t=this._buf.indexOf(`
12
+ `))>=0;){let r=this._buf.slice(0,t);if(this._buf=this._buf.slice(t+1),!r.trim())continue;let n;try{n=JSON.parse(r)}catch{continue}if(n.id!=null&&(n.result!==void 0||n.error!==void 0)){let i=this._pending.get(n.id);i&&(this._pending.delete(n.id),i.resolve(n.result))}else n.method&&n.id!=null?this._onServerRequest(n):n.method&&this._onNotification(n)}}async _onServerRequest(e){e.method.includes("Approval")||/Approval/i.test(e.method)||e.method.endsWith("requestApproval")?this._respond(e.id,{decision:"approved"}):this._respond(e.id,{})}_onNotification(e){e.method==="turn/started"&&(this._turnId=e.params?.turnId||e.params?.turn?.id||this._turnId);let t=this._active;if(!t)return;let r=this._mapper?this._mapper.onMessage(e):[];for(let n of r)if(t.onEvent?t.onEvent(n):n.type==="delta"?t.onDelta?.(n.text):n.type==="tool_use"&&t.onToolUse?.(n.tool.name),n.type==="done"){this._active=null,t.resolve?.({done:!0,reason:n.reason});return}}async runTurn({text:e,onDelta:t,onToolUse:r,onApproval:n,onEvent:i}){return await this._ready,this._mapper=qt({repoRoot:this._workdir}),new Promise(o=>{this._active={onDelta:t,onToolUse:r,onEvent:i,resolve:o};let a={threadId:this._threadId,input:[{type:"text",text:e,text_elements:[]}]};this._model&&(a.model=this._model),this._rpc("turn/start",a).catch(l=>{let d=this._active;this._active=null,d?.resolve?.({done:!0,error:l.message})})})}async interrupt(){if(await this._ready,this._threadId&&this._turnId)return this._rpc("turn/interrupt",{threadId:this._threadId,turnId:this._turnId}).catch(()=>{})}setModel(e){this._model=e&&e!=="default"?e:null}setPermissionMode(){}close(){this._closed=!0;try{this.child.kill("SIGTERM")}catch{}}}});import{spawn as wr}from"node:child_process";import{createInterface as xr}from"node:readline";var br,vr,W,xe=T(()=>{br=Number(process.env.AGENTPAGER_CLI_TIMEOUT_MS||12e4),vr=1500,W=class{constructor({workdir:e,resumeSessionId:t,onSessionId:r,model:n}){this.workdir=e||process.env.HOME,this.sessionId=t||null,this._started=!!t,this.model=n,this.onSessionId=r,this._child=null}get watchdogMs(){return br}get killGraceMs(){return vr}get detached(){return!0}get surfaceErrOnEmpty(){return!0}spawnEnv(){return process.env}runTurn(e){let t=()=>this._doTurn(e);return this._chain=(this._chain||Promise.resolve()).then(t,t),this._chain}_killTree(e,t){if(!(!e||!e.pid))try{process.kill(-e.pid,t)}catch{try{e.kill(t)}catch{}}}interrupt(){let e=this._child;this._killTree(e,"SIGTERM"),e&&setTimeout(()=>this._killTree(e,"SIGKILL"),this.killGraceMs)}close(){this._killTree(this._child,"SIGKILL")}setModel(e){this.model=e}setPermissionMode(){}_doTurn({text:e,onDelta:t,onToolUse:r,onEvent:n}){return new Promise(i=>{let o;try{o=wr(this.bin,this.buildArgs(e),{cwd:this.workdir,stdio:["ignore","pipe","pipe"],detached:this.detached,env:this.spawnEnv()})}catch(g){i({done:!0,error:g.message});return}this._child=o;let a=!1,l=!1,d=null,p="",u=g=>{l||(l=!0,clearTimeout(y),d&&clearTimeout(d),this._child=null,i(g))},O={onDelta:t,onToolUse:r,onEvent:n,dispatch:g=>{g.type==="delta"&&(a=!0),n?n(g):g.type==="delta"?t&&t(g.text):g.type==="tool_use"&&r&&r(g.tool.name)},finishAfterResult:()=>{d||(this._killTree(o,"SIGTERM"),d=setTimeout(()=>this._killTree(o,"SIGKILL"),this.killGraceMs))},isEmitted:()=>a,markEmitted:()=>{a=!0},captureSessionId:g=>{this._started=!0,g&&g!==this.sessionId&&(this.sessionId=g,this.onSessionId&&this.onSessionId(g))}},y=setTimeout(()=>{a||t&&t("\u26A0\uFE0F \u54CD\u5E94\u8D85\u65F6,\u8BF7\u91CD\u8BD5"),this._killTree(o,"SIGKILL"),u({done:!0,error:"timeout"})},this.watchdogMs);xr({input:o.stdout}).on("line",g=>{let w=g.trim();if(!w)return;let h;try{h=JSON.parse(w)}catch{return}this.handleLine(h,O)}),o.stderr.on("data",g=>{p.length<8e3&&(p+=g)}),o.on("close",()=>{if(!a&&this.surfaceErrOnEmpty){let g=p.trim().split(`
13
+ `).map(w=>w.trim()).filter(Boolean).slice(-3).join(" ");/not logged in|unauthor|login|sign in/i.test(p)?(t&&t("\u26A0\uFE0F \u672A\u767B\u5F55:\u8BF7\u5728\u7535\u8111\u4E0A\u767B\u5F55\u8BE5 CLI \u540E\u91CD\u8BD5"),a=!0):g&&(t&&t("\u26A0\uFE0F "+g.slice(-400)),a=!0)}u({done:!0})}),o.on("error",g=>u({done:!0,error:g.message}))})}}});var Jt={};G(Jt,{CodeBuddySession:()=>He});import{randomUUID as Sr}from"node:crypto";var Ir,He,Kt=T(()=>{xe();le();U();Ir=process.env.AGENTPAGER_CODEBUDDY_BIN||"codebuddy",He=class extends W{constructor(e){super(e),this.sessionId=e.resumeSessionId||Sr(),e.resumeSessionId||this.onSessionId&&this.onSessionId(this.sessionId),this._mapper=$()}get bin(){return Ir}buildArgs(e){let t=["-p",e,"--output-format","stream-json","--permission-mode","acceptEdits"];return this._started?t.push("--resume",this.sessionId):t.push("--session-id",this.sessionId),this.model&&this.model!=="default"&&t.push("--model",this.model),t}handleLine(e,t){if(e.type==="system"&&e.subtype==="init"){t.captureSessionId(e.session_id);return}if(e.type==="result"){!t.isEmitted()&&e.result&&t.dispatch(b.delta(String(e.result)));for(let r of this._mapper.onMessage(e))t.dispatch(r);t.finishAfterResult();return}for(let r of this._mapper.onMessage(e))t.dispatch(r)}}});var Wt={};G(Wt,{QwenSession:()=>Xe});import{randomUUID as kr}from"node:crypto";var Er,Xe,Ht=T(()=>{xe();le();U();Er=process.env.AGENTPAGER_QWEN_BIN||"qwen",Xe=class extends W{constructor(e){super(e),this.sessionId=e.resumeSessionId||kr(),e.resumeSessionId||this.onSessionId&&this.onSessionId(this.sessionId),this._mapper=$()}get bin(){return Er}spawnEnv(){return{...process.env,QWEN_CODE_SUPPRESS_YOLO_WARNING:"1"}}buildArgs(e){let t=[e,"-o","stream-json","--approval-mode","auto-edit","--chat-recording"];return this._started?t.push("-r",this.sessionId):t.push("--session-id",this.sessionId),this.model&&this.model!=="default"&&t.push("-m",this.model),t}handleLine(e,t){if(e.type==="system"&&e.subtype==="init"){t.captureSessionId(e.session_id);return}if(e.type==="result"){!t.isEmitted()&&e.result&&t.dispatch(b.delta(String(e.result)));for(let r of this._mapper.onMessage(e))t.dispatch(r);t.finishAfterResult();return}for(let r of this._mapper.onMessage(e))t.dispatch(r)}}});var Xt={};G(Xt,{OpenCodeSession:()=>Ye});import{spawn as Ar}from"node:child_process";import{createInterface as Mr}from"node:readline";var Tr,Ye,Yt=T(()=>{Tr=process.env.AGENTPAGER_OPENCODE_BIN||"opencode",Ye=class{constructor({workdir:e,resumeSessionId:t,onSessionId:r,model:n}){this.workdir=e||process.env.HOME,this.sessionId=t||null,this.model=n,this.onSessionId=r,this._child=null}runTurn(e){let t=()=>this._doTurn(e);return this._chain=(this._chain||Promise.resolve()).then(t,t),this._chain}_doTurn({text:e,onDelta:t,onToolUse:r}){return new Promise(n=>{let i=["run",e,"--format","json","--dangerously-skip-permissions"];this.sessionId&&i.push("-s",this.sessionId),this.model&&this.model!=="default"&&i.push("-m",this.model);let o;try{o=Ar(Tr,i,{cwd:this.workdir,env:process.env,stdio:["ignore","pipe","pipe"]})}catch(l){n({done:!0,error:l.message});return}this._child=o,Mr({input:o.stdout}).on("line",l=>{let d=l.trim();if(!d||d[0]!=="{")return;let p;try{p=JSON.parse(d)}catch{return}p.sessionID&&p.sessionID!==this.sessionId&&(this.sessionId=p.sessionID,this.onSessionId&&this.onSessionId(p.sessionID));let u=p.part||{};p.type==="text"&&u.text?t&&t(u.text):(p.type==="tool"||u.type==="tool")&&(u.tool||u.name)&&r&&r(u.tool||u.name)}),o.stderr.on("data",()=>{}),o.on("close",()=>{this._child=null,n({done:!0})}),o.on("error",l=>{this._child=null,n({done:!0,error:l.message})})})}interrupt(){if(this._child)try{this._child.kill("SIGTERM")}catch{}}setModel(e){this.model=e}setPermissionMode(){}close(){if(this._child)try{this._child.kill("SIGTERM")}catch{}}}});var zt={};G(zt,{GeminiSession:()=>Ve});import{spawn as Cr}from"node:child_process";import{randomUUID as Nr}from"node:crypto";import{createInterface as Or}from"node:readline";import{readFileSync as Rr}from"node:fs";import{join as Pr}from"node:path";function Gr(){if(process.env.GEMINI_API_KEY)return process.env.GEMINI_API_KEY;try{let e=Rr(Pr(process.env.HOME,".gemini",".env"),"utf8").match(/^\s*GEMINI_API_KEY\s*=\s*(.+?)\s*$/m);if(e)return e[1].replace(/^["']|["']$/g,"").trim()}catch{}}var jr,Lr,Vt,Ve,Qt=T(()=>{jr=process.env.AGENTPAGER_GEMINI_BIN||"gemini";Lr=Number(process.env.AGENTPAGER_GEMINI_TIMEOUT_MS||12e4),Vt=1500,Ve=class{constructor({workdir:e,resumeSessionId:t,onSessionId:r,model:n}){this.workdir=e||process.env.HOME,this.sessionId=t||Nr(),this._started=!!t,this._sessionFile=t&&String(t).includes("/")?t:null,this.model=n&&n!=="default"?n:"gemma-4-31b-it",this.onSessionId=r,this._child=null,t||r&&r(this.sessionId)}runTurn(e){let t=()=>this._doTurn(e);return this._chain=(this._chain||Promise.resolve()).then(t,t),this._chain}_killTree(e,t){if(!(!e||!e.pid))try{process.kill(-e.pid,t)}catch{try{e.kill(t)}catch{}}}_doTurn({text:e,onDelta:t,onToolUse:r}){return new Promise(n=>{let i=["-p",e,"-o","stream-json","--approval-mode","yolo","--skip-trust","-e","none"];this._started?this._sessionFile?i.push("--session-file",this._sessionFile):i.push("-r","latest"):i.push("--session-id",this.sessionId),this.model&&this.model!=="default"&&i.push("-m",this.model);let o;try{let v=Gr();o=Cr(jr,i,{cwd:this.workdir,stdio:["ignore","pipe","pipe"],detached:!0,env:{...process.env,...v?{GEMINI_API_KEY:v}:{}}})}catch(v){n({done:!0,error:v.message});return}this._child=o;let a=!1,l=!1,d=null,p="",u=v=>{l||(l=!0,clearTimeout(O),d&&clearTimeout(d),this._child=null,n(v))},_=()=>{if(a)return;let v=p;if(/Auth method|GEMINI_API_KEY|GOOGLE_GENAI/i.test(v)){t&&t("\u26A0\uFE0F gemini \u672A\u767B\u5F55:\u8BF7\u5728\u7535\u8111\u4E0A\u8FD0\u884C `gemini` \u9009 \u201CLogin with Google\u201D \u767B\u5F55\u540E\u91CD\u8BD5"),a=!0;return}if(/quota|RESOURCE_EXHAUSTED|TerminalQuotaError|exhausted your daily|rate.?limit|\b429\b/i.test(v)){let k=(v.match(/retry in ([\d.]+)s/i)||[])[1];t&&t("\u26A0\uFE0F gemini \u4ECA\u65E5\u514D\u8D39\u989D\u5EA6\u5DF2\u7528\u5B8C/\u89E6\u53D1\u9650\u6D41"+(k?`,\u7EA6 ${Math.ceil(Number(k))}s \u540E\u53EF\u91CD\u8BD5`:",\u8BF7\u7A0D\u540E\u91CD\u8BD5\u6216\u5728\u7535\u8111\u4E0A\u6362\u7528\u4ED8\u8D39 key")),a=!0;return}let g=v.trim().split(`
14
+ `).map(k=>k.trim()).filter(Boolean).filter(k=>!/YOLO mode|Approval mode overridden|Loaded cached|DeprecationWarning|^at /i.test(k)),h=(g.find(k=>/error[::]|failed|invalid/i.test(k))||g.slice(-3).join(" ")).slice(-400);h&&(t&&t("\u26A0\uFE0F "+h),a=!0)},A=()=>{d||(this._killTree(o,"SIGTERM"),d=setTimeout(()=>this._killTree(o,"SIGKILL"),Vt))},O=setTimeout(()=>{a||t&&t("\u26A0\uFE0F gemini \u54CD\u5E94\u8D85\u65F6,\u8BF7\u91CD\u8BD5"),this._killTree(o,"SIGKILL"),u({done:!0,error:"timeout"})},Lr);Or({input:o.stdout}).on("line",v=>{let g=v.trim();if(!g)return;let w;try{w=JSON.parse(g)}catch{return}if(w.type==="init")this._started=!0,w.session_id&&w.session_id!==this.sessionId&&(this.sessionId=w.session_id),w.session_id&&this.onSessionId&&this.onSessionId(w.session_id);else if(w.type==="message"&&w.role==="assistant"&&w.content)t&&t(String(w.content)),a=!0;else if(w.type==="tool_call"&&(w.name||w.tool))r&&r(String(w.name||w.tool));else if(w.type==="result"){if(!a&&w.status&&w.status!=="success"){let h=w.error,k=h&&typeof h=="object"?h.message||h.type||JSON.stringify(h):h||w.status;t&&t("\u26A0\uFE0F gemini: "+String(k)),a=!0}A()}}),o.stderr.on("data",v=>{p.length<8e3&&(p+=v)}),o.on("close",()=>{_(),u({done:!0})}),o.on("error",v=>u({done:!0,error:v.message}))})}interrupt(){let e=this._child;this._killTree(e,"SIGTERM"),e&&setTimeout(()=>this._killTree(e,"SIGKILL"),Vt)}setModel(e){this.model=e}setPermissionMode(){}close(){this._killTree(this._child,"SIGKILL")}}});function Zt(){function s(e){if(!e||!e.type)return[];if(e.type==="assistant"&&Array.isArray(e.message?.content))return e.message.content.filter(t=>t.type==="text"&&t.text).map(t=>b.delta(t.text,e.message?.id));if(e.type==="result")return[b.done(e.subtype==="error"||e.is_error?"error":"completed")];if(e.type==="tool_call"){let t=e.tool_call||{},r=t.toolCallId||e.call_id,n=Object.keys(t).find(o=>o.endsWith("ToolCall")),i=n?t[n]:{};if(e.subtype==="started"){let o=Dr(n,i.args);return[b.toolUse({tool_use_id:r,name:o.name,kind:o.kind,title:o.title,input:i.args})]}if(e.subtype==="completed")return[qr(r,n,i,t.startedAtMs,t.completedAtMs)]}return[]}return{onMessage:s}}function be(s){let e=String(s||"").lastIndexOf("/");return e>=0?s.slice(e+1):s}function Dr(s,e={}){if(s==="editToolCall"||s==="writeToolCall")return{name:"Edit",kind:"edit",title:be(e.path)};if(s==="shellToolCall")return{name:"Bash",kind:"bash",title:e.command||""};if(s==="readToolCall")return{name:"Read",kind:"read",title:be(e.path)};if(s==="lsToolCall"||s==="listToolCall")return{name:"List",kind:"read",title:be(e.path)||""};if(s==="globToolCall"||s==="grepToolCall"||s==="searchToolCall")return{name:"Search",kind:"search",title:e.query||e.pattern||""};let t=String(s||"tool").replace(/ToolCall$/,"");return{name:t.charAt(0).toUpperCase()+t.slice(1),kind:B({name:t}),title:""}}function qr(s,e,t,r,n){let i=t?.result?.success,o=r&&n?Number(n)-Number(r):i?.executionTime||void 0,a={tool_use_id:s,status:i?"ok":"error",...o?{duration_ms:o}:{}};if(e==="shellToolCall"&&i)typeof i.exitCode=="number"&&(a.exit_code=i.exitCode,a.status=i.exitCode===0?"ok":"error"),a.output=(i.stdout||"")+(i.stderr||"");else if((e==="editToolCall"||e==="writeToolCall")&&i){let l=be(i.path||t?.args?.path),d=/^---\s+\/dev\/null/m.test(i.diffString||""),p=Je(i.diffString||"");a.diff=[{path:l,verb:d?"added":"edited",add:i.linesAdded??p.add,del:i.linesRemoved??p.del,hunks:p.hunks}]}return b.toolResult(a)}var es=T(()=>{U()});var ts={};G(ts,{CursorSession:()=>ze});var Br,ze,ss=T(()=>{xe();es();Br=process.env.AGENTPAGER_CURSOR_BIN||`${process.env.HOME}/.local/bin/cursor-agent`,ze=class extends W{constructor(e){super(e),this._mapper=Zt()}get bin(){return Br}buildArgs(e){let t=["-p",e,"--output-format","stream-json","--force","--trust"];return this.sessionId&&t.push("--resume",this.sessionId),this.model&&this.model!=="default"&&t.push("--model",this.model),t}handleLine(e,t){let r=e.chatId||e.chat_id||e.session_id||e.sessionId||e.threadId||e.thread_id||e.session&&(e.session.id||e.session.chatId)||e.type==="init"&&e.id||null;if(r&&t.captureSessionId(r),e.type==="result"){for(let n of this._mapper.onMessage(e))t.dispatch(n);t.finishAfterResult();return}for(let n of this._mapper.onMessage(e))t.dispatch(n)}}});function de(s){let e=[],t=new Map,r=new Map,n=0,i=!1,o="none";for(let l of s||[]){let d=l&&l.payload?l.payload:l;if(l&&typeof l.seq=="number"&&(n=Math.max(n,l.seq)),!d||typeof d!="object")continue;switch(d.type||Qr(d)){case"user":e.push({kind:"user",id:`u${e.length}`,text:d.text||"",...d.images?{images:d.images}:{}}),i=!0,o="thinking",r.clear();break;case"reasoning":e.push({kind:"reasoning",id:`r${e.length}`,elapsed_ms:d.elapsed_ms||0,text:d.text||""});break;case"delta":{let u=d.item_id||"_default",_=r.get(u);_||(_={kind:"assistant",id:`a${e.length}`,text:"",phase:d.phase||"commentary",streaming:!0},r.set(u,_),e.push(_)),_.text+=d.text||"",_.streaming=!0,d.phase&&(_.phase=d.phase),o="assistant_streaming";break}case"tool_use":{let u=d.type?d.tool||{}:{name:d.tool,title:d.target},_={kind:"tool",id:`t${e.length}`,tool_use_id:u.tool_use_id,name:u.name,tool_kind:u.kind,title:u.title||"",status:"running"};e.push(_),u.tool_use_id&&t.set(u.tool_use_id,_),o="tool_active";break}case"tool_result":{let u=d.result||{},_=u.tool_use_id?t.get(u.tool_use_id):null;if(_){if(_.status=u.status==="error"?"error":"ok",typeof u.exit_code=="number"&&(_.exit_code=u.exit_code),typeof u.duration_ms=="number"&&(_.duration_ms=u.duration_ms),u.output!=null){let A=jt(u.output);_.output=A.output,_.output_truncated=A.output_truncated||!!u.output_truncated}Array.isArray(u.diff)&&(_.diff=u.diff,_.add=fs(u.diff,"add"),_.del=fs(u.diff,"del"))}o="assistant_streaming";break}case"done":for(let u of r.values())u.streaming=!1;i=!1,o="none";break;default:break}}let a=[...e].reverse().find(l=>l.kind==="tool"&&l.status==="running");return{based_on_seq:n,rows:e,tailActivity:i?o:"none",activeToolGroupId:a?a.id:null}}function Qr(s){switch(s.kind){case"chat.assistant_delta":return"delta";case"chat.tool_use":return"tool_use";case"chat.assistant_done":return"done";default:return null}}function fs(s,e){return s.reduce((t,r)=>t+(r[e]||0),0)}var rt=T(()=>{U()});var Ee={};G(Ee,{loadImage:()=>on,saveImage:()=>hs,saveImageIfAbsent:()=>ke});import{mkdirSync as Zr,writeFileSync as en,readFileSync as tn,existsSync as ps,statSync as sn}from"node:fs";import{join as Ie}from"node:path";import{homedir as rn}from"node:os";function hs(s,e,t){if(!it(s))throw new Error("bad_image_id");Zr(Se,{recursive:!0});let r=ms[String(e||"").toLowerCase()]||"jpg",n=Buffer.from(String(t||""),"base64");if(!n.length)throw new Error("empty_image");if(n.length>8*1024*1024)throw new Error("image_too_large");let i=Ie(Se,s+"."+r);return en(i,n),{path:i,bytes:n.length,media_type:nt[r]}}function ke(s,e,t){if(!it(s))throw new Error("bad_image_id");let r=ms[String(e||"").toLowerCase()]||"jpg",n=Ie(Se,s+"."+r);return ps(n)?{path:n,bytes:sn(n).size,media_type:nt[r]}:hs(s,e,t)}function on(s){if(!it(s))return null;for(let e of nn){let t=Ie(Se,s+"."+e);if(ps(t)){let r=tn(t);return{path:t,bytes:r.length,media_type:nt[e],data:r.toString("base64")}}}return null}var Se,ms,nt,nn,it,fe=T(()=>{Se=Ie(rn(),".agentpager","media"),ms={"image/png":"png","image/webp":"webp","image/gif":"gif"},nt={png:"image/png",webp:"image/webp",gif:"image/gif",jpg:"image/jpeg"},nn=["jpg","png","webp","gif"],it=s=>/^[A-Za-z0-9_-]{1,64}$/.test(String(s||""))});var gs={};G(gs,{listDirs:()=>dn});import{execFile as an}from"node:child_process";import{promisify as cn}from"node:util";import{homedir as ln}from"node:os";async function dn(){let s=new Set;try{let{stdout:t}=await un("bash",["-c",`find "${_s}" -maxdepth 4 \\( -name node_modules -o -name Library -o -name '*gce-backup*' -o \\( -name '.*' ! -name '.git' \\) \\) -prune -o -type d -name .git -print 2>/dev/null | head -120`],{timeout:7e3,maxBuffer:1048576});t.split(`
15
+ `).filter(Boolean).forEach(r=>s.add(r.replace(/\/\.git$/,"")))}catch{}let e=[...s].map(t=>({path:t,name:t.split("/").pop()||t}));return e.sort((t,r)=>t.name.localeCompare(r.name)),[...e,{path:_s,name:"~ (\u7528\u6237\u4E3B\u76EE\u5F55)"}]}var un,_s,ys=T(()=>{un=cn(an),_s=ln()});var xs={};G(xs,{listModels:()=>gn});import{execFile as fn}from"node:child_process";import{promisify as pn}from"node:util";import{readFileSync as mn,existsSync as hn}from"node:fs";import{homedir as _n}from"node:os";import{join as ot}from"node:path";async function gn(s){let e=String(s||"").toLowerCase();if(e.includes("cursor")){try{let{stdout:t}=await ws("cursor-agent",["models"],{timeout:8e3}),r=[],n="";for(let i of t.split(`
16
+ `)){let o=i.match(/^\s*([\w.\-:/]+)\s+-\s+(.+?)\s*$/);if(!o)continue;let a=/\(current\)/i.test(o[2]);a&&(n=o[1]),r.push({id:o[1],label:o[2].replace(/\s*\(current\)\s*/i,""),current:a})}if(r.length)return{models:r,current:n}}catch{}return{models:[],current:""}}if(e.includes("opencode")){try{let{stdout:t}=await ws("opencode",["models"],{timeout:12e3}),r=t.split(`
17
+ `).map(n=>n.trim()).filter(Boolean).map(n=>({id:n,label:n,current:!1}));if(r.length)return{models:r,current:""}}catch{}return{models:[],current:""}}if(e.includes("qwen")){try{let r=JSON.parse(ct(ot(at,".qwen","settings.json"))||"{}").modelProviders,n=[];Array.isArray(r)?n=r.map(o=>o&&o.name).filter(Boolean):r&&typeof r=="object"&&(n=Object.values(r).flatMap(o=>Array.isArray(o)?o.map(a=>a&&a.name):[o&&o.name]).filter(Boolean));let i=[...new Set(n.map(o=>String(o).replace(/^\[[^\]]*\]\s*/,"").trim()).filter(Boolean))];if(i.length)return{models:se(i),current:""}}catch{}return{models:se(["qwen3-coder"]),current:""}}if(e.includes("codex")){let t=(ct(ot(at,".codex","config.toml")).match(/^\s*model\s*=\s*"([^"]+)"/m)||[])[1]||"",r=[...new Set([t,...Ae.codex].filter(Boolean))];return{models:se(r,t),current:t}}if(e.includes("codebuddy")){let t="";try{t=JSON.parse(ct(ot(at,".codebuddy","settings.json"))||"{}").model||""}catch{}let r=[...new Set([t,...Ae.codebuddy].filter(Boolean))];return{models:se(r,t),current:t}}return e.includes("gemini")?{models:se(Ae.gemini,"gemma-4-31b-it"),current:"gemma-4-31b-it"}:{models:se(Ae.claude),current:""}}var ws,at,Ae,se,ct,bs=T(()=>{ws=pn(fn),at=_n(),Ae={claude:["fable","opus","sonnet","haiku"],gemini:["gemma-4-31b-it","gemma-4-26b-a4b-it","gemini-2.5-pro","gemini-3.5-flash","gemini-3-flash-preview","gemini-3.1-flash-lite","gemini-3.1-pro-preview"],codex:["gpt-5.5","gpt-5.5-codex","gpt-5"],codebuddy:["glm-5.1","deepseek-v3.2","kimi-k2.5","gpt-5.5","gemini-3-pro"]},se=(s,e)=>s.map(t=>({id:t,label:t,current:t===e})),ct=s=>{try{return hn(s)?mn(s,"utf8"):""}catch{return""}}});var Ge={};G(Ge,{listClaude:()=>An,listNative:()=>Xn,readClaude:()=>Ps,readNative:()=>Yn,searchClaude:()=>Mn});import{openSync as yn,readSync as wn,closeSync as xn,fstatSync as bn,readdirSync as L,statSync as J,existsSync as R,readFileSync as z,writeFileSync as vn,renameSync as Sn}from"node:fs";import{homedir as H}from"node:os";import{join as M}from"node:path";import{execFileSync as dt}from"node:child_process";import{createHash as Is}from"node:crypto";function Ce(s){return typeof s=="string"?s:Array.isArray(s)?s.map(e=>typeof e=="string"?e:e&&e.type==="text"&&e.text||"").join(""):""}function In(s){if(!Array.isArray(s))return null;let e=[];for(let t of s)if(t&&t.type==="image"&&t.source&&t.source.type==="base64"&&t.source.data)try{let r="cc_"+Is("sha1").update(t.source.data).digest("hex").slice(0,24),n=ke(r,t.source.media_type,t.source.data);e.push({id:r,media_type:n.media_type,bytes:n.bytes})}catch{}return e.length?e:null}function kn(s){if(!Array.isArray(s&&s.content))return null;let e=[];for(let t of s.content)if(t&&t.type==="input_image"&&typeof t.image_url=="string"){let r=t.image_url.match(/^data:(image\/[a-z+.-]+);base64,(.+)$/is);if(!r)continue;try{let n="cx_"+Is("sha1").update(r[2]).digest("hex").slice(0,24),i=ke(n,r[1],r[2]);e.push({id:n,media_type:i.media_type,bytes:i.bytes})}catch{}}return e.length?e:null}function C(s){let e=(s||"").trim();return!e||/^(\[Image: [^\]]+\]\s*)+$/.test(e)?!0:/^</.test(e)||/^Caveat:/.test(e)||/^This session is being continued/.test(e)||/^\[Request interrupted/.test(e)||/^Command:/.test(e)}function Ne(s){return String(s||"").replace(/^\s*<([a-z_]*metadata)>[\s\S]*?<\/\1>\s*/i,"").replace(/^\s*<task>\s*/i,"").replace(/<\/task>/gi," ").replace(/^\s*ou_[0-9a-f]{16,}\s*[::]\s*/i,"").trim()}function K(s,e,t){let r=yn(s,"r");try{let n=bn(r).size,i=Math.min(t,n),o=e?Math.max(0,n-i):0,a=Buffer.alloc(i);return wn(r,a,0,i,o),a.toString("utf8")}catch{return""}finally{xn(r)}}function P(s){let e=[];for(let t of s.split(`
18
+ `)){let r=t.trim();if(r)try{e.push(JSON.parse(r))}catch{}}return e}function En(s){let e="",t="",r="",n="";for(let a of P(K(s,!1,65536))){if(!t&&a.cwd&&(t=a.cwd),!n&&a.type==="ai-title"&&a.aiTitle&&(n=String(a.aiTitle).replace(/\s+/g," ").trim().slice(0,60)),!e&&a.type==="user"&&a.message){let l=Ne(Ce(a.message.content));l&&!C(l)&&(e=l.replace(/\s+/g," ").trim().slice(0,40))}if(n&&t)break}let i=P(K(s,!0,65536)),o=0;for(let a=i.length-1;a>=0;a--){let l=i[a];if(!o&&l&&l.timestamp&&(o=Date.parse(l.timestamp)||0),!n&&l.type==="ai-title"&&l.aiTitle&&(n=String(l.aiTitle).replace(/\s+/g," ").trim().slice(0,60)),!r&&(l.type==="assistant"||l.type==="user")&&l.message){let d=Ne(Ce(l.message.content));d&&!C(d)&&(r=d.replace(/\s+/g," ").trim().slice(0,50))}if(o&&n&&r)break}return{title:n||e,cwd:t,preview:r,ts:o}}function ft(){if(!R(Te))return[];let s=[];for(let e of L(Te)){let t=M(Te,e),r;try{r=J(t)}catch{continue}if(r.isDirectory())for(let n of L(t)){if(!n.endsWith(".jsonl"))continue;let i=M(t,n),o;try{o=J(i)}catch{continue}o.size<64||s.push({id:n.replace(/\.jsonl$/,""),proj:e,fp:i,mtime:o.mtimeMs})}}return s.sort((e,t)=>t.mtime-e.mtime)}function pt(s){let e=En(s.fp);return{id:s.id,provider:"claude",project:s.proj,cwd:e.cwd,title:e.title||"(\u65E0\u6807\u9898\u4F1A\u8BDD)",preview:e.preview,updated_at:e.ts||Math.round(s.mtime)}}function An(s=20,e=0){let t=ft(),r=t.length,n=Math.max(0,e|0),i=t.slice(n,n+s);return{items:i.map(pt),total:r,offset:n,hasMore:n+i.length<r}}function Mn(s,e=50){let t=(s||"").trim();if(!t)return{items:[],total:0,q:t};let r=ft();if(!r.length)return{items:[],total:0,q:t};let n=new Set,i=200;for(let a=0;a<r.length;a+=i){let l=r.slice(a,a+i).map(d=>d.fp);try{dt("grep",["-l","-i","-F","--",t,...l],{encoding:"utf8",maxBuffer:67108864}).split(`
19
+ `).forEach(p=>{p.trim()&&n.add(p.trim())})}catch{}}let o=r.filter(a=>n.has(a.fp));return{items:o.slice(0,e).map(pt),total:o.length,q:t}}function ks(){if(!R(vs))return[];let s=[],e=(t,r)=>{if(r>4)return;let n;try{n=L(t)}catch{return}for(let i of n){let o=M(t,i),a;try{a=J(o)}catch{continue}if(a.isDirectory())e(o,r+1);else if(i.startsWith("rollout-")&&i.endsWith(".jsonl")&&a.size>=64){let l=i.match(/-([0-9a-f-]{36})\.jsonl$/);s.push({id:l?l[1]:i.replace(/\.jsonl$/,""),fp:o,mtime:a.mtimeMs})}}};return e(vs,0),s.sort((t,r)=>r.mtime-t.mtime)}function ie(s){return Array.isArray(s.content)?s.content.map(e=>e&&typeof e.text=="string"?e.text:"").join(""):""}function Tn(s){let e="",t="",r="";for(let n of P(K(s,!1,65536))){let i=n.payload||n;if(!t&&n.type==="session_meta"&&i.cwd&&(t=i.cwd),!e&&n.type==="response_item"&&i.role==="user"){let o=Ne(ie(i));o&&!C(o)&&(e=o.replace(/\s+/g," ").slice(0,40))}if(e&&t)break}for(let n of P(K(s,!0,65536)).reverse()){let i=n.payload||n;if(n.type==="response_item"){let o=Ne(ie(i));if(o&&!C(o)){r=o.replace(/\s+/g," ").slice(0,50);break}}}return{title:e,cwd:t,preview:r}}function Cn(s){let e=Tn(s.fp);return{id:s.id,provider:"codex",project:e.cwd?e.cwd.split("/").pop():"",cwd:e.cwd,title:e.title||"(\u65E0\u6807\u9898\u4F1A\u8BDD)",preview:e.preview,updated_at:Math.round(s.mtime)}}function Nn(s,e){let t=ks().find(n=>n.id===s);if(!t)return{id:s,msgs:[]};let r=[];for(let n of P(z(t.fp,"utf8"))){if(n.type!=="response_item")continue;let i=n.payload||n,o=ie(i).trim(),a=i.role==="user"?kn(i):null,l=o&&!C(o)?o:"";!l&&!a||r.push({role:i.role==="user"?"me":"agent",text:l,...a?{images:a}:{}})}return{id:s,msgs:r.slice(-(e||400))}}function Oe(s,e){if(!R(s))return[];let t=[];for(let r of L(s)){let n=e?M(s,r,e):M(s,r),i;try{i=J(n)}catch{continue}if(i.isDirectory())for(let o of L(n)){if(!o.endsWith(".jsonl"))continue;let a=M(n,o),l;try{l=J(a)}catch{continue}l.size<64||t.push({id:o.replace(/\.jsonl$/,""),fp:a,mtime:l.mtimeMs})}}return t.sort((r,n)=>n.mtime-r.mtime)}function Re(s){return s?Array.isArray(s.parts)?s.parts.map(e=>e&&typeof e.text=="string"?e.text:"").join(""):Ce(s.content):""}function On(s){let e="",t="",r="";for(let n of P(K(s,!1,65536))){if(!t&&n.cwd&&(t=n.cwd),!e&&n.type==="user"&&n.message){let i=Re(n.message).trim();i&&!C(i)&&(e=i.replace(/\s+/g," ").slice(0,40))}if(e&&t)break}for(let n of P(K(s,!0,65536)).reverse())if((n.type==="assistant"||n.type==="user")&&n.message){let i=Re(n.message).trim();if(i&&!C(i)){r=i.replace(/\s+/g," ").slice(0,50);break}}return{title:e,cwd:t,preview:r}}function Rn(s){let e=On(s.fp);return{id:s.id,provider:"qwen",project:e.cwd?e.cwd.split("/").pop():"",cwd:e.cwd,title:e.title||"(\u65E0\u6807\u9898\u4F1A\u8BDD)",preview:e.preview,updated_at:Math.round(s.mtime)}}function Pn(s,e){let t=Oe(Es,"chats").find(n=>n.id===s);if(!t)return{id:s,msgs:[]};let r=[];for(let n of P(z(t.fp,"utf8")))if(n.type==="user"&&n.message){let i=Re(n.message).trim();i&&!C(i)&&r.push({role:"me",text:i})}else if(n.type==="assistant"&&n.message){let i=Re(n.message).trim();i&&r.push({role:"agent",text:i})}return{id:s,msgs:r.slice(-(e||400))}}function jn(s){let e="",t="",r="";for(let n of P(K(s,!1,65536))){if(!t&&n.cwd&&(t=n.cwd),!e&&n.role==="user"&&Array.isArray(n.content)){let i=ie(n).trim();i&&!C(i)&&(e=i.replace(/\s+/g," ").slice(0,40))}if(e&&t)break}for(let n of P(K(s,!0,65536)).reverse())if(Array.isArray(n.content)){let i=ie(n).trim();if(i&&!C(i)){r=i.replace(/\s+/g," ").slice(0,50);break}}return{title:e,cwd:t,preview:r}}function Gn(s){let e=jn(s.fp);return{id:s.id,provider:"codebuddy",project:e.cwd?e.cwd.split("/").pop():"",cwd:e.cwd,title:e.title||"(\u65E0\u6807\u9898\u4F1A\u8BDD)",preview:e.preview,updated_at:Math.round(s.mtime)}}function Ln(s,e){let t=Oe(As,"").find(n=>n.id===s);if(!t)return{id:s,msgs:[]};let r=[];for(let n of P(z(t.fp,"utf8"))){if(!Array.isArray(n.content))continue;let i=ie(n).trim();!i||C(i)||r.push({role:n.role==="user"?"me":"agent",text:i})}return{id:s,msgs:r.slice(-(e||400))}}function je(s,e){try{let t=dt("sqlite3",["-json",s,e],{encoding:"utf8",maxBuffer:16777216,timeout:5e3});return t.trim()?JSON.parse(t):[]}catch{return[]}}function Dn(){if(!R(re))return[];let s;try{s=J(re)}catch{return[]}return Y({fp:re,mtime:s.mtimeMs},()=>je(re,"SELECT id,title,directory,time_updated FROM session ORDER BY time_updated DESC;").map(t=>({id:t.id,provider:"opencode",project:t.directory?String(t.directory).split("/").pop():"",cwd:t.directory||"",title:t.title||"(\u65E0\u6807\u9898\u4F1A\u8BDD)",preview:"",updated_at:Number(t.time_updated)||0})))||[]}function qn(s,e){if(!R(re))return{id:s,msgs:[]};let t=String(s).replace(/'/g,""),r=je(re,`SELECT m.data AS mdata, p.data AS pdata FROM part p JOIN message m ON m.id=p.message_id WHERE p.session_id='${t}' ORDER BY p.time_created;`),n=[];for(let i of r){let o="agent";try{JSON.parse(i.mdata).role==="user"&&(o="me")}catch{}let a="";try{let l=JSON.parse(i.pdata);l&&l.type==="text"&&(a=l.text||"")}catch{}a=(a||"").trim(),!(!a||C(a))&&n.push({role:o,text:a})}return{id:s,msgs:n.slice(-(e||400))}}function Ms(s){return typeof s=="string"?s:Array.isArray(s)?s.map(e=>e&&e.text||(typeof e=="string"?e:"")).join(""):""}function Bn(s){let e="",t="";for(let r of je(s,"SELECT CAST(data AS TEXT) AS t FROM blobs;")){let n;try{n=JSON.parse(r.t)}catch{continue}let i=Ms(n.content);if(!t){let o=i.match(/Workspace Path:\s*([^\n]+)/);o&&(t=o[1].trim())}if(!e&&n.role==="user"){let o=Ts(i);o&&!Cs(o)&&!C(o)&&(e=o.replace(/\s+/g," ").slice(0,40))}if(e&&t)break}return{title:e,cwd:t}}function Un(s){if(!R(ne))return"";for(let e of L(ne)){let t=M(ne,e,s,"store.db");if(R(t))return t}return""}function $n(s,e){let t=Un(s);if(!t)return{id:s,msgs:[]};let r=[];for(let n of je(t,"SELECT CAST(data AS TEXT) AS t FROM blobs;")){let i;try{i=JSON.parse(n.t)}catch{continue}if(i.role!=="user"&&i.role!=="assistant")continue;let o=Ts(Ms(i.content));!o||Cs(o)||C(o)||r.push({role:i.role==="user"?"me":"agent",text:o})}return{id:s,msgs:r.slice(-(e||400))}}function Fn(){if(!R(ne))return[];let s=[];for(let e of L(ne)){let t=M(ne,e),r;try{r=J(t)}catch{continue}if(r.isDirectory())for(let n of L(t)){let i=M(t,n,"store.db");if(!R(i))continue;let o;try{o=J(i)}catch{continue}s.push(Y({fp:i,mtime:o.mtimeMs},()=>{let a=Bn(i);return{id:n,provider:"cursor",project:a.cwd?a.cwd.split("/").pop():"",cwd:a.cwd,title:a.title||"cursor \u4F1A\u8BDD",preview:"",updated_at:o.mtimeMs}}))}}return s}function Ns(s){let e=[];for(let t of P(s)){let r=t.$set&&t.$set.messages||t.messages;if(Array.isArray(r))for(let n of r){let i=Array.isArray(n.content)?n.content.map(o=>o&&o.text||"").join(""):typeof n.content=="string"?n.content:"";i&&e.push({role:n.type==="user"?"me":"agent",text:i})}}return e}function Jn(){if(!R(Me))return[];let s=[];for(let e of L(Me)){let t=M(Me,e,"chats");if(!R(t))continue;let r="";try{r=z(M(Me,e,".project_root"),"utf8").trim()}catch{}for(let n of L(t)){if(!n.startsWith("session-")||!n.endsWith(".jsonl"))continue;let i=M(t,n),o;try{o=J(i)}catch{continue}let a=Y({fp:i,mtime:o.mtimeMs},()=>{let l=K(i,!1,2e5);if(!l.includes('"messages"'))return null;let d=Ns(l);if(!d.some(u=>!lt(u.text.trim())))return null;let p="";for(let u of d){let _=u.text.trim();if(u.role==="me"&&_&&!lt(_)){p=_.replace(/\s+/g," ").slice(0,40);break}}return{id:i,provider:"gemini",project:r?r.split("/").pop():"",cwd:r,title:p||"(\u65E0\u6807\u9898\u4F1A\u8BDD)",preview:"",updated_at:o.mtimeMs}});a&&s.push(a)}}return s}function Kn(s,e){if(!R(s))return{id:s,msgs:[]};let t=Ns(z(s,"utf8")).filter(r=>{let n=r.text.trim();return n&&!lt(n)}).map(r=>({role:r.role,text:r.text.trim()}));return{id:s,msgs:t.slice(-(e||400))}}function Wn(s){if(!s.length)return s;Rs();let e=s.filter(t=>{let r=V.get("cxreal:"+t.fp);return!r||r.mtime!==t.mtime});if(e.length){let t=new Set;for(let r=0;r<e.length;r+=200){let n=e.slice(r,r+200).map(i=>i.fp);try{dt("grep",["-l","-F","--",'"type":"output_text"',...n],{encoding:"utf8",maxBuffer:1<<26}).split(`
20
+ `).forEach(i=>{i.trim()&&t.add(i.trim())})}catch{}}for(let r of e)V.set("cxreal:"+r.fp,{mtime:r.mtime,item:t.has(r.fp)});Pe=!0}return s.filter(t=>{let r=V.get("cxreal:"+t.fp);return r&&r.item})}function Rs(){if(!Ss){Ss=!0;try{let s=JSON.parse(z(ut,"utf8"));if(s&&s.v===Os&&s.files)for(let[e,t]of Object.entries(s.files))V.set(e,t)}catch{}}}function Hn(){if(Pe){Pe=!1;try{let s=ut+".tmp";vn(s,JSON.stringify({v:Os,files:Object.fromEntries(V)})),Sn(s,ut)}catch{}}}function Y(s,e){let t=V.get(s.fp);if(t&&t.mtime===s.mtime)return t.item;let r=e(s);return V.set(s.fp,{mtime:s.mtime,item:r}),Pe=!0,r}function Xn(s=20,e=0){Rs();let t=[...ft().map(o=>Y(o,pt)),...Wn(ks()).map(o=>Y(o,Cn)),...Oe(Es,"chats").map(o=>Y(o,Rn)),...Oe(As,"").map(o=>Y(o,Gn)),...Dn(),...Fn(),...Jn()].filter(Boolean).sort((o,a)=>(a.updated_at||0)-(o.updated_at||0));Hn();let r=t.length,n=Math.max(0,e|0),i=t.slice(n,n+s);return{items:i,total:r,offset:n,hasMore:n+i.length<r}}function Yn(s,e,t,r=400){let n=String(s||"");return n.includes("codex")?Nn(e,r):n.includes("qwen")?Pn(e,r):n.includes("codebuddy")?Ln(e,r):n.includes("opencode")?qn(e,r):n.includes("gemini")?Kn(e,r):n.includes("cursor")?$n(e,r):Ps(e,t,r)}function Ps(s,e,t=400){let r=M(Te,e||"",s+".jsonl");if(!R(r))return{id:s,rows:[]};let n=$(),i=[];for(let a of P(z(r,"utf8")))if(a.type==="user"&&a.message){let l=a.message.content;if(Array.isArray(l)&&l.some(A=>A&&A.type==="tool_result")){i.push(...n.onMessage(a));continue}let p=Ce(l),u=In(l),_=p&&!C(p)?p.trim():"";(_||u)&&i.push(b.user(_,u||void 0))}else a.type==="assistant"&&a.message?i.push(...n.onMessage(a)):a.type==="result"&&i.push(...n.onMessage(a));let o=de(i);for(let a of o.rows)a.kind==="assistant"&&(a.streaming=!1);return{id:s,rows:o.rows.slice(-t)}}var Te,vs,Es,As,re,ne,Ts,Cs,Me,lt,ut,Os,V,Ss,Pe,Le=T(()=>{le();rt();U();fe();Te=M(H(),".claude","projects");vs=M(H(),".codex","sessions");Es=M(H(),".qwen","projects");As=M(H(),".codebuddy","projects");re=M(H(),".local","share","opencode","opencode.db");ne=M(H(),".cursor","chats");Ts=s=>s.replace(/<\/?user_query>/g,"").trim(),Cs=s=>/^<user_info>|^<environment|^<additional|^<system/.test(s);Me=M(H(),".gemini","tmp");lt=s=>C(s)||/^<session_context>/.test(s);ut=M(H(),".agentpager","native-cache.json"),Os=1,V=new Map,Ss=!1,Pe=!1});import{readFileSync as Ls,writeFileSync as Ds,mkdirSync as qs,existsSync as Bs}from"node:fs";import{homedir as Us}from"node:os";import{join as mt}from"node:path";import{randomUUID as $s}from"node:crypto";var De=process.env.AGENTPAGER_HOME||mt(Us(),".agentpager"),pe=mt(De,"config.json");function qe(){return Bs(pe)?JSON.parse(Ls(pe,"utf8")):null}function Q(s){return qs(De,{recursive:!0}),Ds(pe,JSON.stringify(s,null,2)),s}function me(){let s=qe();return s||(s={device_id:"device_"+$s().slice(0,12),device_kp:{stub:!0},relay_url:process.env.AGENTPAGER_RELAY||"ws://127.0.0.1:8090/ws",relay_http:process.env.AGENTPAGER_RELAY_HTTP||"http://127.0.0.1:8090",binding:null,agents:[]},Q(s))}var oe={DIR:De,FILE:pe};Ue();import{WebSocket as nr}from"ws";import Z from"tweetnacl";var er=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298];function ae(s){let e=[1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225],t=s.length,r=new Uint8Array((t+8>>6<<6)+64);r.set(s),r[t]=128;let n=t*8,i=new DataView(r.buffer);i.setUint32(r.length-4,n>>>0),i.setUint32(r.length-8,Math.floor(n/4294967296));let o=new Uint32Array(64),a=(p,u)=>p>>>u|p<<32-u;for(let p=0;p<r.length;p+=64){for(let h=0;h<16;h++)o[h]=i.getUint32(p+h*4);for(let h=16;h<64;h++){let k=a(o[h-15],7)^a(o[h-15],18)^o[h-15]>>>3,c=a(o[h-2],17)^a(o[h-2],19)^o[h-2]>>>10;o[h]=o[h-16]+k+o[h-7]+c|0}let[u,_,A,O,y,v,g,w]=e;for(let h=0;h<64;h++){let k=a(y,6)^a(y,11)^a(y,25),c=y&v^~y&g,f=w+k+c+er[h]+o[h]|0,m=a(u,2)^a(u,13)^a(u,22),S=u&_^u&A^_&A,E=m+S|0;w=g,g=v,v=y,y=O+f|0,O=A,A=_,_=u,u=f+E|0}e[0]=e[0]+u|0,e[1]=e[1]+_|0,e[2]=e[2]+A|0,e[3]=e[3]+O|0,e[4]=e[4]+y|0,e[5]=e[5]+v|0,e[6]=e[6]+g|0,e[7]=e[7]+w|0}let l=new Uint8Array(32),d=new DataView(l.buffer);for(let p=0;p<8;p++)d.setUint32(p*4,e[p]>>>0);return l}var ge=(s,e)=>{let t=new Uint8Array(s.length+e.length);return t.set(s),t.set(e,s.length),t};function ye(s,e){s.length>64&&(s=ae(s));let t=new Uint8Array(64);t.set(s);let r=new Uint8Array(64),n=new Uint8Array(64);for(let i=0;i<64;i++)r[i]=t[i]^54,n[i]=t[i]^92;return ae(ge(n,ae(ge(r,e))))}function _t(s,e,t,r){let n=ye(e,s),i=new Uint8Array(r),o=new Uint8Array(0),a=0,l=1;for(;a<r;)o=ye(n,ge(ge(o,t),new Uint8Array([l++]))),i.set(o.subarray(0,Math.min(o.length,r-a)),a),a+=o.length;return i}function gt(s,e){if(s.length!==e.length)return!1;let t=0;for(let r=0;r<s.length;r++)t|=s[r]^e[r];return t===0}var ee=s=>new TextEncoder().encode(s),yt=(...s)=>{let e=0;for(let n of s)e+=n.length;let t=new Uint8Array(e),r=0;for(let n of s)t.set(n,r),r+=n.length;return t},ce="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";function te(s){let e="";for(let t=0;t<s.length;t+=3){let r=s[t],n=t+1<s.length?s[t+1]:0,i=t+2<s.length?s[t+2]:0;e+=ce[r>>2]+ce[(r&3)<<4|n>>4],e+=t+1<s.length?ce[(n&15)<<2|i>>6]:"=",e+=t+2<s.length?ce[i&63]:"="}return e}function X(s){let e=s.replace(/=+$/,""),t=new Uint8Array(e.length*6>>3),r=0,n=0,i=0;for(let o of e)n=n<<6|ce.indexOf(o),r+=6,r>=8&&(r-=8,t[i++]=n>>r&255);return t}function tr(s){let e=s.map(r=>r instanceof Uint8Array?r:ee(String(r))),t=[];for(let r of e){let n=new Uint8Array(4);new DataView(n.buffer).setUint32(0,r.length,!0),t.push(n,r)}return yt(...t)}var sr="ABCDEFGHJKMNPQRSTUVWXYZ23456789";function wt(s=8){let e="";for(;e.length<s;){let t=Z.randomBytes(1)[0];t<248&&(e+=sr[t%31])}return e}function rr(s){let e="";for(let t of s)e+=t.toString(16).padStart(2,"0");return e}function xt(s){return rr(ae(ee("agentpager-psid|"+s))).slice(0,32)}function bt(){return Z.box.keyPair()}function vt(s,e){let t=Z.scalarMult(s,e);if(t.every(r=>r===0))throw new Error("insecure_ecdh: low-order/zero peer key");return t}function St({psid:s,phone_id:e,device_id:t,epk_phone:r,epk_device:n}){return tr([s,e,t,r,n])}function $e(s,e,t){return ye(ee("agentpager-pair|"+s),yt(e,ee("|"+t)))}function It(s,e){return gt(s,e)}function kt(s,e){return _t(s,e,ee("agentpager-chan"),32)}function Et(s,e){let t=Z.randomBytes(24),r=Z.secretbox(ee(JSON.stringify(e)),t,s);return{n:te(t),c:te(r)}}function At(s,e){let t=Z.secretbox.open(X(e.c),X(e.n),s);return t?JSON.parse(new TextDecoder().decode(t)):null}function Mt(s,{onCode:e,timeoutMs:t=6e5}={}){return new Promise((r,n)=>{let i=wt();e&&e(i);let o=xt(i),a=bt(),l=new nr(`${s.relay_url}?role=device&id=${s.device_id}`),d=setTimeout(()=>{try{l.close()}catch{}n(new Error("pair_timeout"))},t),p=null,u=null,_=!1,A=!1,O=null,y=h=>{clearTimeout(d);try{l.close()}catch{}h?n(h):r(s)},v=()=>St({psid:o,phone_id:p.phone_id,device_id:s.device_id,epk_phone:p.epk,epk_device:a.publicKey});l.on("open",()=>l.send(JSON.stringify({type:"pair_offer",psid:o,device_id:s.device_id,epk:te(a.publicKey)}))),l.on("message",h=>{let k;try{k=JSON.parse(h.toString())}catch{return}if(k.type==="pair_peer"){p={phone_id:k.phone_id,epk:X(k.epk)};let c=v();try{u=kt(vt(a.secretKey,p.epk),c)}catch(f){return y(new Error("pair_failed: "+f.message))}l.send(JSON.stringify({type:"pair_mac",psid:o,mac:te($e(i,c,"device"))})),_=!0,O&&g(O),w()}else if(k.type==="pair_mac"){if(!p){O=k.mac;return}g(k.mac)}}),l.on("error",h=>y(h));function g(h){if(A=It(X(h),$e(i,v(),"phone")),!A)return y(new Error("pair_failed: mac_mismatch (wrong code or MITM)"));w()}function w(){_&&A&&u&&(s.binding={phone_id:p.phone_id,paired_at:Date.now(),chan_key:te(u)},Q(s),y(null))}})}import{hostname as Vn}from"node:os";import{WebSocket as ir}from"ws";import{EventEmitter as or}from"node:events";var we=class extends or{constructor({relay_url:e,device_id:t}){super(),this.url=`${e}?role=device&id=${t}`,this.device_id=t,this.ws=null,this.backoff=500,this.alive=!1,this.stopped=!1}connect(){return this.ws=new ir(this.url),this.ws.on("open",()=>{this.alive=!0,this.backoff=500,this.emit("open"),this._heartbeat()}),this.ws.on("message",e=>{let t;try{t=JSON.parse(e.toString())}catch{return}t.type==="envelope"?this.emit("envelope",t.envelope):t.type==="pair_result"?this.emit("pair_result",t):t.type==="delivery.expired"?this.emit("expired",t.msg_id):t.type==="paired"?this.emit("paired",t):this.emit("control",t)}),this.ws.on("pong",()=>{this.alive=!0}),this.ws.on("close",()=>{this._down()}),this.ws.on("error",e=>{this.emit("error",e)}),this}_heartbeat(){clearInterval(this._hb),this._hb=setInterval(()=>{if(!(!this.ws||this.ws.readyState!==this.ws.OPEN)){if(!this.alive){try{this.ws.terminate()}catch{}return}this.alive=!1;try{this.ws.ping()}catch{}}},3e4)}_down(){clearInterval(this._hb),this.emit("close"),!this.stopped&&(this.backoff=Math.min(this.backoff*2,15e3),setTimeout(()=>this.connect(),this.backoff))}send(e){return this.ws&&this.ws.readyState===this.ws.OPEN?(this.ws.send(JSON.stringify(e)),!0):!1}sendEnvelope(e){return this.send({type:"envelope",envelope:e})}stop(){this.stopped=!0,clearInterval(this._hb);try{this.ws.close()}catch{}}};import{randomUUID as ar}from"node:crypto";var cr=0;function Tt(s,e,t,r){return{v:1,from:e,to:t,msg_id:ar(),counter:++cr,ts:Date.now(),box:Et(s,r)}}function Ct(s,e){return At(s,e.box)}import{existsSync as Ur}from"node:fs";le();async function rs({provider:s,workdir:e,resumeSessionId:t,onSessionId:r,model:n}){if(s==="mock")return new Ze({resumeSessionId:t,onSessionId:r});if(s==="codex"){let{CodexSession:o}=await Promise.resolve().then(()=>(Ft(),$t));return new o({workdir:e,resumeSessionId:t,onSessionId:r,model:n})}if(s==="codebuddy"){let{CodeBuddySession:o}=await Promise.resolve().then(()=>(Kt(),Jt));return new o({workdir:e,resumeSessionId:t,onSessionId:r,model:n})}if(s==="qwen"){let{QwenSession:o}=await Promise.resolve().then(()=>(Ht(),Wt));return new o({workdir:e,resumeSessionId:t,onSessionId:r,model:n})}if(s==="opencode"){let{OpenCodeSession:o}=await Promise.resolve().then(()=>(Yt(),Xt));return new o({workdir:e,resumeSessionId:t,onSessionId:r,model:n})}if(s==="gemini"){let{GeminiSession:o}=await Promise.resolve().then(()=>(Qt(),zt));return new o({workdir:e,resumeSessionId:t,onSessionId:r,model:n})}if(s==="cursor"){let{CursorSession:o}=await Promise.resolve().then(()=>(ss(),ts));return new o({workdir:e,resumeSessionId:t,onSessionId:r,model:n})}let{query:i}=await import("@anthropic-ai/claude-agent-sdk");return new Qe({query:i,workdir:e,resumeSessionId:t,onSessionId:r,model:n})}function ns(s){let e=String(s||"").toLowerCase(),t={structured_tools:!1,structured_diff:!1,reasoning:!1,hot_model_switch:!0,resume:!0,interactive_approval:!1};return e==="codex"?{...t,structured_tools:!0,structured_diff:!0,reasoning:!0}:e==="claude"||e===""?{...t,structured_tools:!0,structured_diff:!0}:e==="qwen"||e==="codebuddy"?{...t,structured_tools:!0,structured_diff:!0,reasoning:!0}:e==="cursor"?{...t,structured_tools:!0,structured_diff:!0}:e==="mock"?{...t,hot_model_switch:!1,resume:!0}:t}function $r(){if(process.env.AGENTPAGER_CLAUDE_BIN)return process.env.AGENTPAGER_CLAUDE_BIN;for(let s of[process.env.HOME+"/.local/bin/claude",process.env.HOME+"/.npm-global/bin/claude"])if(Ur(s))return s;return"claude"}var Qe=class{constructor({query:e,workdir:t,resumeSessionId:r,onSessionId:n,model:i}){this._queue=[],this._waiter=null,this._closed=!1,this._active=null,this._reported=!1,this.onSessionId=n,this._mapper=$();let o=$r(),a=this;async function*l(){for(;!a._closed;){let d=await new Promise(p=>{a._queue.length?p(a._queue.shift()):a._waiter=p});if(d===null)return;yield{type:"user",message:{role:"user",content:d}}}}this.q=e({prompt:l(),options:{pathToClaudeCodeExecutable:o,cwd:t,permissionMode:"default",settingSources:[],...i?{model:i}:{},...r?{resume:r}:{},canUseTool:async(d,p)=>({behavior:"allow",updatedInput:p})}}),this._pump()}async _pump(){try{for await(let e of this.q){!this._reported&&e.session_id&&(this._reported=!0,this.onSessionId?.(e.session_id));let t=this._active;for(let r of this._mapper.onMessage(e))t?.onEvent?t.onEvent(r):r.type==="delta"?t?.onDelta?.(r.text):r.type==="tool_use"&&t?.onToolUse?.(r.tool.name),r.type==="done"&&(this._active=null,t?.resolve?.({done:!0,reason:r.reason}))}}catch(e){let t=this._active;this._active=null,t?.resolve?.({done:!0,interrupted:!0,error:e.message})}this._closed=!0}runTurn({text:e,onDelta:t,onToolUse:r,onEvent:n}){return new Promise(i=>{if(this._active={onDelta:t,onToolUse:r,onEvent:n,resolve:i},this._waiter){let o=this._waiter;this._waiter=null,o(e)}else this._queue.push(e)})}interrupt(){return this.q.interrupt()}setModel(e){return this.q.setModel(e)}setPermissionMode(e){return this.q.setPermissionMode(e)}close(){if(this._closed=!0,this._waiter){let e=this._waiter;this._waiter=null,e(null)}}},Ze=class{constructor({resumeSessionId:e,onSessionId:t}){this.resumed=!!e,t?.(e||"mock-session")}async runTurn({text:e,onDelta:t,onToolUse:r}){if(this._aborted=!1,e&&e.includes("__throw__"))throw new Error("mock provider blew up");t(this.resumed?`echo(resumed): ${e}`:`echo: ${e}`);for(let n=0;n<12&&!this._aborted;n++)await new Promise(i=>setTimeout(i,50));return this._aborted?(t("[mock] interrupted"),{done:!0,interrupted:!0}):(r("Bash"),t("[mock] tool ran (auto-approved)"),{done:!0})}interrupt(){this._aborted=!0}setModel(){}setPermissionMode(){}close(){}};import{openSync as is,writeSync as os,fsyncSync as as,closeSync as cs,readFileSync as Fr,renameSync as ls,existsSync as us,mkdirSync as Jr}from"node:fs";import{join as tt}from"node:path";var et=tt(oe.DIR,"transcripts"),F=500,Kr=2*F,Wr=3*F,ve=class{constructor(e){Jr(et,{recursive:!0}),this.file=tt(et,`${e}.jsonl`);let t=this._readLines();this.seq=this._lastSeqFrom(t),this._lines=t.length}renameTo(e){let t=tt(et,`${e}.jsonl`);this.file!==t&&us(this.file)&&ls(this.file,t),this.file=t}_readLines(){return us(this.file)?Fr(this.file,"utf8").trim().split(`
21
+ `).filter(Boolean):[]}_lastSeqFrom(e){for(let t=e.length-1;t>=0;t--)try{return JSON.parse(e[t]).seq||0}catch{}return 0}append(e){let t=++this.seq,r=JSON.stringify({seq:t,ts:Date.now(),payload:e})+`
22
+ `,n=is(this.file,"a");try{os(n,r),as(n)}finally{cs(n)}return++this._lines>Wr&&this._compact(),t}_compact(){let e=this._readLines().slice(-Kr),t=`${this.file}.tmp`,r=is(t,"w");try{os(r,e.join(`
23
+ `)+`
24
+ `),as(r)}finally{cs(r)}ls(t,this.file),this._lines=e.length}recordsAfter(e,t=F){let r=this._readLines(),n=[];for(let i=r.length-1;i>=0;i--){let o;try{o=JSON.parse(r[i])}catch{continue}if(o.seq<=e||(n.unshift(o),n.length>=t))break}return n}};import{readFileSync as Hr,writeFileSync as Xr,existsSync as Yr,mkdirSync as Vr}from"node:fs";import{join as zr}from"node:path";var st=zr(oe.DIR,"sessions.json");function ds(){if(!Yr(st))return{};try{return JSON.parse(Hr(st,"utf8"))}catch{return{}}}function ue(s){Vr(oe.DIR,{recursive:!0}),Xr(st,JSON.stringify(s,null,2))}U();rt();function js(s,{provider:e}={}){let t=e||process.env.AGENTPAGER_PROVIDER||"claude",r=s.binding?.phone_id,n=s.binding?.chan_key?X(s.binding.chan_key):null,i=ds(),o=new Map,a=new Map,l=new Map,d=new Set,p=Number(process.env.AGENTPAGER_SESSION_IDLE_MS||1800*1e3),u=setInterval(()=>{let c=Date.now();for(let[f,m]of a)if(!(d.has(f)||c-(l.get(f)||0)<=p)){try{m.close()}catch{}a.delete(f),l.delete(f),N("evicted idle provider session",f)}},6e4);u.unref&&u.unref();let _=new we(s).connect();_.on("open",()=>N("relay connected",s.device_id)),_.on("close",()=>N("relay disconnected")),_.on("error",c=>N("relay error",c.message));let A=new Set,O=[];_.on("envelope",async c=>{if(c.from!==r){N("drop wrong phone_id",c.from,"want",r,c.msg_id);return}let f=Ct(n,c);if(!f){N("drop undecryptable envelope",c.msg_id);return}if(c.msg_id&&A.has(c.msg_id)){N("drop duplicate",c.msg_id);return}c.msg_id&&(A.add(c.msg_id),O.push(c.msg_id),O.length>1e3&&A.delete(O.shift()));try{await k(f)}catch(m){N("handle error",m.message)}});function y(c){if(!r||!n){N("no binding/key; cannot send");return}_.sendEnvelope(Tt(n,s.device_id,r,c))}let v=new Map,g=c=>v.get(c)||c;function w(c){let f=o.get(c);return f||(f=new ve(c),o.set(c,f)),f}function h(c,f){c=g(c);let m=w(c),S=m.append(f);i[c]&&(i[c].last_seq=S,ue(i));let E=Fe(f);E&&y({...E,session_id:c,seq:S});let x={kind:"thread_render_frame",session_id:c,seq:S,events:[f]};f.type!=="delta"&&(x.render_state=de(m.recordsAfter(0,F))),y(x)}async function k(c){switch(N("recv "+c.kind+(c.offset!=null?" offset="+c.offset:"")),c.session_id&&(c.session_id=g(c.session_id)),c.kind){case"session.create":{let f=i[c.session_id];if(f){y({kind:"session.created",session_id:c.session_id,agent_ref:f.agent_ref});return}if(c.resume&&c.resume.session_id){let E=s.agents.find(I=>I.provider===(c.resume.provider||"claude"))||s.agents[0]||{},x={agent_id:E.agent_id||"native",agent_version:E.agent_version||1,provider:c.resume.provider||"claude",workdir:c.resume.workdir||E.workdir};i[c.session_id]={agent_ref:x,provider_session_id:c.resume.session_id,last_seq:0,updated_at:Date.now()},ue(i),y({kind:"session.created",session_id:c.session_id,agent_ref:x});return}let m=s.agents.find(E=>E.agent_id===c.agent_ref?.agent_id)||s.agents[0];if(!m){y({kind:"session.error",session_id:c.session_id,error:"no_agent"});return}let S={agent_id:m.agent_id,agent_version:m.agent_version,provider:m.provider,workdir:c.workdir||m.workdir};i[c.session_id]={agent_ref:S,provider_session_id:null,last_seq:0,updated_at:Date.now(),model:c.model},ue(i),y({kind:"session.created",session_id:c.session_id,agent_ref:S});return}case"chat.user":{let f=i[c.session_id];if(!f){y({kind:"session.error",session_id:c.session_id,error:"unknown_session"});return}let m=a.get(c.session_id);m||(m=await rs({provider:t==="mock"?"mock":f.agent_ref.provider,workdir:f.agent_ref.workdir,model:f.model,resumeSessionId:f.provider_session_id||void 0,onSessionId:x=>{if(!x||f.provider_session_id===x)return;f.provider_session_id=x;let I=c.session_id;if(x!==I&&!i[x]){i[x]=i[I],delete i[I];let D=o.get(I);D&&(D.renameTo(x),o.set(x,D),o.delete(I));let j=a.get(I);j&&(a.set(x,j),a.delete(I)),l.has(I)&&(l.set(x,l.get(I)),l.delete(I)),d.has(I)&&(d.add(x),d.delete(I)),v.set(I,x),N("session rekeyed",I,"->",x)}ue(i),y({kind:"session.bound",session_id:I,provider_session_id:x})}}),a.set(g(c.session_id),m)),l.set(g(c.session_id),Date.now()),d.add(g(c.session_id));let S=c.text||"",E=null;if(Array.isArray(c.image_ids)&&c.image_ids.length){let{loadImage:x}=await Promise.resolve().then(()=>(fe(),Ee)),I=c.image_ids.slice(0,6).map(D=>({id:D,...x(D)||{}})).filter(D=>D.data);I.length&&(E=I.map(j=>({id:j.id,media_type:j.media_type,bytes:j.bytes})),(t==="mock"?"mock":f.agent_ref.provider)==="claude"?S=[...I.map(j=>({type:"image",source:{type:"base64",media_type:j.media_type,data:j.data}})),...c.text?[{type:"text",text:c.text}]:[]]:S=(c.text||"")+I.map(j=>`
25
+
26
+ [\u7528\u6237\u53D1\u6765\u56FE\u7247,\u6587\u4EF6\u8DEF\u5F84: ${j.path}]`).join(""))}h(c.session_id,b.user(c.text,E));try{await m.runTurn({text:S,onEvent:x=>{x.type!=="done"&&h(c.session_id,x)},onDelta:x=>h(c.session_id,b.delta(x)),onToolUse:x=>h(c.session_id,b.toolUse({tool_use_id:Ot(),name:x,kind:B({name:x})}))})}catch(x){N("run error",x.message)}finally{d.delete(g(c.session_id)),l.set(g(c.session_id),Date.now())}h(c.session_id,b.done());return}case"run.interrupt":{let f=a.get(c.session_id);if(f?.interrupt){try{await f.interrupt()}catch(m){N("interrupt err",m.message)}y({kind:"run.interrupted",session_id:c.session_id})}else y({kind:"run.error",session_id:c.session_id,error:"no_active_run"});return}case"run.set_model":{let f=a.get(c.session_id);if(f?.setModel)try{await f.setModel(c.model),y({kind:"run.model_set",session_id:c.session_id,model:c.model})}catch(m){y({kind:"run.error",session_id:c.session_id,error:m.message})}else y({kind:"run.error",session_id:c.session_id,error:"no_active_run"});return}case"image.upload":{let{saveImage:f}=await Promise.resolve().then(()=>(fe(),Ee));try{let m=f(c.image_id,c.media_type,c.data);y({kind:"image.upload.result",image_id:c.image_id,ok:!0,bytes:m.bytes})}catch(m){N("image.upload failed",c.image_id,m.message),y({kind:"image.upload.result",image_id:c.image_id,ok:!1,error:m.message})}return}case"image.fetch":{let{loadImage:f}=await Promise.resolve().then(()=>(fe(),Ee)),m=f(c.image_id);y(m?{kind:"image.fetch.result",image_id:c.image_id,media_type:m.media_type,data:m.data}:{kind:"image.fetch.result",image_id:c.image_id,error:"not_found"});return}case"history.pull":{let f=w(c.session_id),m=f.recordsAfter(c.after_seq||0,F),S=m.map(x=>{let I=Fe(x.payload);return I?{seq:x.seq,ts:x.ts,...I}:null}).filter(Boolean),E=de(f.recordsAfter(0,F));y({kind:"history.batch",session_id:c.session_id,after_seq:c.after_seq||0,records:S,capped:m.length>=F,render_state:E});return}case"agent.list":{let{versionsFor:f}=await Promise.resolve().then(()=>(Ue(),ht)),m=await f(s.agents.map(S=>S.provider));y({kind:"agent.list.result",host:Vn().replace(/\.local$/i,""),agents:s.agents.map(S=>({...S,online:!0,capabilities:ns(S.provider),cliVersion:m[S.provider]||""}))});return}case"agent.dirs":{let{listDirs:f}=await Promise.resolve().then(()=>(ys(),gs));y({kind:"agent.dirs.result",dirs:await f()});return}case"agent.models":{let f=i[c.session_id],m=c.provider||f?.agent_ref?.provider||s.agents.find(x=>x.agent_id===c.agent_id)?.provider||"claude",{listModels:S}=await Promise.resolve().then(()=>(bs(),xs)),E=await S(m);y({kind:"agent.models.result",provider:m,models:E.models,current:E.current});return}case"native.list":{let{listNative:f}=await Promise.resolve().then(()=>(Le(),Ge)),m=f(c.limit||20,c.offset||0);N("native.list -> items="+m.items.length+" total="+m.total+" hasMore="+m.hasMore),y({kind:"native.list.result",items:m.items,total:m.total,offset:m.offset,hasMore:m.hasMore});return}case"native.history":{let{readNative:f}=await Promise.resolve().then(()=>(Le(),Ge)),m=f(c.provider,c.id,c.project,c.cap||300);y({kind:"native.history.result",id:c.id,msgs:m.msgs,rows:m.rows});return}case"tool.output":{let f=w(c.session_id),m="";for(let S of f.recordsAfter(0,F)){let E=S.payload||S;E.type==="tool_result"&&E.result&&E.result.tool_use_id===c.tool_use_id&&E.result.output!=null&&(m=E.result.output)}y({kind:"tool.output.result",session_id:c.session_id,tool_use_id:c.tool_use_id,output:m});return}case"native.search":{let{searchClaude:f}=await Promise.resolve().then(()=>(Le(),Ge)),m=f(c.q,c.limit||50);y({kind:"native.search.result",items:m.items,total:m.total,q:m.q});return}default:N("unknown kind",c.kind)}}return{rc:_,stop:()=>{clearInterval(u);for(let c of a.values())try{c.close()}catch{}_.stop()}}}function N(...s){console.log(`[${new Date().toISOString()}][daemon]`,...s)}var[,,zn,...zo]=process.argv;async function Qn(s){console.log(`
27
+ \u{1F4F1} \u7528\u624B\u673A\u91CC\u7684 AgentPager \u626B\u7801\u914D\u5BF9(\u626B\u4E0D\u4E86\u53EF\u624B\u52A8\u8F93\u4E0B\u9762\u7684\u7801):
28
+ `);try{let e=(await import("qrcode-terminal")).default;await new Promise(t=>e.generate(s,{small:!0},r=>{console.log(r),t()}))}catch{}console.log(` \u914D\u5BF9\u7801: ${s}
29
+ (\u7B49\u5F85\u624B\u673A\u626B\u7801\u2026\u6700\u957F 2 \u5206\u949F)
30
+ `)}process.on("uncaughtException",s=>console.error(`[${new Date().toISOString()}][uncaughtException]`,s?.stack||s));process.on("unhandledRejection",s=>console.error(`[${new Date().toISOString()}][unhandledRejection]`,s?.stack||s));async function Zn(){switch(zn){case"pair":{let s=_e(me());Q(s);let e=await Mt(s,{onCode:Qn});console.log(`
31
+ paired \u2713 device=${e.device_id} phone=${e.binding.phone_id}`),console.log(`agents: ${s.agents.map(t=>t.name).join(", ")||"(none \u2014 install claude/codex)"}`);break}case"start":{let s=_e(me());Q(s),s.binding||(console.error("not paired \u2014 run: agentpager pair (\u626B\u7801\u914D\u5BF9)"),process.exit(1)),js(s),console.log(`daemon started, device=${s.device_id}, bound to ${s.binding.phone_id}`);break}case"status":{let s=qe();if(!s){console.log("not configured");break}console.log(JSON.stringify({device_id:s.device_id,paired:!!s.binding,agents:s.agents.length,relay:s.relay_url},null,2));break}case"doctor":{let s=me(),e=he();console.log(`device_id: ${s.device_id}`),console.log(`relay: ${s.relay_url}`),console.log(`paired: ${s.binding?"yes":"no"}`),console.log(`provider CLIs detected: ${e.join(", ")||"NONE \u2014 install claude or codex"}`);break}default:console.log("agentpager <pair|start|status|doctor>")}}Zn().catch(s=>{console.error("error:",s.message),process.exit(1)});
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "agentpager-cli",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "AgentPager daemon — 手机遥控你电脑上的编程 Agent(Claude Code/Codex/Gemini 等 7 家)。配对后在微信小程序里实时查看会话、续聊、语音输入、发图。",
6
+ "bin": {
7
+ "agentpager": "dist/cli.js"
8
+ },
9
+ "scripts": {
10
+ "test:crypto": "node test/crypto.test.mjs",
11
+ "e2e:mock": "AGENTPAGER_PROVIDER=mock node test/e2e.mjs",
12
+ "e2e:claude": "AGENTPAGER_PROVIDER=claude node test/e2e.mjs",
13
+ "e2e:pairing": "node test/e2e-pairing.mjs",
14
+ "e2e:interrupt": "node test/e2e-interrupt.mjs",
15
+ "e2e:resume": "node test/e2e-resume.mjs",
16
+ "e2e:claude-resume": "node test/e2e-claude-resume.mjs",
17
+ "e2e:codex-proto": "node test/e2e-codex-proto.mjs",
18
+ "test:hashes": "node test/hashes.test.mjs",
19
+ "test:miniapp": "node test/miniapp-fidelity.test.mjs",
20
+ "test:codex-events": "node test/codex-events.test.mjs",
21
+ "test:claude-events": "node test/claude-events.test.mjs",
22
+ "test:qwen-events": "node test/qwen-events.test.mjs",
23
+ "test:codebuddy-events": "node test/codebuddy-events.test.mjs",
24
+ "test:cursor-events": "node test/cursor-events.test.mjs",
25
+ "test:render-state": "node test/render-state.test.mjs",
26
+ "test:transcript": "node test/transcript.test.mjs",
27
+ "test:session-robustness": "node test/session-robustness.test.mjs",
28
+ "e2e:robustness": "node test/e2e-robustness.mjs",
29
+ "test:weapp-pair": "node test/weapp-pair.test.mjs",
30
+ "capture:codex": "AGENTPAGER_CODEX_BIN=$(which codex) node tools/capture-codex.mjs",
31
+ "capture:claude": "node tools/capture-claude.mjs",
32
+ "build": "esbuild src/cli.mjs --bundle --minify --platform=node --format=esm --packages=external --outfile=dist/cli.js",
33
+ "prepublishOnly": "npm run build"
34
+ },
35
+ "dependencies": {
36
+ "@anthropic-ai/claude-agent-sdk": "^0.3.0",
37
+ "qrcode-terminal": "^0.12.0",
38
+ "tweetnacl": "^1.0.3",
39
+ "ws": "^8.18.0"
40
+ },
41
+ "devDependencies": {
42
+ "esbuild": "^0.28.1"
43
+ },
44
+ "files": [
45
+ "dist"
46
+ ],
47
+ "license": "SEE LICENSE IN LICENSE",
48
+ "keywords": [
49
+ "agent",
50
+ "claude-code",
51
+ "codex",
52
+ "remote-control",
53
+ "wechat-miniprogram",
54
+ "cli"
55
+ ],
56
+ "engines": {
57
+ "node": ">=18"
58
+ }
59
+ }