@truesayer/node 0.1.0 → 0.1.2

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 (3) hide show
  1. package/README.md +9 -0
  2. package/dist/node.js +33 -26
  3. package/package.json +3 -1
package/README.md CHANGED
@@ -11,6 +11,11 @@ Install and run:
11
11
  ```bash
12
12
  npm install -g @truesayer/node
13
13
 
14
+ truesayer-node doctor \
15
+ --server https://truesayer.ai \
16
+ --api-key sk_node_xxx \
17
+ --node-home ~/.truesayer-node
18
+
14
19
  truesayer-node \
15
20
  --server https://truesayer.ai \
16
21
  --api-key sk_node_xxx \
@@ -28,6 +33,10 @@ TRUESAYER_NODE_HOME=~/.truesayer-node
28
33
  truesayer-node
29
34
  ```
30
35
 
36
+ The runtime connects to `wss://truesayer.ai/api/nodes/ws` with
37
+ `Authorization: Bearer <NODE_API_KEY>`. The key is not sent in the WebSocket
38
+ URL.
39
+
31
40
  Only connect this runtime to a Truesayer Server you trust. Provider API keys,
32
41
  provider base URLs, login state, worktrees, and runtime cache stay local to the
33
42
  Node process and must not be uploaded to Server.
package/dist/node.js CHANGED
@@ -1,34 +1,41 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var Nt=Object.create;var ke=Object.defineProperty;var It=Object.getOwnPropertyDescriptor;var Pt=Object.getOwnPropertyNames;var At=Object.getPrototypeOf,xt=Object.prototype.hasOwnProperty;var St=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of Pt(t))!xt.call(e,o)&&o!==r&&ke(e,o,{get:()=>t[o],enumerable:!(n=It(t,o))||n.enumerable});return e};var J=(e,t,r)=>(r=e!=null?Nt(At(e)):{},St(t||!e||!e.__esModule?ke(r,"default",{value:e,enumerable:!0}):r,e));var Rt=require("fs"),Tt=require("path");var ht=J(require("os")),N=require("fs"),vt=require("path");var Ee=require("crypto"),S=require("fs"),D=J(require("path")),_e=J(require("simple-git")),Mt=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,z=new Map;function Ct(){let{PAGER:e,GIT_PAGER:t,...r}=process.env;return{...r,GIT_TERMINAL_PROMPT:"0",GIT_AUTHOR_NAME:process.env.TRUESAYER_GIT_AUTHOR_NAME||process.env.GIT_AUTHOR_NAME||"Truesayer",GIT_AUTHOR_EMAIL:process.env.TRUESAYER_GIT_AUTHOR_EMAIL||process.env.GIT_AUTHOR_EMAIL||"truesayer@example.invalid",GIT_COMMITTER_NAME:process.env.TRUESAYER_GIT_COMMITTER_NAME||process.env.GIT_COMMITTER_NAME||"Truesayer",GIT_COMMITTER_EMAIL:process.env.TRUESAYER_GIT_COMMITTER_EMAIL||process.env.GIT_COMMITTER_EMAIL||"truesayer@example.invalid"}}function Ot(e){return(0,_e.default)(e,{trimmed:!0}).env(Ct())}async function I(e,t){return(await Ot(t).raw(e)).trim()}async function Re(e){return I(["rev-parse","--show-toplevel"],e)}function Dt(e){return`agent/work/${Mt.test(e)?e:`action-${e.replace(/[^A-Za-z0-9_-]/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")||"unknown"}`}`}async function Te(e,t){let r=z.get(e)??Promise.resolve(),n=()=>{},o=r.catch(()=>{}).then(()=>new Promise(s=>{n=s}));z.set(e,o),await r.catch(()=>{});try{return await t()}finally{n(),z.get(e)===o&&z.delete(e)}}async function Ut(e,t){try{return await I(["rev-parse","--verify",`refs/heads/${e}`],t),!0}catch{return!1}}async function Ne(e){try{return await I(["rev-parse","--is-inside-work-tree"],e)==="true"}catch{return!1}}function Ft(e){return e instanceof Error?e.message:String(e)}async function we(e,t,r){try{await I(e,r);return}catch(n){if(!Ft(n).includes("already exists")||!(0,S.existsSync)(t))throw n;if(await Ne(t))return;(0,S.rmSync)(t,{recursive:!0,force:!0}),await I(e,r)}}async function Ie(e){let t=Dt(e.actionId),r=await Re(e.repoPath),n=D.default.resolve(e.worktreePath);return Te(r,async()=>{(0,S.existsSync)(n)&&!await Ne(n)&&(0,S.rmSync)(n,{recursive:!0,force:!0}),(0,S.mkdirSync)(D.default.dirname(n),{recursive:!0}),(0,S.existsSync)(n)||(await Ut(t,r)?await we(["worktree","add",n,t],n,r):await we(["worktree","add","-b",t,n,e.baseBranch],n,r));let o=await I(["merge-base",e.baseBranch,t],n);return{branch:t,path:n,baseSha:o,baseRef:e.baseBranch}})}async function Pe(e){return I(["rev-parse","HEAD"],e)}function Y(e){return(0,Ee.createHash)("sha256").update(e).digest("hex")}function X(e){return e.split(`
3
- `).map(t=>t.trimEnd()).filter(Boolean)}async function Ht(e){return X(await I(["diff","--cached","--name-only"],e)).length>0}async function Z(e,t){let r=["ls-files","--others","--exclude-standard"];return t&&r.push("--",t),X(await I(r,e))}function de(e,t){if(D.default.isAbsolute(t))throw new Error(`Absolute git file paths are not allowed: ${t}`);let r=D.default.resolve(e),n=D.default.resolve(r,t),o=D.default.relative(r,n);if(!(o&&o!==".."&&!o.startsWith(`..${D.default.sep}`)&&!D.default.isAbsolute(o)))throw new Error(`Unsafe git file path outside worktree: ${t}`);return n}function Ae(e){if(e.includes(0))return null;let t=e.toString("utf8");return t.length===0?0:t.endsWith(`
4
- `)?t.slice(0,-1).split(/\r\n|\r|\n/).length:t.split(/\r\n|\r|\n/).length}function Lt(e,t){let r=Ae(t);if(r===null)return[`diff --git a/${e} b/${e}`,"new file mode 100644","Binary files /dev/null and b/"+e+" differ"].join(`
2
+ "use strict";var or=Object.create;var Ke=Object.defineProperty;var sr=Object.getOwnPropertyDescriptor;var ir=Object.getOwnPropertyNames;var ar=Object.getPrototypeOf,dr=Object.prototype.hasOwnProperty;var cr=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of ir(t))!dr.call(e,o)&&o!==r&&Ke(e,o,{get:()=>t[o],enumerable:!(n=sr(t,o))||n.enumerable});return e};var V=(e,t,r)=>(r=e!=null?or(ar(e)):{},cr(t||!e||!e.__esModule?Ke(r,"default",{value:e,enumerable:!0}):r,e));var er=require("fs"),tr=require("path");var ae=V(require("os")),x=require("fs"),M=require("path");var Ye=require("crypto"),F=require("fs"),q=V(require("path")),Xe=V(require("simple-git")),ur=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,ce=new Map,lr=["PATH","HOME","LANG","LC_ALL","TMPDIR","TEMP","TMP","SSH_AUTH_SOCK","GIT_SSH","GIT_SSH_COMMAND","GIT_EXEC_PATH","GIT_CONFIG_GLOBAL","GIT_CONFIG_SYSTEM","SystemRoot","USERPROFILE"];function pr(e){let t={};for(let n of lr){let o=process.env[n];o!==void 0&&(t[n]=o)}let r=q.default.resolve(e);return{...t,GIT_TERMINAL_PROMPT:"0",GIT_CONFIG_COUNT:"1",GIT_CONFIG_KEY_0:"safe.directory",GIT_CONFIG_VALUE_0:r,GIT_AUTHOR_NAME:process.env.TRUESAYER_GIT_AUTHOR_NAME||process.env.GIT_AUTHOR_NAME||"Truesayer",GIT_AUTHOR_EMAIL:process.env.TRUESAYER_GIT_AUTHOR_EMAIL||process.env.GIT_AUTHOR_EMAIL||"truesayer@example.invalid",GIT_COMMITTER_NAME:process.env.TRUESAYER_GIT_COMMITTER_NAME||process.env.GIT_COMMITTER_NAME||"Truesayer",GIT_COMMITTER_EMAIL:process.env.TRUESAYER_GIT_COMMITTER_EMAIL||process.env.GIT_COMMITTER_EMAIL||"truesayer@example.invalid"}}function mr(e){return(0,Xe.default)(e,{trimmed:!0,unsafe:{allowUnsafeConfigEnvCount:!0}}).env(pr(e))}async function I(e,t){return(await mr(t).raw(e)).trim()}async function Ne(e){return I(["rev-parse","--show-toplevel"],e)}function fr(e){return`agent/work/${ur.test(e)?e:`action-${e.replace(/[^A-Za-z0-9_-]/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")||"unknown"}`}`}async function Ze(e,t){let r=ce.get(e)??Promise.resolve(),n=()=>{},o=r.catch(()=>{}).then(()=>new Promise(s=>{n=s}));ce.set(e,o),await r.catch(()=>{});try{return await t()}finally{n(),ce.get(e)===o&&ce.delete(e)}}async function gr(e,t){try{return await I(["rev-parse","--verify",`refs/heads/${e}`],t),!0}catch{return!1}}async function Se(e){try{return await I(["rev-parse","--is-inside-work-tree"],e)==="true"}catch{return!1}}async function hr(e){try{return await I(["rev-parse","--verify","HEAD"],e),!0}catch{return!1}}async function vr(e){if(await hr(e))return;if((await I(["status","--porcelain"],e)).trim()){await I(["add","-A"],e),await I(["commit","-m","Initial workspace snapshot","--no-gpg-sign"],e);return}await I(["commit","--allow-empty","-m","Initial workspace snapshot","--no-gpg-sign"],e)}async function Ie(e){let t=q.default.resolve(e.path),r=e.baseRef?.trim()||"main";(0,F.mkdirSync)(t,{recursive:!0});let n=!1;await Se(t)||(await I(["init","-b",r],t),n=!0);let o=await Ne(t);await vr(o);try{await I(["rev-parse","--verify",r],o)}catch{throw new Error(`baseRef not found: ${r}`)}return{path:t,baseRef:r,initialized:n,empty:!1,repoRoot:o}}function yr(e){return e instanceof Error?e.message:String(e)}async function ze(e,t,r){try{await I(e,r);return}catch(n){if(!yr(n).includes("already exists")||!(0,F.existsSync)(t))throw n;if(await Se(t))return;(0,F.rmSync)(t,{recursive:!0,force:!0}),await I(e,r)}}async function Qe(e){let t=fr(e.actionId),r=await Ne(e.repoPath),n=q.default.resolve(e.worktreePath);return Ze(r,async()=>{(0,F.existsSync)(n)&&!await Se(n)&&(0,F.rmSync)(n,{recursive:!0,force:!0}),(0,F.mkdirSync)(q.default.dirname(n),{recursive:!0}),(0,F.existsSync)(n)||(await gr(t,r)?await ze(["worktree","add",n,t],n,r):await ze(["worktree","add","-b",t,n,e.baseBranch],n,r));let o=await I(["merge-base",e.baseBranch,t],n);return{branch:t,path:n,baseSha:o,baseRef:e.baseBranch}})}async function Pe(e){return I(["rev-parse","HEAD"],e)}function ue(e){return(0,Ye.createHash)("sha256").update(e).digest("hex")}function le(e){return e.split(`
3
+ `).map(t=>t.trimEnd()).filter(Boolean)}async function kr(e){return le(await I(["diff","--cached","--name-only"],e)).length>0}async function wr(e){try{return await I(["symbolic-ref","--short","HEAD"],e)}catch{return I(["rev-parse","HEAD"],e)}}async function br(e,t){return I(["rev-parse","--verify",e],t)}function Rr(e,t){return e===t||`refs/heads/${e}`===t||e===`refs/heads/${t}`}async function pe(e,t){let r=["ls-files","--others","--exclude-standard"];return t&&r.push("--",t),le(await I(r,e))}function Ae(e,t){if(q.default.isAbsolute(t))throw new Error(`Absolute git file paths are not allowed: ${t}`);let r=q.default.resolve(e),n=q.default.resolve(r,t),o=q.default.relative(r,n);if(!(o&&o!==".."&&!o.startsWith(`..${q.default.sep}`)&&!q.default.isAbsolute(o)))throw new Error(`Unsafe git file path outside worktree: ${t}`);return n}function et(e){if(e.includes(0))return null;let t=e.toString("utf8");return t.length===0?0:t.endsWith(`
4
+ `)?t.slice(0,-1).split(/\r\n|\r|\n/).length:t.split(/\r\n|\r|\n/).length}function _r(e,t){let r=et(t);if(r===null)return[`diff --git a/${e} b/${e}`,"new file mode 100644","Binary files /dev/null and b/"+e+" differ"].join(`
5
5
  `);let n=t.toString("utf8"),o=n.length===0?[]:n.replace(/\n$/,"").split(/\r\n|\r|\n/);return[`diff --git a/${e} b/${e}`,"new file mode 100644","--- /dev/null",`+++ b/${e}`,`@@ -0,0 +1,${r} @@`,...o.map(s=>`+${s}`)].join(`
6
- `)}async function $t(e,t){let r=X(await I(["diff","--name-status",e],t)),n=new Set(r.map(s=>s.split(" ").at(-1)??"")),o=(await Z(t)).filter(s=>!n.has(s)).map(s=>`A ${s}`);return[...r,...o].join(`
7
- `)}async function jt(e,t){let r=X(await I(["diff","--numstat",e],t)),n=new Set(r.map(s=>s.split(" ").slice(2).join(" ")).filter(Boolean)),o=await Promise.all((await Z(t)).filter(s=>!n.has(s)).map(s=>{let a=(0,S.readFileSync)(de(t,s));return`${Ae(a)??"-"} 0 ${s}`}));return[...r,...o].join(`
8
- `)}async function qt(e,t,r){return new Set(await Z(t,r)).has(r)?Lt(r,(0,S.readFileSync)(de(t,r))):I(["diff",e,"--",r],t)}function Bt(e){return e.replace(/^"(.*)"$/,"$1").replace(/^a\//,"").replace(/^b\//,"")}function Wt(e){let t=/^diff --git a\/(.+?) b\/(.+)$/.exec(e.trim());return t?Bt(t[2]??t[1]??""):null}function Kt(e){let t=new Map,r=null,n=[],o=()=>{if(!r)return;let s=n.join(`
6
+ `)}async function Er(e,t){let r=le(await I(["diff","--name-status",e],t)),n=new Set(r.map(s=>s.split(" ").at(-1)??"")),o=(await pe(t)).filter(s=>!n.has(s)).map(s=>`A ${s}`);return[...r,...o].join(`
7
+ `)}async function Tr(e,t){let r=le(await I(["diff","--numstat",e],t)),n=new Set(r.map(s=>s.split(" ").slice(2).join(" ")).filter(Boolean)),o=await Promise.all((await pe(t)).filter(s=>!n.has(s)).map(s=>{let a=(0,F.readFileSync)(Ae(t,s));return`${et(a)??"-"} 0 ${s}`}));return[...r,...o].join(`
8
+ `)}async function Nr(e,t,r){return new Set(await pe(t,r)).has(r)?_r(r,(0,F.readFileSync)(Ae(t,r))):I(["diff",e,"--",r],t)}function Sr(e){return e.replace(/^"(.*)"$/,"$1").replace(/^a\//,"").replace(/^b\//,"")}function Ir(e){let t=/^diff --git a\/(.+?) b\/(.+)$/.exec(e.trim());return t?Sr(t[2]??t[1]??""):null}function Pr(e){let t=new Map,r=null,n=[],o=()=>{if(!r)return;let s=n.join(`
9
9
  `);t.set(r,s.endsWith(`
10
10
  `)?s:`${s}
11
11
  `)};for(let s of e.split(`
12
- `)){let a=Wt(s);if(a){o(),r=a,n=[s];continue}r&&n.push(s)}return o(),t}function be(e){let t=Number(e);return Number.isFinite(t)?t:0}function Gt(e){let t=e.trim();if(!t.includes(" => "))return t;let r=/^(.*)\{.* => (.*)\}(.*)$/.exec(t);return r?`${r[1]}${r[2]}${r[3]}`:t.slice(t.lastIndexOf(" => ")+4).trim()}function Jt(e){let t=new Map;for(let r of e.split(`
13
- `).filter(Boolean)){let[n,o,...s]=r.split(" "),a=Gt(s.join(" "));a&&t.set(a,{additions:be(n),deletions:be(o)})}return t}function zt(e){let[t,...r]=e.split(" "),n=t.charAt(0),o=n==="R"||n==="C"?r.at(-1)?.trim():r.join(" ").trim();return o?{path:o,status:n==="A"?"added":n==="D"?"deleted":n==="R"?"renamed":"modified"}:null}function Yt(e,t){let r=Jt(t);return e.split(`
14
- `).filter(Boolean).map(zt).filter(n=>n!==null).map(n=>({...n,additions:r.get(n.path)?.additions??0,deletions:r.get(n.path)?.deletions??0}))}function Vt(e,t){return Y((0,S.readFileSync)(de(e,t)))}function Xt(e,t){if(t.size===0)return Y(e);let r=Array.from(t.entries()).sort(([n],[o])=>n.localeCompare(o)).map(([n,o])=>`${n}\0${o}`).join(`
15
- `);return Y(`${e}\0untracked-content\0${r}`)}function Zt(e){return Yt(e.fileListRaw,e.numstatRaw).map(t=>{let r=e.diffByFile.get(t.path)??"",n=e.untrackedContentHashes.get(t.path);return{path:t.path,status:t.status,additions:t.additions,deletions:t.deletions,patchHash:Y(n?`${r}\0untracked-content\0${n}`:r),untracked:e.untracked.has(t.path)}})}async function V(e){let t=await Re(e),r=await I(["rev-parse","HEAD"],t),[n,o,s,a,i]=await Promise.all([$t(r,t),jt(r,t),I(["diff","--no-textconv","--no-ext-diff",r],t),Z(t),Ht(t)]),c=await Promise.all(a.map(y=>qt(r,t,y))),p=new Map(a.map(y=>[y,Vt(t,y)])),k=[s,...c].filter(Boolean).join(`
16
- `),b=k&&!k.endsWith(`
17
- `)?`${k}
18
- `:k,m=Kt(b);return{repoRoot:t,baseSha:r,diff:b,diffHash:Xt(b,p),hasStagedChanges:i,files:Zt({fileListRaw:n,numstatRaw:o,diffByFile:m,untracked:new Set(a),untrackedContentHashes:p})}}function Qt(e,t,r){let n=e.files.find(o=>o.path===t);if(!n)throw new Error("file is not in current git diff");if(r&&n.patchHash!==r)throw new Error("git diff changed; refresh before restoring");return n}async function xe(e){let t=await V(e.worktreePath);if(t.baseSha!==e.baseSha)throw new Error("git base changed; refresh before restoring");if(t.hasStagedChanges)throw new Error("staged changes are not supported");let r=e.filePath?[Qt(t,e.filePath,e.expectedPatchHash)]:t.files;if(!e.filePath&&e.expectedDiffHash&&t.diffHash!==e.expectedDiffHash)throw new Error("git diff changed; refresh before restoring");let n=r.filter(a=>!a.untracked).map(a=>a.path),o=r.filter(a=>a.untracked).map(a=>a.path),s=t.repoRoot;return await Te(s,async()=>{n.length>0&&await I(["restore",`--source=${e.baseSha}`,"--worktree","--",...n],s),o.length>0&&await I(["clean","-f","--",...o],s)}),V(s)}var Q=require("fs"),Se=require("os"),A=require("path");function ce(){return process.env.TRUESAYER_NODE_HOME?.trim()||(0,A.join)((0,Se.homedir)(),".truesayer-node")}function Me(e){return(0,A.join)(e?.trim()||ce(),"provider.json")}function L(e){return e.replace(/[^a-zA-Z0-9_-]/g,"_").slice(0,120)||"unknown"}function Ce(e){return(0,Q.mkdirSync)(e,{recursive:!0,mode:448}),(0,Q.chmodSync)(e,448),e}function er(e){return{HOME:e,CLAUDE_CONFIG_DIR:(0,A.join)(e,".claude"),CODEX_HOME:(0,A.join)(e,".codex")}}function ue(e){let t=e.truesayerNodeHome?.trim()||ce(),r=L(e.agentId),n=(0,A.join)(t,"agents",r),o=(0,A.join)(t,"runtime-home"),s=(0,A.join)(n,"space"),a=(0,A.join)(s,"profile");for(let i of[o,(0,A.join)(o,".claude"),(0,A.join)(o,".codex"),s,a])Ce(i);return{agentRoot:n,providerHome:o,spaceRoot:s,profileDir:a,providerEnv:er(o)}}function Oe(e){let t=e.truesayerNodeHome?.trim()||ce(),r=L(e.workspaceId),n=L(e.agentSessionId),o=L(e.agentRunId),s=L(e.repoAlias),a=ue({truesayerNodeHome:t,workspaceId:e.workspaceId,agentId:e.agentId}),{agentRoot:i,providerHome:c,spaceRoot:p,profileDir:k}=a,b=(0,A.join)(p,"context",n),m=(0,A.join)(p,"agent-run",o),y=(0,A.join)(p,"worktree",r,s,o);for(let d of[b,m,y])Ce(d);return{agentRoot:i,providerHome:c,spaceRoot:p,profileDir:k,contextDir:b,agentRunDir:m,worktreeDir:y,fileToolRoot:p,providerEnv:a.providerEnv}}var te=require("fs/promises"),je=require("os"),qe=require("path"),le=require("@anthropic-ai/claude-agent-sdk");var Ue=J(require("os")),$=require("fs"),M=require("@anthropic-ai/claude-agent-sdk"),u=require("zod/v4"),tr=16*1024,rr=12e3;function nr(e){return{content:[{type:"text",text:JSON.stringify(e??{})}]}}var De=u.z.object({id:u.z.string().describe("Stable slug for this task item, such as implement-todo-app."),label:u.z.string().trim().min(1).describe('Descriptive task title, such as "\u5B9E\u73B0\u5168\u6808 Todo app"; do not use only "1", "step 1", or "phase 1".'),ownerAgentId:u.z.string().describe("Target Truesayer teammate id from list_channel_agents or resolve_channel_agent. Do not put responsibilities, roles, names, or mention text here."),status:u.z.enum(["todo","active","done","blocked"]).optional(),estMinutes:u.z.number().optional(),dependsOn:u.z.array(u.z.string()).optional()}).passthrough(),or=u.z.object({creationCheckId:u.z.string().uuid(),name:u.z.string().optional(),description:u.z.string().optional(),providerName:u.z.string().optional(),providerId:u.z.string().optional(),modelId:u.z.string().optional(),selectedModel:u.z.string().optional(),reasoningEffort:u.z.enum(["default","none","minimal","low","medium","high","xhigh","max"]).optional(),thinkingMode:u.z.enum(["default","disabled","adaptive"]).optional(),serviceTier:u.z.enum(["default","fast","flex"]).optional(),responsibility:u.z.string().optional()}).passthrough();function sr(e){if(!e.startsWith("/tmp/")&&!e.startsWith(`${Ue.default.tmpdir()}/`))return!1;try{let t=(0,$.statSync)(e);return t.isFile()&&t.size>0}catch{return!1}}function ir(e){try{let t=(0,$.statSync)(e),r=Math.max(0,t.size-tr);return(0,$.readFileSync)(e).subarray(r).toString("utf8").replace(/\0/g,"").trim().slice(-rr)}catch{return""}}function ar(e){if(typeof e.logTail=="string"&&e.logTail.trim())return e;let t=typeof e.logPath=="string"?e.logPath.trim():"";if(!t||!sr(t))return e;let r=ir(t);return r?{...e,logTail:r}:e}function dr(e,t,r={}){let n=async(s,a)=>{let i=s==="record_background_service"?ar(a):a;return nr(await t({agentRunId:e,toolName:s,args:i}))},o=(0,M.tool)("reply_to_channel","Reply visibly in the current Truesayer channel as this agent.",{body:u.z.string(),attachmentIds:u.z.array(u.z.string()).optional(),messageId:u.z.string().optional()},async s=>n("reply_to_channel",s),{alwaysLoad:!0});return r.mode==="silent_relevance"?[o]:[o,(0,M.tool)("create_agent","Create an active Truesayer teammate profile and bind it to a Node runtime provider/model. This is a protected action that blocks for human approval. It does not add the new teammate to the current channel; channel membership must be granted by the frontend, an admin API, setup seed, or an explicit Server policy.",{creationCheckId:u.z.string().uuid(),name:u.z.string(),description:u.z.string(),providerId:u.z.string().optional(),providerName:u.z.string().optional(),modelId:u.z.string().optional(),selectedModel:u.z.string().optional(),reasoningEffort:u.z.enum(["default","none","minimal","low","medium","high","xhigh","max"]).optional(),thinkingMode:u.z.enum(["default","disabled","adaptive"]).optional(),serviceTier:u.z.enum(["default","fast","flex"]).optional(),systemPrompt:u.z.string().optional(),soul:u.z.string().optional(),tone:u.z.number().optional()},async s=>n("create_agent",s),{alwaysLoad:!0}),(0,M.tool)("create_agents","Create multiple active Truesayer teammate profiles in one protected action. This blocks for human approval before the Server creates the profiles. Each agents[] item must include a stable creationCheckId UUIDv7; reuse the same creationCheckId when retrying the same logical agent creation request. It does not add the new teammates to the current channel; channel membership must be granted by the frontend, an admin API, setup seed, or an explicit Server policy.",{summary:u.z.string().describe("Human-readable summary shown on the approval activity card."),agents:u.z.array(or.extend({name:u.z.string(),description:u.z.string()})).min(1)},async s=>n("create_agents",s),{alwaysLoad:!0}),(0,M.tool)("message_agent",'Send a work request or update to another Truesayer agent. This is only for immediately runnable work. If the message continues or refers to a structured task-card item, include planItemId so the Server can reuse the existing handoff instead of creating duplicate work. Do not use it to pre-send future or dependency-blocked work such as "audit after implementation"; represent that as blocked items in delegate_plan instead. Use this to delegate execution instead of visibly @mentioning that agent. After a successful delegation, end the current run. Truesayer may wake the current agent with downstream results and evidence; decide the next step yourself.',{toAgentId:u.z.string(),body:u.z.string(),refTaskId:u.z.string().optional(),planItemId:u.z.string().optional()},async s=>n("message_agent",s),{alwaysLoad:!0}),(0,M.tool)("resolve_channel_agent","Resolve an agent name, mention, or id to a unique teammate in the current Truesayer channel. This is read-only and returns blockers for not_found, not_bound, or ambiguous matches.",{query:u.z.string()},async s=>n("resolve_channel_agent",s),{alwaysLoad:!0}),(0,M.tool)("list_channel_agents","List all Truesayer agents in this workspace and mark whether each one can access the current Truesayer channel. Use this before delegate_plan or message_agent when agent ids or channel access may have changed.",{},async s=>n("list_channel_agents",s),{alwaysLoad:!0}),(0,M.tool)("delegate_plan","Create a channel task card and delegate active items to specific Truesayer agents. Active items are immediately sent to their owner agents as executable work when this tool succeeds. Do not call message_agent to notify the same owner about the same active item. Each item label must describe the actual assigned work in enough detail for the owner to execute it, not only an ordinal. Use blocked items for future or dependency-blocked work, and only make an item active when it should run now. Put all instructions for that phase in the item label/status/dependencies before calling this tool. Do not create plan items owned by yourself or the current agent; coordinator-owned follow-up work such as final review, deciding whether to continue, summary, or reply must stay outside the task card. Do not render coordinator-owned follow-up work as task table rows in visible replies. Use a short sentence instead. Call list_channel_agents first when you need current agent ids or channel access. When the user asks to assign, delegate, create task cards, or start a phase, use this before Bash/Edit/Read unless the user asked you to implement the work yourself. After successful delegation, end the current run. Truesayer may wake the current agent with downstream results and evidence; decide the next step yourself, such as verify, delegate more work, update the plan, report a blocker, or reply to the channel.",{items:u.z.array(De),replace:u.z.boolean().optional()},async s=>n("delegate_plan",s),{alwaysLoad:!0}),(0,M.tool)("emit_plan","Create or update the visible channel task card for this agent run. Each item label must describe the actual work, not only an ordinal. Do not create plan items owned by yourself or the current agent; coordinator-owned follow-up work such as final review, deciding whether to continue, summary, or reply must stay outside the task card. Do not render coordinator-owned follow-up work as task table rows in visible replies. Use a short sentence instead. Existing unfinished downstream items are preserved unless replace is true. Use delegate_plan instead when active items should be assigned to other agents. Call list_channel_agents first when ownerAgentId values need current agent ids or channel access.",{items:u.z.array(De),replace:u.z.boolean().optional()},async s=>n("emit_plan",s),{alwaysLoad:!0}),(0,M.tool)("update_plan_item","Update one item on the current canonical task card. Do not provide or guess a root task id; the Truesayer Server chooses the writable plan from this agent run context.",{itemId:u.z.string(),status:u.z.enum(["todo","active","done","blocked"])},async s=>n("update_plan_item",s),{alwaysLoad:!0}),(0,M.tool)("record_background_service","Record a visible background service started for human inspection. Use this after starting a keep-alive dev/server process in the background and after a bounded health check succeeds. Include PID, port, URL, and log path so Activity can show a visible background service row. This records observability only; it does not start, stop, or clean up the process.",{label:u.z.string().optional(),pid:u.z.number().optional(),port:u.z.number().optional(),url:u.z.string().optional(),healthUrl:u.z.string().optional(),logPath:u.z.string().optional(),cwd:u.z.string().optional()},async s=>n("record_background_service",s),{alwaysLoad:!0})]}function Fe(e,t,r={}){return(0,M.createSdkMcpServer)({name:"truesayer-platform",version:"0.1.0",tools:dr(e,t,r),alwaysLoad:!0})}var He=["Truesayer platform tools are available as local tools. They send JSON-RPC requests from the Node process to the Truesayer Server over the existing WebSocket.","Use reply_to_channel for visible channel replies.","Use create_agents to create long-lived teammates that do not yet exist. Put what the teammate does in description, not role. Every agents[] item must include a stable creationCheckId UUIDv7; reuse it when retrying the same logical agent creation. create_agents blocks for human approval before the Server creates the profiles, and returns agentId plus mentionName values to use in message_agent and task card ownerAgentId.","Use create_agent only when creating exactly one teammate. It is also protected and blocks for human approval.","create_agent and create_agents do not add new teammates to the current channel. Channel membership/invitation must be granted by the frontend, an admin API, setup seed, or an explicit Server policy, never by agent authority.","Use list_channel_agents to get the realtime list of all Truesayer agents in this workspace and whether each can access the current channel. Use it before delegate_plan or message_agent when IDs, names, or channel membership may have changed.","Use resolve_channel_agent to turn a teammate name or @mention in the current channel into the agentId required by message_agent and task card ownerAgentId. If it returns not_bound, ambiguous, or not_found, report that blocker instead of guessing an id.","message_agent is only for immediately runnable work. If continuing a structured task-card item, include planItemId. The recipient may start as soon as the tool succeeds, so do not use message_agent to pre-send future, conditional, or dependency-blocked work.","Use delegate_plan or emit_plan for visible channel task cards, and update_plan_item to update item status. Task item labels must be descriptive enough for the assigned agent to execute from the item alone.","delegate_plan active items with valid ownerAgentId values are already sent to their owner agents as executable work when the tool succeeds. Do not follow delegate_plan with message_agent for the same active item; put the full task instructions into the active plan item before delegating.","Future or dependency-blocked work must be represented as blocked task card items with delegate_plan or emit_plan. Do not send those items through message_agent until they are actually runnable.","Do not create plan items owned by yourself or the current agent. Coordinator-owned follow-up work such as final review, deciding whether to continue, summary, or reply is not a task-card item. After delegated work finishes, Truesayer may wake the current agent with downstream results and evidence, and you decide the next step yourself: verify, delegate more work, update the plan, report a blocker, or reply to the channel.","If a prompt asks you to create a collaboration team, call create_agents once with the whole team so the human sees one approval card. If the tool is rejected or blocked, report that blocker instead of retrying.","If a prompt asks you to assign, delegate, create task cards, update a plan, or start a phased handoff with existing teammates, your first tool call must be delegate_plan or message_agent before any file, git, shell, package-manager, or code-edit tool.","A coordinating agent must not do another agent's assigned implementation, audit, or optimization work itself. Create the task card or agent message, then end the current run. Truesayer may wake the current agent with a continuation when downstream work reports back.","Never send message_agent to yourself as an availability test. If no suitable teammate exists, call create_agent first; if provider capability is missing, reply with the blocker.","Only use message_agent after delegate_plan for genuinely new follow-up communication, not as a notification that the delegated active item exists.","Do not use provider-native Agent, Task, TodoRead, or TodoWrite for product coordination. Truesayer task cards, plan updates, and teammate handoffs must go through Truesayer platform tools so the Server can audit every agent run.","If the provider UI prefixes Truesayer tools as MCP tools, select the matching tool whose name ends with create_agents, create_agent, resolve_channel_agent, reply_to_channel, message_agent, delegate_plan, emit_plan, update_plan_item, or record_background_service.","Long-running or continuously-running service/watch commands, such as dev servers, file watchers, npm start, npm run start, npm run dev, vite, next dev, nodemon, tsx --watch, tail -f, database servers, or queue workers, must not be run as foreground blocking commands. Start them in the background, redirect logs to a file, record the PID, and run a bounded health check with timeout. Stop or clean up the process when validation is complete unless the task explicitly asks to keep the service available for human inspection; in that case keep it running and call record_background_service with PID, port, URL, and log path. Finite commands such as install, build, test, lint, migration, and one-shot scripts should run in the foreground and must return an exit code.","Do not try to access the Truesayer Server database, provider secrets, or Server-only environment variables from Node."].join(`
19
- `);function Le(e){let t=Object.entries(e??{});return t.length===0?"":["Available Node runtime providers for create_agent/create_agents runtime selection:",...t.map(([r,n])=>`- ${r} (${n.kind}): ${n.models.join(", ")}`)].join(`
20
- `)}var cr=["DATABASE_URL","TRUESAYER_API_KEY","TRUESAYER_ADMIN_API_KEY","BETTER_AUTH_SECRET","ASSET_STORAGE_DRIVER","S3_ENDPOINT","S3_BUCKET","S3_ACCESS_KEY_ID","S3_SECRET_ACCESS_KEY","S3_REGION","S3_FORCE_PATH_STYLE"];function ur(e){let t={...e};return!t.ANTHROPIC_API_KEY&&t.AGENT_API_KEY&&(t.ANTHROPIC_API_KEY=t.AGENT_API_KEY),t.ANTHROPIC_BASE_URL||(t.ANTHROPIC_BASE_URL=t.ANTHROPIC_API_URL||t.AGENT_BASE_URL||void 0),t}function j(e={}){let t={...process.env};for(let r of cr)delete t[r];return ur({...t,...e})}function ee(){return j()}var lr=["Agent","Task","TodoRead","TodoWrite"];async function*pr(){}function mr(e){return Array.from(new Set(e.map(t=>t.trim()).filter(Boolean)))}function gr(e){return mr((e??[]).map(t=>t.value))}function fr(e,t,r,n){let o;return new Promise((s,a)=>{o=setTimeout(()=>{r(),a(new Error(n))},t),o.unref?.(),e.then(i=>{o&&clearTimeout(o),s(i)},i=>{o&&clearTimeout(o),a(i)})})}async function Be(e={}){let t=e.cwd??await(0,te.mkdtemp)((0,qe.join)((0,je.tmpdir)(),"truesayer-claude-model-probe-")),r=!e.cwd,n=new AbortController,o=(0,le.query)({prompt:pr(),options:{cwd:t,env:ee(),abortController:n,maxTurns:1}});try{let s=await fr(o.initializationResult(),e.timeoutMs??3e4,()=>n.abort(),"Claude Code model discovery timed out");return gr(s.models)}finally{o.close(),r&&await(0,te.rm)(t,{recursive:!0,force:!0})}}function hr(e,t,r){let n=[e?.trim(),t?He:"",t?Le(r):""].filter(Boolean).join(`
12
+ `)){let a=Ir(s);if(a){o(),r=a,n=[s];continue}r&&n.push(s)}return o(),t}function Ve(e){let t=Number(e);return Number.isFinite(t)?t:0}function Ar(e){let t=e.trim();if(!t.includes(" => "))return t;let r=/^(.*)\{.* => (.*)\}(.*)$/.exec(t);return r?`${r[1]}${r[2]}${r[3]}`:t.slice(t.lastIndexOf(" => ")+4).trim()}function xr(e){let t=new Map;for(let r of e.split(`
13
+ `).filter(Boolean)){let[n,o,...s]=r.split(" "),a=Ar(s.join(" "));a&&t.set(a,{additions:Ve(n),deletions:Ve(o)})}return t}function Cr(e){let[t,...r]=e.split(" "),n=t.charAt(0),o=n==="R"||n==="C"?r.at(-1)?.trim():r.join(" ").trim();return o?{path:o,status:n==="A"?"added":n==="D"?"deleted":n==="R"?"renamed":"modified"}:null}function Mr(e,t){let r=xr(t);return e.split(`
14
+ `).filter(Boolean).map(Cr).filter(n=>n!==null).map(n=>({...n,additions:r.get(n.path)?.additions??0,deletions:r.get(n.path)?.deletions??0}))}function Dr(e,t){return ue((0,F.readFileSync)(Ae(e,t)))}function Or(e,t){if(t.size===0)return ue(e);let r=Array.from(t.entries()).sort(([n],[o])=>n.localeCompare(o)).map(([n,o])=>`${n}\0${o}`).join(`
15
+ `);return ue(`${e}\0untracked-content\0${r}`)}function Ur(e){return Mr(e.fileListRaw,e.numstatRaw).map(t=>{let r=e.diffByFile.get(t.path)??"",n=e.untrackedContentHashes.get(t.path);return{path:t.path,status:t.status,additions:t.additions,deletions:t.deletions,patchHash:ue(n?`${r}\0untracked-content\0${n}`:r),untracked:e.untracked.has(t.path)}})}async function Y(e,t="main"){let r=await Ne(e),n=await wr(r),o=t.trim()||"main",s=Rr(n,o)?await I(["rev-parse","HEAD"],r):await br(o,r),[a,i,c,m,v]=await Promise.all([Er(s,r),Tr(s,r),I(["diff","--no-textconv","--no-ext-diff",s],r),pe(r),kr(r)]),l=await Promise.all(m.map(b=>Nr(s,r,b))),f=new Map(m.map(b=>[b,Dr(r,b)])),y=[c,...l].filter(Boolean).join(`
16
+ `),d=y&&!y.endsWith(`
17
+ `)?`${y}
18
+ `:y,k=Pr(d);return{repoRoot:r,baseSha:s,baseRef:o,currentRef:n,diff:d,diffHash:Or(d,f),hasStagedChanges:v,files:Ur({fileListRaw:a,numstatRaw:i,diffByFile:k,untracked:new Set(m),untrackedContentHashes:f})}}function Lr(e,t,r){let n=e.files.find(o=>o.path===t);if(!n)throw new Error("file is not in current git diff");if(r&&n.patchHash!==r)throw new Error("git diff changed; refresh before restoring");return n}async function tt(e){let t=await Y(e.worktreePath,e.baseRef??void 0);if(t.baseSha!==e.baseSha)throw new Error("git base changed; refresh before restoring");if(t.hasStagedChanges)throw new Error("staged changes are not supported");let r=e.filePath?[Lr(t,e.filePath,e.expectedPatchHash)]:t.files;if(!e.filePath&&e.expectedDiffHash&&t.diffHash!==e.expectedDiffHash)throw new Error("git diff changed; refresh before restoring");let n=r.filter(a=>!a.untracked).map(a=>a.path),o=r.filter(a=>a.untracked).map(a=>a.path),s=t.repoRoot;return await Ze(s,async()=>{n.length>0&&await I(["restore",`--source=${e.baseSha}`,"--worktree","--",...n],s),o.length>0&&await I(["clean","-f","--",...o],s)}),Y(s,e.baseRef??void 0)}var me=require("fs"),rt=require("os"),U=require("path");function Z(){return process.env.TRUESAYER_NODE_HOME?.trim()||(0,U.join)((0,rt.homedir)(),".truesayer-node")}function fe(e){return(0,U.join)(e?.trim()||Z(),"provider.json")}function X(e){return e.replace(/[^a-zA-Z0-9_-]/g,"_").slice(0,120)||"unknown"}function nt(e){return(0,me.mkdirSync)(e,{recursive:!0,mode:448}),(0,me.chmodSync)(e,448),e}function Fr(e){return{HOME:e,CLAUDE_CONFIG_DIR:(0,U.join)(e,".claude"),CODEX_HOME:(0,U.join)(e,".codex")}}function xe(e){let t=e.truesayerNodeHome?.trim()||Z(),r=X(e.agentId),n=(0,U.join)(t,"agents",r),o=(0,U.join)(t,"runtime-home"),s=(0,U.join)(n,"space"),a=(0,U.join)(s,"profile");for(let i of[o,(0,U.join)(o,".claude"),(0,U.join)(o,".codex"),s,a])nt(i);return{agentRoot:n,providerHome:o,spaceRoot:s,profileDir:a,providerEnv:Fr(o)}}function ot(e){let t=e.truesayerNodeHome?.trim()||Z(),r=X(e.workspaceId),n=X(e.agentSessionId),o=X(e.agentRunId),s=X(e.repoAlias),a=xe({truesayerNodeHome:t,workspaceId:e.workspaceId,agentId:e.agentId}),{agentRoot:i,providerHome:c,spaceRoot:m,profileDir:v}=a,l=(0,U.join)(t,"workspace",r),f=(0,U.join)(m,"context",n),y=(0,U.join)(m,"agent-run",o),d=(0,U.join)(l,"worktree",s,o);for(let k of[l,f,y,d])nt(k);return{agentRoot:i,workspaceRoot:l,providerHome:c,spaceRoot:m,profileDir:v,contextDir:f,agentRunDir:y,worktreeDir:d,fileToolRoot:d,providerEnv:a.providerEnv}}var C=require("fs"),G=require("path");function Hr(e){return e.replace(/[^a-zA-Z0-9_-]/g,"_").slice(0,120)||"unknown"}function Ce(e){(0,C.mkdirSync)(e,{recursive:!0,mode:448}),(0,C.chmodSync)(e,448)}function $r(e){if(!(0,C.existsSync)(e))return{};try{let t=JSON.parse((0,C.readFileSync)(e,"utf8"));return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}catch{return{}}}function st(e){return typeof e=="string"&&e.trim()?e.trim():""}function qr(e){return typeof e=="number"&&Number.isFinite(e)?Math.trunc(e):0}var Q=class{constructor(t){this.root=(0,G.join)(t?.trim()||Z(),"provider-sessions"),Ce(this.root)}sessionDir(t){return(0,G.join)(this.root,Hr(t))}eventsPath(t){return(0,G.join)(this.sessionDir(t),"events.jsonl")}statePath(t){return(0,G.join)(this.sessionDir(t),"state.json")}readState(t){let r=$r(this.statePath(t));return{providerSessionId:t,agentRunId:st(r.agentRunId),providerName:st(r.providerName),ackLine:Math.max(0,qr(r.ackLine))}}writeState(t){let r=this.statePath(t.providerSessionId);Ce((0,G.dirname)(r)),(0,C.writeFileSync)(r,`${JSON.stringify(t,null,2)}
19
+ `,{mode:384}),(0,C.chmodSync)(r,384)}append(t){let r=this.readState(t.providerSessionId),n=this.eventsPath(t.providerSessionId);Ce((0,G.dirname)(n));let o=this.readEvents(t.providerSessionId).length+1;return(0,C.appendFileSync)(n,`${JSON.stringify(t.raw)}
20
+ `,{mode:384}),(0,C.chmodSync)(n,384),this.writeState({providerSessionId:t.providerSessionId,agentRunId:t.agentRunId||r.agentRunId,providerName:t.providerName||r.providerName,ackLine:r.ackLine}),{line:o,raw:t.raw}}markAck(t,r){if(!t||!Number.isFinite(r)||r<=0)return;let n=this.readState(t);this.writeState({...n,ackLine:Math.max(n.ackLine,Math.trunc(r))})}readEvents(t){let r=this.eventsPath(t);return(0,C.existsSync)(r)?(0,C.readFileSync)(r,"utf8").split(`
21
+ `).filter(n=>n.trim().length>0).map((n,o)=>{try{return{line:o+1,raw:JSON.parse(n)}}catch{return{line:o+1,raw:{type:"node.raw_parse_failed"}}}}):[]}unackedBatches(t=100){return(0,C.existsSync)(this.root)?(0,C.readdirSync)(this.root,{withFileTypes:!0}).filter(r=>r.isDirectory()).flatMap(r=>{let n=this.readState(r.name);if(!n.agentRunId||!n.providerSessionId)return[];let o=this.readEvents(n.providerSessionId).filter(s=>s.line>n.ackLine).slice(0,t);return o.length>0?[{...n,events:o}]:[]}):[]}};var ye=require("fs/promises"),ct=require("os"),ut=require("path"),Oe=require("@anthropic-ai/claude-agent-sdk");var it=V(require("os")),ee=require("fs"),D=require("@anthropic-ai/claude-agent-sdk"),u=require("zod/v4"),jr=16*1024,Wr=12e3;function Gr(e){return{content:[{type:"text",text:JSON.stringify(e??{})}]}}var Me=u.z.object({id:u.z.string().describe("Stable slug for this task item, such as implement-todo-app."),label:u.z.string().trim().min(1).describe('Descriptive task title, such as "\u5B9E\u73B0\u5168\u6808 Todo app"; do not use only "1", "step 1", or "phase 1".'),ownerAgentId:u.z.string().describe("Target Truesayer teammate id from list_channel_agents or resolve_channel_agent. Do not put responsibilities, roles, names, or mention text here."),status:u.z.enum(["todo","active","done","blocked"]).optional(),estMinutes:u.z.number().optional(),dependsOn:u.z.array(u.z.string()).optional()}).passthrough(),Br=u.z.object({creationCheckId:u.z.string().uuid(),name:u.z.string().optional(),description:u.z.string().optional(),providerName:u.z.string().optional(),providerId:u.z.string().optional(),modelId:u.z.string().optional(),selectedModel:u.z.string().optional(),reasoningEffort:u.z.enum(["default","none","minimal","low","medium","high","xhigh","max"]).optional(),thinkingMode:u.z.enum(["default","disabled","adaptive"]).optional(),serviceTier:u.z.enum(["default","fast","flex"]).optional(),responsibility:u.z.string().optional()}).passthrough();function Jr(e){if(!e.startsWith("/tmp/")&&!e.startsWith(`${it.default.tmpdir()}/`))return!1;try{let t=(0,ee.statSync)(e);return t.isFile()&&t.size>0}catch{return!1}}function Kr(e){try{let t=(0,ee.statSync)(e),r=Math.max(0,t.size-jr);return(0,ee.readFileSync)(e).subarray(r).toString("utf8").replace(/\0/g,"").trim().slice(-Wr)}catch{return""}}function zr(e){if(typeof e.logTail=="string"&&e.logTail.trim())return e;let t=typeof e.logPath=="string"?e.logPath.trim():"";if(!t||!Jr(t))return e;let r=Kr(t);return r?{...e,logTail:r}:e}function De(e,t){let r=async(o,s)=>{let a=o==="record_background_service"?zr(s):s;return Gr(await t({agentRunId:e,toolName:o,args:a}))};return[(0,D.tool)("reply_to_channel",'Publish the final visible message or meaningful stage update in the current Truesayer channel. Use intent="update" only for a meaningful stage synchronization that a human should see; use intent="final" for the run-ending report after all required work, validation, delegation, background-service recording, and blocker checks are complete. Do not use it for acknowledgements, "I will check" notes, or low-value chatter. After calling it, do not call more tools; after a final reply succeeds, finish the turn.',{body:u.z.string(),intent:u.z.enum(["update","final"]).optional(),attachmentIds:u.z.array(u.z.string()).optional(),messageId:u.z.string().optional()},async o=>r("reply_to_channel",o),{alwaysLoad:!0}),(0,D.tool)("create_agent","Create an active Truesayer teammate profile and bind it to a Node runtime provider/model. This is a protected action that blocks for human approval. It does not add the new teammate to the current channel; channel membership must be granted by the frontend, an admin API, setup seed, or an explicit Server policy.",{creationCheckId:u.z.string().uuid(),name:u.z.string(),description:u.z.string(),providerId:u.z.string().optional(),providerName:u.z.string().optional(),modelId:u.z.string().optional(),selectedModel:u.z.string().optional(),reasoningEffort:u.z.enum(["default","none","minimal","low","medium","high","xhigh","max"]).optional(),thinkingMode:u.z.enum(["default","disabled","adaptive"]).optional(),serviceTier:u.z.enum(["default","fast","flex"]).optional(),systemPrompt:u.z.string().optional(),soul:u.z.string().optional(),tone:u.z.number().optional()},async o=>r("create_agent",o),{alwaysLoad:!0}),(0,D.tool)("create_agents","Create multiple active Truesayer teammate profiles in one protected action. This blocks for human approval before the Server creates the profiles. Each agents[] item must include a stable creationCheckId UUIDv7; reuse the same creationCheckId when retrying the same logical agent creation request. It does not add the new teammates to the current channel; channel membership must be granted by the frontend, an admin API, setup seed, or an explicit Server policy.",{summary:u.z.string().describe("Human-readable summary shown on the approval activity card."),agents:u.z.array(Br.extend({name:u.z.string(),description:u.z.string()})).min(1)},async o=>r("create_agents",o),{alwaysLoad:!0}),(0,D.tool)("request_add_agents_to_channel","Request human approval to add existing Truesayer agent teammates to the current channel. Use this after create_agents returns agentIds and list_channel_agents shows those agents are not_bound. The Server blocks until a human approves, then grants channel membership and active channel agent instances for the listed agentIds.",{summary:u.z.string().describe("Human-readable summary shown on the approval activity card."),agentIds:u.z.array(u.z.string()).min(1).describe("Existing Truesayer agent ids to add to the current channel. Use ids returned by create_agents or list_channel_agents; do not use names.")},async o=>r("request_add_agents_to_channel",o),{alwaysLoad:!0}),(0,D.tool)("request_change_channel_workdir","Request human approval to change the current channel code directory. Use this when the current channel should run agents against a different local Git repository path. The Server blocks until a human approves, asks the connected Node to prepare that path, and only then updates the channel.",{summary:u.z.string().describe("Human-readable summary shown on the approval activity card."),path:u.z.string().trim().min(1).describe("Absolute or Node-local path to the Git repository or directory to initialize as the current channel code space."),baseRef:u.z.string().trim().optional().describe("Git base ref for agent worktrees; defaults to main.")},async o=>r("request_change_channel_workdir",o),{alwaysLoad:!0}),(0,D.tool)("message_agent",'Send a work request or update to another Truesayer agent. This is only for immediately runnable work. If the message continues or refers to a structured task-card item, include planItemId so the Server can reuse the existing handoff instead of creating duplicate work. Do not use it to pre-send future or dependency-blocked work such as "audit after implementation"; represent that as blocked items in delegate_plan instead. Use this to delegate execution instead of visibly @mentioning that agent. After a successful delegation, end the current run. Truesayer may wake the current agent with downstream results and evidence; decide the next step yourself.',{toAgentId:u.z.string(),body:u.z.string(),refTaskId:u.z.string().optional(),planItemId:u.z.string().optional()},async o=>r("message_agent",o),{alwaysLoad:!0}),(0,D.tool)("resolve_channel_agent","Resolve an agent name, mention, or id to a unique teammate in the current Truesayer channel. This is read-only and returns blockers for not_found, not_bound, or ambiguous matches.",{query:u.z.string()},async o=>r("resolve_channel_agent",o),{alwaysLoad:!0}),(0,D.tool)("list_channel_agents","List all Truesayer agents in this workspace and mark whether each one can access the current Truesayer channel. Use this before delegate_plan or message_agent when agent ids or channel access may have changed.",{},async o=>r("list_channel_agents",o),{alwaysLoad:!0}),(0,D.tool)("delegate_plan","Create a channel task card and delegate active items to specific Truesayer agents. Active items are immediately sent to their owner agents as executable work when this tool succeeds. Do not call message_agent to notify the same owner about the same active item. Each item label must describe the actual assigned work in enough detail for the owner to execute it, not only an ordinal. Use blocked items for future or dependency-blocked work, and only make an item active when it should run now. Put all instructions for that phase in the item label/status/dependencies before calling this tool. Do not create plan items owned by yourself or the current agent; coordinator-owned follow-up work such as final review, deciding whether to continue, summary, or reply must stay outside the task card. Do not render coordinator-owned follow-up work as task table rows in visible replies. Use a short sentence instead. Call list_channel_agents first when you need current agent ids or channel access. When the user asks to assign, delegate, create task cards, or start a phase, use this before Bash/Edit/Read unless the user asked you to implement the work yourself. After successful delegation, end the current run. Truesayer may wake the current agent with downstream results and evidence; decide the next step yourself, such as verify, delegate more work, update the plan, report a blocker, or reply to the channel.",{items:u.z.array(Me),replace:u.z.boolean().optional()},async o=>r("delegate_plan",o),{alwaysLoad:!0}),(0,D.tool)("emit_plan","Create or update the visible channel task card for this agent run. Each item label must describe the actual work, not only an ordinal. Do not create plan items owned by yourself or the current agent; coordinator-owned follow-up work such as final review, deciding whether to continue, summary, or reply must stay outside the task card. Do not render coordinator-owned follow-up work as task table rows in visible replies. Use a short sentence instead. Existing unfinished downstream items are preserved unless replace is true. Use delegate_plan instead when active items should be assigned to other agents. Call list_channel_agents first when ownerAgentId values need current agent ids or channel access.",{items:u.z.array(Me),replace:u.z.boolean().optional()},async o=>r("emit_plan",o),{alwaysLoad:!0}),(0,D.tool)("advance_plan",'Create or advance the Server-owned execution plan. Use this after planning to let Truesayer decide the next runnable task. Items may include executionKind="self" or "agent" and scheduleKind="blocking" or "parallel". For blocking agent work, the Server queues the teammate run and marks the current agent session as waiting until the child task completes. If this returns self_task, execute only that returned task and later call update_task. If this returns waiting or dispatched, do not also message the same teammate.',{items:u.z.array(Me).optional()},async o=>r("advance_plan",o),{alwaysLoad:!0}),(0,D.tool)("update_plan_item","Update one item on the current canonical task card. Do not provide or guess a root task id; the Truesayer Server chooses the writable plan from this agent run context.",{itemId:u.z.string(),status:u.z.enum(["todo","active","done","blocked"])},async o=>r("update_plan_item",o),{alwaysLoad:!0}),(0,D.tool)("update_task","Mark the Server-assigned plan task for this agent run as done, blocked, or cancelled. Use this before a final reply when advance_plan or a delegated plan task assigned concrete work to this run. The Server rejects updates for tasks not assigned to this agent run.",{taskId:u.z.string(),status:u.z.enum(["done","blocked","cancelled"]),summary:u.z.string().optional(),evidence:u.z.record(u.z.string(),u.z.unknown()).optional()},async o=>r("update_task",o),{alwaysLoad:!0}),(0,D.tool)("record_background_service","Record a visible background service started for human inspection. Use this after starting a keep-alive dev/server process in the background and after a bounded health check succeeds. Include PID, port, URL, and log path so Activity can show a visible background service row. This records observability only; it does not start, stop, or clean up the process.",{label:u.z.string().optional(),pid:u.z.number().optional(),port:u.z.number().optional(),url:u.z.string().optional(),healthUrl:u.z.string().optional(),logPath:u.z.string().optional(),cwd:u.z.string().optional()},async o=>r("record_background_service",o),{alwaysLoad:!0})]}function at(e,t){return(0,D.createSdkMcpServer)({name:"truesayer-platform",version:"0.1.0",tools:De(e,t),alwaysLoad:!0})}var ge=["Truesayer platform tools are available as local tools. They send JSON-RPC requests from the Node process to the Truesayer Server over the existing WebSocket.",'reply_to_channel publishes a human-facing channel message. It has intent="update" for a meaningful stage synchronization and intent="final" for the run-ending report.','Use reply_to_channel intent="update" sparingly, only when the human should see a concrete stage result, blocker, approval context, or coordination state. Do not use it for acknowledgements, "I will check" notes, or low-value chatter.','Before reply_to_channel intent="final", finish all required tool work: verification, git/status checks, service health checks, record_background_service when needed, delegation, and blocker analysis. After a final reply succeeds, do not call more tools, do not continue verification, and finish the turn.',"Visible mentions in channel messages must use the canonical token <@teamMemberId>. Plain @name text is display-only and does not route work. Use list_channel_agents or resolve_channel_agent to get exact teammate ids before mentioning another teammate.","Use create_agents to create long-lived teammates that do not yet exist. Put what the teammate does in description, not role. Every agents[] item must include a stable creationCheckId UUIDv7; reuse it when retrying the same logical agent creation. create_agents blocks for human approval before the Server creates the profiles, and returns agentId plus mentionName values to use in message_agent and task card ownerAgentId.","Use create_agent only when creating exactly one teammate. It is also protected and blocks for human approval.","create_agent and create_agents do not add new teammates to the current channel. After creating teammates for current-channel collaboration, call request_add_agents_to_channel with the returned agentIds. It blocks for human approval before the Server grants channel access.","Use request_change_channel_workdir when you need to change the current channel code directory. It is protected and blocks for human approval before the Server stores the new channel path.","Use list_channel_agents to get the realtime list of all Truesayer agents in this workspace and whether each can access the current channel. Use it before delegate_plan or message_agent when IDs, names, or channel membership may have changed.","Use resolve_channel_agent to turn a teammate name or @mention in the current channel into the agentId required by message_agent and task card ownerAgentId. If it returns not_bound, ambiguous, or not_found, report that blocker instead of guessing an id.","message_agent is only for immediately runnable work. If continuing a structured task-card item, include planItemId. The recipient may start as soon as the tool succeeds, so do not use message_agent to pre-send future, conditional, or dependency-blocked work.","Use advance_plan as the preferred execution entrypoint for structured plans. It lets the Server choose runnable self tasks, blocking teammate handoffs, or parallel teammate handoffs from the plan state.","Use delegate_plan or emit_plan for legacy visible channel task cards, and update_plan_item to update legacy item status. Task item labels must be descriptive enough for the assigned agent to execute from the item alone.","Use update_task before final reply when the Server assigned a concrete plan task to this run. update_task changes machine state; reply_to_channel is the human-facing stage or final message.","delegate_plan active items with valid ownerAgentId values are already sent to their owner agents as executable work when the tool succeeds. Do not follow delegate_plan with message_agent for the same active item; put the full task instructions into the active plan item before delegating.","Future or dependency-blocked work must be represented as blocked task card items with delegate_plan or emit_plan. Do not send those items through message_agent until they are actually runnable.","Do not create plan items owned by yourself or the current agent. Coordinator-owned follow-up work such as final review, deciding whether to continue, summary, or reply is not a task-card item. After delegated work finishes, Truesayer may wake the current agent with downstream results and evidence, and you decide the next step yourself: verify, delegate more work, update the plan, report a blocker, or reply to the channel.","If a prompt asks you to create a collaboration team, call create_agents once with the whole team so the human sees one approval card. After it succeeds, call request_add_agents_to_channel once with the created agentIds when those teammates need to work in the current channel. If either tool is rejected or blocked, report that blocker instead of retrying.","If a prompt asks you to assign, delegate, create task cards, update a plan, or start a phased handoff with existing teammates, your first tool call must be delegate_plan or message_agent in the legacy flow, or advance_plan in the Server-owned plan execution flow, before any file, git, shell, package-manager, or code-edit tool.","A coordinating agent must not do another agent's assigned implementation, audit, or optimization work itself. Create the task card or agent message, then end the current run. Truesayer may wake the current agent with a continuation when downstream work reports back.","Never send message_agent to yourself as an availability test. If no suitable teammate exists, call create_agent first; if provider capability is missing, reply with the blocker.","Only use message_agent after delegate_plan for genuinely new follow-up communication, not as a notification that the delegated active item exists.","Do not use provider-native Agent, Task, TodoRead, or TodoWrite for product coordination. Truesayer task cards, plan updates, and teammate handoffs must go through Truesayer platform tools so the Server can audit every agent run.","If the provider UI prefixes Truesayer tools as MCP tools, select the matching tool whose name ends with create_agents, create_agent, request_add_agents_to_channel, request_change_channel_workdir, resolve_channel_agent, reply_to_channel, message_agent, delegate_plan, emit_plan, advance_plan, update_task, update_plan_item, or record_background_service.","Long-running or continuously-running service/watch commands, such as dev servers, file watchers, npm start, npm run start, npm run dev, vite, next dev, nodemon, tsx --watch, tail -f, database servers, or queue workers, must not be run as foreground blocking commands. Start them in the background, redirect logs to a file, record the PID, and run a bounded health check with timeout. Stop or clean up the process when validation is complete unless the task explicitly asks to keep the service available for human inspection; in that case keep it running and call record_background_service with PID, port, URL, and log path. Finite commands such as install, build, test, lint, migration, and one-shot scripts should run in the foreground and must return an exit code.","Do not try to access the Truesayer Server database, provider secrets, or Server-only environment variables from Node."].join(`
22
+ `);function he(e){let t=Object.entries(e??{});return t.length===0?"":["Available Node runtime providers for create_agent/create_agents runtime selection:",...t.map(([r,n])=>`- ${r} (${n.kind}): ${n.models.join(", ")}`)].join(`
23
+ `)}var Vr=["PATH","HOME","USER","LOGNAME","SHELL","TMPDIR","TEMP","TMP","LOCALAPPDATA","APPDATA","XDG_CONFIG_HOME","XDG_CACHE_HOME","XDG_DATA_HOME","CLAUDE_CONFIG_DIR","CODEX_HOME","SSL_CERT_FILE","SSL_CERT_DIR","NODE_EXTRA_CA_CERTS","LANG","LC_ALL","TERM","SystemRoot","ComSpec","PATHEXT","WINDIR","TRUESAYER_CODEX_BIN","TRUESAYER_CODEX_REQUEST_TIMEOUT_MS","CODEX_CAPTURE_PATH","FAKE_CODEX_CAPTURE_PATH"];function Yr(e=process.env){let t={};for(let r of Vr){let n=e[r];typeof n=="string"&&n.length>0&&(t[r]=n)}return t}function te(e={}){return{...Yr(),...e}}function ve(){return te()}var Xr=["Agent","Task","TodoRead","TodoWrite"];async function*Zr(){}function Qr(e){return Array.from(new Set(e.map(t=>t.trim()).filter(Boolean)))}function en(e){return Qr((e??[]).map(t=>t.value))}function tn(e,t,r,n){let o;return new Promise((s,a)=>{o=setTimeout(()=>{r(),a(new Error(n))},t),o.unref?.(),e.then(i=>{o&&clearTimeout(o),s(i)},i=>{o&&clearTimeout(o),a(i)})})}async function lt(e={}){let t=e.cwd??await(0,ye.mkdtemp)((0,ut.join)((0,ct.tmpdir)(),"truesayer-claude-model-probe-")),r=!e.cwd,n=new AbortController,o=(0,Oe.query)({prompt:Zr(),options:{cwd:t,env:ve(),abortController:n,maxTurns:1}});try{let s=await tn(o.initializationResult(),e.timeoutMs??3e4,()=>n.abort(),"Claude Code model discovery timed out");return en(s.models)}finally{o.close(),r&&await(0,ye.rm)(t,{recursive:!0,force:!0})}}function rn(e,t,r){let n=[e?.trim(),t?ge:"",t?he(r):""].filter(Boolean).join(`
21
24
 
22
- `);return n?{type:"preset",preset:"claude_code",append:n}:void 0}function P(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}function vr(e){return typeof e=="string"&&e.trim()?e.trim():""}function yr(e){return typeof e=="string"?e.trim():Array.isArray(e)?e.filter(r=>typeof r=="string"&&r.trim().length>0).map(r=>r.trim()).join(" "):""}function We(...e){for(let t of e){let r=yr(t);if(r)return r}return""}function F(...e){for(let t of e){let r=vr(t);if(r)return r}return""}function Ke(e,t=""){let r=e.toLowerCase(),n=t.toLowerCase();return["read","grep","glob","ls"].includes(r)?"read":["write","edit","multiedit"].includes(r)?"write":r==="update"?"update":r==="bash"||r==="exec"||r==="exec_command"||r==="codex_command"?/(^|[;&|]\s*)apply_patch\b/.test(n)?"write":/^\s*(sed\s+-n\b|cat\b|head\b|tail\b|nl\b|find\b|ls\b|rg\b|grep\b|pwd\b)/.test(n)?"read":"exec":r.startsWith("mcp__truesayer__")?"platform_tool":"exec"}function Ge(e){return e==="read"?"read":e==="write"?"write":e==="update"?"update":e==="platform_tool"?"platform_tool":"exec"}function kr(e){return P(e)}function wr(e,t){let r=F(e.name);if(!r)return null;let n=kr(e.input),o=We(n.command,n.cmd,n.commandLine),s=F(n.file_path,n.path,n.filePath),a=Ke(r,o),i=F(e.id);return i&&t?.set(i,{rawToolName:r,command:o,path:s,operation:a}),{type:"agent_run.tool.started",payload:{provider:"claude",toolName:Ge(a),toolCallId:i,...o?{command:o}:{},...s?{path:s}:{},operation:a}}}function br(e,t){let n=(Array.isArray(P(e.message).content)?P(e.message).content:[]).map(P).find(m=>m.type==="tool_result");if(!n)return null;let o=P(e.toolUseResult),s=P(o.file),a=F(n.tool_use_id,n.toolUseId),i=t?.get(a)??{},c=F(s.filePath,s.file_path,o.filePath,o.file_path,i.path),p=We(o.command,o.cmd,i.command),k=F(i.operation)||(c?"read":Ke(p?"Bash":"tool",p)),b=c&&typeof s.numLines=="number"?`${s.numLines} lines`:F(o.stdout,o.output,n.content);return{type:"agent_run.tool.completed",payload:{provider:"claude",toolName:Ge(k),toolCallId:a,...p?{command:p}:{},...c?{path:c}:{},operation:k,...b?{output:b}:{}}}}function Er(e,t=new Map){let r=P(e),n=P(r.message),o=Array.isArray(n.content)?n.content:[],s=[];for(let i of o.map(P))if(i.type==="tool_use"){let c=wr(i,t);c&&s.push(c)}let a=br(r,t);return a&&s.push(a),s}function _r(e){if(e.type==="result"){let t=e.result;return typeof t=="string"?t:null}return null}function q(e){return typeof e=="number"&&Number.isFinite(e)?e:void 0}function $e(...e){for(let t of e){let r=q(t);if(r!==void 0)return Math.max(0,Math.trunc(r))}}function Rr(e){let t=P(e),r=P(t.usage),n=P(t.tokenUsage),o=P(t.token_usage),s=P(t.tokens),a=P(t.usageSummary);return{inputTokens:$e(r.input_tokens,r.inputTokens,r.prompt_tokens,r.promptTokens,n.input_tokens,n.inputTokens,n.prompt_tokens,n.promptTokens,o.input_tokens,o.inputTokens,o.prompt_tokens,o.promptTokens,s.input_tokens,s.inputTokens,s.prompt_tokens,s.promptTokens,a.input_tokens,a.inputTokens,t.input_tokens,t.inputTokens,t.total_input_tokens,t.prompt_tokens,t.promptTokens),outputTokens:$e(r.output_tokens,r.outputTokens,r.completion_tokens,r.completionTokens,n.output_tokens,n.outputTokens,n.completion_tokens,n.completionTokens,o.output_tokens,o.outputTokens,o.completion_tokens,o.completionTokens,s.output_tokens,s.outputTokens,s.completion_tokens,s.completionTokens,a.output_tokens,a.outputTokens,t.output_tokens,t.outputTokens,t.total_output_tokens,t.completion_tokens,t.completionTokens),costUsd:q(t.total_cost_usd)??q(t.cost_usd)??q(r.total_cost_usd)??q(r.cost_usd)}}function Tr(e){return e.type!=="result"?{}:Rr(e)}async function Nr(e,t){let r="",n={},o=2,s=[],a=new Map;try{for await(let i of t){for(let c of Er(i,a))s.push({eventId:`${e}:claude:${o}`,eventSeq:o,type:c.type,payload:c.payload}),o+=1;r=_r(i)??r,n={...n,...Tr(i)}}return{output:r.trim()||"Agent run completed",...n,events:s}}catch(i){let c=i instanceof Error?i:new Error(String(i));throw c.events=s,c.emittedEventIds=new Set,c}finally{t.close()}}async function Je(e){if(e.provider.kind!=="claude-code"&&e.provider.kind!=="claude-compatible")throw new Error(`unsupported node provider kind: ${e.provider.kind}`);let t=new AbortController,r=e.invokeTool?{truesayer:Fe(e.agentRunId,e.invokeTool,{mode:e.toolMode})}:void 0,n=(0,le.query)({prompt:e.prompt,options:{cwd:e.cwd,env:e.env,model:e.selectedModel,systemPrompt:hr(e.systemPrompt,!!e.invokeTool,e.availableProviders),mcpServers:r,maxTurns:e.maxTurns??80,permissionMode:"bypassPermissions",allowDangerouslySkipPermissions:!0,disallowedTools:[...lr],abortController:t}});return Nr(e.agentRunId,n)}var H=require("fs"),Qe=require("child_process"),et=require("readline"),tt=require("module"),W=require("path");function ze(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}function Ye(e){return typeof e=="string"?e.trim():""}function Ir(e){let t=ze(e),r=Ye(t.type);return r==="add"||r==="delete"?{type:r}:r==="update"?{type:r,move_path:typeof t.move_path=="string"?t.move_path:null}:null}function Pr(e){let t=ze(e),r=Ye(t.path),n=Ir(t.kind);return!r||!n?null:{path:r,kind:n,diff:typeof t.diff=="string"?t.diff:""}}function pe(e){return Array.isArray(e)?e.map(Pr).filter(t=>t!==null).map(t=>{let r=Ar(t.kind);return{path:r==="renamed"&&t.kind.type==="update"&&t.kind.move_path?t.kind.move_path:t.path,status:r,...t.diff?{diff:t.diff}:{}}}):[]}function Ar(e){return e.type==="add"?"added":e.type==="delete"?"deleted":e.move_path?"renamed":"modified"}var ge=6e4,xr=(0,tt.createRequire)(__filename);function Sr(){let e=xr.resolve("@openai/codex/package.json");return(0,W.join)((0,W.dirname)(e),"bin","codex.js")}function R(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}function _(e){return typeof e=="string"&&e.trim()?e.trim():""}function Ve(e){return typeof e=="string"?e:""}function E(...e){for(let t of e){let r=_(t);if(r)return r}return""}function me(...e){for(let t of e)if(typeof t=="number"&&Number.isFinite(t))return t}function Mr(e){return typeof e=="string"?e.trim():Array.isArray(e)?e.filter(r=>typeof r=="string"&&r.trim().length>0).map(r=>r.trim()).join(" "):""}function Cr(...e){for(let t of e){let r=Mr(t);if(r)return r}return""}function Or(e){return e.some(t=>["read","search","listFiles"].includes(E(t.type)))?"read":"exec"}function Xe(e){return e==="read"?"read":e==="write"?"write":e==="update"?"update":e==="platform_tool"?"platform_tool":"exec"}function Dr(e){return Array.isArray(e)?e.map(R).filter(t=>E(t.type)):[]}function Ur(e){return Array.from(new Set(e.map(t=>E(t.path)).filter(Boolean)))}function Fr(e){return e.some(t=>t.status!=="added")?"update":"write"}function Hr(e){let t=E(e.tool);if(e.type!=="mcpToolCall")return t;let r=E(e.server);return r&&t?`${r}.${t}`:t}function Lr(e){let t=e.method,r=e.params??{},n=R(r.item),o=_(n.type),s=t==="item/completed"?"agent_run.tool.completed":"agent_run.tool.started";if(t!=="item/started"&&t!=="item/completed")return null;if(o==="commandExecution"){let a=Cr(n.command),i=Dr(n.commandActions),c=Or(i),p=Ur(i),k=E(n.status),b=E(n.aggregatedOutput),m=me(n.exitCode),y=me(n.durationMs);return{type:s,payload:{provider:"codex",toolName:Xe(c),toolCallId:E(n.id),...a?{command:a}:{},...E(n.cwd)?{cwd:E(n.cwd)}:{},...p[0]?{path:p[0]}:{},...p.length>0?{paths:p}:{},operation:c,...k?{status:k}:{},...m===void 0?{}:{exitCode:m},...b?{output:b}:{},...y===void 0?{}:{durationMs:y},...i.length>0?{commandActions:i}:{}}}}if(o==="fileChange"){let a=pe(n.changes);if(a.length===0)return null;let i=a.map(k=>k.path),c=Fr(a),p=E(n.status);return{type:s,payload:{provider:"codex",toolName:Xe(c),toolCallId:E(n.id),command:"fileChange",path:i[0],paths:i,operation:c,...p?{status:p}:{},fileChanges:a,...a[0]?.diff?{diff:a[0].diff}:{}}}}if(o==="dynamicToolCall"||o==="mcpToolCall"){let a=Hr(n),i=me(n.durationMs);return{type:s,payload:{provider:"codex",toolName:"platform_tool",toolCallId:E(n.id),platformToolName:a,...n.arguments===void 0?{}:{arguments:n.arguments},operation:"platform_tool",...E(n.status)?{status:E(n.status)}:{},...typeof n.success=="boolean"?{success:n.success}:{},...n.contentItems===void 0||n.contentItems===null?{}:{contentItems:n.contentItems},...n.result===void 0||n.result===null?{}:{result:n.result},...n.error===void 0||n.error===null?{}:{error:n.error},...i===void 0?{}:{durationMs:i}}}}return null}function $r(e){if(e.method!=="item/fileChange/patchUpdated")return null;let t=e.params??{},r=pe(t.changes);if(r.length===0)return null;let n=r.map(o=>o.path);return{type:"agent_run.provider_event",payload:{provider:"codex",method:e.method,...E(t.itemId)?{itemId:E(t.itemId)}:{},paths:n,changes:r,...E(t.threadId)?{threadId:E(t.threadId)}:{},...E(t.turnId)?{turnId:E(t.turnId)}:{}}}}function jr(e){let t=e.params??{};if(e.method==="item/completed"){let r=R(t.item);if(r.type==="agentMessage"){let n=_(r.text);return n?{type:"agent_run.message.completed",payload:{provider:"codex",text:n,..._(r.phase)?{phase:_(r.phase)}:{}}}:null}}return e.method==="error"?{type:"agent_run.provider_event",payload:{provider:"codex",method:e.method,params:t}}:e.method==="turn/diff/updated"?{type:"agent_run.provider_event",payload:{provider:"codex",method:e.method,...E(t.threadId)?{threadId:E(t.threadId)}:{},...E(t.turnId)?{turnId:E(t.turnId)}:{},...Ve(t.diff)?{diff:Ve(t.diff)}:{}}}:null}function qr(e){return Lr(e)??$r(e)??jr(e)}function rt(e){if(e.method!=="error")return null;let t=e.params??{};if(t.willRetry===!0)return null;let r=R(t.error),n=R(r.codexErrorInfo),o=_(t.codexErrorInfo)||_(r.codexErrorInfo)||Object.keys(n)[0]||_(t.code)||_(t.errorCode)||_(r.code),s=_(t.message)||_(r.message)||_(t.error)||"Codex app-server provider error";return new Error(`Codex app-server error${o?` ${o}`:""}: ${s}`)}function Br(e){let t=e.TRUESAYER_CODEX_REQUEST_TIMEOUT_MS?.trim();if(!t)return ge;let r=Number(t);return Number.isFinite(r)&&r>0?Math.trunc(r):ge}function Wr(e){if(e.exitCode!==null||e.killed)return;let t=e.pid;if(t&&process.platform!=="win32")try{process.kill(-t,"SIGTERM");return}catch{}e.kill("SIGTERM")}function nt(e){let t=e.env.TRUESAYER_CODEX_BIN||Sr(),r=(0,Qe.spawn)(process.execPath,[t,"app-server","--listen","stdio://",...e.args??[]],{cwd:e.cwd,env:e.env,stdio:["pipe","pipe","pipe"],detached:e.detached===!0}),n=new Map,o=[],s=e.requestTimeoutMs??ge,a=1,i=!1;function c(){return o.join("").slice(-1e3).trim()}function p(m,y){return new Error(`Codex app-server request timed out after ${s}ms (method ${y.method}, requestId ${m}, stderr: ${c()||"no stderr"})`)}function k(m,y){for(let[d,g]of n)n.delete(d),g.timeout&&clearTimeout(g.timeout),e.onRequestEvent?.("failed",{method:g.method,requestId:d,elapsedMs:Date.now()-g.startedAt,reason:y,error:m.message}),g.reject(m)}let b=(0,et.createInterface)({input:r.stdout});return b.on("line",m=>{let y=m.trim();if(!y)return;let d;try{d=JSON.parse(y)}catch{return}let g=R(d),h=g.id;if((typeof h=="number"||typeof h=="string")&&n.has(h)){let l=n.get(h);n.delete(h),l?.timeout&&clearTimeout(l.timeout);let w=g;w.error?(e.onRequestEvent?.("failed",{method:l?.method??"unknown",requestId:h,elapsedMs:l?Date.now()-l.startedAt:void 0,reason:"error",error:w.error.message??"Codex app-server request failed"}),l?.reject(new Error(w.error.message??"Codex app-server request failed"))):(e.onRequestEvent?.("completed",{method:l?.method??"unknown",requestId:h,elapsedMs:l?Date.now()-l.startedAt:void 0}),l?.resolve(w.result));return}let f=_(g.method);if(f){let l={method:f,params:R(g.params)};e.onNotification?.(l);let w=rt(l);w&&k(w,"provider_error")}}),r.stderr.on("data",m=>{o.push(m.toString("utf8")),o.length>25&&o.shift()}),r.on("exit",(m,y)=>{if(i)return;let d=`Codex app-server exited (code ${m??"null"}, signal ${y??"null"}): ${c()||"no stderr"}`,g=new Error(d);k(g,"app_server_exit"),e.onExit?.(g)}),{stderrTail:c,request(m,y){let d=a;a+=1,e.onRequestEvent?.("started",{method:m,requestId:d});let g=new Promise((h,f)=>{let l={method:m,startedAt:Date.now(),resolve:h,reject:f},w=setTimeout(()=>{if(!n.delete(d))return;let C=p(d,l);e.onRequestEvent?.("failed",{method:m,requestId:d,elapsedMs:Date.now()-l.startedAt,reason:"timeout"}),f(C)},s);typeof w.unref=="function"&&w.unref(),l.timeout=w,n.set(d,l)});return r.stdin.write(`${JSON.stringify({id:d,method:m,params:y})}
23
- `),g},notify(m,y){r.stdin.write(`${JSON.stringify({method:m,...y===void 0?{}:{params:y}})}
24
- `)},close(){i=!0,b.close(),Wr(r)}}}function Kr(e){let t=R(e).data;if(!Array.isArray(t))return[];let r=t.flatMap(n=>{let o=R(n),s=_(o.model)||_(o.id);return s?[s]:[]});return Array.from(new Set(r.map(n=>n.trim()).filter(Boolean)))}async function ot(e={}){let t=nt({env:e.env??j(),detached:process.platform!=="win32",requestTimeoutMs:e.timeoutMs??3e4});try{return await t.request("initialize",{clientInfo:{name:"truesayer",title:"Truesayer",version:"0.1.0"},capabilities:{experimentalApi:!0,optOutNotificationMethods:[]}}),t.notify("initialized"),Kr(await t.request("model/list",{includeHidden:!1,limit:100}))}finally{t.close()}}function st(e){return e?(0,W.join)(e,"codex-app-server-session.json"):void 0}function Gr(e){let t=st(e);if(!(!t||!(0,H.existsSync)(t)))try{let r=JSON.parse((0,H.readFileSync)(t,"utf8"));return _(R(r).threadId)||void 0}catch{return}}function Jr(e,t){let r=st(e);r&&(0,H.writeFileSync)(r,`${JSON.stringify({threadId:t})}
25
- `,{mode:384})}var zr=["Long-running or continuously-running service/watch commands, such as dev servers, file watchers, npm start, npm run start, npm run dev, vite, next dev, nodemon, tsx --watch, tail -f, database servers, or queue workers, must not be run as foreground blocking commands. Start them in the background, redirect logs to a file, record the PID, and run a bounded health check with timeout. Stop or clean up the process when validation is complete unless the task explicitly asks to keep the service available for human inspection; in that case keep it running in the background and report PID, port, URL, and log path. Finite commands such as install, build, test, lint, migration, and one-shot scripts should run in the foreground and must return an exit code.","Do not try to access the Truesayer Server database, provider secrets, or Server-only environment variables from Node.","All file creation and manual file edits MUST use apply_patch or Codex native fileChange. This overrides any base instruction that allows shell redirection, here-docs, cat, tee, scripts, or generated-file exceptions. Do not create or edit files with cat, tee, heredoc, sed -i, perl -pi, python/node scripts, or shell redirection, even for generated files like package.json or temporary scratch files under /tmp."].join(`
26
- `);function Yr(e){return["Truesayer runtime instructions:",[e.systemPrompt?.trim(),zr].filter(Boolean).join(`
25
+ `);return n?{type:"preset",preset:"claude_code",append:n}:void 0}function L(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}function nn(e){return typeof e=="string"&&e.trim()?e.trim():""}function on(e){return typeof e=="string"?e.trim():Array.isArray(e)?e.filter(r=>typeof r=="string"&&r.trim().length>0).map(r=>r.trim()).join(" "):""}function pt(...e){for(let t of e){let r=on(t);if(r)return r}return""}function J(...e){for(let t of e){let r=nn(t);if(r)return r}return""}function mt(e,t=""){let r=e.toLowerCase(),n=t.toLowerCase();return["read","grep","glob","ls"].includes(r)?"read":["write","edit","multiedit"].includes(r)?"write":r==="update"?"update":r==="bash"||r==="exec"||r==="exec_command"||r==="codex_command"?/(^|[;&|]\s*)apply_patch\b/.test(n)?"write":/^\s*(sed\s+-n\b|cat\b|head\b|tail\b|nl\b|find\b|ls\b|rg\b|grep\b|pwd\b)/.test(n)?"read":"exec":r.startsWith("mcp__truesayer__")?"platform_tool":"exec"}function ft(e){return e==="read"?"read":e==="write"?"write":e==="update"?"update":e==="platform_tool"?"platform_tool":"exec"}function sn(e){return L(e)}function an(e,t){let r=J(e.name);if(!r)return null;let n=sn(e.input),o=pt(n.command,n.cmd,n.commandLine),s=J(n.file_path,n.path,n.filePath),a=mt(r,o),i=J(e.id);return i&&t?.set(i,{rawToolName:r,command:o,path:s,operation:a}),{type:"agent_run.tool.started",payload:{provider:"claude",toolName:ft(a),toolCallId:i,...o?{command:o}:{},...s?{path:s}:{},operation:a}}}function dn(e,t){let n=(Array.isArray(L(e.message).content)?L(e.message).content:[]).map(L).find(f=>f.type==="tool_result");if(!n)return null;let o=L(e.toolUseResult),s=L(o.file),a=J(n.tool_use_id,n.toolUseId),i=t?.get(a)??{},c=J(s.filePath,s.file_path,o.filePath,o.file_path,i.path),m=pt(o.command,o.cmd,i.command),v=J(i.operation)||(c?"read":mt(m?"Bash":"tool",m)),l=c&&typeof s.numLines=="number"?`${s.numLines} lines`:J(o.stdout,o.output,n.content);return{type:"agent_run.tool.completed",payload:{provider:"claude",toolName:ft(v),toolCallId:a,...m?{command:m}:{},...c?{path:c}:{},operation:v,...l?{output:l}:{}}}}function cn(e,t=new Map){let r=L(e),n=L(r.message),o=Array.isArray(n.content)?n.content:[],s=[];for(let i of o.map(L))if(i.type==="tool_use"){let c=an(i,t);c&&s.push(c)}let a=dn(r,t);return a&&s.push(a),s}function un(e){if(e.type==="result"){let t=e.result;return typeof t=="string"?t:null}return null}function re(e){return typeof e=="number"&&Number.isFinite(e)?e:void 0}function dt(...e){for(let t of e){let r=re(t);if(r!==void 0)return Math.max(0,Math.trunc(r))}}function ln(e){let t=L(e),r=L(t.usage),n=L(t.tokenUsage),o=L(t.token_usage),s=L(t.tokens),a=L(t.usageSummary);return{inputTokens:dt(r.input_tokens,r.inputTokens,r.prompt_tokens,r.promptTokens,n.input_tokens,n.inputTokens,n.prompt_tokens,n.promptTokens,o.input_tokens,o.inputTokens,o.prompt_tokens,o.promptTokens,s.input_tokens,s.inputTokens,s.prompt_tokens,s.promptTokens,a.input_tokens,a.inputTokens,t.input_tokens,t.inputTokens,t.total_input_tokens,t.prompt_tokens,t.promptTokens),outputTokens:dt(r.output_tokens,r.outputTokens,r.completion_tokens,r.completionTokens,n.output_tokens,n.outputTokens,n.completion_tokens,n.completionTokens,o.output_tokens,o.outputTokens,o.completion_tokens,o.completionTokens,s.output_tokens,s.outputTokens,s.completion_tokens,s.completionTokens,a.output_tokens,a.outputTokens,t.output_tokens,t.outputTokens,t.total_output_tokens,t.completion_tokens,t.completionTokens),costUsd:re(t.total_cost_usd)??re(t.cost_usd)??re(r.total_cost_usd)??re(r.cost_usd)}}function pn(e){return e.type!=="result"?{}:ln(e)}async function mn(e,t){let r=typeof e=="string"?e:e.agentRunId,n=typeof e=="string"?void 0:e.emitRawEvent,o="",s={},a=2,i=[],c=new Map;try{for await(let m of t){await n?.(m);for(let v of cn(m,c))i.push({eventId:`${r}:claude:${a}`,eventSeq:a,type:v.type,payload:v.payload}),a+=1;o=un(m)??o,s={...s,...pn(m)}}return{output:o.trim()||"Agent run completed",...s,events:i}}catch(m){let v=m instanceof Error?m:new Error(String(m));throw v.events=i,v.emittedEventIds=new Set,v}finally{t.close()}}async function gt(e){if(e.provider.kind!=="claude-code"&&e.provider.kind!=="claude-compatible")throw new Error(`unsupported node provider kind: ${e.provider.kind}`);let t=new AbortController,r=e.invokeTool?{truesayer:at(e.agentRunId,e.invokeTool)}:void 0,n=(0,Oe.query)({prompt:e.prompt,options:{...fn(e.providerSessionId)?{sessionId:e.providerSessionId}:{},cwd:e.cwd,env:e.env,model:e.selectedModel,systemPrompt:rn(e.systemPrompt,!!e.invokeTool,e.availableProviders),mcpServers:r,maxTurns:e.maxTurns??80,permissionMode:"bypassPermissions",allowDangerouslySkipPermissions:!0,disallowedTools:[...Xr],abortController:t}});return mn(e,n)}function fn(e){return/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(e)}var z=require("fs"),wt=require("child_process"),bt=require("readline"),Rt=require("module"),oe=require("path"),Fe=require("zod/v4");function ht(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}function vt(e){return typeof e=="string"?e.trim():""}function gn(e){let t=ht(e),r=vt(t.type);return r==="add"||r==="delete"?{type:r}:r==="update"?{type:r,move_path:typeof t.move_path=="string"?t.move_path:null}:null}function hn(e){let t=ht(e),r=vt(t.path),n=gn(t.kind);return!r||!n?null:{path:r,kind:n,diff:typeof t.diff=="string"?t.diff:""}}function Ue(e){return Array.isArray(e)?e.map(hn).filter(t=>t!==null).map(t=>{let r=vn(t.kind);return{path:r==="renamed"&&t.kind.type==="update"&&t.kind.move_path?t.kind.move_path:t.path,status:r,...t.diff?{diff:t.diff}:{}}}):[]}function vn(e){return e.type==="add"?"added":e.type==="delete"?"deleted":e.move_path?"renamed":"modified"}var He=6e4,_t=1,yn=(0,Rt.createRequire)(__filename);function kn(){let e=yn.resolve("@openai/codex/package.json");return(0,oe.join)((0,oe.dirname)(e),"bin","codex.js")}function N(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}function S(e){return typeof e=="string"&&e.trim()?e.trim():""}function $e(e){return typeof e=="string"?e:""}function P(...e){for(let t of e){let r=S(t);if(r)return r}return""}function Le(...e){for(let t of e)if(typeof t=="number"&&Number.isFinite(t))return t}function wn(e){return typeof e=="string"?e.trim():Array.isArray(e)?e.filter(r=>typeof r=="string"&&r.trim().length>0).map(r=>r.trim()).join(" "):""}function bn(...e){for(let t of e){let r=wn(t);if(r)return r}return""}function Rn(e){return e.some(t=>["read","search","listFiles"].includes(P(t.type)))?"read":"exec"}function yt(e){return e==="read"?"read":e==="write"?"write":e==="update"?"update":e==="platform_tool"?"platform_tool":"exec"}function _n(e){return Array.isArray(e)?e.map(N).filter(t=>P(t.type)):[]}function En(e){return Array.from(new Set(e.map(t=>P(t.path)).filter(Boolean)))}function Tn(e){return e.some(t=>t.status!=="added")?"update":"write"}function Nn(e){let t=P(e.tool);if(e.type!=="mcpToolCall")return t;let r=P(e.server);return r&&t?`${r}.${t}`:t}function Sn(e){let t=e.method,r=e.params??{},n=N(r.item),o=S(n.type),s=t==="item/completed"?"agent_run.tool.completed":"agent_run.tool.started";if(t!=="item/started"&&t!=="item/completed")return null;if(o==="commandExecution"){let a=bn(n.command),i=_n(n.commandActions),c=Rn(i),m=En(i),v=P(n.status),l=P(n.aggregatedOutput),f=Le(n.exitCode),y=Le(n.durationMs);return{type:s,payload:{provider:"codex",toolName:yt(c),toolCallId:P(n.id),...a?{command:a}:{},...P(n.cwd)?{cwd:P(n.cwd)}:{},...m[0]?{path:m[0]}:{},...m.length>0?{paths:m}:{},operation:c,...v?{status:v}:{},...f===void 0?{}:{exitCode:f},...l?{output:l}:{},...y===void 0?{}:{durationMs:y},...i.length>0?{commandActions:i}:{}}}}if(o==="fileChange"){let a=Ue(n.changes);if(a.length===0)return null;let i=a.map(v=>v.path),c=Tn(a),m=P(n.status);return{type:s,payload:{provider:"codex",toolName:yt(c),toolCallId:P(n.id),command:"fileChange",path:i[0],paths:i,operation:c,...m?{status:m}:{},fileChanges:a,...a[0]?.diff?{diff:a[0].diff}:{}}}}if(o==="dynamicToolCall"||o==="mcpToolCall"){let a=Nn(n),i=Le(n.durationMs);return{type:s,payload:{provider:"codex",toolName:"platform_tool",toolCallId:P(n.id),platformToolName:a,...n.arguments===void 0?{}:{arguments:n.arguments},operation:"platform_tool",...P(n.status)?{status:P(n.status)}:{},...typeof n.success=="boolean"?{success:n.success}:{},...n.contentItems===void 0||n.contentItems===null?{}:{contentItems:n.contentItems},...n.result===void 0||n.result===null?{}:{result:n.result},...n.error===void 0||n.error===null?{}:{error:n.error},...i===void 0?{}:{durationMs:i}}}}return null}function In(e){if(e.method!=="item/fileChange/patchUpdated")return null;let t=e.params??{},r=Ue(t.changes);if(r.length===0)return null;let n=r.map(o=>o.path);return{type:"agent_run.provider_event",payload:{provider:"codex",method:e.method,...P(t.itemId)?{itemId:P(t.itemId)}:{},paths:n,changes:r,...P(t.threadId)?{threadId:P(t.threadId)}:{},...P(t.turnId)?{turnId:P(t.turnId)}:{}}}}function Pn(e){let t=e.params??{};if(e.method==="item/completed"){let r=N(t.item);if(r.type==="agentMessage"){let n=S(r.text);return n?{type:"agent_run.message.completed",payload:{provider:"codex",text:n,...S(r.phase)?{phase:S(r.phase)}:{}}}:null}}return e.method==="error"?{type:"agent_run.provider_event",payload:{provider:"codex",method:e.method,params:t}}:e.method==="turn/diff/updated"?{type:"agent_run.provider_event",payload:{provider:"codex",method:e.method,...P(t.threadId)?{threadId:P(t.threadId)}:{},...P(t.turnId)?{turnId:P(t.turnId)}:{},...$e(t.diff)?{diff:$e(t.diff)}:{}}}:null}function An(e){return Sn(e)??In(e)??Pn(e)}function Et(e){if(e.method!=="error")return null;let t=e.params??{};if(t.willRetry===!0)return null;let r=N(t.error),n=N(r.codexErrorInfo),o=S(t.codexErrorInfo)||S(r.codexErrorInfo)||Object.keys(n)[0]||S(t.code)||S(t.errorCode)||S(r.code),s=S(t.message)||S(r.message)||S(t.error)||"Codex app-server provider error";return new Error(`Codex app-server error${o?` ${o}`:""}: ${s}`)}function xn(e){if(e.method!=="turn/completed")return null;let t=e.params??{},r=N(t.turn),n=S(r.status);if(n!=="failed"&&n!=="interrupted")return null;let o=N(r.error),s=P(o.message,r.error,r.lastError,t.error,n==="interrupted"?"Codex turn interrupted":"Codex turn failed");return new Error(s)}function Cn(e){let t=e.TRUESAYER_CODEX_REQUEST_TIMEOUT_MS?.trim();if(!t)return He;let r=Number(t);return Number.isFinite(r)&&r>0?Math.trunc(r):He}function Mn(e){if(e.exitCode!==null||e.killed)return;let t=e.pid;if(t&&process.platform!=="win32")try{process.kill(-t,"SIGTERM");return}catch{}e.kill("SIGTERM")}function Tt(e){let t=e.env.TRUESAYER_CODEX_BIN||kn(),r=(0,wt.spawn)(process.execPath,[t,"app-server","--listen","stdio://",...e.args??[]],{cwd:e.cwd,env:e.env,stdio:["pipe","pipe","pipe"],detached:e.detached===!0}),n=new Map,o=[],s=e.requestTimeoutMs??He,a=1,i=!1;function c(){return o.join("").slice(-1e3).trim()}function m(f,y){return new Error(`Codex app-server request timed out after ${s}ms (method ${y.method}, requestId ${f}, stderr: ${c()||"no stderr"})`)}function v(f,y){for(let[d,k]of n)n.delete(d),k.timeout&&clearTimeout(k.timeout),e.onRequestEvent?.("failed",{method:k.method,requestId:d,elapsedMs:Date.now()-k.startedAt,reason:y,error:f.message}),k.reject(f)}let l=(0,bt.createInterface)({input:r.stdout});return l.on("line",f=>{let y=f.trim();if(!y)return;let d;try{d=JSON.parse(y)}catch{return}let k=N(d),b=k.id;if((typeof b=="number"||typeof b=="string")&&n.has(b)){let w=n.get(b);n.delete(b),w?.timeout&&clearTimeout(w.timeout);let p=k;p.error?(e.onRequestEvent?.("failed",{method:w?.method??"unknown",requestId:b,elapsedMs:w?Date.now()-w.startedAt:void 0,reason:"error",error:p.error.message??"Codex app-server request failed"}),w?.reject(new Error(p.error.message??"Codex app-server request failed"))):(e.onRequestEvent?.("completed",{method:w?.method??"unknown",requestId:b,elapsedMs:w?Date.now()-w.startedAt:void 0}),w?.resolve(p.result));return}let R=S(k.method);if(R){if((typeof b=="number"||typeof b=="string")&&e.onServerRequest){e.onServerRequest({id:b,method:R,params:N(k.params)}).then(A=>{r.stdin.write(`${JSON.stringify({id:b,result:A})}
26
+ `)}).catch(A=>{r.stdin.write(`${JSON.stringify({id:b,error:{code:-32603,message:A instanceof Error?A.message:String(A)}})}
27
+ `)});return}let p={method:R,params:N(k.params)};e.onNotification?.(p);let g=Et(p);g&&v(g,"provider_error")}}),r.stderr.on("data",f=>{o.push(f.toString("utf8")),o.length>25&&o.shift()}),r.on("exit",(f,y)=>{if(i)return;let d=`Codex app-server exited (code ${f??"null"}, signal ${y??"null"}): ${c()||"no stderr"}`,k=new Error(d);v(k,"app_server_exit"),e.onExit?.(k)}),{stderrTail:c,request(f,y){let d=a;a+=1,e.onRequestEvent?.("started",{method:f,requestId:d});let k=new Promise((b,R)=>{let w={method:f,startedAt:Date.now(),resolve:b,reject:R},p=setTimeout(()=>{if(!n.delete(d))return;let g=m(d,w);e.onRequestEvent?.("failed",{method:f,requestId:d,elapsedMs:Date.now()-w.startedAt,reason:"timeout"}),R(g)},s);typeof p.unref=="function"&&p.unref(),w.timeout=p,n.set(d,w)});return r.stdin.write(`${JSON.stringify({id:d,method:f,params:y})}
28
+ `),k},notify(f,y){r.stdin.write(`${JSON.stringify({method:f,...y===void 0?{}:{params:y}})}
29
+ `)},close(){i=!0,l.close(),Mn(r)}}}function Dn(e){let t=N(e).data;if(!Array.isArray(t))return[];let r=t.flatMap(n=>{let o=N(n),s=S(o.model)||S(o.id);return s?[s]:[]});return Array.from(new Set(r.map(n=>n.trim()).filter(Boolean)))}async function Nt(e={}){let t=Tt({env:e.env??te(),detached:process.platform!=="win32",requestTimeoutMs:e.timeoutMs??3e4});try{return await t.request("initialize",{clientInfo:{name:"truesayer",title:"Truesayer",version:"0.1.0"},capabilities:{experimentalApi:!0,optOutNotificationMethods:[]}}),t.notify("initialized"),Dn(await t.request("model/list",{includeHidden:!1,limit:100}))}finally{t.close()}}function St(e){return e?(0,oe.join)(e,"codex-app-server-session.json"):void 0}function On(e){let t=St(e);if(!t||!(0,z.existsSync)(t))return{};try{let r=JSON.parse((0,z.readFileSync)(t,"utf8")),n=N(r),o=S(n.threadId),s=n.platformToolsVersion;return{threadId:o||void 0,platformToolsVersion:typeof s=="number"&&Number.isFinite(s)?s:void 0}}catch{return{}}}function Un(e,t,r){let n=St(e);n&&(0,z.writeFileSync)(n,`${JSON.stringify({threadId:t,...r?{platformToolsVersion:_t}:{}})}
30
+ `,{mode:384})}var Ln=["Long-running or continuously-running service/watch commands, such as dev servers, file watchers, npm start, npm run start, npm run dev, vite, next dev, nodemon, tsx --watch, tail -f, database servers, or queue workers, must not be run as foreground blocking commands. Start them in the background, redirect logs to a file, record the PID, and run a bounded health check with timeout. Stop or clean up the process when validation is complete unless the task explicitly asks to keep the service available for human inspection; in that case keep it running in the background and report PID, port, URL, and log path. Finite commands such as install, build, test, lint, migration, and one-shot scripts should run in the foreground and must return an exit code.","Do not try to access the Truesayer Server database, provider secrets, or Server-only environment variables from Node.","All file creation and manual file edits MUST use apply_patch or Codex native fileChange. This overrides any base instruction that allows shell redirection, here-docs, cat, tee, scripts, or generated-file exceptions. Do not create or edit files with cat, tee, heredoc, sed -i, perl -pi, python/node scripts, or shell redirection, even for generated files like package.json or temporary scratch files under /tmp."].join(`
31
+ `);function Fn(e){return["Truesayer runtime instructions:",[e.systemPrompt?.trim(),e.invokeTool?ge:"",e.invokeTool?he(e.availableProviders):"",Ln].filter(Boolean).join(`
27
32
 
28
33
  `)].join(`
29
- `)}function Vr(e){return e.prompt}function re(e){return JSON.stringify(e)}function Xr(e){return/^[A-Za-z0-9_-]+$/.test(e)?e:re(e)}function Zr(e){if(e.provider.source!=="provider-file"||e.provider.kind!=="codex"&&e.provider.kind!=="openai-compatible")return[];let t=e.provider.baseUrl?.trim()||e.env.OPENAI_BASE_URL?.trim();if(!t)return[];let r=e.providerName.trim();if(!r)return[];let n=[`name=${re(e.provider.displayName||r)}`,`base_url=${re(t)}`,'wire_api="responses"','env_key="OPENAI_API_KEY"',"requires_openai_auth=false","supports_websockets=false"].join(",");return["-c",`model_provider=${re(r)}`,"-c",`model_providers.${Xr(r)}={${n}}`]}function Qr(e){let t=R(e),r=R(t.last),n=R(t.total);return{inputTokens:ne(r.input_tokens,r.inputTokens,r.prompt_tokens,r.promptTokens,n.input_tokens,n.inputTokens,n.prompt_tokens,n.promptTokens,t.input_tokens,t.inputTokens,t.prompt_tokens,t.promptTokens),outputTokens:ne(r.output_tokens,r.outputTokens,r.completion_tokens,r.completionTokens,n.output_tokens,n.outputTokens,n.completion_tokens,n.completionTokens,t.output_tokens,t.outputTokens,t.completion_tokens,t.completionTokens)}}function B(e){return typeof e=="number"&&Number.isFinite(e)?e:void 0}function ne(...e){for(let t of e){let r=B(t);if(r!==void 0)return Math.max(0,Math.trunc(r))}}function en(e){let t=R(e),r=R(t.usage),n=R(t.tokenUsage),o=R(t.token_usage),s=R(t.tokens),a=R(t.usageSummary);return{inputTokens:ne(r.input_tokens,r.inputTokens,r.prompt_tokens,r.promptTokens,n.input_tokens,n.inputTokens,n.prompt_tokens,n.promptTokens,o.input_tokens,o.inputTokens,o.prompt_tokens,o.promptTokens,s.input_tokens,s.inputTokens,s.prompt_tokens,s.promptTokens,a.input_tokens,a.inputTokens,t.input_tokens,t.inputTokens,t.total_input_tokens,t.prompt_tokens,t.promptTokens),outputTokens:ne(r.output_tokens,r.outputTokens,r.completion_tokens,r.completionTokens,n.output_tokens,n.outputTokens,n.completion_tokens,n.completionTokens,o.output_tokens,o.outputTokens,o.completion_tokens,o.completionTokens,s.output_tokens,s.outputTokens,s.completion_tokens,s.completionTokens,a.output_tokens,a.outputTokens,t.output_tokens,t.outputTokens,t.total_output_tokens,t.completion_tokens,t.completionTokens),costUsd:B(t.total_cost_usd)??B(t.cost_usd)??B(r.total_cost_usd)??B(r.cost_usd)}}function Ze(...e){let t={};for(let r of e)r&&(r.inputTokens!==void 0&&(t.inputTokens=r.inputTokens),r.outputTokens!==void 0&&(t.outputTokens=r.outputTokens),"costUsd"in r&&r.costUsd!==void 0&&(t.costUsd=r.costUsd));return t}function tn(e){let t=[],r=new Set,n=new Map,o=new Map,s=new Map,a=new Map,i=2,c="",p=null,k=null;function b(l){t.push(l),!r.has(l.eventId)&&(r.add(l.eventId),e.emitEvent?.(l))}function m(l,w){b({eventId:`${e.agentRunId}:codex:${i}`,eventSeq:i,type:`agent_run.provider_request.${l}`,payload:{provider:"codex",...w}}),i+=1}function y(l){let w=qr(l);w&&(b({eventId:`${e.agentRunId}:codex:${i}`,eventSeq:i,type:w.type,payload:w.payload}),i+=1)}function d(l,w={}){let T={output:c.trim()||"Codex run completed",...w.inputTokens===void 0?{}:{inputTokens:w.inputTokens},...w.outputTokens===void 0?{}:{outputTokens:w.outputTokens}};s.set(l,T);let x=a.get(l)??[];a.delete(l);for(let O of x)O.resolve(T)}function g(l){for(let w of a.values())for(let C of w)C.reject(l);a.clear()}function h(l){let w=l.params??{},C=rt(l);if(l.method==="item/agentMessage/delta"){let T=_(w.itemId),x=_(w.delta);if(T&&x){let O=`${n.get(T)??""}${x}`;n.set(T,O),c=O}}if(l.method==="item/completed"){let T=R(w.item);if(T.type==="agentMessage"){let x=_(T.text);x&&(c=x)}}if(l.method==="turn/completed"){let T=R(w.turn),x=_(T.id),O=_(T.status);x&&O==="completed"&&d(x,Ze(o.get(x),en(T)))}if(l.method==="thread/tokenUsage/updated"){let T=_(w.turnId);T&&o.set(T,Ze(o.get(T),Qr(w.tokenUsage)))}y(l),C&&(p=C,g(p))}let f=nt({cwd:e.cwd,env:e.env,args:Zr(e),requestTimeoutMs:Br(e.env),onNotification:h,onRequestEvent:m,onExit(l){k=l,g(l)}});return{events:t,emittedEventIds:r,stderrTail:f.stderrTail,request:f.request,notify:f.notify,close:f.close,waitForTurnCompleted(l){let w=s.get(l);return w!==void 0?Promise.resolve(w):p?Promise.reject(p):k?Promise.reject(k):(m("started",{method:"turn/completed",turnId:l}),new Promise((C,T)=>{let x={resolve:C,reject:T},O=a.get(l)??[];O.push(x),a.set(l,O)}))}}}function rn(e){let t=_(R(R(e).thread).id);if(!t)throw new Error("Codex app-server did not return a thread id");return t}function nn(e){let t=_(R(R(e).turn).id);if(!t)throw new Error("Codex app-server did not return a turn id");return t}async function it(e){if(e.provider.kind!=="codex"&&e.provider.kind!=="openai-compatible")throw new Error(`unsupported node provider kind: ${e.provider.kind}`);let t=tn(e),r=e.provider.source==="provider-file"?e.providerName:void 0,n={...e.reasoningEffort&&e.reasoningEffort!=="default"?{reasoningEffort:e.reasoningEffort}:{},...e.serviceTier&&e.serviceTier!=="default"?{serviceTier:e.serviceTier}:{}},o=Yr(e);try{await t.request("initialize",{clientInfo:{name:"truesayer-node",title:"Truesayer Node",version:"0.1.0"},capabilities:{experimentalApi:!0,optOutNotificationMethods:[]}}),t.notify("initialized");let s=Gr(e.sessionStateDir);if(s)await t.request("thread/resume",{threadId:s,model:e.selectedModel,...r?{modelProvider:r}:{},cwd:e.cwd,approvalPolicy:"never",sandbox:"danger-full-access",experimentalRawEvents:!1,excludeTurns:!0,persistExtendedHistory:!0,developerInstructions:o,...n});else{let p=await t.request("thread/start",{model:e.selectedModel,...r?{modelProvider:r}:{},cwd:e.cwd,approvalPolicy:"never",sandbox:"danger-full-access",experimentalRawEvents:!1,persistExtendedHistory:!0,developerInstructions:o,...n});s=rn(p),Jr(e.sessionStateDir,s)}let a=await t.request("turn/start",{threadId:s,input:[{type:"text",text:Vr(e),text_elements:[]}],cwd:e.cwd,approvalPolicy:"never",model:e.selectedModel,...n}),i=nn(a),c=await t.waitForTurnCompleted(i);return{output:c.output.trim()||"Codex run completed",...c.inputTokens===void 0?{}:{inputTokens:c.inputTokens},...c.outputTokens===void 0?{}:{outputTokens:c.outputTokens},events:t.events,emittedEventIds:t.emittedEventIds}}catch(s){throw s instanceof Error&&(s.events=t.events,s.emittedEventIds=t.emittedEventIds),s}finally{t.close()}}function oe(e){return Array.from(new Set(e.map(t=>t.trim()).filter(Boolean)))}function fe(e){return typeof e=="object"&&e!==null?e:void 0}function at(e){return typeof e=="string"&&e.trim()?e.trim():void 0}function on(e){return e.replace(/\/+$/,"")}function dt(e,t){let r=on(e);return t==="v1/models"&&/\/v1$/i.test(r)?`${r}/models`:`${r}/${t}`}function sn(e){if(!e.baseUrl?.trim()||!e.apiKey?.trim())return[];let t=e.kind.toLowerCase(),r=e.baseUrl.trim(),n=[];return(t.includes("claude")||t.includes("anthropic"))&&n.push({url:dt(r,"v1/models"),auth:"anthropic"}),(t.includes("openai")||t==="codex")&&n.push({url:dt(r,"models"),auth:"bearer"}),n.filter((o,s,a)=>a.findIndex(i=>i.url===o.url)===s)}function an(e){let t=fe(e);return at(t?.id)??at(t?.model)}function dn(e){let t=fe(e)?.data;if(!Array.isArray(t))return[];let r=t.flatMap(s=>{let a=an(s);if(!a)return[];let i=fe(s),c=typeof i?.created=="number"?i.created:typeof i?.created_at=="number"?i.created_at:void 0;return[{id:a,created:c}]}),o=r.some(s=>s.created!==void 0)?[...r].sort((s,a)=>(a.created??Number.NEGATIVE_INFINITY)-(s.created??Number.NEGATIVE_INFINITY)):r;return oe(o.map(s=>s.id))}async function cn(e,t){let r={accept:"application/json"};e.auth==="anthropic"?(r["x-api-key"]=t,r["anthropic-version"]="2023-06-01"):r.authorization=`Bearer ${t}`;let n=await fetch(e.url,{method:"GET",headers:r});if(!n.ok)throw new Error(`HTTP ${n.status}`);let o=dn(await n.json().catch(()=>null));if(o.length===0)throw new Error("response did not contain model ids");return o}async function he(e,t){let r=t.apiKey?.trim();if(!r)throw new Error(`provider ${e} cannot discover models without an API key`);let n=sn(t);if(n.length===0)throw new Error(`provider ${e} cannot discover models without a supported baseUrl`);let o=[];for(let s of n)try{return await cn(s,r)}catch(a){o.push(`${s.url}: ${a instanceof Error?a.message:String(a)}`)}throw new Error(`provider ${e} model discovery failed: ${o.join("; ")}`)}async function ct(e,t){if(t.source==="provider-file"&&t.models?.length)return oe(t.models);if(t.source==="provider-file")try{return await he(e,t)}catch(r){return console.warn(`[node] provider ${e} model discovery unavailable:`,r instanceof Error?r.message:String(r)),[]}if(t.source!=="native")return[];try{if(e==="local-claude-code"&&t.kind==="claude-code")return await Be();if(e==="local-codex"&&t.kind==="codex")return await ot()}catch(r){console.warn(`[node] provider ${e} unavailable:`,r instanceof Error?r.message:String(r))}return[]}var un=15e3;function ln(e){let t=e.emittedEventIds??new Set;return(e.events??[]).filter(r=>!t.has(r.eventId))}var ut={"local-claude-code":{kind:"claude-code",displayName:"Local Claude Code",source:"native"},"local-codex":{kind:"codex",displayName:"Local Codex",source:"native"}};function pn(e){return e.split(/[-_\s]+/).filter(Boolean).map(t=>`${t[0]?.toUpperCase()??""}${t.slice(1)}`).join(" ")}function mn(e){if(!e?.trim()||!(0,N.existsSync)(e))return{};gn(e);let t;try{t=JSON.parse((0,N.readFileSync)(e,"utf8"))}catch{throw new Error(`provider file is not valid JSON: ${e}`)}let r=t&&typeof t=="object"&&!Array.isArray(t)&&t.providers&&typeof t.providers=="object"&&!Array.isArray(t.providers)?t.providers:{},n={};for(let[o,s]of Object.entries(r)){let a=o.trim();if(!a||!s||typeof s!="object"||Array.isArray(s))continue;let i=s,c=typeof i.kind=="string"&&i.kind.trim()?i.kind.trim():"openai-compatible",p=typeof i.displayName=="string"&&i.displayName.trim()?i.displayName.trim():pn(a),k=Array.isArray(i.models)?Array.from(new Set(i.models.filter(h=>typeof h=="string"&&h.trim().length>0).map(h=>h.trim()))):void 0,b=typeof i.apiKey=="string"&&i.apiKey.trim()?i.apiKey.trim():void 0,m=typeof i.baseUrl=="string"&&i.baseUrl.trim()?i.baseUrl.trim():void 0,y=typeof i.ANTHROPIC_DEFAULT_HAIKU_MODEL=="string"&&i.ANTHROPIC_DEFAULT_HAIKU_MODEL.trim()?i.ANTHROPIC_DEFAULT_HAIKU_MODEL.trim():void 0,d=typeof i.ANTHROPIC_DEFAULT_SONNET_MODEL=="string"&&i.ANTHROPIC_DEFAULT_SONNET_MODEL.trim()?i.ANTHROPIC_DEFAULT_SONNET_MODEL.trim():void 0,g=typeof i.ANTHROPIC_DEFAULT_OPUS_MODEL=="string"&&i.ANTHROPIC_DEFAULT_OPUS_MODEL.trim()?i.ANTHROPIC_DEFAULT_OPUS_MODEL.trim():void 0;n[a]={kind:c,displayName:p,source:"provider-file",...lt(c,k)?.length?{models:lt(c,k)}:{},...b?{apiKey:b}:{},...m?{baseUrl:m}:{},...y?{anthropicDefaultHaikuModel:y}:{},...d?{anthropicDefaultSonnetModel:d}:{},...g?{anthropicDefaultOpusModel:g}:{}}}return n}function gn(e){if(process.platform!=="win32")try{((0,N.statSync)(e).mode&63)!==0&&console.warn(`[node] provider file permissions are too broad; run chmod 600 ${e}`)}catch{return}}function yt(e){process.platform!=="win32"&&(0,N.chmodSync)(e,384)}function fn(e){return(0,N.mkdirSync)((0,vt.dirname)(e),{recursive:!0,mode:448}),(0,N.existsSync)(e)||(0,N.writeFileSync)(e,`${JSON.stringify({providers:{}},null,2)}
30
- `,{mode:384}),yt(e),ye(e),e}function lt(e,t){if(!t?.length)return;if(!e.toLowerCase().includes("claude"))return t;let r=t.filter(n=>!["haiku","sonnet","opus"].includes(n.trim().toLowerCase()));return r.length>0?r:void 0}function K(e){if(!e)return;let t=e.trim();if(t)return t.length>8?`${t.slice(0,4)}***${t.slice(-4)}`:`${t.slice(0,4)}***`}function ie(e){let t=mn(e);for(let r of Object.keys(t))if(ut[r])throw new Error(`duplicate provider name: ${r}`);return{...ut,...t}}async function hn(e={}){let t=ie(e.providerFile),r={},n=e.probeProviderModels??ct,o=await Promise.all(Object.entries(t).map(async([s,a])=>[s,await n(s,a,{})]));for(let[s,a]of o){let i=t[s];i&&a.length!==0&&(r[s]={kind:i.kind,displayName:i.displayName,source:i.source,models:a,modelsDiscoveredBy:i.source==="provider-file"?i.models?.length?"provider-file":"api-probe":"sdk-probe",...i.source==="provider-file"&&i.baseUrl?{baseUrl:i.baseUrl}:{},...i.source==="provider-file"&&K(i.apiKey)?{apiKeyPreview:K(i.apiKey)}:{},...i.source==="provider-file"?{configEditable:!0}:{},...i.source==="provider-file"&&i.anthropicDefaultHaikuModel?{anthropicDefaultHaikuModel:i.anthropicDefaultHaikuModel}:{},...i.source==="provider-file"&&i.anthropicDefaultSonnetModel?{anthropicDefaultSonnetModel:i.anthropicDefaultSonnetModel}:{},...i.source==="provider-file"&&i.anthropicDefaultOpusModel?{anthropicDefaultOpusModel:i.anthropicDefaultOpusModel}:{}})}return r}function vn(e){return Object.fromEntries(Object.entries(e).map(([t,r])=>[t,{kind:r.kind,displayName:r.displayName,source:r.source,models:r.models,modelsDiscoveredBy:r.modelsDiscoveredBy}]))}function yn(e,t){return{type:"node.hello",payload:{nodeName:e.nodeName,nodeVersion:e.nodeVersion,platform:{os:process.platform,arch:process.arch,hostname:ht.default.hostname()},capabilities:{providers:vn(t),supportsWorktrees:!0,browserE2E:(e.probeBrowserE2E??wn)()}}}}var kn={"libnss3.so":["/usr/lib/x86_64-linux-gnu/libnss3.so","/usr/lib/aarch64-linux-gnu/libnss3.so","/usr/lib64/libnss3.so"],"libatk-bridge-2.0.so.0":["/usr/lib/x86_64-linux-gnu/libatk-bridge-2.0.so.0","/usr/lib/aarch64-linux-gnu/libatk-bridge-2.0.so.0","/usr/lib64/libatk-bridge-2.0.so.0"],"libcups.so.2":["/usr/lib/x86_64-linux-gnu/libcups.so.2","/usr/lib/aarch64-linux-gnu/libcups.so.2","/usr/lib64/libcups.so.2"],"libxkbcommon.so.0":["/usr/lib/x86_64-linux-gnu/libxkbcommon.so.0","/usr/lib/aarch64-linux-gnu/libxkbcommon.so.0","/usr/lib64/libxkbcommon.so.0"],"libgbm.so.1":["/usr/lib/x86_64-linux-gnu/libgbm.so.1","/usr/lib/aarch64-linux-gnu/libgbm.so.1","/usr/lib64/libgbm.so.1"],"libasound.so.2":["/usr/lib/x86_64-linux-gnu/libasound.so.2","/usr/lib/aarch64-linux-gnu/libasound.so.2","/usr/lib64/libasound.so.2"]};function wn(){let e=process.env.TRUESAYER_NODE_BROWSER_E2E?.trim().toLowerCase();if(e==="available"||e==="unavailable"||e==="unknown")return{status:e,diagnostics:["set by TRUESAYER_NODE_BROWSER_E2E"]};if(process.platform!=="linux")return{status:"unknown",diagnostics:["automatic browser dependency detection only supports linux"]};let t=Object.entries(kn).filter(([,r])=>!r.some(n=>(0,N.existsSync)(n))).map(([r])=>r);return t.length>0?{status:"unavailable",diagnostics:t.map(r=>`missing ${r}`)}:{status:"unknown",diagnostics:["linux chromium libraries found; browser binary availability not verified"]}}function U(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}function v(e){return typeof e=="string"&&e.trim()?e.trim():""}function bn(e){return j(e)}function En(e,t){let r=e;if(!r?.trim())return{};let n=ie(r)[t];if(!n||n.source!=="provider-file")return{};let o={};return n.kind==="codex"||n.kind==="openai-compatible"?(n.apiKey&&(o.OPENAI_API_KEY=n.apiKey),n.baseUrl&&(o.OPENAI_BASE_URL=n.baseUrl),o):(n.apiKey&&(o.ANTHROPIC_API_KEY=n.apiKey),n.baseUrl&&(o.ANTHROPIC_BASE_URL=n.baseUrl),n.anthropicDefaultOpusModel&&(o.ANTHROPIC_DEFAULT_OPUS_MODEL=n.anthropicDefaultOpusModel,o.ANTHROPIC_DEFAULT_SONNET_MODEL=n.anthropicDefaultSonnetModel||n.anthropicDefaultOpusModel,o.ANTHROPIC_DEFAULT_HAIKU_MODEL=n.anthropicDefaultHaikuModel||n.anthropicDefaultOpusModel),o)}function _n(e){let t=U(e),r=t.id;return t.jsonrpc==="2.0"&&(typeof r=="string"||typeof r=="number"||r===null)&&("result"in t||"error"in t)}function Rn(e){let t=U(e),r=t.id;return t.jsonrpc==="2.0"&&(typeof r=="string"||typeof r=="number"||r===null)&&typeof t.method=="string"&&t.method.trim().length>0}function Tn(e,t){return JSON.stringify({jsonrpc:"2.0",id:e,result:t})}function Nn(e,t){return JSON.stringify({jsonrpc:"2.0",id:e,error:{code:-32e3,message:t}})}function In(e){let t=0,r=new Map;return{invokeTool(n){if(e.readyState!==1)throw new Error("node websocket is not open");let o=`tool:${++t}`,s={jsonrpc:"2.0",id:o,method:"tool.invoke",params:{...n,toolCallId:n.toolCallId??o}},a=new Promise((i,c)=>{r.set(o,{resolve:i,reject:c})});try{e.send(JSON.stringify(s))}catch(i){throw r.delete(o),i}return a},handleJsonRpcMessage(n){if(!_n(n)||n.id===null)return!1;let o=r.get(n.id);if(!o)return!1;if(r.delete(n.id),"error"in n&&n.error){let s=typeof n.error.message=="string"?n.error.message:"JSON-RPC tool call failed";return o.reject(new Error(s)),!0}return o.resolve(n.result),!0},rejectPending(n){for(let o of r.values())o.reject(n);r.clear()}}}function Pn(e){let t=U(e.runtimeSelection),r=v(t.providerName)||v(t.providerId),n=v(t.selectedModel)||v(t.modelId);if(!r||!n)throw new Error("agent.provision requires providerName and selectedModel");return{providerName:r,selectedModel:n}}var G=new Map;function ve(e){let t=v(e.repoPath);if(!t)throw new Error("repoPath is required");return t}function kt(e){let t=e.files.reduce((n,o)=>n+o.additions,0),r=e.files.reduce((n,o)=>n+o.deletions,0);return{repoRoot:e.repoRoot,baseSha:e.baseSha,diff:e.diff,diffHash:e.diffHash,hasStagedChanges:e.hasStagedChanges,files:e.files,totalAdditions:t,totalDeletions:r,updatedAt:new Date().toISOString()}}async function An(e){return kt(await V(ve(e)))}async function xn(e){let t=ve(e),r=v(e.baseSha);if(!r)throw new Error("baseSha is required");let n=v(e.scope);if(n!=="file"&&n!=="all")throw new Error("scope must be file or all");let o=n==="file"?v(e.filePath):void 0;if(n==="file"&&!o)throw new Error("filePath is required");return kt(await xe({worktreePath:t,baseSha:r,expectedDiffHash:v(e.diffHash)||void 0,filePath:o,expectedPatchHash:v(e.patchHash)||void 0}))}function Sn(e){let t=!1,r=null,n=new Set,o=()=>{if(r=null,t){n.clear();return}let i=Array.from(n).sort();n.clear(),e.emitMessage?.({type:"repo.changed",payload:{watchId:e.watchId,repoPath:e.repoPath,channelId:e.channelId,changedPaths:i,changedAt:new Date().toISOString()}})},s=(i,c)=>{t||(c&&n.add(String(c)),!r&&(r=setTimeout(o,750),typeof r.unref=="function"&&r.unref()))},a;try{a=(0,N.watch)(e.repoPath,{recursive:!0},s)}catch{a=(0,N.watch)(e.repoPath,s)}return{close(){t=!0,r&&(clearTimeout(r),r=null),n.clear(),a.close()}}}function Mn(e){let t=v(e.params.watchId)||"default",r=ve(e.params),n=v(e.params.channelId);if(!n)throw new Error("channelId is required");return G.get(t)?.close(),G.delete(t),G.set(t,Sn({watchId:t,repoPath:r,channelId:n,emitMessage:e.emitMessage})),{ok:!0,watchId:t,repoPath:r,channelId:n}}function Cn(e){let t=v(e.watchId)||"default";return G.get(t)?.close(),G.delete(t),{ok:!0,watchId:t}}async function On(e){let t=U(e.request.params);if(e.request.method==="provider.updateConfig")return Un({providerFile:e.providerFile,providers:e.providers,params:U(e.request.params)});if(e.request.method==="provider.discoverModels")return Dn({providerFile:e.providerFile,providers:e.providers,params:U(e.request.params)});if(e.request.method==="repo.snapshot")return An(t);if(e.request.method==="repo.restore")return xn(t);if(e.request.method==="repo.watch")return Mn({params:t,emitMessage:e.emitMessage});if(e.request.method==="repo.unwatch")return Cn(t);if(e.request.method!=="agent.provision")throw new Error(`unsupported node request method: ${e.request.method}`);let r=v(t.workspaceId),n=v(t.agentId);if(!r||!n)throw new Error("agent.provision requires workspaceId and agentId");let{providerName:o,selectedModel:s}=Pn(t),a=e.providers[o];if(!a||!a.models.includes(s))throw new Error(`provider/model is not available on this node: ${o}/${s}`);let i=ue({truesayerNodeHome:e.truesayerNodeHome,workspaceId:r,agentId:n});return{ok:!0,agentId:n,providerName:o,selectedModel:s,providerHome:i.providerHome,agentRoot:i.agentRoot,spaceRoot:i.spaceRoot,profileDir:i.profileDir,providerHomeExposedToFileTools:!1}}function wt(e,t){(0,N.writeFileSync)(e,`${JSON.stringify(t,null,2)}
31
- `,{mode:384}),yt(e)}async function Dn(e){let t=v(e.params.providerName)||v(e.params.providerId);if(!t)throw new Error("provider.discoverModels requires providerName");let r=e.providers[t];if(!r)throw new Error(`provider is not available on this node: ${t}`);if(r.source!=="provider-file")throw new Error(`provider model discovery is not editable on this node: ${t}`);if(!e.providerFile?.trim())throw new Error("provider.discoverModels requires provider file");let o=ie(e.providerFile)[t];if(!o||o.source!=="provider-file")throw new Error(`provider not found in provider file: ${t}`);let s=await he(t,o),a=ye(e.providerFile),i=a.providers,c=i[t];if(!c||typeof c!="object"||Array.isArray(c))throw new Error(`provider not found in provider file: ${t}`);return i[t]={...c,models:s},wt(e.providerFile,a),e.providers[t]={...r,models:s,modelsDiscoveredBy:"api-probe"},{ok:!0,providerName:t,models:s,source:"api-probe"}}function ye(e){let t;try{t=JSON.parse((0,N.readFileSync)(e,"utf8"))}catch{throw new Error(`provider file is not valid JSON: ${e}`)}if(!t||typeof t!="object"||Array.isArray(t))throw new Error("provider file must be a JSON object");let r=t;if(!r.providers||typeof r.providers!="object"||Array.isArray(r.providers))throw new Error("provider file must contain a providers object");return r}function Un(e){let t=v(e.params.providerName)||v(e.params.providerId);if(!t)throw new Error("provider.updateConfig requires providerName");let r=e.providers[t];if(r&&(r.source!=="provider-file"||r.configEditable!==!0))throw new Error(`provider is not editable on this node: ${t}`);if(!e.providerFile?.trim())throw new Error("provider.updateConfig requires provider file");let n=Object.prototype.hasOwnProperty.call(e.params,"baseUrl"),o=Object.prototype.hasOwnProperty.call(e.params,"apiKey"),s=Object.prototype.hasOwnProperty.call(e.params,"kind"),a=Object.prototype.hasOwnProperty.call(e.params,"models"),i=Object.prototype.hasOwnProperty.call(e.params,"defaultModel"),c=Object.prototype.hasOwnProperty.call(e.params,"anthropicDefaultOpusModel"),p=Object.prototype.hasOwnProperty.call(e.params,"anthropicDefaultSonnetModel"),k=Object.prototype.hasOwnProperty.call(e.params,"anthropicDefaultHaikuModel");if(!s&&!n&&!o&&!a&&!i&&!c&&!p&&!k)throw new Error("provider.updateConfig requires at least one provider config field");let b=ye(e.providerFile),m=b.providers,y=m[t];if(y&&(typeof y!="object"||Array.isArray(y)))throw new Error(`provider not found in provider file: ${t}`);if(!r&&!s)throw new Error("provider.updateConfig requires kind when creating a provider");let d=y?{...y}:{kind:v(e.params.kind),displayName:v(e.params.displayName)||t};if(s){let f=v(e.params.kind);if(!["claude-compatible","openai-compatible"].includes(f))throw new Error("unsupported provider kind");d.kind=f}if(n){let f=v(e.params.baseUrl);if(!f)throw new Error("baseUrl cannot be empty");d.baseUrl=f}if(o){let f=v(e.params.apiKey);if(!f)throw new Error("apiKey cannot be empty");d.apiKey=f}if(a){let f=oe(Array.isArray(e.params.models)?e.params.models.filter(l=>typeof l=="string"):[]);if(f.length===0)throw new Error("models cannot be empty");d.models=f}if(i){let f=v(e.params.defaultModel);f?d.defaultModel=f:delete d.defaultModel}if(c){let f=v(e.params.anthropicDefaultOpusModel);if(!f)throw new Error("anthropicDefaultOpusModel cannot be empty");d.ANTHROPIC_DEFAULT_OPUS_MODEL=f}if(p){let f=v(e.params.anthropicDefaultSonnetModel);f?d.ANTHROPIC_DEFAULT_SONNET_MODEL=f:delete d.ANTHROPIC_DEFAULT_SONNET_MODEL}if(k){let f=v(e.params.anthropicDefaultHaikuModel);f?d.ANTHROPIC_DEFAULT_HAIKU_MODEL=f:delete d.ANTHROPIC_DEFAULT_HAIKU_MODEL}m[t]=d,wt(e.providerFile,b);let g=typeof d.kind=="string"?d.kind:r?.kind??"openai-compatible",h=Array.isArray(d.models)?d.models.filter(f=>typeof f=="string"):r?.models??[];return e.providers[t]={kind:g,displayName:typeof d.displayName=="string"?d.displayName:r?.displayName??t,source:"provider-file",models:h,modelsDiscoveredBy:r?.modelsDiscoveredBy??(h.length>0?"provider-file":"api-probe"),...typeof d.baseUrl=="string"?{baseUrl:d.baseUrl}:{},configEditable:!0,...K(typeof d.apiKey=="string"?d.apiKey:void 0)?{apiKeyPreview:K(typeof d.apiKey=="string"?d.apiKey:void 0)}:{},...typeof d.defaultModel=="string"?{defaultModel:d.defaultModel}:{},...typeof d.ANTHROPIC_DEFAULT_OPUS_MODEL=="string"?{anthropicDefaultOpusModel:d.ANTHROPIC_DEFAULT_OPUS_MODEL}:{},...typeof d.ANTHROPIC_DEFAULT_SONNET_MODEL=="string"?{anthropicDefaultSonnetModel:d.ANTHROPIC_DEFAULT_SONNET_MODEL}:{},...typeof d.ANTHROPIC_DEFAULT_HAIKU_MODEL=="string"?{anthropicDefaultHaikuModel:d.ANTHROPIC_DEFAULT_HAIKU_MODEL}:{}},{ok:!0,providerName:t,...s?{kind:g}:{},apiKeyPreview:K(typeof d.apiKey=="string"?d.apiKey:void 0)??null,...a?{models:Array.isArray(d.models)?d.models:[]}:{},...i?{defaultModel:typeof d.defaultModel=="string"?d.defaultModel:null}:{},...k?{anthropicDefaultHaikuModel:typeof d.ANTHROPIC_DEFAULT_HAIKU_MODEL=="string"?d.ANTHROPIC_DEFAULT_HAIKU_MODEL:null}:{},...p?{anthropicDefaultSonnetModel:typeof d.ANTHROPIC_DEFAULT_SONNET_MODEL=="string"?d.ANTHROPIC_DEFAULT_SONNET_MODEL:null}:{},...c?{anthropicDefaultOpusModel:typeof d.ANTHROPIC_DEFAULT_OPUS_MODEL=="string"?d.ANTHROPIC_DEFAULT_OPUS_MODEL:null}:{},needsRestart:!0}}var Fn=/api[-_]?key|secret|token|password|authorization|base[-_]?url|api[-_]?url/i;function se(e,t=0){if(t>6)return"[redacted:depth]";if(Array.isArray(e))return e.map(n=>se(n,t+1));if(!e||typeof e!="object")return typeof e=="string"&&e.length>1e3?`${e.slice(0,1e3)}...`:e;let r={};for(let[n,o]of Object.entries(e))r[n]=Fn.test(n)?"[redacted]":se(o,t+1);return r}function Hn(e){if(["opus","sonnet","haiku"].includes(e.selectedModel))return e.selectedModel;let t=e.providerFile?.trim()?ie(e.providerFile)[e.providerName]:void 0,r=e.provider.anthropicDefaultOpusModel??t?.anthropicDefaultOpusModel,n=e.provider.anthropicDefaultSonnetModel??t?.anthropicDefaultSonnetModel,o=e.provider.anthropicDefaultHaikuModel??t?.anthropicDefaultHaikuModel;return e.selectedModel===n?"sonnet":e.selectedModel===o?"haiku":e.selectedModel===r||r?"opus":e.selectedModel}function Ln(e){return e.provider.kind==="claude-code"||e.provider.kind==="claude-compatible"?Hn(e):e.selectedModel}function pt(e){return e==="default"||e==="none"||e==="minimal"||e==="low"||e==="medium"||e==="high"||e==="xhigh"||e==="max"?e:void 0}function mt(e){return e==="default"||e==="disabled"||e==="adaptive"?e:void 0}function gt(e){return e==="default"||e==="fast"||e==="flex"?e:void 0}function $n(e){let t=U(e);if(t.type!=="agent_run.assigned")return null;let r=v(t.agentRunId),n=U(t.payload),o=U(n.runtimeSelection),s=v(n.workspaceId),a=v(n.agentId),i=v(n.agentSessionId),c=v(n.prompt),p=v(o.providerName),k=v(o.selectedModel);return!r||!s||!a||!i||!c||!p||!k?null:{type:"agent_run.assigned",agentRunId:r,payload:{workspaceId:s,agentId:a,agentSessionId:i,channelId:v(n.channelId)||null,systemPrompt:v(n.systemPrompt)||null,prompt:c,toolMode:v(n.toolMode)==="silent_relevance"?"silent_relevance":"full",repoAlias:v(n.repoAlias)||"default",repoPath:v(n.repoPath)||null,baseBranch:v(n.baseBranch)||null,runtimeSelection:{providerName:p,selectedModel:k,...pt(o.reasoningEffort)?{reasoningEffort:pt(o.reasoningEffort)}:{},...mt(o.thinkingMode)?{thinkingMode:mt(o.thinkingMode)}:{},...gt(o.serviceTier)?{serviceTier:gt(o.serviceTier)}:{}}}}}function jn(e){switch(e.kind){case"claude-code":case"claude-compatible":return Je;case"codex":case"openai-compatible":return it;default:return async()=>{throw new Error(`unsupported node provider kind: ${e.kind}`)}}}function qn(e){return{type:"agent_run.rejected",agentRunId:e.agentRunId,payload:{reason:"capability_mismatch",providerName:e.payload.runtimeSelection.providerName,selectedModel:e.payload.runtimeSelection.selectedModel}}}function Bn(e){return["<truesayer_workspace_context>",`Current channel worktree root: ${e.cwd}`,e.worktreePath?`Node-managed worktree path: ${e.worktreePath}`:null,e.repoPath?`Source repository path: ${e.repoPath}`:null,"Treat the current channel as the active repository workspace. Unless the user explicitly says otherwise, repository modifications may span the whole worktree.","</truesayer_workspace_context>","",e.prompt].filter(r=>!!r).join(`
32
- `)}async function Wn(e){let{providerName:t,selectedModel:r}=e.message.payload.runtimeSelection,n=e.providers[t];if(!n||!n.models.includes(r)){let d=qn(e.message);return await e.emitMessage?.(d),{messages:[d]}}let o=Oe({truesayerNodeHome:e.truesayerNodeHome,workspaceId:e.message.payload.workspaceId,agentId:e.message.payload.agentId,agentSessionId:e.message.payload.agentSessionId,agentRunId:e.message.agentRunId,repoAlias:e.message.payload.repoAlias||"default"}),s=o.worktreeDir,a={cwd:s};if(e.message.payload.repoPath){let d=await Ie({actionId:e.message.agentRunId,baseBranch:e.message.payload.baseBranch||"main",repoPath:e.message.payload.repoPath,worktreePath:o.worktreeDir});s=d.path,a.cwd=s,a.repoPath=e.message.payload.repoPath,a.worktreePath=d.path,a.branch=d.branch,a.baseSha=d.baseSha,a.baseRef=d.baseRef,a.headSha=await Pe(d.path)}else a.worktreePath=o.worktreeDir;let i=Bn({prompt:e.message.payload.prompt,cwd:s,repoPath:e.message.payload.repoPath,worktreePath:v(a.worktreePath)}),c=[],p=async d=>{c.push(d),await e.emitMessage?.(d)},k=1,b=0,m=async(d,g)=>{k+=1,await p({type:"agent_run.event_batch",agentRunId:e.message.agentRunId,payload:{events:[{eventId:`${e.message.agentRunId}:event:${k}`,eventSeq:k,type:d,payload:g}]}})},y=e.invokeTool?async d=>{b+=1;let g=d.toolCallId||`${e.message.agentRunId}:tool:${b}`;await m("agent_run.tool.started",{toolCallId:g,toolName:d.toolName,status:"started",args:se(d.args)});try{let h=await e.invokeTool({...d,toolCallId:g});return await m("agent_run.tool.completed",{toolCallId:g,toolName:d.toolName,status:"completed",result:se(h)}),h}catch(h){throw await m("agent_run.tool.failed",{toolCallId:g,toolName:d.toolName,status:"failed",error:h instanceof Error?h.message:String(h)}),h}}:void 0;await p({type:"agent_run.accepted",agentRunId:e.message.agentRunId,payload:{agentId:e.message.payload.agentId,agentSessionId:e.message.payload.agentSessionId,providerName:t,selectedModel:r}}),await p({type:"agent_run.event_batch",agentRunId:e.message.agentRunId,payload:{events:[{eventId:`${e.message.agentRunId}:workspace-prepared`,eventSeq:1,type:"agent_run.workspace_prepared",payload:{workspacePrepared:!0,fileToolRoot:"space",providerHomeExposedToFileTools:!1,...a}}]}});try{let d=e.runProviderAgent??jn(n),g;try{g=await d({agentRunId:e.message.agentRunId,agentId:e.message.payload.agentId,agentSessionId:e.message.payload.agentSessionId,prompt:i,toolMode:e.message.payload.toolMode,provider:n,availableProviders:e.providers,providerName:t,selectedModel:Ln({providerFile:e.providerFile,providerName:t,provider:n,selectedModel:r}),reasoningEffort:e.message.payload.runtimeSelection.reasoningEffort,thinkingMode:e.message.payload.runtimeSelection.thinkingMode,serviceTier:e.message.payload.runtimeSelection.serviceTier,cwd:s,env:bn({...o.providerEnv,...En(e.providerFile,t)}),sessionStateDir:o.contextDir,systemPrompt:e.message.payload.systemPrompt??void 0,invokeTool:y,emitEvent:async f=>{await p({type:"agent_run.event_batch",agentRunId:e.message.agentRunId,payload:{events:[f]}})}})}catch(f){let l=f instanceof Error?f:void 0,w=l?.emittedEventIds??new Set,C=(l?.events??[]).filter(T=>!w.has(T.eventId));throw C.length&&await p({type:"agent_run.event_batch",agentRunId:e.message.agentRunId,payload:{events:C}}),f}let h=ln(g);h.length&&await p({type:"agent_run.event_batch",agentRunId:e.message.agentRunId,payload:{events:h}}),await p({type:"agent_run.completed",agentRunId:e.message.agentRunId,payload:{output:g.output,...g.inputTokens===void 0?{}:{inputTokens:g.inputTokens},...g.outputTokens===void 0?{}:{outputTokens:g.outputTokens}}})}catch(d){await p({type:"agent_run.failed",agentRunId:e.message.agentRunId,payload:{error:d instanceof Error?d.message:String(d)}})}return{layout:o,messages:c}}function Kn(e,t){let r=new URL(e);return r.protocol=r.protocol==="https:"?"wss:":"ws:",r.pathname="/api/nodes/ws",r.search="",r.searchParams.set("apiKey",t),r.toString()}function Gn(){let e=globalThis.WebSocket;if(!e)throw new Error("global WebSocket is not available; run with Node 22+ or pass WebSocketImpl");return e}function ft(e){e.readyState===1&&e.send(JSON.stringify({type:"node.heartbeat"}))}function Jn(e){ft(e);let t=setInterval(()=>{ft(e)},un);return typeof t.unref=="function"&&t.unref(),()=>clearInterval(t)}async function bt(e){let t=e.WebSocketImpl??Gn(),r=fn(e.providerFile??Me(e.truesayerNodeHome)),n=await hn({providerFile:r,probeProviderModels:e.probeProviderModels}),o=yn({...e,providerFile:r},n),s=new t(Kn(e.serverUrl,e.apiKey)),a=In(s),i=new Set;await new Promise((c,p)=>{let k=!1,b=null;s.addEventListener("open",()=>{s.send(JSON.stringify(o))}),s.addEventListener("message",m=>{let y=typeof m.data=="string"?m.data:"";try{let d=JSON.parse(y);if(a.handleJsonRpcMessage(d))return;if(Rn(d)){(async()=>{try{let h=await On({truesayerNodeHome:e.truesayerNodeHome,providerFile:r,providers:n,request:d,runProviderAgent:e.runProviderAgent,emitMessage:f=>{s.send(JSON.stringify(f))}});s.send(Tn(d.id,h))}catch(h){s.send(Nn(d.id,h instanceof Error?h.message:String(h)))}})();return}if(d.type==="node.ready"){k=!0,b??=Jn(s);return}let g=$n(d);if(g){if(i.has(g.agentRunId))return;i.add(g.agentRunId),Wn({truesayerNodeHome:e.truesayerNodeHome,providerFile:r,providers:n,message:g,invokeTool:a.invokeTool,runProviderAgent:e.runProviderAgent,emitMessage:h=>{s.send(JSON.stringify(h))}}).catch(h=>{s.send(JSON.stringify({type:"agent_run.failed",agentRunId:g.agentRunId,payload:{error:h instanceof Error?h.message:String(h)}}))})}}catch{}}),s.addEventListener("error",m=>{b?.(),b=null,p(new Error(`node ws error: ${String(m)}`))}),s.addEventListener("close",()=>{b?.(),b=null,a.rejectPending(new Error("node websocket closed")),k?c():p(new Error("node ws closed before node.ready"))})})}var zn=["DATABASE_URL","TRUESAYER_API_KEY","TRUESAYER_ADMIN_API_KEY","BETTER_AUTH_SECRET","ASSET_STORAGE_DRIVER","S3_ENDPOINT","S3_BUCKET","S3_ACCESS_KEY_ID","S3_SECRET_ACCESS_KEY","S3_REGION","S3_FORCE_PATH_STYLE"];function ae(e){let t=`${e}=`,r=process.argv.find(o=>o.startsWith(t));if(r)return r.slice(t.length);let n=process.argv.indexOf(e);if(n>=0)return process.argv[n+1]}function Yn(...e){return process.argv.some(t=>e.includes(t))}function Vn(){let e=zn.filter(t=>process.env[t]?.trim());if(e.length>0)throw new Error(`forbidden Server-only env present in Node process: ${e.join(", ")}`)}function Xn(){let e=Number(process.versions.node.split(".")[0]);if(!Number.isFinite(e)||e<22)throw new Error(`truesayer-node requires Node.js >=22. Current: ${process.version}`)}function Et(){return"Usage: truesayer-node --server <url> --api-key <key> [--node-name <name>] [--node-home <path>]"}function _t(){if(process.env.npm_package_version)return process.env.npm_package_version;try{let e=JSON.parse((0,Rt.readFileSync)((0,Tt.join)(__dirname,"..","package.json"),"utf8"));return typeof e.version=="string"&&e.version.trim()?e.version:"0.1.0"}catch{return"0.1.0"}}async function Zn(){if(Yn("--version","-v")){console.log(_t());return}Xn(),Vn();let e=ae("--server")??process.env.SERVER_URL,t=ae("--api-key")??process.env.NODE_API_KEY,r=ae("--node-name")??process.env.NODE_NAME??"truesayer-node",n=ae("--node-home")??process.env.TRUESAYER_NODE_HOME;if(!e)throw new Error(`--server or SERVER_URL is required
33
- ${Et()}`);if(!t)throw new Error(`--api-key or NODE_API_KEY is required
34
- ${Et()}`);await bt({serverUrl:e,apiKey:t,nodeName:r,nodeVersion:_t(),truesayerNodeHome:n})}Zn().catch(e=>{console.error("[node] Fatal:",e instanceof Error?e.message:String(e)),process.exit(1)});
34
+ `)}function Hn(e){return e.prompt}function ke(e){return JSON.stringify(e)}function $n(e){return/^[A-Za-z0-9_-]+$/.test(e)?e:ke(e)}function qn(e){if(e.provider.source!=="provider-file"||e.provider.kind!=="codex"&&e.provider.kind!=="openai-compatible")return[];let t=e.provider.baseUrl?.trim()||e.env.OPENAI_BASE_URL?.trim();if(!t)return[];let r=e.providerName.trim();if(!r)return[];let n=[`name=${ke(e.provider.displayName||r)}`,`base_url=${ke(t)}`,'wire_api="responses"','env_key="OPENAI_API_KEY"',"requires_openai_auth=false","supports_websockets=false"].join(",");return["-c",`model_provider=${ke(r)}`,"-c",`model_providers.${$n(r)}={${n}}`]}function jn(e){return e===void 0?null:e}function Wn(e){return e&&typeof e=="object"&&!Array.isArray(e)?Fe.z.toJSONSchema(Fe.z.object(e)):{type:"object",properties:{},additionalProperties:!0}}function Gn(e){if(!e.invokeTool)return null;let t=De(e.agentRunId,e.invokeTool),r=new Map;return{dynamicTools:t.map(o=>{let s=o.handler;return r.set(o.name,async a=>s(a)),{namespace:"truesayer",name:o.name,description:o.description,inputSchema:jn(Wn(o.inputSchema)),deferLoading:!1}}),handlers:r}}function Bn(e){let t=N(e).content;if(Array.isArray(t)){let r=t.map(N).map(n=>$e(n.text)).filter(Boolean).join(`
35
+ `);if(r)return r}return JSON.stringify(e??{})}async function Jn(e,t){if(e.method!=="item/tool/call")throw new Error(`Unsupported Codex app-server request: ${e.method}`);if(!t)return{contentItems:[{type:"inputText",text:"Truesayer platform tools are not available for this run."}],success:!1};let r=S(e.params?.tool),n=t.handlers.get(r);if(!n)return{contentItems:[{type:"inputText",text:`Unknown Truesayer platform tool: ${r||"(missing)"}`}],success:!1};try{let o=N(e.params?.arguments),s=await n(o);return{contentItems:[{type:"inputText",text:Bn(s)}],success:!0}}catch(o){return{contentItems:[{type:"inputText",text:o instanceof Error?o.message:String(o)}],success:!1}}}function Kn(e){let t=N(e),r=N(t.last),n=N(t.total);return{inputTokens:we(r.input_tokens,r.inputTokens,r.prompt_tokens,r.promptTokens,n.input_tokens,n.inputTokens,n.prompt_tokens,n.promptTokens,t.input_tokens,t.inputTokens,t.prompt_tokens,t.promptTokens),outputTokens:we(r.output_tokens,r.outputTokens,r.completion_tokens,r.completionTokens,n.output_tokens,n.outputTokens,n.completion_tokens,n.completionTokens,t.output_tokens,t.outputTokens,t.completion_tokens,t.completionTokens)}}function ne(e){return typeof e=="number"&&Number.isFinite(e)?e:void 0}function we(...e){for(let t of e){let r=ne(t);if(r!==void 0)return Math.max(0,Math.trunc(r))}}function zn(e){let t=N(e),r=N(t.usage),n=N(t.tokenUsage),o=N(t.token_usage),s=N(t.tokens),a=N(t.usageSummary);return{inputTokens:we(r.input_tokens,r.inputTokens,r.prompt_tokens,r.promptTokens,n.input_tokens,n.inputTokens,n.prompt_tokens,n.promptTokens,o.input_tokens,o.inputTokens,o.prompt_tokens,o.promptTokens,s.input_tokens,s.inputTokens,s.prompt_tokens,s.promptTokens,a.input_tokens,a.inputTokens,t.input_tokens,t.inputTokens,t.total_input_tokens,t.prompt_tokens,t.promptTokens),outputTokens:we(r.output_tokens,r.outputTokens,r.completion_tokens,r.completionTokens,n.output_tokens,n.outputTokens,n.completion_tokens,n.completionTokens,o.output_tokens,o.outputTokens,o.completion_tokens,o.completionTokens,s.output_tokens,s.outputTokens,s.completion_tokens,s.completionTokens,a.output_tokens,a.outputTokens,t.output_tokens,t.outputTokens,t.total_output_tokens,t.completion_tokens,t.completionTokens),costUsd:ne(t.total_cost_usd)??ne(t.cost_usd)??ne(r.total_cost_usd)??ne(r.cost_usd)}}function kt(...e){let t={};for(let r of e)r&&(r.inputTokens!==void 0&&(t.inputTokens=r.inputTokens),r.outputTokens!==void 0&&(t.outputTokens=r.outputTokens),"costUsd"in r&&r.costUsd!==void 0&&(t.costUsd=r.costUsd));return t}function Vn(e,t){let r=[],n=new Set,o=new Map,s=new Map,a=new Map,i=new Map,c=2,m="",v=null,l=null;function f(p){r.push(p),!n.has(p.eventId)&&(n.add(p.eventId),e.emitEvent?.(p))}function y(p,g){f({eventId:`${e.agentRunId}:codex:${c}`,eventSeq:c,type:`agent_run.provider_request.${p}`,payload:{provider:"codex",...g}}),c+=1}function d(p){let g=An(p);g&&(f({eventId:`${e.agentRunId}:codex:${c}`,eventSeq:c,type:g.type,payload:g.payload}),c+=1)}function k(p,g={}){let T={output:m.trim()||"Codex run completed",...g.inputTokens===void 0?{}:{inputTokens:g.inputTokens},...g.outputTokens===void 0?{}:{outputTokens:g.outputTokens}};a.set(p,T);let _=i.get(p)??[];i.delete(p);for(let E of _)E.resolve(T)}function b(p){for(let g of i.values())for(let A of g)A.reject(p);i.clear()}function R(p){e.emitRawEvent?.(p);let g=p.params??{},A=Et(p),T=xn(p);if(p.method==="item/agentMessage/delta"){let E=S(g.itemId),O=S(g.delta);if(E&&O){let j=`${o.get(E)??""}${O}`;o.set(E,j),m=j}}if(p.method==="item/completed"){let E=N(g.item);if(E.type==="agentMessage"){let O=S(E.text);O&&(m=O)}}if(p.method==="turn/completed"){let E=N(g.turn),O=S(E.id),j=S(E.status);O&&j==="completed"&&k(O,kt(s.get(O),zn(E)))}if(p.method==="thread/tokenUsage/updated"){let E=S(g.turnId);E&&s.set(E,kt(s.get(E),Kn(g.tokenUsage)))}d(p);let _=A??T;_&&(v=_,b(_))}let w=Tt({cwd:e.cwd,env:e.env,args:qn(e),requestTimeoutMs:Cn(e.env),onNotification:R,onServerRequest:p=>Jn(p,t),onRequestEvent:y,onExit(p){l=p,b(p)}});return{events:r,emittedEventIds:n,stderrTail:w.stderrTail,request:w.request,notify:w.notify,close:w.close,waitForTurnCompleted(p){let g=a.get(p);return g!==void 0?Promise.resolve(g):v?Promise.reject(v):l?Promise.reject(l):(y("started",{method:"turn/completed",turnId:p}),new Promise((A,T)=>{let _={resolve:A,reject:T},E=i.get(p)??[];E.push(_),i.set(p,E)}))}}}function Yn(e){let t=S(N(N(e).thread).id);if(!t)throw new Error("Codex app-server did not return a thread id");return t}function Xn(e){let t=S(N(N(e).turn).id);if(!t)throw new Error("Codex app-server did not return a turn id");return t}async function It(e){if(e.provider.kind!=="codex"&&e.provider.kind!=="openai-compatible")throw new Error(`unsupported node provider kind: ${e.provider.kind}`);let t=Gn(e),r=Vn(e,t),n=e.provider.source==="provider-file"?e.providerName:void 0,o={...e.reasoningEffort&&e.reasoningEffort!=="default"?{reasoningEffort:e.reasoningEffort}:{},...e.serviceTier&&e.serviceTier!=="default"?{serviceTier:e.serviceTier}:{}},s=Fn(e),a=()=>{};try{if(e.abortSignal?.aborted)throw new Error("Interrupted by user");await r.request("initialize",{clientInfo:{name:"truesayer-node",title:"Truesayer Node",version:"0.1.0"},capabilities:{experimentalApi:!0,optOutNotificationMethods:[]}}),r.notify("initialized");let i=On(e.sessionStateDir),c=i.threadId;if(t&&i.platformToolsVersion!==_t&&(c=void 0),c)await r.request("thread/resume",{threadId:c,model:e.selectedModel,...n?{modelProvider:n}:{},cwd:e.cwd,approvalPolicy:"never",sandbox:"danger-full-access",experimentalRawEvents:!1,excludeTurns:!0,persistExtendedHistory:!0,developerInstructions:s,...t?{dynamicTools:t.dynamicTools}:{},...o});else{let y=await r.request("thread/start",{model:e.selectedModel,...n?{modelProvider:n}:{},cwd:e.cwd,approvalPolicy:"never",sandbox:"danger-full-access",experimentalRawEvents:!1,persistExtendedHistory:!0,developerInstructions:s,...t?{dynamicTools:t.dynamicTools}:{},...o});c=Yn(y),Un(e.sessionStateDir,c,t)}let m=await r.request("turn/start",{threadId:c,input:[{type:"text",text:Hn(e),text_elements:[]}],cwd:e.cwd,approvalPolicy:"never",model:e.selectedModel,...o}),v=Xn(m),l=e.abortSignal?new Promise((y,d)=>{let k=()=>{r.request("turn/interrupt",{threadId:c,turnId:v}).catch(()=>{}),d(new Error("Interrupted by user"))};e.abortSignal?.addEventListener("abort",k,{once:!0}),a=()=>e.abortSignal?.removeEventListener("abort",k)}):null,f=await(l?Promise.race([r.waitForTurnCompleted(v),l]):r.waitForTurnCompleted(v));return{output:f.output.trim()||"Codex run completed",...f.inputTokens===void 0?{}:{inputTokens:f.inputTokens},...f.outputTokens===void 0?{}:{outputTokens:f.outputTokens},events:r.events,emittedEventIds:r.emittedEventIds}}catch(i){throw i instanceof Error&&(i.events=r.events,i.emittedEventIds=r.emittedEventIds),i}finally{a(),r.close()}}function be(e){return Array.from(new Set(e.map(t=>t.trim()).filter(Boolean)))}function qe(e){return typeof e=="object"&&e!==null?e:void 0}function Pt(e){return typeof e=="string"&&e.trim()?e.trim():void 0}function Zn(e){return e.replace(/\/+$/,"")}function At(e,t){let r=Zn(e);return t==="v1/models"&&/\/v1$/i.test(r)?`${r}/models`:`${r}/${t}`}function Qn(e){if(!e.baseUrl?.trim()||!e.apiKey?.trim())return[];let t=e.kind.toLowerCase(),r=e.baseUrl.trim(),n=[];return(t.includes("claude")||t.includes("anthropic"))&&n.push({url:At(r,"v1/models"),auth:"anthropic"}),(t.includes("openai")||t==="codex")&&n.push({url:At(r,"models"),auth:"bearer"}),n.filter((o,s,a)=>a.findIndex(i=>i.url===o.url)===s)}function eo(e){let t=qe(e);return Pt(t?.id)??Pt(t?.model)}function to(e){let t=qe(e)?.data;if(!Array.isArray(t))return[];let r=t.flatMap(s=>{let a=eo(s);if(!a)return[];let i=qe(s),c=typeof i?.created=="number"?i.created:typeof i?.created_at=="number"?i.created_at:void 0;return[{id:a,created:c}]}),o=r.some(s=>s.created!==void 0)?[...r].sort((s,a)=>(a.created??Number.NEGATIVE_INFINITY)-(s.created??Number.NEGATIVE_INFINITY)):r;return be(o.map(s=>s.id))}async function ro(e,t){let r={accept:"application/json"};e.auth==="anthropic"?(r["x-api-key"]=t,r["anthropic-version"]="2023-06-01"):r.authorization=`Bearer ${t}`;let n=await fetch(e.url,{method:"GET",headers:r});if(!n.ok)throw new Error(`HTTP ${n.status}`);let o=to(await n.json().catch(()=>null));if(o.length===0)throw new Error("response did not contain model ids");return o}async function je(e,t){let r=t.apiKey?.trim();if(!r)throw new Error(`provider ${e} cannot discover models without an API key`);let n=Qn(t);if(n.length===0)throw new Error(`provider ${e} cannot discover models without a supported baseUrl`);let o=[];for(let s of n)try{return await ro(s,r)}catch(a){o.push(`${s.url}: ${a instanceof Error?a.message:String(a)}`)}throw new Error(`provider ${e} model discovery failed: ${o.join("; ")}`)}async function xt(e,t){if(t.source==="provider-file"&&t.models?.length)return be(t.models);if(t.source==="provider-file")try{return await je(e,t)}catch(r){return console.warn(`[node] provider ${e} model discovery unavailable:`,r instanceof Error?r.message:String(r)),[]}if(t.source!=="native")return[];try{if(e==="local-claude-code"&&t.kind==="claude-code")return await lt();if(e==="local-codex"&&t.kind==="codex")return await Nt()}catch(r){console.warn(`[node] provider ${e} unavailable:`,r instanceof Error?r.message:String(r))}return[]}var $t=V(require("ws")),no=15e3;function oo(e){let t=e.emittedEventIds??new Set;return(e.events??[]).filter(r=>!t.has(r.eventId))}var Ct={"local-claude-code":{kind:"claude-code",displayName:"Local Claude Code",source:"native"},"local-codex":{kind:"codex",displayName:"Local Codex",source:"native"}};function so(e){return e.split(/[-_\s]+/).filter(Boolean).map(t=>`${t[0]?.toUpperCase()??""}${t.slice(1)}`).join(" ")}function io(e){if(!e?.trim()||!(0,x.existsSync)(e))return{};ao(e);let t;try{t=JSON.parse((0,x.readFileSync)(e,"utf8"))}catch{throw new Error(`provider file is not valid JSON: ${e}`)}let r=t&&typeof t=="object"&&!Array.isArray(t)&&t.providers&&typeof t.providers=="object"&&!Array.isArray(t.providers)?t.providers:{},n={};for(let[o,s]of Object.entries(r)){let a=o.trim();if(!a||!s||typeof s!="object"||Array.isArray(s))continue;let i=s,c=typeof i.kind=="string"&&i.kind.trim()?i.kind.trim():"openai-compatible",m=typeof i.displayName=="string"&&i.displayName.trim()?i.displayName.trim():so(a),v=Array.isArray(i.models)?Array.from(new Set(i.models.filter(b=>typeof b=="string"&&b.trim().length>0).map(b=>b.trim()))):void 0,l=typeof i.apiKey=="string"&&i.apiKey.trim()?i.apiKey.trim():void 0,f=typeof i.baseUrl=="string"&&i.baseUrl.trim()?i.baseUrl.trim():void 0,y=typeof i.ANTHROPIC_DEFAULT_HAIKU_MODEL=="string"&&i.ANTHROPIC_DEFAULT_HAIKU_MODEL.trim()?i.ANTHROPIC_DEFAULT_HAIKU_MODEL.trim():void 0,d=typeof i.ANTHROPIC_DEFAULT_SONNET_MODEL=="string"&&i.ANTHROPIC_DEFAULT_SONNET_MODEL.trim()?i.ANTHROPIC_DEFAULT_SONNET_MODEL.trim():void 0,k=typeof i.ANTHROPIC_DEFAULT_OPUS_MODEL=="string"&&i.ANTHROPIC_DEFAULT_OPUS_MODEL.trim()?i.ANTHROPIC_DEFAULT_OPUS_MODEL.trim():void 0;n[a]={kind:c,displayName:m,source:"provider-file",...Mt(c,v)?.length?{models:Mt(c,v)}:{},...l?{apiKey:l}:{},...f?{baseUrl:f}:{},...y?{anthropicDefaultHaikuModel:y}:{},...d?{anthropicDefaultSonnetModel:d}:{},...k?{anthropicDefaultOpusModel:k}:{}}}return n}function ao(e){if(process.platform!=="win32")try{((0,x.statSync)(e).mode&63)!==0&&console.warn(`[node] provider file permissions are too broad; run chmod 600 ${e}`)}catch{return}}function qt(e){process.platform!=="win32"&&(0,x.chmodSync)(e,384)}function co(e){return(0,x.mkdirSync)((0,M.dirname)(e),{recursive:!0,mode:448}),(0,x.existsSync)(e)||(0,x.writeFileSync)(e,`${JSON.stringify({providers:{}},null,2)}
36
+ `,{mode:384}),qt(e),Ge(e),e}function Mt(e,t){if(!t?.length)return;if(!e.toLowerCase().includes("claude"))return t;let r=t.filter(n=>!["haiku","sonnet","opus"].includes(n.trim().toLowerCase()));return r.length>0?r:void 0}function se(e){if(!e)return;let t=e.trim();if(t)return t.length>8?`${t.slice(0,4)}***${t.slice(-4)}`:`${t.slice(0,4)}***`}function _e(e){let t=io(e);for(let r of Object.keys(t))if(Ct[r])throw new Error(`duplicate provider name: ${r}`);return{...Ct,...t}}async function uo(e={}){let t=_e(e.providerFile),r={},n=e.probeProviderModels??xt,o=await Promise.all(Object.entries(t).map(async([s,a])=>[s,await n(s,a,{})]));for(let[s,a]of o){let i=t[s];i&&a.length!==0&&(r[s]={kind:i.kind,displayName:i.displayName,source:i.source,models:a,modelsDiscoveredBy:i.source==="provider-file"?i.models?.length?"provider-file":"api-probe":"sdk-probe",...i.source==="provider-file"&&i.baseUrl?{baseUrl:i.baseUrl}:{},...i.source==="provider-file"&&se(i.apiKey)?{apiKeyPreview:se(i.apiKey)}:{},...i.source==="provider-file"?{configEditable:!0}:{},...i.source==="provider-file"&&i.anthropicDefaultHaikuModel?{anthropicDefaultHaikuModel:i.anthropicDefaultHaikuModel}:{},...i.source==="provider-file"&&i.anthropicDefaultSonnetModel?{anthropicDefaultSonnetModel:i.anthropicDefaultSonnetModel}:{},...i.source==="provider-file"&&i.anthropicDefaultOpusModel?{anthropicDefaultOpusModel:i.anthropicDefaultOpusModel}:{}})}return r}function lo(e){return Object.fromEntries(Object.entries(e).map(([t,r])=>[t,{kind:r.kind,displayName:r.displayName,source:r.source,models:r.models,modelsDiscoveredBy:r.modelsDiscoveredBy}]))}function po(e,t){return{type:"node.hello",payload:{nodeName:e.nodeName,nodeVersion:e.nodeVersion,platform:{os:process.platform,arch:process.arch,hostname:ae.default.hostname()},capabilities:{providers:lo(t),supportsWorktrees:!0,browserE2E:(e.probeBrowserE2E??fo)()}}}}var mo={"libnss3.so":["/usr/lib/x86_64-linux-gnu/libnss3.so","/usr/lib/aarch64-linux-gnu/libnss3.so","/usr/lib64/libnss3.so"],"libatk-bridge-2.0.so.0":["/usr/lib/x86_64-linux-gnu/libatk-bridge-2.0.so.0","/usr/lib/aarch64-linux-gnu/libatk-bridge-2.0.so.0","/usr/lib64/libatk-bridge-2.0.so.0"],"libcups.so.2":["/usr/lib/x86_64-linux-gnu/libcups.so.2","/usr/lib/aarch64-linux-gnu/libcups.so.2","/usr/lib64/libcups.so.2"],"libxkbcommon.so.0":["/usr/lib/x86_64-linux-gnu/libxkbcommon.so.0","/usr/lib/aarch64-linux-gnu/libxkbcommon.so.0","/usr/lib64/libxkbcommon.so.0"],"libgbm.so.1":["/usr/lib/x86_64-linux-gnu/libgbm.so.1","/usr/lib/aarch64-linux-gnu/libgbm.so.1","/usr/lib64/libgbm.so.1"],"libasound.so.2":["/usr/lib/x86_64-linux-gnu/libasound.so.2","/usr/lib/aarch64-linux-gnu/libasound.so.2","/usr/lib64/libasound.so.2"]};function fo(){let e=process.env.TRUESAYER_NODE_BROWSER_E2E?.trim().toLowerCase();if(e==="available"||e==="unavailable"||e==="unknown")return{status:e,diagnostics:["set by TRUESAYER_NODE_BROWSER_E2E"]};if(process.platform!=="linux")return{status:"unknown",diagnostics:["automatic browser dependency detection only supports linux"]};let t=Object.entries(mo).filter(([,r])=>!r.some(n=>(0,x.existsSync)(n))).map(([r])=>r);return t.length>0?{status:"unavailable",diagnostics:t.map(r=>`missing ${r}`)}:{status:"unknown",diagnostics:["linux chromium libraries found; browser binary availability not verified"]}}function $(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}function h(e){return typeof e=="string"&&e.trim()?e.trim():""}function go(e){return te(e)}function ho(e,t){let r=e;if(!r?.trim())return{};let n=_e(r)[t];if(!n||n.source!=="provider-file")return{};let o={};return n.kind==="codex"||n.kind==="openai-compatible"?(n.apiKey&&(o.OPENAI_API_KEY=n.apiKey),n.baseUrl&&(o.OPENAI_BASE_URL=n.baseUrl),o):(n.apiKey&&(o.ANTHROPIC_API_KEY=n.apiKey),n.baseUrl&&(o.ANTHROPIC_BASE_URL=n.baseUrl),n.anthropicDefaultOpusModel&&(o.ANTHROPIC_DEFAULT_OPUS_MODEL=n.anthropicDefaultOpusModel,o.ANTHROPIC_DEFAULT_SONNET_MODEL=n.anthropicDefaultSonnetModel||n.anthropicDefaultOpusModel,o.ANTHROPIC_DEFAULT_HAIKU_MODEL=n.anthropicDefaultHaikuModel||n.anthropicDefaultOpusModel),o)}function vo(e){let t=$(e),r=t.id;return t.jsonrpc==="2.0"&&(typeof r=="string"||typeof r=="number"||r===null)&&("result"in t||"error"in t)}function yo(e){let t=$(e),r=t.id;return t.jsonrpc==="2.0"&&(typeof r=="string"||typeof r=="number"||r===null)&&typeof t.method=="string"&&t.method.trim().length>0}function ko(e,t){return JSON.stringify({jsonrpc:"2.0",id:e,result:t})}function wo(e,t){return JSON.stringify({jsonrpc:"2.0",id:e,error:{code:-32e3,message:t}})}function bo(e){let t=0,r=new Map;return{invokeTool(n){if(e.readyState!==1)throw new Error("node websocket is not open");let o=`tool:${++t}`,s={jsonrpc:"2.0",id:o,method:"tool.invoke",params:{...n,toolCallId:n.toolCallId??o}},a=new Promise((i,c)=>{r.set(o,{resolve:i,reject:c})});try{e.send(JSON.stringify(s))}catch(i){throw r.delete(o),i}return a},handleJsonRpcMessage(n){if(!vo(n)||n.id===null)return!1;let o=r.get(n.id);if(!o)return!1;if(r.delete(n.id),"error"in n&&n.error){let s=typeof n.error.message=="string"?n.error.message:"JSON-RPC tool call failed";return o.reject(new Error(s)),!0}return o.resolve(n.result),!0},rejectPending(n){for(let o of r.values())o.reject(n);r.clear()}}}function Ro(e){let t=$(e.runtimeSelection),r=h(t.providerName)||h(t.providerId),n=h(t.selectedModel)||h(t.modelId);if(!r||!n)throw new Error("agent.provision requires providerName and selectedModel");return{providerName:r,selectedModel:n}}var ie=new Map;function jt(e){let t=$(e),r=h(t.path);return r?{path:r,baseRef:h(t.baseRef)||null}:null}function Ee(e){let t=jt(e.workspaceCodeRepository);if(!t)throw new Error("workspaceCodeRepository.path is required");return t}function Dt(e){return(0,M.resolve)(e?.trim()||process.env.TRUESAYER_NODE_HOME||ae.default.homedir())}function _o(e,t){let r=e.trim();return r?r==="~"?ae.default.homedir():r.startsWith("~/")?(0,M.resolve)(ae.default.homedir(),r.slice(2)):(0,M.isAbsolute)(r)?(0,M.resolve)(r):(0,M.resolve)(Dt(t),r):Dt(t)}function Ot(e){try{return(0,x.statSync)(e).isDirectory()}catch{return!1}}function Eo(e){try{return(0,x.statSync)((0,M.join)(e,".git")).isDirectory()||(0,x.statSync)((0,M.join)(e,".git")).isFile()}catch{return!1}}function To(e,t){let r=h(e.path),n=typeof e.limit=="number"&&Number.isFinite(e.limit)?Math.trunc(e.limit):50,o=Math.min(Math.max(n,1),100),s=_o(r,t),a=/[\\/]$/.test(r),i=Ot(s)||a?s:(0,M.dirname)(s),c=Ot(s)||a?"":(0,M.basename)(s).toLowerCase(),m=[],v=null;try{m=(0,x.readdirSync)(i,{withFileTypes:!0}).filter(l=>l.isDirectory()&&l.name.toLowerCase().startsWith(c)).sort((l,f)=>l.name.localeCompare(f.name)).slice(0,o).map(l=>{let f=(0,M.join)(i,l.name);return{name:l.name,path:f,isDirectory:!0,isGitRepository:Eo(f)}})}catch(l){v=l instanceof Error?l.message:String(l)}return{path:r,basePath:i,parentPath:(0,M.dirname)(i)===i?null:(0,M.dirname)(i),entries:m,error:v}}function Wt(e){let t=e.files.reduce((n,o)=>n+o.additions,0),r=e.files.reduce((n,o)=>n+o.deletions,0);return{repoRoot:e.repoRoot,baseSha:e.baseSha,baseRef:e.baseRef,currentRef:e.currentRef,diff:e.diff,diffHash:e.diffHash,hasStagedChanges:e.hasStagedChanges,files:e.files,totalAdditions:t,totalDeletions:r,updatedAt:new Date().toISOString()}}async function No(e){let t=Ee(e);return Wt(await Y(t.path,t.baseRef??void 0))}async function So(e){let t=Ee(e),r=h(e.baseSha);if(!r)throw new Error("baseSha is required");let n=h(e.scope);if(n!=="file"&&n!=="all")throw new Error("scope must be file or all");let o=n==="file"?h(e.filePath):void 0;if(n==="file"&&!o)throw new Error("filePath is required");return Wt(await tt({worktreePath:t.path,baseSha:r,baseRef:t.baseRef,expectedDiffHash:h(e.diffHash)||void 0,filePath:o,expectedPatchHash:h(e.patchHash)||void 0}))}function Io(e){let t=!1,r=null,n=new Set,o=()=>{if(r=null,t){n.clear();return}let i=Array.from(n).sort();n.clear(),e.emitMessage?.({type:"repo.changed",payload:{watchId:e.watchId,workspaceCodeRepository:{path:e.repositoryPath},channelId:e.channelId,changedPaths:i,changedAt:new Date().toISOString()}})},s=(i,c)=>{t||(c&&n.add(String(c)),!r&&(r=setTimeout(o,750),typeof r.unref=="function"&&r.unref()))},a;try{a=(0,x.watch)(e.repositoryPath,{recursive:!0},s)}catch{a=(0,x.watch)(e.repositoryPath,s)}return{close(){t=!0,r&&(clearTimeout(r),r=null),n.clear(),a.close()}}}function Po(e){let t=h(e.params.watchId)||"default",r=Ee(e.params),n=h(e.params.channelId);if(!n)throw new Error("channelId is required");return ie.get(t)?.close(),ie.delete(t),ie.set(t,Io({watchId:t,repositoryPath:r.path,channelId:n,emitMessage:e.emitMessage})),{ok:!0,watchId:t,workspaceCodeRepository:r,channelId:n}}function Ao(e){let t=h(e.watchId)||"default";return ie.get(t)?.close(),ie.delete(t),{ok:!0,watchId:t}}async function xo(e){let t=$(e.request.params);if(e.request.method==="provider.updateConfig")return Mo({providerFile:e.providerFile,providers:e.providers,params:$(e.request.params)});if(e.request.method==="provider.discoverModels")return Co({providerFile:e.providerFile,providers:e.providers,params:$(e.request.params)});if(e.request.method==="repo.snapshot")return No(t);if(e.request.method==="repo.restore")return So(t);if(e.request.method==="channel_code_repository.prepare"){let c=Ee(t);return Ie({path:c.path,baseRef:c.baseRef})}if(e.request.method==="channel_code_repository.path_suggestions")return To(t,e.truesayerNodeHome);if(e.request.method==="repo.watch")return Po({params:t,emitMessage:e.emitMessage});if(e.request.method==="repo.unwatch")return Ao(t);if(e.request.method!=="agent.provision")throw new Error(`unsupported node request method: ${e.request.method}`);let r=h(t.workspaceId),n=h(t.agentId);if(!r||!n)throw new Error("agent.provision requires workspaceId and agentId");let{providerName:o,selectedModel:s}=Ro(t),a=e.providers[o];if(!a||!a.models.includes(s))throw new Error(`provider/model is not available on this node: ${o}/${s}`);let i=xe({truesayerNodeHome:e.truesayerNodeHome,workspaceId:r,agentId:n});return{ok:!0,agentId:n,providerName:o,selectedModel:s,providerHome:i.providerHome,agentRoot:i.agentRoot,spaceRoot:i.spaceRoot,profileDir:i.profileDir,providerHomeExposedToFileTools:!1}}function Gt(e,t){(0,x.writeFileSync)(e,`${JSON.stringify(t,null,2)}
37
+ `,{mode:384}),qt(e)}async function Co(e){let t=h(e.params.providerName)||h(e.params.providerId);if(!t)throw new Error("provider.discoverModels requires providerName");let r=e.providers[t];if(!r)throw new Error(`provider is not available on this node: ${t}`);if(r.source!=="provider-file")throw new Error(`provider model discovery is not editable on this node: ${t}`);if(!e.providerFile?.trim())throw new Error("provider.discoverModels requires provider file");let o=_e(e.providerFile)[t];if(!o||o.source!=="provider-file")throw new Error(`provider not found in provider file: ${t}`);let s=await je(t,o),a=Ge(e.providerFile),i=a.providers,c=i[t];if(!c||typeof c!="object"||Array.isArray(c))throw new Error(`provider not found in provider file: ${t}`);return i[t]={...c,models:s},Gt(e.providerFile,a),e.providers[t]={...r,models:s,modelsDiscoveredBy:"api-probe"},{ok:!0,providerName:t,models:s,source:"api-probe"}}function Ge(e){let t;try{t=JSON.parse((0,x.readFileSync)(e,"utf8"))}catch{throw new Error(`provider file is not valid JSON: ${e}`)}if(!t||typeof t!="object"||Array.isArray(t))throw new Error("provider file must be a JSON object");let r=t;if(!r.providers||typeof r.providers!="object"||Array.isArray(r.providers))throw new Error("provider file must contain a providers object");return r}function Mo(e){let t=h(e.params.providerName)||h(e.params.providerId);if(!t)throw new Error("provider.updateConfig requires providerName");let r=e.providers[t];if(r&&(r.source!=="provider-file"||r.configEditable!==!0))throw new Error(`provider is not editable on this node: ${t}`);if(!e.providerFile?.trim())throw new Error("provider.updateConfig requires provider file");let n=Object.prototype.hasOwnProperty.call(e.params,"baseUrl"),o=Object.prototype.hasOwnProperty.call(e.params,"apiKey"),s=Object.prototype.hasOwnProperty.call(e.params,"kind"),a=Object.prototype.hasOwnProperty.call(e.params,"models"),i=Object.prototype.hasOwnProperty.call(e.params,"defaultModel"),c=Object.prototype.hasOwnProperty.call(e.params,"anthropicDefaultOpusModel"),m=Object.prototype.hasOwnProperty.call(e.params,"anthropicDefaultSonnetModel"),v=Object.prototype.hasOwnProperty.call(e.params,"anthropicDefaultHaikuModel");if(!s&&!n&&!o&&!a&&!i&&!c&&!m&&!v)throw new Error("provider.updateConfig requires at least one provider config field");let l=Ge(e.providerFile),f=l.providers,y=f[t];if(y&&(typeof y!="object"||Array.isArray(y)))throw new Error(`provider not found in provider file: ${t}`);if(!r&&!s)throw new Error("provider.updateConfig requires kind when creating a provider");let d=y?{...y}:{kind:h(e.params.kind),displayName:h(e.params.displayName)||t};if(s){let R=h(e.params.kind);if(!["claude-compatible","openai-compatible"].includes(R))throw new Error("unsupported provider kind");d.kind=R}if(n){let R=h(e.params.baseUrl);if(!R)throw new Error("baseUrl cannot be empty");d.baseUrl=R}if(o){let R=h(e.params.apiKey);if(!R)throw new Error("apiKey cannot be empty");d.apiKey=R}if(a){let R=be(Array.isArray(e.params.models)?e.params.models.filter(w=>typeof w=="string"):[]);if(R.length===0)throw new Error("models cannot be empty");d.models=R}if(i){let R=h(e.params.defaultModel);R?d.defaultModel=R:delete d.defaultModel}if(c){let R=h(e.params.anthropicDefaultOpusModel);if(!R)throw new Error("anthropicDefaultOpusModel cannot be empty");d.ANTHROPIC_DEFAULT_OPUS_MODEL=R}if(m){let R=h(e.params.anthropicDefaultSonnetModel);R?d.ANTHROPIC_DEFAULT_SONNET_MODEL=R:delete d.ANTHROPIC_DEFAULT_SONNET_MODEL}if(v){let R=h(e.params.anthropicDefaultHaikuModel);R?d.ANTHROPIC_DEFAULT_HAIKU_MODEL=R:delete d.ANTHROPIC_DEFAULT_HAIKU_MODEL}f[t]=d,Gt(e.providerFile,l);let k=typeof d.kind=="string"?d.kind:r?.kind??"openai-compatible",b=Array.isArray(d.models)?d.models.filter(R=>typeof R=="string"):r?.models??[];return e.providers[t]={kind:k,displayName:typeof d.displayName=="string"?d.displayName:r?.displayName??t,source:"provider-file",models:b,modelsDiscoveredBy:r?.modelsDiscoveredBy??(b.length>0?"provider-file":"api-probe"),...typeof d.baseUrl=="string"?{baseUrl:d.baseUrl}:{},configEditable:!0,...se(typeof d.apiKey=="string"?d.apiKey:void 0)?{apiKeyPreview:se(typeof d.apiKey=="string"?d.apiKey:void 0)}:{},...typeof d.defaultModel=="string"?{defaultModel:d.defaultModel}:{},...typeof d.ANTHROPIC_DEFAULT_OPUS_MODEL=="string"?{anthropicDefaultOpusModel:d.ANTHROPIC_DEFAULT_OPUS_MODEL}:{},...typeof d.ANTHROPIC_DEFAULT_SONNET_MODEL=="string"?{anthropicDefaultSonnetModel:d.ANTHROPIC_DEFAULT_SONNET_MODEL}:{},...typeof d.ANTHROPIC_DEFAULT_HAIKU_MODEL=="string"?{anthropicDefaultHaikuModel:d.ANTHROPIC_DEFAULT_HAIKU_MODEL}:{}},{ok:!0,providerName:t,...s?{kind:k}:{},apiKeyPreview:se(typeof d.apiKey=="string"?d.apiKey:void 0)??null,...a?{models:Array.isArray(d.models)?d.models:[]}:{},...i?{defaultModel:typeof d.defaultModel=="string"?d.defaultModel:null}:{},...v?{anthropicDefaultHaikuModel:typeof d.ANTHROPIC_DEFAULT_HAIKU_MODEL=="string"?d.ANTHROPIC_DEFAULT_HAIKU_MODEL:null}:{},...m?{anthropicDefaultSonnetModel:typeof d.ANTHROPIC_DEFAULT_SONNET_MODEL=="string"?d.ANTHROPIC_DEFAULT_SONNET_MODEL:null}:{},...c?{anthropicDefaultOpusModel:typeof d.ANTHROPIC_DEFAULT_OPUS_MODEL=="string"?d.ANTHROPIC_DEFAULT_OPUS_MODEL:null}:{},needsRestart:!0}}var Do=/api[-_]?key|secret|token|password|authorization|base[-_]?url|api[-_]?url/i,Oo=/(api[-_]?key|secret|token|password|authorization)\s*[:=]\s*([^\s,;]+)/gi;function Re(e,t=0){if(t>6)return"[redacted:depth]";if(Array.isArray(e))return e.map(n=>Re(n,t+1));if(!e||typeof e!="object")return typeof e=="string"&&e.length>1e3?`${e.slice(0,1e3)}...`:e;let r={};for(let[n,o]of Object.entries(e))r[n]=Do.test(n)?"[redacted]":Re(o,t+1);return r}function Uo(e){return(e instanceof Error?e.message:String(e)).replace(Oo,"$1=[redacted]").replace(/Bearer\s+[A-Za-z0-9._~+/=-]+/gi,"Bearer [redacted]").slice(0,1e3)}function Lo(e){if(["opus","sonnet","haiku"].includes(e.selectedModel))return e.selectedModel;let t=e.providerFile?.trim()?_e(e.providerFile)[e.providerName]:void 0,r=e.provider.anthropicDefaultOpusModel??t?.anthropicDefaultOpusModel,n=e.provider.anthropicDefaultSonnetModel??t?.anthropicDefaultSonnetModel,o=e.provider.anthropicDefaultHaikuModel??t?.anthropicDefaultHaikuModel;return e.selectedModel===n?"sonnet":e.selectedModel===o?"haiku":e.selectedModel===r||r?"opus":e.selectedModel}function Fo(e){return e.provider.kind==="claude-code"||e.provider.kind==="claude-compatible"?Lo(e):e.selectedModel}function Ut(e){return e==="default"||e==="none"||e==="minimal"||e==="low"||e==="medium"||e==="high"||e==="xhigh"||e==="max"?e:void 0}function Lt(e){return e==="default"||e==="disabled"||e==="adaptive"?e:void 0}function Ft(e){return e==="default"||e==="fast"||e==="flex"?e:void 0}function Ho(e){let t=$(e);if(t.type!=="agent_run.assigned")return null;let r=h(t.agentRunId),n=$(t.payload),o=$(n.runtimeSelection),s=h(n.workspaceId),a=h(n.agentId),i=h(n.agentSessionId),c=h(n.providerSessionId)||i,m=h(n.prompt),v=h(o.providerName),l=h(o.selectedModel);return!r||!s||!a||!i||!m||!v||!l?null:{type:"agent_run.assigned",agentRunId:r,payload:{workspaceId:s,agentId:a,agentSessionId:i,providerSessionId:c,channelId:h(n.channelId)||null,systemPrompt:h(n.systemPrompt)||null,prompt:m,repoAlias:h(n.repoAlias)||"default",workspaceCodeRepository:jt(n.workspaceCodeRepository),runtimeSelection:{providerName:v,selectedModel:l,...Ut(o.reasoningEffort)?{reasoningEffort:Ut(o.reasoningEffort)}:{},...Lt(o.thinkingMode)?{thinkingMode:Lt(o.thinkingMode)}:{},...Ft(o.serviceTier)?{serviceTier:Ft(o.serviceTier)}:{}}}}}function $o(e){switch(e.kind){case"claude-code":case"claude-compatible":return gt;case"codex":case"openai-compatible":return It;default:return async()=>{throw new Error(`unsupported node provider kind: ${e.kind}`)}}}function qo(e){return{type:"agent_run.rejected",agentRunId:e.agentRunId,payload:{reason:"capability_mismatch",providerName:e.payload.runtimeSelection.providerName,selectedModel:e.payload.runtimeSelection.selectedModel}}}function jo(e){return["<truesayer_workspace_context>",`Current channel worktree root: ${e.cwd}`,e.worktreePath?`Node-managed worktree path: ${e.worktreePath}`:null,e.workspaceCodeRepository?.path?`Workspace code repository: ${e.workspaceCodeRepository.path}`:null,"Treat the current channel as the active repository workspace. Unless the user explicitly says otherwise, repository modifications may span the whole worktree.","</truesayer_workspace_context>","",e.prompt].filter(r=>!!r).join(`
38
+ `)}async function Wo(e){let t=h(e.worktreePath);if(!t)return null;let r=h(e.baseSha);if(!r&&!h(e.branch))return null;try{let[n,o]=await Promise.all([Pe(t),Y(t,h(e.baseRef)||void 0).catch(()=>null)]);return{...e,headSha:n,dirty:o?o.files.length>0||o.hasStagedChanges:void 0,hasCommitsSinceBase:!!(r&&n&&r!==n)}}catch{return{...e,refreshFailed:!0}}}async function Go(e){let{providerName:t,selectedModel:r}=e.message.payload.runtimeSelection,n=e.message.payload.providerSessionId||e.message.payload.agentSessionId,o=new Q(e.truesayerNodeHome),s=e.providers[t];if(!s||!s.models.includes(r)){let T=qo(e.message);return await e.emitMessage?.(T),{messages:[T]}}let a=ot({truesayerNodeHome:e.truesayerNodeHome,workspaceId:e.message.payload.workspaceId,agentId:e.message.payload.agentId,agentSessionId:e.message.payload.agentSessionId,agentRunId:e.message.agentRunId,repoAlias:e.message.payload.repoAlias||"default"}),i=a.worktreeDir,c={cwd:i};if(e.message.payload.workspaceCodeRepository){let T=e.message.payload.workspaceCodeRepository,_=await Ie({path:T.path,baseRef:T.baseRef||"main"}),E=await Qe({actionId:e.message.agentRunId,baseBranch:_.baseRef,repoPath:_.repoRoot,worktreePath:a.worktreeDir});i=E.path,c.cwd=i,c.workspaceCodeRepository={path:_.path,baseRef:_.baseRef},c.worktreePath=E.path,c.branch=E.branch,c.baseSha=E.baseSha,c.baseRef=E.baseRef,c.headSha=await Pe(E.path)}else c.worktreePath=a.worktreeDir;let m=jo({prompt:e.message.payload.prompt,cwd:i,workspaceCodeRepository:e.message.payload.workspaceCodeRepository,worktreePath:h(c.worktreePath)}),v=[],l=async T=>{v.push(T),await e.emitMessage?.(T)},f=async T=>{let _=o.append({providerSessionId:n,agentRunId:e.message.agentRunId,providerName:t,raw:T});await l({type:"agent_run.event_batch",agentRunId:e.message.agentRunId,payload:{providerSessionId:n,providerName:t,rawEvents:[_]}})},y=1,d=0,k=!1,b=null,R=new Promise(T=>{b=T}),w=new AbortController,p=()=>{w.abort(e.abortSignal?.reason??new Error("Interrupted by user"))};e.abortSignal&&(e.abortSignal.aborted?p():e.abortSignal.addEventListener("abort",p,{once:!0}));let g=async(T,_)=>{y+=1,await l({type:"agent_run.event_batch",agentRunId:e.message.agentRunId,payload:{events:[{eventId:`${e.message.agentRunId}:event:${y}`,eventSeq:y,type:T,payload:_}]}})},A=e.invokeTool?async T=>{d+=1;let _=T.toolCallId||`${e.message.agentRunId}:tool:${d}`;await g("agent_run.tool.started",{toolCallId:_,toolName:T.toolName,status:"started",args:Re(T.args)});try{let E=await e.invokeTool({...T,toolCallId:_});await g("agent_run.tool.completed",{toolCallId:_,toolName:T.toolName,status:"completed",result:Re(E)});let O=$(T.args);if(T.toolName==="reply_to_channel"&&O.intent==="final"&&!k){k=!0;let j=h(O.body)||"Final reply delivered";b?.({output:j}),w.abort(new Error("Final reply delivered"))}return E}catch(E){throw await g("agent_run.tool.failed",{toolCallId:_,toolName:T.toolName,status:"failed",error:E instanceof Error?E.message:String(E)}),E}}:void 0;await l({type:"agent_run.accepted",agentRunId:e.message.agentRunId,payload:{agentId:e.message.payload.agentId,agentSessionId:e.message.payload.agentSessionId,providerSessionId:n,providerName:t,selectedModel:r}}),await l({type:"agent_run.event_batch",agentRunId:e.message.agentRunId,payload:{events:[{eventId:`${e.message.agentRunId}:workspace-prepared`,eventSeq:1,type:"agent_run.workspace_prepared",payload:{workspacePrepared:!0,fileToolRoot:"worktree",providerHomeExposedToFileTools:!1,...c}}]}});try{if(e.abortSignal?.aborted)throw new Error("Interrupted by user");let T=e.runProviderAgent??$o(s),_,E=!1,O=T({agentRunId:e.message.agentRunId,agentId:e.message.payload.agentId,agentSessionId:e.message.payload.agentSessionId,providerSessionId:n,prompt:m,provider:s,availableProviders:e.providers,providerName:t,selectedModel:Fo({providerFile:e.providerFile,providerName:t,provider:s,selectedModel:r}),reasoningEffort:e.message.payload.runtimeSelection.reasoningEffort,thinkingMode:e.message.payload.runtimeSelection.thinkingMode,serviceTier:e.message.payload.runtimeSelection.serviceTier,cwd:i,env:go({...a.providerEnv,...ho(e.providerFile,t)}),sessionStateDir:a.contextDir,systemPrompt:e.message.payload.systemPrompt??void 0,invokeTool:A,emitEvent:async B=>{await l({type:"agent_run.event_batch",agentRunId:e.message.agentRunId,payload:{events:[B]}})},emitRawEvent:f,abortSignal:w.signal}).then(B=>(E=!0,B));try{_=await Promise.race([O,R]),!E&&k&&O.catch(()=>{})}catch(B){let Be=B instanceof Error?B:void 0,rr=Be?.emittedEventIds??new Set,Je=(Be?.events??[]).filter(nr=>!rr.has(nr.eventId));throw Je.length&&await l({type:"agent_run.event_batch",agentRunId:e.message.agentRunId,payload:{events:Je}}),B}let j=oo(_);j.length&&await l({type:"agent_run.event_batch",agentRunId:e.message.agentRunId,payload:{events:j}});let de=await Wo(c);de&&await l({type:"agent_run.event_batch",agentRunId:e.message.agentRunId,payload:{events:[{eventId:`${e.message.agentRunId}:git-terminal-evidence`,eventSeq:1e6,type:"agent_run.git_terminal_evidence",payload:de}]}}),await g("agent_run.completed",{output:_.output,..._.inputTokens===void 0?{}:{inputTokens:_.inputTokens},..._.outputTokens===void 0?{}:{outputTokens:_.outputTokens}}),await l({type:"agent_run.completed",agentRunId:e.message.agentRunId,payload:{output:_.output,...de?{git:de}:{},..._.inputTokens===void 0?{}:{inputTokens:_.inputTokens},..._.outputTokens===void 0?{}:{outputTokens:_.outputTokens}}})}catch(T){let _=Uo(T);await g("agent_run.failed",{error:_}),await l({type:"agent_run.failed",agentRunId:e.message.agentRunId,payload:{error:_}})}return e.abortSignal?.removeEventListener("abort",p),{layout:a,messages:v}}function Bo(e){let t=new URL(e);return t.protocol=t.protocol==="https:"?"wss:":"ws:",t.pathname="/api/nodes/ws",t.search="",t.toString()}function Jo(){return $t.default}function Ht(e){e.readyState===1&&e.send(JSON.stringify({type:"node.heartbeat"}))}function We(e,t){if(e.readyState!==1)return!1;try{return e.send(JSON.stringify(t)),!0}catch{return!1}}function Ko(e){Ht(e);let t=setInterval(()=>{Ht(e)},no);return typeof t.unref=="function"&&t.unref(),()=>clearInterval(t)}async function Bt(e){let t=e.WebSocketImpl??Jo(),r=co(e.providerFile??fe(e.truesayerNodeHome)),n=await uo({providerFile:r,probeProviderModels:e.probeProviderModels}),o=po({...e,providerFile:r},n),s=new t(Bo(e.serverUrl),{headers:{Authorization:`Bearer ${e.apiKey}`}}),a=new Q(e.truesayerNodeHome),i=bo(s),c=new Set,m=new Map,v=()=>{for(let l of a.unackedBatches())We(s,{type:"agent_run.event_batch",agentRunId:l.agentRunId,payload:{providerSessionId:l.providerSessionId,providerName:l.providerName,rawEvents:l.events}})};await new Promise((l,f)=>{let y=!1,d=null,k=null;s.addEventListener("open",()=>{s.send(JSON.stringify(o))}),s.addEventListener("message",b=>{let R=typeof b.data=="string"?b.data:"";try{let w=JSON.parse(R);if(i.handleJsonRpcMessage(w))return;if(yo(w)){(async()=>{try{let g=await xo({truesayerNodeHome:e.truesayerNodeHome,providerFile:r,providers:n,request:w,runProviderAgent:e.runProviderAgent,emitMessage:A=>{s.send(JSON.stringify(A))}});s.send(ko(w.id,g))}catch(g){s.send(wo(w.id,g instanceof Error?g.message:String(g)))}})();return}if(w.type==="node.ready"){y=!0,d??=Ko(s),k??=(()=>{let g=setInterval(v,2e3);return typeof g.unref=="function"&&g.unref(),()=>clearInterval(g)})(),v();return}if(w.type==="agent_run.event_ack"){let g=$(w.payload),A=h(g.providerSessionId),T=typeof g.ackLine=="number"?g.ackLine:0;a.markAck(A,T);return}let p=Ho(w);if(p){if(c.has(p.agentRunId))return;c.add(p.agentRunId);let g=new AbortController;m.set(p.agentRunId,g),Go({truesayerNodeHome:e.truesayerNodeHome,providerFile:r,providers:n,message:p,invokeTool:i.invokeTool,runProviderAgent:e.runProviderAgent,abortSignal:g.signal,emitMessage:A=>{We(s,A)}}).catch(A=>{We(s,{type:"agent_run.failed",agentRunId:p.agentRunId,payload:{error:A instanceof Error?A.message:String(A)}})}).finally(()=>{m.delete(p.agentRunId)});return}if(w.type==="agent_run.cancel"){let g=h(w.agentRunId);m.get(g)?.abort(new Error("Interrupted by user"))}}catch{}}),s.addEventListener("error",b=>{d?.(),d=null,k?.(),k=null,f(new Error(`node ws error: ${String(b)}`))}),s.addEventListener("close",()=>{d?.(),d=null,k?.(),k=null,i.rejectPending(new Error("node websocket closed")),y?l():f(new Error("node ws closed before node.ready"))})})}var W=require("fs"),Jt=require("os"),Kt=require("path");var zt=["DATABASE_URL","APP_SECRET","ASSET_STORAGE_DRIVER","S3_ENDPOINT","S3_BUCKET","S3_ACCESS_KEY_ID","S3_SECRET_ACCESS_KEY","S3_REGION","S3_FORCE_PATH_STYLE"];function zo(e=process.env){return e.TRUESAYER_NODE_HOME?.trim()||(0,Kt.join)((0,Jt.homedir)(),".truesayer-node")}function Vt(e=process.env){let t=zt.filter(r=>e[r]?.trim());if(t.length>0)throw new Error(`Node \u8FDB\u7A0B\u5E26\u6709 Server-only \u73AF\u5883\u53D8\u91CF\uFF1A${t.join(", ")}\u3002\u8BF7\u4ECE Node runtime \u73AF\u5883\u4E2D\u79FB\u9664\u8FD9\u4E9B\u53D8\u91CF\u540E\u518D\u542F\u52A8\u3002`)}function K(e,t){return{name:e,status:"pass",message:t}}function Vo(e,t){return{name:e,status:"warn",message:t}}function H(e,t){return{name:e,status:"fail",message:t}}function Yo(e){let t=e.trim().match(/^v?(\d+)/);if(t)return Number.parseInt(t[1],10)}function Xo(e){let t=e.hostname.toLowerCase();return t==="localhost"||t==="127.0.0.1"||t==="::1"||t==="0.0.0.0"}function Zo(e){let t=Yo(e);return t?t<22?H("Node \u7248\u672C","\u5F53\u524D Node \u7248\u672C\u4E0D\u6EE1\u8DB3 runtime WebSocket \u8981\u6C42\u3002\u8BF7\u5347\u7EA7\u5230 Node 22 \u6216\u66F4\u65B0\u7248\u672C\u3002"):K("Node \u7248\u672C","Node \u7248\u672C\u6EE1\u8DB3 runtime WebSocket \u8981\u6C42\u3002"):H("Node \u7248\u672C","\u65E0\u6CD5\u8BC6\u522B\u5F53\u524D Node \u7248\u672C\u3002\u8BF7\u4F7F\u7528 Node 22 \u6216\u66F4\u65B0\u7248\u672C\u3002")}function Qo(e){if(!e?.trim())return H("Server URL","\u7F3A\u5C11 SERVER_URL \u6216 --server\u3002\u751F\u4EA7\u793A\u4F8B\u4F7F\u7528 https://truesayer.ai\u3002");let t;try{t=new URL(e)}catch{return H("Server URL","SERVER_URL \u4E0D\u662F\u5408\u6CD5 URL\u3002\u8BF7\u8BBE\u7F6E\u4E3A https://truesayer.ai \u6216\u672C\u5730\u5F00\u53D1\u5730\u5740\u3002")}return t.protocol==="https:"?K("Server URL","Server URL \u4F7F\u7528 HTTPS\u3002"):t.protocol==="http:"&&Xo(t)?K("Server URL","\u672C\u5730\u5F00\u53D1\u5730\u5740\u5141\u8BB8\u4F7F\u7528 HTTP\u3002"):H("Server URL","\u751F\u4EA7 Server URL \u5FC5\u987B\u4F7F\u7528 HTTPS\uFF1BHTTP \u53EA\u5141\u8BB8 localhost\u3001127.0.0.1\u3001::1 \u6216 0.0.0.0\u3002")}function es(e){return e?.trim()?K("Node API key","\u5DF2\u914D\u7F6E Node API key\u3002"):H("Node API key","\u7F3A\u5C11 NODE_API_KEY \u6216 --api-key\u3002\u8BF7\u4F7F\u7528 Server \u7B7E\u53D1\u7684 Node registration key\u3002")}function ts(e,t,r){let n=e?.trim()||zo(r);try{(0,W.mkdirSync)(n,{recursive:!0,mode:448}),t!=="win32"&&(0,W.chmodSync)(n,448);let o=(0,W.statSync)(n);return o.isDirectory()?t!=="win32"&&(o.mode&63)!==0?H("Node home","TRUESAYER_NODE_HOME \u6743\u9650\u8FC7\u5BBD\u3002\u8BF7\u6267\u884C chmod 700\u3002"):K("Node home","TRUESAYER_NODE_HOME \u53EF\u521B\u5EFA\u4E14\u6743\u9650\u5DF2\u6536\u655B\u3002"):H("Node home","TRUESAYER_NODE_HOME \u6307\u5411\u7684\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55\u3002\u8BF7\u6539\u6210 Node \u53EF\u5199\u76EE\u5F55\u3002")}catch{return H("Node home","TRUESAYER_NODE_HOME \u4E0D\u53EF\u521B\u5EFA\u6216\u4E0D\u53EF\u5199\u3002\u8BF7\u6539\u6210 Node \u8FDB\u7A0B\u53EF\u5199\u76EE\u5F55\u3002")}}function rs(e,t){try{let r=(0,W.statSync)(e);if(!r.isFile())return H("Provider file","<node-home>/provider.json \u6307\u5411\u7684\u8DEF\u5F84\u4E0D\u662F\u6587\u4EF6\u3002");if(t!=="win32"&&(r.mode&63)!==0)return H("Provider file","provider.json \u6743\u9650\u8FC7\u5BBD\u3002\u8BF7\u6267\u884C chmod 600\u3002");let n=JSON.parse((0,W.readFileSync)(e,"utf8"));return!n||typeof n!="object"||Array.isArray(n)?H("Provider file","provider.json \u5FC5\u987B\u662F\u5408\u6CD5 JSON object\u3002"):K("Provider file","provider.json \u662F\u5408\u6CD5 JSON\uFF0C\u4E14\u6743\u9650\u6EE1\u8DB3\u8981\u6C42\u3002")}catch(r){return r instanceof SyntaxError?H("Provider file","provider.json \u4E0D\u662F\u5408\u6CD5 JSON\u3002\u8BF7\u4FEE\u6B63 JSON \u8BED\u6CD5\u3002"):Vo("Provider file","\u672A\u627E\u5230 <node-home>/provider.json\uFF1B\u542F\u52A8\u65F6\u4F1A\u521B\u5EFA\u7A7A provider registry\uFF0C\u5F53\u524D\u53EA\u4F7F\u7528 native provider \u767B\u5F55\u6001\u3002")}}function ns(e){let t=zt.filter(r=>e[r]?.trim());return t.length===0?K("Server-only env","\u672A\u53D1\u73B0 Server-only \u73AF\u5883\u53D8\u91CF\u3002"):H("Server-only env",`Node runtime \u4E0D\u5E94\u643A\u5E26\u8FD9\u4E9B Server-only \u73AF\u5883\u53D8\u91CF\uFF1A${t.join(", ")}\u3002\u8BF7\u4ECE\u542F\u52A8\u73AF\u5883\u4E2D\u79FB\u9664\u3002`)}function Yt(e={}){let t=e.env??process.env,r=e.platform??process.platform,n=e.truesayerNodeHome??t.TRUESAYER_NODE_HOME,o=e.providerFile??fe(n),s=[Zo(e.nodeVersion??process.versions.node),Qo(e.serverUrl??t.SERVER_URL),es(e.apiKey??t.NODE_API_KEY),ts(n,r,t),rs(o,r),ns(t)];return{ok:s.every(a=>a.status!=="fail"),checks:s}}function Xt(e){let t={pass:"\u901A\u8FC7",warn:"\u8B66\u544A",fail:"\u5931\u8D25"};return["truesayer-node doctor",...e.checks.map(n=>`[${t[n.status]}] ${n.name}\uFF1A${n.message}`),e.ok?"\u7ED3\u679C\uFF1A\u57FA\u7840\u68C0\u67E5\u901A\u8FC7\uFF0C\u53EF\u4EE5\u542F\u52A8 truesayer-node\u3002":"\u7ED3\u679C\uFF1A\u57FA\u7840\u68C0\u67E5\u5931\u8D25\u3002\u8BF7\u4FEE\u590D\u5931\u8D25\u9879\u540E\u518D\u542F\u52A8 truesayer-node\u3002"].join(`
39
+ `)}function Te(e){let t=`${e}=`,r=process.argv.find(o=>o.startsWith(t));if(r)return r.slice(t.length);let n=process.argv.indexOf(e);if(n>=0)return process.argv[n+1]}function os(...e){return process.argv.some(t=>e.includes(t))}function ss(){let e=Number(process.versions.node.split(".")[0]);if(!Number.isFinite(e)||e<22)throw new Error(`truesayer-node requires Node.js >=22. Current: ${process.version}`)}function Zt(){return"Usage: truesayer-node --server <url> --api-key <key> [--node-name <name>] [--node-home <path>]"}function Qt(){if(process.env.npm_package_version)return process.env.npm_package_version;try{let e=JSON.parse((0,er.readFileSync)((0,tr.join)(__dirname,"..","package.json"),"utf8"));return typeof e.version=="string"&&e.version.trim()?e.version:"0.1.0"}catch{return"0.1.0"}}async function is(){let e=process.argv[2];if(os("--version","-v")){console.log(Qt());return}let t=Te("--server")??process.env.SERVER_URL,r=Te("--api-key")??process.env.NODE_API_KEY,n=Te("--node-name")??process.env.NODE_NAME??"truesayer-node",o=Te("--node-home")??process.env.TRUESAYER_NODE_HOME;if(e==="doctor"){let s=Yt({serverUrl:t,apiKey:r,truesayerNodeHome:o,nodeVersion:process.version});console.log(Xt(s)),process.exit(s.ok?0:1)}if(ss(),Vt(),!t)throw new Error(`--server or SERVER_URL is required
40
+ ${Zt()}`);if(!r)throw new Error(`--api-key or NODE_API_KEY is required
41
+ ${Zt()}`);for(;;){try{await Bt({serverUrl:t,apiKey:r,nodeName:n,nodeVersion:Qt(),truesayerNodeHome:o})}catch(s){console.error("[node] connection failed:",s instanceof Error?s.message:String(s))}await new Promise(s=>setTimeout(s,2e3))}}is().catch(e=>{console.error("[node] Fatal:",e instanceof Error?e.message:String(e)),process.exit(1)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truesayer/node",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "private": false,
5
5
  "description": "Truesayer local Node runtime CLI",
6
6
  "license": "UNLICENSED",
@@ -34,10 +34,12 @@
34
34
  "@modelcontextprotocol/sdk": "1.29.0",
35
35
  "@openai/codex": "^0.125.0",
36
36
  "simple-git": "^3.36.0",
37
+ "ws": "^8.21.0",
37
38
  "zod": "^4"
38
39
  },
39
40
  "devDependencies": {
40
41
  "@types/node": "^22.19.17",
42
+ "@types/ws": "^8.18.1",
41
43
  "tsup": "^8.5.0",
42
44
  "tsx": "^4.19.0",
43
45
  "typescript": "^5.7.0"