@aerostack/gateway 0.15.19 → 0.15.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +14 -14
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import{Server as W}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as G}from"@modelcontextprotocol/sdk/server/stdio.js";import{ListToolsRequestSchema as V,CallToolRequestSchema as z,ListResourcesRequestSchema as B,ReadResourceRequestSchema as
|
|
4
|
-
`),process.exit(1)),
|
|
5
|
-
`),process.exit(1));let O;try{if(O=new URL(
|
|
3
|
+
import{Server as W}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as G}from"@modelcontextprotocol/sdk/server/stdio.js";import{ListToolsRequestSchema as V,CallToolRequestSchema as z,ListResourcesRequestSchema as B,ReadResourceRequestSchema as F,ListPromptsRequestSchema as Y,GetPromptRequestSchema as J}from"@modelcontextprotocol/sdk/types.js";import{readFile as Q,writeFile as X}from"node:fs/promises";import{join as Z}from"node:path";import{homedir as ee}from"node:os";import{resolveApproval as b}from"./resolution.js";import{startHookServer as te,installClaudeHook as se,stopHookServer as re}from"./hook-server.js";import{OpenClawConnector as oe,resolveOpenClawToken as ne}from"./openclaw-connector.js";import{info as c,warn as d,error as ae}from"./logger.js";const L=Z(ee(),".openclaw","pre-authorized.json");async function ie(t){try{let s={};try{s=JSON.parse(await Q(L,"utf-8"))}catch{}s[t]=Date.now(),await X(L,JSON.stringify(s))}catch{}}const P=process.env.AEROSTACK_WORKSPACE_URL,u=process.env.AEROSTACK_TOKEN;function R(t,s,r){const e=parseInt(t??String(s),10);return Number.isFinite(e)&&e>=r?e:s}const $=R(process.env.AEROSTACK_APPROVAL_POLL_MS,3e3,500),I=R(process.env.AEROSTACK_APPROVAL_TIMEOUT_MS,864e5,5e3),U=R(process.env.AEROSTACK_REQUEST_TIMEOUT_MS,3e4,1e3),ce=process.env.AEROSTACK_HOOK_SERVER!=="false",le=R(process.env.AEROSTACK_HOOK_PORT,18321,1024),ue=process.env.AEROSTACK_HOOK_AUTO_INSTALL!=="false",pe=process.env.AEROSTACK_OPENCLAW_ENABLED!=="false",D=R(process.env.AEROSTACK_OPENCLAW_PORT,18789,1024),de=process.env.AEROSTACK_OPENCLAW_TOKEN;P||(process.stderr.write(`ERROR: AEROSTACK_WORKSPACE_URL is required
|
|
4
|
+
`),process.exit(1)),u||(process.stderr.write(`ERROR: AEROSTACK_TOKEN is required
|
|
5
|
+
`),process.exit(1));let O;try{if(O=new URL(P),O.protocol!=="https:"&&O.protocol!=="http:")throw new Error("must be http or https")}catch{process.stderr.write(`ERROR: AEROSTACK_WORKSPACE_URL must be a valid HTTP(S) URL
|
|
6
6
|
`),process.exit(1)}O.protocol==="http:"&&!O.hostname.match(/^(localhost|127\.0\.0\.1)$/)&&process.stderr.write(`WARNING: Using HTTP (not HTTPS) \u2014 token will be sent in plaintext
|
|
7
|
-
`);const
|
|
8
|
-
`);let e=null;for(const o of r)if(o.startsWith("data: "))try{e=JSON.parse(o.slice(6))}catch{}return e??{jsonrpc:"2.0",id:s,error:{code:-32603,message:"Empty SSE response"}}}const ge=new Set(["aerostack__guardian_report","aerostack__check_approval","aerostack__guardian_check"]);function we(t,s){if(ge.has(t))return;let r="other";const e=t.toLowerCase();e.includes("exec")||e.includes("bash")||e.includes("shell")||e.includes("command")||e.includes("run")?r="exec_command":e.includes("write")||e.includes("edit")||e.includes("create")||e.includes("patch")?r="file_write":e.includes("delete")||e.includes("remove")||e.includes("trash")||e.includes("unlink")?r="file_delete":e.includes("fetch")||e.includes("http")||e.includes("request")||e.includes("api")||e.includes("get")||e.includes("post")?r="api_call":e.includes("install")||e.includes("package")||e.includes("npm")||e.includes("pip")?r="package_install":e.includes("config")||e.includes("setting")||e.includes("env")?r="config_change":e.includes("deploy")||e.includes("publish")||e.includes("release")?r="deploy":e.includes("send")||e.includes("message")||e.includes("email")||e.includes("notify")||e.includes("slack")||e.includes("telegram")?r="message_send":(e.includes("read")||e.includes("query")||e.includes("search")||e.includes("list")||e.includes("get"))&&(r="data_access");let o;try{const n=JSON.stringify(s);o=n.length>500?n.slice(0,500)+"...":n}catch{o="(unable to serialize)"}
|
|
7
|
+
`);const p=P.replace(/\/+$/,""),K=crypto.randomUUID();function me(){return process.env.AEROSTACK_AGENT_TYPE?process.env.AEROSTACK_AGENT_TYPE:process.env.CLAUDECODE||process.env.CLAUDE_CODE?"claude-code":process.env.MCP_TRANSPORT==="stdio"?"mcp-stdio":"unknown"}const j=me();let m=null,y=Date.now();const he=3e4;async function h(t,s){const r={jsonrpc:"2.0",id:Date.now(),method:t,params:s??{}},e=new AbortController,o=setTimeout(()=>e.abort(),U);try{const n=await fetch(p,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${u}`,"User-Agent":"aerostack-gateway/0.15.14","X-Agent-Id":"aerostack-gateway","X-Bridge-Id":K,"X-Agent-Type":j},body:JSON.stringify(r),signal:e.signal});if(clearTimeout(o),(n.headers.get("content-type")??"").includes("text/event-stream")){const l=await n.text();return fe(l,r.id)}return await n.json()}catch(n){clearTimeout(o);const a=n instanceof Error?n.message:"Unknown error";return n instanceof Error&&n.name==="AbortError"?{jsonrpc:"2.0",id:r.id,error:{code:-32603,message:"Request timed out"}}:{jsonrpc:"2.0",id:r.id,error:{code:-32603,message:`HTTP error: ${a}`}}}}function fe(t,s){const r=t.split(`
|
|
8
|
+
`);let e=null;for(const o of r)if(o.startsWith("data: "))try{e=JSON.parse(o.slice(6))}catch{}return e??{jsonrpc:"2.0",id:s,error:{code:-32603,message:"Empty SSE response"}}}const ge=new Set(["aerostack__guardian_report","aerostack__check_approval","aerostack__guardian_check"]);function we(t,s){if(ge.has(t))return;let r="other";const e=t.toLowerCase();e.includes("exec")||e.includes("bash")||e.includes("shell")||e.includes("command")||e.includes("run")?r="exec_command":e.includes("write")||e.includes("edit")||e.includes("create")||e.includes("patch")?r="file_write":e.includes("delete")||e.includes("remove")||e.includes("trash")||e.includes("unlink")?r="file_delete":e.includes("fetch")||e.includes("http")||e.includes("request")||e.includes("api")||e.includes("get")||e.includes("post")?r="api_call":e.includes("install")||e.includes("package")||e.includes("npm")||e.includes("pip")?r="package_install":e.includes("config")||e.includes("setting")||e.includes("env")?r="config_change":e.includes("deploy")||e.includes("publish")||e.includes("release")?r="deploy":e.includes("send")||e.includes("message")||e.includes("email")||e.includes("notify")||e.includes("slack")||e.includes("telegram")?r="message_send":(e.includes("read")||e.includes("query")||e.includes("search")||e.includes("list")||e.includes("get"))&&(r="data_access");let o;try{const n=JSON.stringify(s);o=n.length>500?n.slice(0,500)+"...":n}catch{o="(unable to serialize)"}h("tools/call",{name:"aerostack__guardian_report",arguments:{action:`${t}(${Object.keys(s).join(", ")})`,category:r,risk_level:"low",details:o}}).catch(()=>{})}const ye=new Set(["aerostack__check_approval"]),H=[{name:"aerostack__chat_check",description:"Check for new messages from the workspace owner. Call this periodically or when asked to check for instructions.",inputSchema:{type:"object",properties:{},required:[]}},{name:"aerostack__chat_reply",description:"Send a reply message to the workspace owner via Agent Chat.",inputSchema:{type:"object",properties:{message:{type:"string",description:"Your reply message to the workspace owner"}},required:["message"]}}],_e=new Set(H.map(t=>t.name));function f(t){return t.replace(/\[/g,"(").replace(/\]/g,")")}const S=[],Ae=100;async function v(t,s){const r=new AbortController,e=setTimeout(()=>r.abort(),U);try{return await fetch(t,{...s,signal:r.signal})}finally{clearTimeout(e)}}async function Ee(){if(S.length>0){const t=S.splice(0);return y=Date.now(),[{type:"text",text:`Messages from workspace owner:
|
|
9
9
|
|
|
10
|
-
${t.map(r=>`${
|
|
10
|
+
${t.map(r=>`${f(r.sender_name)}: ${f(r.content)}`).join(`
|
|
11
11
|
|
|
12
|
-
`)}`}]}try{const s=await v(`${
|
|
12
|
+
`)}`}]}try{const s=await v(`${p}/chat/pending?since=${y}`,{headers:{Authorization:`Bearer ${u}`}});if(!s.ok)return[{type:"text",text:"No new messages."}];const e=(await s.json()).messages??[];return y=Date.now(),e.length===0?[{type:"text",text:"No new messages from the workspace owner."}]:[{type:"text",text:`Messages from workspace owner:
|
|
13
13
|
|
|
14
|
-
${e.map(n=>`${
|
|
14
|
+
${e.map(n=>`${f(n.sender_name)}: ${f(n.content)}`).join(`
|
|
15
15
|
|
|
16
|
-
`)}`}]}catch{return[{type:"text",text:"Failed to check messages."}]}}async function
|
|
16
|
+
`)}`}]}catch{return[{type:"text",text:"Failed to check messages."}]}}async function Te(t){const s=typeof t.message=="string"?t.message.trim().slice(0,1e4):"";if(!s)return[{type:"text",text:"Error: message is required."}];try{const r=await v(`${p}/chat/messages`,{method:"POST",headers:{Authorization:`Bearer ${u}`,"Content-Type":"application/json"},body:JSON.stringify({content:s})});return r.ok?[{type:"text",text:"Reply sent to workspace owner."}]:[{type:"text",text:`Failed to send reply: ${(await r.json().catch(()=>({error:"Unknown error"}))).error||r.statusText}`}]}catch{return[{type:"text",text:"Failed to send reply."}]}}async function Re(t,s){we(t,s);const r=await h("tools/call",{name:t,arguments:s});if(r.error?.code===-32050){const n=r.error.data,a=n?.approval_id;if(!a||!/^[a-zA-Z0-9_-]{4,128}$/.test(a))return{jsonrpc:"2.0",id:r.id,error:{code:-32603,message:"Approval required but no approval_id returned"}};c("Tool gate: blocking until approval resolves",{tool:t,approvalId:a});const i=await b({approvalId:a,wsUrl:n?.ws_url,pollUrl:n?.polling_url??`${p}/approval-status/${a}`,pollIntervalMs:$,timeoutMs:I,token:u});c("Tool gate resolved",{tool:t,status:i.status}),k({approvalId:a,toolName:t,toolArgs:s,sessionKey:null,gate:"tool_gate",pollUrl:"",authToken:u},i.status,!0);const l=x({approvalId:a,toolName:t,toolArgs:s,sessionKey:null,gate:"tool_gate",pollUrl:"",authToken:u},i);return{jsonrpc:"2.0",id:r.id,result:{content:[{type:"text",text:l}]}}}const o=r.result?._meta;if(o?.approval_id&&o?.status==="pending"){const n=o.approval_id;if(!/^[a-zA-Z0-9_-]{4,128}$/.test(n))return r;c("Permission gate: blocking until approval resolves",{tool:t,approvalId:n});const a=await b({approvalId:n,wsUrl:o.ws_url,pollUrl:o.polling_url??`${p}/approval-status/${n}`,pollIntervalMs:$,timeoutMs:I,token:u});c("Permission gate resolved",{tool:t,status:a.status}),k({approvalId:n,toolName:t,toolArgs:s,sessionKey:null,gate:"permission_gate",pollUrl:"",authToken:u},a.status,!0);const i=x({approvalId:n,toolName:t,toolArgs:s,sessionKey:null,gate:"permission_gate",pollUrl:"",authToken:u},a);return{jsonrpc:"2.0",id:r.id,result:{content:[{type:"text",text:i}]}}}return r}function He(t){b({approvalId:t.approvalId,wsUrl:t.wsUrl,pollUrl:t.pollUrl,pollIntervalMs:$,timeoutMs:I,token:t.authToken}).then(async s=>{c("Approval resolved",{tool:t.toolName,status:s.status,session:t.sessionKey});const r=x(t,s),e=t.sessionKey??m?.getLastActiveSession()??null;if((s.status==="approved"||s.status==="executed")&&e&&ie(e).catch(()=>{}),e&&m){if(await m.sendToSession(e,r)){c("Agent resumed via sessions.send",{session:e,status:s.status}),k(t,s.status,!0);return}d("sessions.send failed, falling back to channel notification",{session:e})}try{await g.notification({method:"notifications/claude/channel",params:{content:r,meta:{tool_name:t.toolName,approval_id:t.approvalId,status:s.status,gate:t.gate}}}),c("Agent resumed via channel notification",{tool:t.toolName,status:s.status}),k(t,s.status,!0)}catch(o){d("Channel notification failed",{error:o instanceof Error?o.message:String(o)}),k(t,s.status,!1)}}).catch(s=>{d("Background approval resolver error",{error:s instanceof Error?s.message:String(s)})})}function k(t,s,r){const e=typeof t.toolArgs.action=="string"?t.toolArgs.action:null,o=e??t.toolName.replace(/^(?:\w+__)*aerostack__/,"")??t.toolName,n=e?`${o}`:`${o}(${Object.keys(t.toolArgs).join(", ")})`,a=r?"resume sent to agent":"session unavailable \u2014 resume not delivered";let i;s==="approved"||s==="executed"?i=r?`[RESUMED] ${n} \u2014 ${a}`:`[RESUME FAILED] ${n} \u2014 ${a}`:s==="rejected"?i=`[REJECTED] ${n} \u2014 rejection sent to agent`:s==="changes_requested"?i=`[CHANGES REQUESTED] ${n} \u2014 feedback sent to agent`:i=`[EXPIRED] ${n} \u2014 approval timed out, expiry sent to agent`,h("tools/call",{name:"aerostack__guardian_report",arguments:{action:i.slice(0,500),category:"approval",risk_level:"low",details:JSON.stringify({tool:t.toolName,approvalId:t.approvalId,status:s,delivered:r,session:t.sessionKey}).slice(0,500)}}).catch(()=>{})}function x(t,s){const r=s.reviewer_note?.trim()||null,e=`${t.toolName}(${Object.keys(t.toolArgs).join(", ")})`;switch(s.status){case"approved":case"executed":return t.gate==="tool_gate"?["[APPROVAL RECEIVED] Your pending action has been approved.","",`Action: ${e}`,r?`Reviewer note: "${r}"`:null,"",`Please now execute this action: call ${t.toolName} with the same parameters as before.`].filter(o=>o!==null).join(`
|
|
17
17
|
`):["[APPROVAL RECEIVED] Your request has been approved by the workspace owner.",r?`Reviewer note: "${r}"`:null,"","You may now proceed with the action you requested approval for."].filter(o=>o!==null).join(`
|
|
18
18
|
`);case"changes_requested":return["[CHANGES REQUESTED] The workspace owner reviewed your action and requested changes.","",`Original action: ${e}`,`Reviewer feedback: "${r??"No details provided"}"`,"","Please revise your approach based on this feedback and try again.","Do NOT proceed with the original plan."].join(`
|
|
19
19
|
`);case"rejected":return["[REJECTED] The workspace owner denied this action.","",`Action: ${e}`,r?`Reason: "${r}"`:"No reason provided.","","Do not retry this action. If you believe this was a mistake, inform the user."].join(`
|
|
@@ -46,10 +46,10 @@ or before starting a new one, call aerostack__chat_check to see if the owner sen
|
|
|
46
46
|
If there are messages, read them carefully and respond using aerostack__chat_reply. This keeps
|
|
47
47
|
the owner informed and allows them to steer your work in real time.
|
|
48
48
|
=== END WORKSPACE CHAT ===
|
|
49
|
-
`.trim(),Oe=["delete","remove","drop","truncate","destroy","wipe","reset","deploy","publish","release","push","exec","shell","bash","run","command","terminal","install","uninstall","send","email","notify","webhook"];function Se(t,s){const r=t.toLowerCase(),e=Oe.some(n=>r.includes(n)),o=s??"";return e?`[REQUIRES GUARDIAN APPROVAL] ${o}`.trim():o}let M=null;async function
|
|
49
|
+
`.trim(),Oe=["delete","remove","drop","truncate","destroy","wipe","reset","deploy","publish","release","push","exec","shell","bash","run","command","terminal","install","uninstall","send","email","notify","webhook"];function Se(t,s){const r=t.toLowerCase(),e=Oe.some(n=>r.includes(n)),o=s??"";return e?`[REQUIRES GUARDIAN APPROVAL] ${o}`.trim():o}let M=null;async function A(){if(M)return;const t=await h("initialize",{protocolVersion:"2024-11-05",capabilities:{},clientInfo:{name:"aerostack-gateway",version:"0.15.14"}});if(t.result){const s=t.result,r=s.instructions??"";M={protocolVersion:s.protocolVersion??"2024-11-05",instructions:r?`${r}
|
|
50
50
|
|
|
51
|
-
${N}`:N}}}const
|
|
51
|
+
${N}`:N}}}const g=new W({name:"aerostack-gateway",version:"0.15.14"},{capabilities:{tools:{},resources:{},prompts:{},experimental:{"claude/channel":{}}},instructions:N});g.setRequestHandler(V,async()=>{await A();const t=await h("tools/list");if(t.error)throw new Error(t.error.message);const r=(t.result.tools??[]).filter(e=>!ye.has(e.name)).map(e=>({...e,description:Se(e.name,e.description)}));return r.push(...H),{tools:r}}),g.setRequestHandler(z,async t=>{await A();const{name:s,arguments:r}=t.params;if(_e.has(s))return{content:(s==="aerostack__chat_check"?await Ee():await Te(r??{})).map(i=>({...i,type:"text"}))};const e=await Re(s,r??{});if(e.error)return{content:[{type:"text",text:`Error: ${e.error.message}`}],isError:!0};const n=e.result.content??[{type:"text",text:JSON.stringify(e.result)}];if(Date.now()-y>he)try{const i=await v(`${p}/chat/pending?since=${y}`,{headers:{Authorization:`Bearer ${u}`}});if(i.ok){const E=(await i.json()).messages??[];if(y=Date.now(),E.length>0){const _=E.map(w=>`${f(w.sender_name)}: ${f(w.content)}`).join(`
|
|
52
52
|
`);n.unshift({type:"text",text:`--- WORKSPACE OWNER MESSAGE ---
|
|
53
|
-
${
|
|
54
|
-
--- END MESSAGE \u2014 please acknowledge ---`})}}}catch{}return{content:n}});const ve={uri:"aerostack://guardian/policy",name:"Aerostack Guardian Policy",description:"Mandatory workspace monitoring policy. Read this to understand required approval workflows.",mimeType:"text/plain"};
|
|
55
|
-
`);a=E.pop()??"";let
|
|
53
|
+
${_}
|
|
54
|
+
--- END MESSAGE \u2014 please acknowledge ---`})}}}catch{}return{content:n}});const ve={uri:"aerostack://guardian/policy",name:"Aerostack Guardian Policy",description:"Mandatory workspace monitoring policy. Read this to understand required approval workflows.",mimeType:"text/plain"};g.setRequestHandler(B,async()=>{await A();const t=await h("resources/list");if(t.error)throw new Error(t.error.message);const s=t.result;return{resources:[ve,...s.resources??[]]}}),g.setRequestHandler(F,async t=>{if(await A(),t.params.uri==="aerostack://guardian/policy")return{contents:[{uri:t.params.uri,text:N,mimeType:"text/plain"}]};const s=await h("resources/read",{uri:t.params.uri});if(s.error)throw new Error(s.error.message);return{contents:s.result.contents??[]}}),g.setRequestHandler(Y,async()=>{await A();const t=await h("prompts/list");if(t.error)throw new Error(t.error.message);return{prompts:t.result.prompts??[]}}),g.setRequestHandler(J,async t=>{await A();const s=await h("prompts/get",{name:t.params.name,arguments:t.params.arguments});if(s.error)throw new Error(s.error.message);return{messages:s.result.messages??[]}});async function ke(){c("Connecting to workspace",{url:p});const t=new G;await g.connect(t),c("Ready",{url:p});const s=()=>{v(`${p}/chat/heartbeat`,{method:"POST",headers:{Authorization:`Bearer ${u}`,"Content-Type":"application/json"},body:JSON.stringify({agent_type:j,user_agent:"aerostack-gateway/0.15.14",bridge_id:K})}).catch(()=>{})};s();const r=setInterval(s,12e4);if(process.on("exit",()=>clearInterval(r)),ce)try{const o=await te(async n=>{try{const a=await fetch(`${p}/guardian-batch`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${u}`,"User-Agent":"aerostack-gateway/0.15.14","X-Agent-Id":"aerostack-gateway"},body:JSON.stringify({events:n})});return a.ok?(await a.json()).config?.hook_tracking??null:null}catch{return null}},le);ue&&await se(o)&&c("Claude Code hook auto-installed",{port:o})}catch(e){d("Hook server failed to start (non-fatal)",{error:e instanceof Error?e.message:String(e)})}if(pe)try{const e=de??await ne();e?(m=new oe({port:D,token:e,rpcCall:h}),await m.connect()?c("OpenClaw connector started",{port:D}):(c("OpenClaw gateway not reachable, skipping connector"),m=null)):c("OpenClaw integration skipped (no token found)")}catch(e){d("OpenClaw connector failed (non-fatal)",{error:e instanceof Error?e.message:String(e)})}Ce()}let C=null;function Ce(){C&&C.abort(),C=new AbortController;const t=async()=>{try{const e=await fetch(p,{method:"GET",headers:{Authorization:`Bearer ${u}`,Accept:"text/event-stream"},signal:C.signal});if(!e.ok||!e.body){d("Chat event listener: failed to connect",{status:e.status}),r();return}c("Chat event listener connected");const o=e.body.getReader(),n=new TextDecoder;let a="";for(;;){const{done:i,value:l}=await o.read();if(i)break;a+=n.decode(l,{stream:!0});const E=a.split(`
|
|
55
|
+
`);a=E.pop()??"";let _="",w="";for(const T of E)T.startsWith("event: ")?_=T.slice(7).trim():T.startsWith("data: ")?w=T.slice(6):T===""&&_&&w&&(_==="aerostack_event"&&Ne(w),_="",w="")}c("Chat event listener: stream ended, reconnecting"),r()}catch(e){if(e?.name==="AbortError")return;d("Chat event listener error",{error:e?.message}),r()}};let s=null;const r=()=>{s||(s=setTimeout(()=>{s=null,t()},5e3))};t()}async function Ne(t){try{const s=JSON.parse(t);if(s.type!=="chat_message"||!s.content)return;c("Chat message received from admin",{sender:s.sender_name,sessionId:s.session_id}),S.length>=Ae&&S.shift(),S.push({sender_name:s.sender_name??"Admin",content:s.content,created_at:Date.now()}),y=Date.now();const r=f(s.sender_name??"Admin"),e=f(s.content);if(m){const o=m.getLastActiveSession()||"agent:main:main";m.sendToSession(o,`[Workspace Owner \u2014 ${r}]: ${e}`).catch(()=>{})}try{const{execFile:o}=await import("child_process");c("Spawning agent turn for chat response",{sender:r}),o("openclaw",["agent","--agent","main","--json","-m",`The workspace owner (${r}) says: "${e}". Reply briefly and helpfully. Do NOT call any tools \u2014 just respond with text.`],{timeout:6e4},async(n,a)=>{let i="";if(!n&&a)try{const l=JSON.parse(a.trim());i=l.text||l.reply||l.message||a.trim()}catch{i=a.trim()}(!i||i.length<2)&&(i=`Message received. I'll process "${e.slice(0,100)}" shortly.`);try{const l=await v(`${p}/chat/messages`,{method:"POST",headers:{Authorization:`Bearer ${u}`,"Content-Type":"application/json"},body:JSON.stringify({content:i.slice(0,1e4)})});l.ok?c("Chat reply sent to workspace"):d("Chat reply failed",{status:l.status})}catch(l){d("Failed to send chat reply",{error:l?.message})}})}catch(o){d("Failed to spawn agent turn",{error:o?.message})}}catch{}}function q(){C?.abort(),m?.stop(),re(),process.exit(0)}process.on("SIGTERM",()=>{q()}),process.on("SIGINT",()=>{q()}),ke().catch(t=>{ae("Fatal error",{error:t instanceof Error?t.message:String(t)}),process.exit(1)});
|