vibelet 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/vibelet.mjs +23 -8
- package/dist/index.cjs +1 -1
- package/package.json +1 -1
package/bin/vibelet.mjs
CHANGED
|
@@ -138,6 +138,8 @@ function createDarwinBackend() {
|
|
|
138
138
|
|
|
139
139
|
const envVars = { VIBE_PORT: String(port) };
|
|
140
140
|
if (process.env.VIBELET_RELAY_URL) envVars.VIBELET_RELAY_URL = process.env.VIBELET_RELAY_URL;
|
|
141
|
+
if (process.env.VIBELET_CANONICAL_HOST) envVars.VIBELET_CANONICAL_HOST = process.env.VIBELET_CANONICAL_HOST;
|
|
142
|
+
if (process.env.VIBELET_FALLBACK_HOSTS) envVars.VIBELET_FALLBACK_HOSTS = process.env.VIBELET_FALLBACK_HOSTS;
|
|
141
143
|
const envSection = Object.keys(envVars).length > 0
|
|
142
144
|
? ` <key>EnvironmentVariables</key>
|
|
143
145
|
<dict>
|
|
@@ -246,7 +248,7 @@ Restart=always
|
|
|
246
248
|
RestartSec=3
|
|
247
249
|
StandardOutput=append:${stdoutLogPath}
|
|
248
250
|
StandardError=append:${stderrLogPath}
|
|
249
|
-
Environment=VIBE_PORT=${port}${process.env.VIBELET_RELAY_URL ? `\nEnvironment=VIBELET_RELAY_URL=${process.env.VIBELET_RELAY_URL}` : ''}
|
|
251
|
+
Environment=VIBE_PORT=${port}${process.env.VIBELET_RELAY_URL ? `\nEnvironment=VIBELET_RELAY_URL=${process.env.VIBELET_RELAY_URL}` : ''}${process.env.VIBELET_CANONICAL_HOST ? `\nEnvironment=VIBELET_CANONICAL_HOST=${process.env.VIBELET_CANONICAL_HOST}` : ''}${process.env.VIBELET_FALLBACK_HOSTS ? `\nEnvironment=VIBELET_FALLBACK_HOSTS=${process.env.VIBELET_FALLBACK_HOSTS}` : ''}
|
|
250
252
|
|
|
251
253
|
[Install]
|
|
252
254
|
WantedBy=default.target
|
|
@@ -498,6 +500,8 @@ function printHelp() {
|
|
|
498
500
|
process.stdout.write(` npx ${packageJson.name} Install/start the daemon and print a pairing QR code\n`);
|
|
499
501
|
process.stdout.write(` npx ${packageJson.name} start Same as above\n`);
|
|
500
502
|
process.stdout.write(` npx ${packageJson.name} --relay <url> Use a tunnel URL for remote access\n`);
|
|
503
|
+
process.stdout.write(` npx ${packageJson.name} --host <ip> Set the primary host/IP address\n`);
|
|
504
|
+
process.stdout.write(` npx ${packageJson.name} --fallback-hosts <ips> Comma-separated fallback IPs\n`);
|
|
501
505
|
process.stdout.write(` npx ${packageJson.name} stop Stop the daemon\n`);
|
|
502
506
|
process.stdout.write(` npx ${packageJson.name} restart Restart the daemon\n`);
|
|
503
507
|
process.stdout.write(` npx ${packageJson.name} status Show service and daemon status\n`);
|
|
@@ -511,16 +515,19 @@ function printHelp() {
|
|
|
511
515
|
process.stdout.write(` vibelet\n`);
|
|
512
516
|
}
|
|
513
517
|
|
|
514
|
-
function
|
|
515
|
-
const idx = process.argv.indexOf(
|
|
518
|
+
function parseNamedArg(name, errorHint) {
|
|
519
|
+
const idx = process.argv.indexOf(`--${name}`);
|
|
516
520
|
if (idx === -1) return null;
|
|
517
|
-
const
|
|
518
|
-
if (!
|
|
519
|
-
fail(
|
|
521
|
+
const value = process.argv[idx + 1];
|
|
522
|
+
if (!value || value.startsWith('-')) {
|
|
523
|
+
fail(`--${name} requires an argument${errorHint ? ` (e.g. --${name} ${errorHint})` : ''}`);
|
|
520
524
|
}
|
|
521
|
-
// Remove --relay and URL from argv so they don't interfere with command parsing
|
|
522
525
|
process.argv.splice(idx, 2);
|
|
523
|
-
return
|
|
526
|
+
return value;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
function parseRelayArg() {
|
|
530
|
+
return parseNamedArg('relay', 'https://abc.trycloudflare.com');
|
|
524
531
|
}
|
|
525
532
|
|
|
526
533
|
function loadRelayConfig() {
|
|
@@ -543,6 +550,8 @@ function clearRelayConfig() {
|
|
|
543
550
|
|
|
544
551
|
async function main() {
|
|
545
552
|
const relayArg = parseRelayArg();
|
|
553
|
+
const hostArg = parseNamedArg('host', '100.x.x.x');
|
|
554
|
+
const fallbackHostsArg = parseNamedArg('fallback-hosts', '100.x.x.x,192.168.1.x');
|
|
546
555
|
// --relay "" clears saved relay; --relay <url> saves it; omitted uses saved value
|
|
547
556
|
if (relayArg !== null) {
|
|
548
557
|
if (relayArg) {
|
|
@@ -555,6 +564,12 @@ async function main() {
|
|
|
555
564
|
if (relayUrl) {
|
|
556
565
|
process.env.VIBELET_RELAY_URL = relayUrl;
|
|
557
566
|
}
|
|
567
|
+
if (hostArg) {
|
|
568
|
+
process.env.VIBELET_CANONICAL_HOST = hostArg;
|
|
569
|
+
}
|
|
570
|
+
if (fallbackHostsArg) {
|
|
571
|
+
process.env.VIBELET_FALLBACK_HOSTS = fallbackHostsArg;
|
|
572
|
+
}
|
|
558
573
|
const backend = resolveBackend();
|
|
559
574
|
const command = process.argv[2] ?? 'default';
|
|
560
575
|
|
package/dist/index.cjs
CHANGED
|
@@ -84,7 +84,7 @@ process.stdin.resume();
|
|
|
84
84
|
`)}function lp(t){return Array.isArray(t)?t.map(e=>!e||typeof e!="object"?"":typeof e.text=="string"?e.text:typeof e.content=="string"?e.content:"").filter(Boolean).join(`
|
|
85
85
|
`):""}function cp(t){return Array.isArray(t)&&t.length>0&&t.every(e=>e&&typeof e=="object"&&e.type==="tool_reference")}function up(t){if(typeof t=="string")return t;let e=lp(t);return e||(cp(t)?"":JSON.stringify(t))}function dp(t){return/requested permissions|haven't granted/i.test(t)}function Pl(t){return t.replace(ap,"").replace(/\s+/g," ").trim()}function fp(t){let e=t.toLowerCase();return e==="error"||e==="failed"||e==="unknown error"}function hp(t){return/\brate limit\b/i.test(t)||/\busage limit\b/i.test(t)||/\bquota\b/i.test(t)||/\btoo many requests\b/i.test(t)||/\bcredit balance\b/i.test(t)||/\bcredits? remaining\b/i.test(t)||/\bmax(?:imum)? usage\b/i.test(t)}function pp(t){return t.toLowerCase().startsWith("claude ")?t:`Claude usage limit reached. ${t}`}function Ll(t){let e=Pl(t.resultText??""),n=(t.stderrLines??[]).map(Pl).filter(Boolean).slice(-3),r=[e,...n].find(i=>!!i&&hp(i));if(r)return pp(r);let s=[e,...n].find(i=>!!i&&!fp(i));return s?t.exitCode!=null&&s!==e?`Claude exited with code ${t.exitCode}: ${s}`:s:t.exitCode!=null?`Claude exited with code ${t.exitCode}`:"Claude returned an error result."}function Fn(t){return t.startsWith(Ml)}var Xt=class{proc=null;handler=null;sessionId="";buffer="";cwd="";approvalMode;sawFinalResult=!1;interrupted=!1;exitHandler=null;lastStderr=[];pendingPermissionDescriptions=new Map;hookPort=null;hookSecret=null;hookFiles=null;buildClaudeEnv(){let e=S.buildSanitizedEnv();for(let n of Object.keys(e))n.startsWith("CMUX_")&&delete e[n];return e}async start(e,n,r){return this.cwd=e,this.approvalMode=r,n&&(this.sessionId=n),this.sessionId||(this.sessionId=`pending_${Date.now()}`),Z.info({sessionId:this.sessionId,cwd:e},"session initialized"),v.emit("driver.spawn",{agent:"claude",sessionId:this.sessionId,cwd:e}),this.sessionId}configureHookBridge(e,n){this.hookPort=e,this.hookSecret=n}sendPrompt(e){let n=["-p",e,"--output-format","stream-json","--verbose","--include-partial-messages"];this.sessionId&&!this.sessionId.startsWith("pending_")&&n.push("--resume",this.sessionId),Hn(this.hookFiles),this.hookFiles=null,this.approvalMode!=="acceptEdits"&&this.approvalMode!=="autoApprove"&&this.hookPort&&this.hookSecret&&(this.hookFiles=Rl(this.hookPort,this.hookSecret),n.push("--settings",this.hookFiles.settingsPath)),this.approvalMode==="acceptEdits"&&n.push("--permission-mode","acceptEdits"),this.approvalMode==="autoApprove"&&n.push("--dangerously-skip-permissions");let r=this.sessionId.startsWith("pending_")?"(new)":`(resume ${this.sessionId.slice(0,8)})`;Z.info({sessionId:this.sessionId,label:r,promptPreview:e.slice(0,50)},"running claude"),ms(`New message: ${e.slice(0,60)}`),this.sawFinalResult=!1,this.interrupted=!1,this.lastStderr=[],this.pendingPermissionDescriptions.clear(),this.proc=(0,Nl.spawn)(S.claudePath,n,{cwd:this.cwd||void 0,stdio:["pipe","pipe","pipe"],env:this.buildClaudeEnv()}),this.proc.on("error",s=>{let i=s.message;s.code==="ENOENT"&&this.cwd&&!(0,Ol.existsSync)(this.cwd)&&(i=`Working directory does not exist: ${this.cwd}`),Z.error({sessionId:this.sessionId,error:i,cwd:this.cwd},"spawn error"),v.emit("driver.error",{agent:"claude",sessionId:this.sessionId,error:i}),this.handler?.({type:"error",sessionId:this.sessionId,message:i})}),this.buffer="",this.proc.stdout.on("data",s=>{this.buffer+=s.toString();let i=this.buffer.split(`
|
|
86
86
|
`);this.buffer=i.pop();for(let o of i)if(o.trim())try{this.handleRaw(JSON.parse(o))}catch{Z.warn({sessionId:this.sessionId,linePreview:o.slice(0,100)},"failed to parse stdout line")}}),this.proc.stderr.on("data",s=>{let i=s.toString().trim();i&&(Z.debug({sessionId:this.sessionId,stderr:i},"stderr"),this.lastStderr.push(i),this.lastStderr.length>10&&this.lastStderr.shift())}),this.proc.on("exit",(s,i)=>{Z.info({sessionId:this.sessionId,exitCode:s,signal:i},"process exited");let o=this.interrupted;this.proc=null,Hn(this.hookFiles),this.hookFiles=null,this.interrupted=!1,o&&!this.sawFinalResult?this.handler?.({type:"session.interrupted",sessionId:this.sessionId}):s&&s!==0&&!this.sawFinalResult&&(Z.error({sessionId:this.sessionId,exitCode:s,lastStderr:this.lastStderr.slice(-3)},"abnormal exit"),this.handler?.({type:"error",sessionId:this.sessionId,message:Ll({stderrLines:this.lastStderr,exitCode:s})})),this.exitHandler?.(s)})}respondApproval(e,n){if(Z.info({sessionId:this.sessionId,requestId:e,approved:n},"approval response"),!this.proc?.stdin?.writable)return Z.error({sessionId:this.sessionId},"cannot send approval: stdin not writable"),!1;let r=JSON.stringify({type:"control_response",request_id:e,permission_granted:n});return this.proc.stdin.write(r+`
|
|
87
|
-
`),!0}setApprovalMode(e){this.approvalMode=e,Z.info({sessionId:this.sessionId,approvalMode:e},"approval mode updated")}interrupt(){this.proc&&!this.proc.killed&&(this.interrupted=!0,this.proc.kill("SIGTERM"),Z.info({sessionId:this.sessionId},"interrupted"))}stop(){if(!this.proc)return;this.proc.kill("SIGTERM");let e=this.proc;setTimeout(()=>{e.killed||e.kill("SIGKILL")},5e3).unref(),this.proc=null,Hn(this.hookFiles),this.hookFiles=null}onMessage(e){this.handler=e}onExit(e){this.exitHandler=e}handleRaw(e){let n=e.type;if(n==="system"&&e.subtype==="init"){let r=e.session_id??"";r&&r!==this.sessionId&&(Z.info({oldSessionId:this.sessionId,newSessionId:r},"session ID resolved"),v.emit("driver.init",{agent:"claude",sessionId:r}),this.sessionId=r);return}if(this.handler)switch(n){case"assistant":{let r=e.message?.content;if(!Array.isArray(r))break;for(let s of r)s.type==="tool_use"&&this.handler({type:"tool.call",sessionId:this.sessionId,toolName:s.name,input:s.input??{},toolCallId:s.id});break}case"user":{let r=e.message?.content;if(!Array.isArray(r))break;for(let s of r)if(s.type==="tool_result"){let i=up(s.content);if(!i)continue;if(s.is_error===!0&&typeof s.tool_use_id=="string"&&dp(i)){this.pendingPermissionDescriptions.set(s.tool_use_id,i);continue}this.handler({type:"tool.result",sessionId:this.sessionId,toolCallId:s.tool_use_id,output:i})}break}case"control_request":{let r=e.request;r?.subtype==="can_use_tool"&&(v.emit("approval.request",{agent:"claude",sessionId:this.sessionId,toolName:r.tool_name}),this.handler({type:"approval.request",sessionId:this.sessionId,requestId:e.request_id,toolName:r.tool_name??"unknown",input:r.input??{},description:r.description??r.title??""}));break}case"stream_event":{let r=e.event;r?.type==="content_block_delta"&&r?.delta?.type==="text_delta"&&r?.delta?.text&&this.handler({type:"text.delta",sessionId:this.sessionId,content:r.delta.text});break}case"result":{this.sawFinalResult=!0;let r=typeof e.result=="string"?e.result:"";if(e.is_error){ms("Claude failed."),this.handler({type:"error",sessionId:this.sessionId,message:Ll({resultText:r,stderrLines:this.lastStderr})});break}let s=Array.isArray(e.permission_denials)?e.permission_denials:[];if(s.length>0){let a=s[0]??{},l=typeof a.tool_use_id=="string"?a.tool_use_id:`missing_${Date.now()}`,c=typeof a.tool_name=="string"?a.tool_name:"unknown",u=a.tool_input&&typeof a.tool_input=="object"?a.tool_input:{},d=this.pendingPermissionDescriptions.get(l)??`Claude requested permissions to use ${c}.`;v.emit("approval.request",{agent:"claude",sessionId:this.sessionId,toolName:c}),this.handler({type:"approval.request",sessionId:this.sessionId,requestId:`${Ml}${l}`,toolName:c,input:u,description:d})}this.pendingPermissionDescriptions.clear();let i=e.total_cost_usd,o=e.usage?{inputTokens:e.usage.input_tokens,outputTokens:e.usage.output_tokens}:void 0;ms("Claude finished. Run `claude --continue` to continue on desktop."),v.emit("session.done",{agent:"claude",sessionId:this.sessionId,cost:i,usage:o}),this.handler({type:"session.done",sessionId:this.sessionId,cost:i,usage:o});break}}}};var ql=require("child_process"),Wl=require("fs");var ys=class{counters=new Map;timers=new Map;gauges=new Map;startTime=Date.now();logInterval=null;increment(e,n={}){this.counters.has(e)||this.counters.set(e,[]);let r=this.counters.get(e),s=JSON.stringify(n),i=r.find(o=>JSON.stringify(o.labels)===s);i?i.value++:r.push({value:1,labels:n})}gauge(e,n){this.gauges.set(e,n)}startTimer(e){let n=performance.now();return()=>{let r=Math.round(performance.now()-n),s=this.timers.get(e)??{count:0,totalMs:0,minMs:1/0,maxMs:0,lastMs:0};return s.count++,s.totalMs+=r,s.minMs=Math.min(s.minMs,r),s.maxMs=Math.max(s.maxMs,r),s.lastMs=r,this.timers.set(e,s),r}}snapshot(){let e={};for(let[s,i]of this.counters)e[s]=i.map(o=>({...o}));let n={};for(let[s,i]of this.timers)n[s]={...i,minMs:i.minMs===1/0?0:i.minMs};let r={};for(let[s,i]of this.gauges)r[s]=i;return{uptimeMs:Date.now()-this.startTime,counters:e,timers:n,gauges:r}}startPeriodicLog(e=6e4){this.logInterval||(this.logInterval=setInterval(()=>{let n=this.snapshot();B.info({metrics:n},"periodic metrics snapshot")},e),this.logInterval.unref())}stopPeriodicLog(){this.logInterval&&(clearInterval(this.logInterval),this.logInterval=null)}},I=new ys;var Dl=require("node:fs"),_s=require("node:path"),gp="@vibelet/cli";function Bl(t){try{let e=JSON.parse((0,Dl.readFileSync)(t,"utf8"));if(e.name===gp&&typeof e.version=="string"&&e.version.length>0)return e.version}catch{}return null}function mp(){return"0.0.
|
|
87
|
+
`),!0}setApprovalMode(e){this.approvalMode=e,Z.info({sessionId:this.sessionId,approvalMode:e},"approval mode updated")}interrupt(){this.proc&&!this.proc.killed&&(this.interrupted=!0,this.proc.kill("SIGTERM"),Z.info({sessionId:this.sessionId},"interrupted"))}stop(){if(!this.proc)return;this.proc.kill("SIGTERM");let e=this.proc;setTimeout(()=>{e.killed||e.kill("SIGKILL")},5e3).unref(),this.proc=null,Hn(this.hookFiles),this.hookFiles=null}onMessage(e){this.handler=e}onExit(e){this.exitHandler=e}handleRaw(e){let n=e.type;if(n==="system"&&e.subtype==="init"){let r=e.session_id??"";r&&r!==this.sessionId&&(Z.info({oldSessionId:this.sessionId,newSessionId:r},"session ID resolved"),v.emit("driver.init",{agent:"claude",sessionId:r}),this.sessionId=r);return}if(this.handler)switch(n){case"assistant":{let r=e.message?.content;if(!Array.isArray(r))break;for(let s of r)s.type==="tool_use"&&this.handler({type:"tool.call",sessionId:this.sessionId,toolName:s.name,input:s.input??{},toolCallId:s.id});break}case"user":{let r=e.message?.content;if(!Array.isArray(r))break;for(let s of r)if(s.type==="tool_result"){let i=up(s.content);if(!i)continue;if(s.is_error===!0&&typeof s.tool_use_id=="string"&&dp(i)){this.pendingPermissionDescriptions.set(s.tool_use_id,i);continue}this.handler({type:"tool.result",sessionId:this.sessionId,toolCallId:s.tool_use_id,output:i})}break}case"control_request":{let r=e.request;r?.subtype==="can_use_tool"&&(v.emit("approval.request",{agent:"claude",sessionId:this.sessionId,toolName:r.tool_name}),this.handler({type:"approval.request",sessionId:this.sessionId,requestId:e.request_id,toolName:r.tool_name??"unknown",input:r.input??{},description:r.description??r.title??""}));break}case"stream_event":{let r=e.event;r?.type==="content_block_delta"&&r?.delta?.type==="text_delta"&&r?.delta?.text&&this.handler({type:"text.delta",sessionId:this.sessionId,content:r.delta.text});break}case"result":{this.sawFinalResult=!0;let r=typeof e.result=="string"?e.result:"";if(e.is_error){ms("Claude failed."),this.handler({type:"error",sessionId:this.sessionId,message:Ll({resultText:r,stderrLines:this.lastStderr})});break}let s=Array.isArray(e.permission_denials)?e.permission_denials:[];if(s.length>0){let a=s[0]??{},l=typeof a.tool_use_id=="string"?a.tool_use_id:`missing_${Date.now()}`,c=typeof a.tool_name=="string"?a.tool_name:"unknown",u=a.tool_input&&typeof a.tool_input=="object"?a.tool_input:{},d=this.pendingPermissionDescriptions.get(l)??`Claude requested permissions to use ${c}.`;v.emit("approval.request",{agent:"claude",sessionId:this.sessionId,toolName:c}),this.handler({type:"approval.request",sessionId:this.sessionId,requestId:`${Ml}${l}`,toolName:c,input:u,description:d})}this.pendingPermissionDescriptions.clear();let i=e.total_cost_usd,o=e.usage?{inputTokens:e.usage.input_tokens,outputTokens:e.usage.output_tokens}:void 0;ms("Claude finished. Run `claude --continue` to continue on desktop."),v.emit("session.done",{agent:"claude",sessionId:this.sessionId,cost:i,usage:o}),this.handler({type:"session.done",sessionId:this.sessionId,cost:i,usage:o});break}}}};var ql=require("child_process"),Wl=require("fs");var ys=class{counters=new Map;timers=new Map;gauges=new Map;startTime=Date.now();logInterval=null;increment(e,n={}){this.counters.has(e)||this.counters.set(e,[]);let r=this.counters.get(e),s=JSON.stringify(n),i=r.find(o=>JSON.stringify(o.labels)===s);i?i.value++:r.push({value:1,labels:n})}gauge(e,n){this.gauges.set(e,n)}startTimer(e){let n=performance.now();return()=>{let r=Math.round(performance.now()-n),s=this.timers.get(e)??{count:0,totalMs:0,minMs:1/0,maxMs:0,lastMs:0};return s.count++,s.totalMs+=r,s.minMs=Math.min(s.minMs,r),s.maxMs=Math.max(s.maxMs,r),s.lastMs=r,this.timers.set(e,s),r}}snapshot(){let e={};for(let[s,i]of this.counters)e[s]=i.map(o=>({...o}));let n={};for(let[s,i]of this.timers)n[s]={...i,minMs:i.minMs===1/0?0:i.minMs};let r={};for(let[s,i]of this.gauges)r[s]=i;return{uptimeMs:Date.now()-this.startTime,counters:e,timers:n,gauges:r}}startPeriodicLog(e=6e4){this.logInterval||(this.logInterval=setInterval(()=>{let n=this.snapshot();B.info({metrics:n},"periodic metrics snapshot")},e),this.logInterval.unref())}stopPeriodicLog(){this.logInterval&&(clearInterval(this.logInterval),this.logInterval=null)}},I=new ys;var Dl=require("node:fs"),_s=require("node:path"),gp="@vibelet/cli";function Bl(t){try{let e=JSON.parse((0,Dl.readFileSync)(t,"utf8"));if(e.name===gp&&typeof e.version=="string"&&e.version.length>0)return e.version}catch{}return null}function mp(){return"0.0.7"}var ut=mp();var A=B.child({module:"codex"});function Q(t){return!t||typeof t!="object"||Array.isArray(t)?null:t}function k(t){return typeof t=="string"&&t.trim().length>0?t.trim():null}function yp(t){let e=k(t);return e?e.replace(/[^a-z0-9]/gi,"").toLowerCase():null}function Ss(t){return t?k(t.itemId)??k(t.id)??k(t.callId)??k(t.call_id):null}function vs(t,e){let n={};for(let[r,s]of Object.entries(t))e.includes(r)||(n[r]=s);return n}function jl(t){return/\bapprove\b|\ballow\b|\baccept\b|\byes\b|\bcontinue\b|\bproceed\b|\brun\b|\bapply\b/i.test(t)}function Gl(t){return/\bdeny\b|\breject\b|\bdecline\b|\bno\b|\bcancel\b|\babort\b|\bstop\b/i.test(t)}function Hl(t,e){if(!Array.isArray(t))return null;for(let n of t){let r=Q(n);if(!r)continue;let s=k(r.id),i=Array.isArray(r.options)?r.options.map(c=>Q(c)).filter(c=>!!c):[];if(!s||i.length===0)continue;let o=i.map(c=>k(c.label)).filter(c=>!!c);if(o.length===0)continue;let a=e?o.find(c=>jl(c)):o.find(c=>Gl(c)),l=e?o[0]:o[o.length-1];return{questionId:s,label:a??l}}return null}function _p(t){let e=Hl(t,!0),n=Hl(t,!1);return!e||!n?null:e.questionId!==n.questionId?{questionId:e.questionId,approveLabel:e.label,denyLabel:n.label}:{questionId:e.questionId,approveLabel:e.label,denyLabel:n.label}}function Sp(t){if(!Array.isArray(t)||t.length===0)return!1;let e=t.map(s=>Q(s)).filter(s=>!!s).flatMap(s=>(Array.isArray(s.options)?s.options:[]).map(o=>Q(o)).filter(o=>!!o).map(o=>k(o.label)).filter(o=>!!o)),n=e.some(s=>jl(s)),r=e.some(s=>Gl(s));return n&&r}function Fl(t){let e=yp(t.type??t.itemType);if(e==="commandexecution")return{toolName:"Bash",input:vs(t,["id","itemId","type","itemType","stdout","stderr","exitCode","exit_code","status","success","error"])};if(e==="filechange")return{toolName:"Patch",input:vs(t,["id","itemId","type","itemType","stdout","stderr","exitCode","exit_code","status","success","error"])};if(e==="mcptoolcall"){let n=k(t.server),r=k(t.tool)??k(t.name);return r?{toolName:n?`mcp__${n}__${r}`:r,input:Q(t.arguments)??Q(t.input)??{}}:null}return null}function vp(t){if(!Array.isArray(t))return"";for(let e of t){let n=Q(e);if(!n)continue;let r=k(n.question)??k(n.header);if(r)return r}return""}function Ul(t,e){return t==="autoApprove"?{approvalPolicy:"never",sandbox:"danger-full-access",sandboxPolicy:{type:"dangerFullAccess"}}:{approvalPolicy:"on-request",sandbox:"workspace-write",sandboxPolicy:{type:"workspaceWrite",writableRoots:[e],readOnlyAccess:{type:"fullAccess"},networkAccess:!0,excludeTmpdirEnvVar:!1,excludeSlashTmp:!1}}}var Un=class{proc=null;handler=null;exitHandler=null;buffer="";rpcId=0;pending=new Map;threadId="";lastStderr=[];approvalRequests=new Map;toolContextByCallId=new Map;approvalMode;cwd="";async start(e,n,r){this.approvalMode=r,this.cwd=e,this.approvalRequests.clear(),this.toolContextByCallId.clear();let s=S.codexPath,i,o=this.buildSpawnArgs();if(S.isTransientPath(s)){let c=S.execViaLoginShell("codex",o);i=c.command,o=c.args,A.info({spawnCmd:i,argsPreview:o.slice(0,2)},"spawning via login shell")}else i=s,A.info({spawnCmd:i,args:o},"spawning");v.emit("driver.spawn",{agent:"codex",cwd:e,resumeSessionId:n}),this.lastStderr=[],this.proc=(0,ql.spawn)(i,o,{cwd:e||void 0,stdio:["pipe","pipe","pipe"],env:S.buildSanitizedEnv()}),this.proc.on("error",c=>{let u=c.message;c.code==="ENOENT"&&e&&!(0,Wl.existsSync)(e)&&(u=`Working directory does not exist: ${e}`),A.error({error:u,cwd:e},"spawn error"),v.emit("driver.error",{agent:"codex",error:u})}),this.proc.stdout.on("data",c=>{this.buffer+=c.toString();let u=this.buffer.split(`
|
|
88
88
|
`);this.buffer=u.pop();for(let d of u)if(d.trim())try{this.handleRaw(JSON.parse(d))}catch{A.warn({linePreview:d.slice(0,200)},"failed to parse stdout line")}}),this.proc.stderr.on("data",c=>{let u=c.toString().trim();u&&(A.debug({stderr:u},"stderr"),this.lastStderr.push(u),this.lastStderr.length>10&&this.lastStderr.shift())}),this.proc.on("exit",c=>{A.info({threadId:this.threadId,exitCode:c},"process exited"),c&&c!==0&&A.error({threadId:this.threadId,exitCode:c,lastStderr:this.lastStderr.slice(-3)},"abnormal exit"),this.proc=null,this.approvalRequests.clear(),this.toolContextByCallId.clear();for(let[,{reject:u}]of this.pending)u(new Error(`Codex process exited with code ${c}`));this.pending.clear(),this.exitHandler?.(c),c&&this.handler&&this.threadId&&this.handler({type:"error",sessionId:this.threadId,message:`Codex process exited with code ${c}`})});let a=I.startTimer("rpc.duration");await this.rpc("initialize",{clientInfo:{name:"@vibelet/cli",version:ut},capabilities:{experimentalApi:!0}}),a(),this.rpcNotify("initialized",{});let l=Ul(this.approvalMode,e);if(n){let c=await this.rpc("thread/resume",{threadId:n,approvalPolicy:l.approvalPolicy,sandbox:l.sandbox,persistExtendedHistory:!0});this.threadId=c?.thread?.id??n,A.info({threadId:this.threadId},"thread resumed"),v.emit("driver.init",{agent:"codex",sessionId:this.threadId})}else{let c=await this.rpc("thread/start",{cwd:e,approvalPolicy:l.approvalPolicy,sandbox:l.sandbox,experimentalRawEvents:!0,persistExtendedHistory:!0});this.threadId=c?.thread?.id??c?.threadId??"",A.info({threadId:this.threadId},"thread created"),v.emit("driver.init",{agent:"codex",sessionId:this.threadId})}return this.threadId}buildSpawnArgs(){return["app-server","--listen","stdio://"]}sendPrompt(e){let n=Ul(this.approvalMode,this.cwd||process.cwd());A.info({threadId:this.threadId,promptPreview:e.slice(0,50)},"turn/start"),this.rpc("turn/start",{threadId:this.threadId,input:[{type:"text",text:e}],approvalPolicy:n.approvalPolicy,sandboxPolicy:n.sandboxPolicy}).then(r=>A.debug({resultPreview:JSON.stringify(r).slice(0,200)},"turn/start result")).catch(r=>{A.error({threadId:this.threadId,error:r.message},"sendPrompt error"),this.handler?.({type:"error",sessionId:this.threadId,message:r.message})})}respondApproval(e,n){if(!this.proc?.stdin?.writable)return!1;let r=this.approvalRequests.get(e),s=r?.rpcId??Number(e);if(!Number.isFinite(s))return!1;let i;if(!r)i=n?{decision:"approve"}:{decision:"deny",reason:"User denied from Vibelet"};else{switch(r.kind){case"command-execution":case"file-change":i={decision:n?"accept":"decline"};break;case"request-user-input-approval":i={answers:{[r.questionId]:{answers:[n?r.approveLabel:r.denyLabel]}}};break;case"exec-command-legacy":case"apply-patch-legacy":i={decision:n?"approved":"denied"};break;default:i={decision:n?"accept":"decline"};break}this.approvalRequests.delete(e)}return A.info({threadId:this.threadId,rpcId:s,approved:n},"approval response"),this.proc.stdin.write(JSON.stringify({jsonrpc:"2.0",id:s,result:i})+`
|
|
89
89
|
`),!0}interrupt(){this.rpc("turn/interrupt",{threadId:this.threadId}).catch(()=>{})}setApprovalMode(e){this.approvalMode=e,A.info({approvalMode:e},"approval mode updated (takes effect on restart)")}stop(){if(!this.proc)return;this.proc.kill("SIGTERM");let e=this.proc;setTimeout(()=>{e.killed||e.kill("SIGKILL")},5e3).unref(),this.proc=null,this.approvalRequests.clear(),this.toolContextByCallId.clear();for(let[,{reject:n}]of this.pending)n(new Error("Process stopped"));this.pending.clear()}onMessage(e){this.handler=e}onExit(e){this.exitHandler=e}rpc(e,n){let r=++this.rpcId,s=I.startTimer("rpc.duration");return new Promise((i,o)=>{if(this.pending.set(r,{resolve:a=>{s(),i(a)},reject:a=>{s(),o(a)}}),!this.proc?.stdin?.writable){this.pending.delete(r),s(),o(new Error("Process not available"));return}this.proc.stdin.write(JSON.stringify({jsonrpc:"2.0",method:e,id:r,params:n})+`
|
|
90
90
|
`),setTimeout(()=>{this.pending.has(r)&&(this.pending.delete(r),A.error({method:e,rpcId:r,threadId:this.threadId},"RPC timeout"),s(),o(new Error(`RPC timeout: ${e}`)))},3e4).unref()})}rpcNotify(e,n){this.proc?.stdin?.writable&&this.proc.stdin.write(JSON.stringify({jsonrpc:"2.0",method:e,params:n})+`
|