grix-connector 4.7.0 → 4.7.1
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/adapter/claude/claude-bridge-server.js +1 -1
- package/dist/adapter/claude/claude-tools.js +1 -1
- package/dist/adapter/claude/claude-worker-client.js +1 -1
- package/dist/adapter/claude/mcp-http-launcher.js +2 -2
- package/dist/adapter/claude/result-timeout.js +1 -1
- package/dist/assets/dsh-bridge/{grix-dsh-bridge-4.7.0.tgz → grix-dsh-bridge-4.7.1.tgz} +0 -0
- package/dist/assets/dsh-bridge/manifest.json +5 -5
- package/dist/core/access/allowlist-store.js +1 -1
- package/dist/core/file-ops/list-files.js +1 -1
- package/dist/core/installer/npm-registry.js +4 -4
- package/dist/core/upgrade/npm-upgrader.js +2 -2
- package/dist/log.js +2 -2
- package/dist/mcp/stream-http/config.js +1 -1
- package/dist/mcp/stream-http/connection-binding.js +1 -1
- package/dist/mcp/stream-http/security.js +1 -1
- package/dist/mcp/stream-http/tool-executor.js +1 -1
- package/dist/mcp/stream-http/tool-registry.js +1 -1
- package/dist/mcp/stream-http/tool-schemas.js +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import c from"node:http";import{randomUUID as d}from"node:crypto";import{log as o}from"../../core/log/index.js";function l(t){t.writeHead(401,{"content-type":"application/json"}),t.end(JSON.stringify({error:"unauthorized"}))}function u(t){t.writeHead(404,{"content-type":"application/json"}),t.end(JSON.stringify({error:"not_found"}))}function h(t,e){t.writeHead(400,{"content-type":"application/json"}),t.end(JSON.stringify({error:e}))}function p(t,e={ok:!0}){t.writeHead(200,{"content-type":"application/json"}),t.end(JSON.stringify(e))}async function v(t){const e=[];for await(const
|
|
1
|
+
import c from"node:http";import{randomUUID as d}from"node:crypto";import{log as o}from"../../core/log/index.js";function l(t){t.writeHead(401,{"content-type":"application/json"}),t.end(JSON.stringify({error:"unauthorized"}))}function u(t){t.writeHead(404,{"content-type":"application/json"}),t.end(JSON.stringify({error:"not_found"}))}function h(t,e){t.writeHead(400,{"content-type":"application/json"}),t.end(JSON.stringify({error:e}))}function p(t,e={ok:!0}){t.writeHead(200,{"content-type":"application/json"}),t.end(JSON.stringify(e))}async function v(t){const e=[];for await(const r of t)e.push(r);const n=Buffer.concat(e).toString("utf8").trim();return n?JSON.parse(n):{}}function k(t){const e=(t.headers.authorization??"").trim();return e.toLowerCase().startsWith("bearer ")?e.slice(7).trim():""}class w{host="127.0.0.1";port=0;token;callbacks;server=null;address=null;constructor(e){this.token=d(),this.callbacks=e}getToken(){return this.token}getURL(){return this.address?`http://${this.address.address}:${this.address.port}`:""}async start(){this.server||(this.server=c.createServer(async(e,n)=>{try{await this.handleRequest(e,n)}catch(r){h(n,r instanceof Error?r.message:String(r))}}),await new Promise((e,n)=>{this.server.once("error",n),this.server.listen(this.port,this.host,()=>{this.server.off("error",n),e()})}),this.address=this.server.address(),o.info("claude-bridge",`Bridge server listening on ${this.getURL()}`))}async stop(){if(!this.server)return;const e=this.server;this.server=null,this.address=null,e.closeIdleConnections?.(),e.closeAllConnections?.(),await new Promise((n,r)=>{e.close(s=>s?r(s):n())})}async handleRequest(e,n){if(k(e)!==this.token){l(n);return}if(e.method!=="POST"){n.writeHead(405,{"content-type":"application/json"}),n.end(JSON.stringify({error:"method_not_allowed"}));return}const r=new URL(e.url,"http://localhost").pathname,s=await v(e),i=f.get(r);if(!i){u(n);return}const a=await i(this.callbacks,s);p(n,a??{ok:!0})}}const f=new Map([["/v1/worker/register",async(t,e)=>(o.info("claude-bridge",`Worker registered: ${e.worker_id} (pid=${e.pid})`),t.onRegisterWorker(e))],["/v1/worker/status",async(t,e)=>(o.info("claude-bridge",`Worker status: ${e.status}`),t.onStatusUpdate(e))],["/v1/worker/send-text",async(t,e)=>t.onSendText(e)],["/v1/worker/send-stream-chunk",async(t,e)=>t.onSendStreamChunk(e)],["/v1/worker/send-media",async(t,e)=>t.onSendMedia(e)],["/v1/worker/delete-message",async(t,e)=>t.onDeleteMessage(e)],["/v1/worker/ack-event",async(t,e)=>t.onAckEvent(e)],["/v1/worker/event-result",async(t,e)=>t.onSendEventResult(e)],["/v1/worker/event-stop-ack",async(t,e)=>t.onSendEventStopAck(e)],["/v1/worker/event-stop-result",async(t,e)=>t.onSendEventStopResult(e)],["/v1/worker/session-composing",async(t,e)=>t.onSetSessionComposing(e)],["/v1/worker/agent-invoke",async(t,e)=>t.onAgentInvoke(e)],["/v1/worker/local-action-result",async(t,e)=>t.onLocalActionResult(e)]]);export{w as ClaudeBridgeServer};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{randomUUID as x}from"node:crypto";import{CallToolRequestSchema as S,ListToolsRequestSchema as w}from"@modelcontextprotocol/sdk/types.js";import{log as f}from"../../core/log/index.js";import{toolCallToInvoke as k}from"../../core/mcp/tools.js";const E=new Set(["contact_search","session_search","message_history","message_search","group_create","group_detail_read","group_leave_self","group_member_add","group_member_remove","group_member_role_update","group_all_members_muted_update","group_member_speaking_update","group_dissolve","send_msg","delete_msg","agent_api_create","agent_category_list","agent_category_create","agent_category_update","agent_category_assign","agent_api_key_rotate"]),y=3e4,I=[{name:"reply",description:"Send a visible message back to the chat for this grix-claude event.",inputSchema:{type:"object",properties:{text:{type:"string",description:"The visible reply text to send."},chat_id:{type:"string",description:"The target chat/session id from the <channel> tag."},event_id:{type:"string",description:"The Aibot event_id from the <channel> tag."},reply_to:{type:"string",description:"Optional message_id to quote instead of the inbound trigger message."},files:{type:"array",items:{type:"string"},description:"Optional absolute local file paths. Each file is uploaded through Agent API OSS presign before sending."},final:{type:"boolean",description:"Whether this is the final reply for the event. Defaults to false \u2014 the event stays open while Claude continues working, and auto-completes after inactivity. Set true only when this is definitively the last message for the event."}},required:["chat_id","event_id"]}},{name:"complete",description:"Finish an event without sending a visible reply so the backend does not time out.",inputSchema:{type:"object",properties:{event_id:{type:"string",description:"The Aibot event_id from the <channel> tag."},status:{type:"string",enum:["responded","canceled","failed"]},code:{type:"string"},msg:{type:"string"}},required:["event_id","status"]}},{name:"delete_message",description:"Delete a previously sent message in the same grix-claude chat.",inputSchema:{type:"object",properties:{chat_id:{type:"string"},message_id:{type:"string"}},required:["chat_id","message_id"]}},{name:"status",description:"Show grix-claude runtime status, upstream access state, bridge health, and startup hints.",inputSchema:{type:"object",properties:{}}},{name:"send",description:"Send a message to a chat session proactively, without requiring an inbound event. Use for notifications or scheduled reports.",inputSchema:{type:"object",properties:{chat_id:{type:"string",description:"The target chat/session id."},text:{type:"string",description:"The message text to send."}},required:["chat_id","text"]}},{name:"access_pair",description:"Forward a sender pairing approval code to upstream access control.",inputSchema:{type:"object",properties:{code:{type:"string"}},required:["code"]}},{name:"access_deny",description:"Forward a sender pairing denial code to upstream access control.",inputSchema:{type:"object",properties:{code:{type:"string"}},required:["code"]}},{name:"allow_sender",description:"Ask upstream access control to allow a sender_id.",inputSchema:{type:"object",properties:{sender_id:{type:"string"}},required:["sender_id"]}},{name:"remove_sender",description:"Ask upstream access control to remove a sender_id.",inputSchema:{type:"object",properties:{sender_id:{type:"string"}},required:["sender_id"]}},{name:"access_policy",description:"Ask upstream access control to update the sender access policy.",inputSchema:{type:"object",properties:{policy:{type:"string",enum:["allowlist","open","disabled"]}},required:["policy"]}},{name:"grix_query",description:"Search contacts, sessions, message history, or messages by keyword in the Grix/AIBot platform.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["contact_search","session_search","message_history","message_search"]},keyword:{type:"string"},id:{type:"string"},sessionId:{type:"string"},limit:{type:"number"},offset:{type:"number"},beforeId:{type:"string"}},required:["action"]}},{name:"grix_group",description:"Manage groups in the Grix/AIBot platform: create, get details, leave, dissolve, manage members and permissions.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["create","detail","leave","add_members","remove_members","update_member_role","update_all_members_muted","update_member_speaking","dissolve"]},sessionId:{type:"string"},name:{type:"string"},memberIds:{type:"array",items:{type:"string"}},memberTypes:{type:"array",items:{type:"integer",enum:[1,2]}},memberId:{type:"string"},role:{type:"integer",enum:[1,2]},memberType:{type:"integer",description:"Member type (for update_member_role / update_member_speaking)."},allMembersMuted:{type:"boolean"},isSpeakMuted:{type:"boolean"},canSpeakWhenAllMuted:{type:"boolean",description:"Allow speaking when all muted (for update_member_speaking)."}},required:["action"]}},{name:"grix_message_send",description:"Send a message to a session in the Grix/AIBot platform.",inputSchema:{type:"object",properties:{sessionId:{type:"string"},content:{type:"string"},msgType:{type:"number"},quotedMessageId:{type:"string"},threadId:{type:"string"}},required:["sessionId","content"]}},{name:"grix_message_unsend",description:"Recall/unsend a message in the Grix/AIBot platform.",inputSchema:{type:"object",properties:{sessionId:{type:"string"},msgId:{type:"string"}},required:["sessionId","msgId"]}},{name:"grix_admin",description:"Agent and category management in the Grix/AIBot platform: create agents, manage categories, rotate API keys.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["create_agent","list_categories","create_category","update_category","assign_category","rotate_api_key"]},agentId:{type:"string"},agentName:{type:"string"},introduction:{type:"string"},isMain:{type:"boolean"},categoryId:{type:"string"},name:{type:"string"},parentId:{type:"string"},sortOrder:{type:"number"}},required:["action"]}}];function q(n,e){n.setRequestHandler(w,async()=>({tools:I})),n.setRequestHandler(S,async i=>{const{name:r,arguments:t}=i.params,s=t??{};try{switch(r){case"reply":return await A(s,e);case"complete":return await $(s,e);case"delete_message":return await T(s,e);case"status":return j(e);case"send":return await M(s,e);case"access_pair":case"access_deny":case"allow_sender":case"remove_sender":case"access_policy":return await R(r,s,e);case"grix_query":case"grix_group":case"grix_message_send":case"grix_message_unsend":case"grix_admin":return await O(r,s,e);default:return{content:[{type:"text",text:`Unknown tool: ${r}`}],isError:!0}}}catch(a){return f.error("claude-tools",`Tool ${r} error: ${a}`),{content:[{type:"text",text:`Error: ${a instanceof Error?a.message:String(a)}`}],isError:!0}}})}async function A(n,e){const i=e.getActiveEvent();if(!i)return{content:[{type:"text",text:"No active event to reply to"}],isError:!0};const r=String(n.text??""),t=String(n.chat_id??""),s=String(n.event_id??i.eventId),a=n.reply_to,d=n.files,_=n.final===!0;if(!t||!s)return{content:[{type:"text",text:"reply requires chat_id and event_id"}],isError:!0};if(!r.trim()&&(!d||d.length===0))return{content:[{type:"text",text:"reply requires at least one of text or files"}],isError:!0};const{text:g,quotedMessageId:v}=e.resolveQuotedMessageId(a,r),b=[];let m=0;const h=`reply_${s}_${Date.now()}`;try{if(g){const p=e.splitText(g);for(let o=0;o<p.length;o++){if(!e.isEventActive(s))return c("ignored: event no longer active");m++,e.bridge.sendStreamChunk(s,t,p[o],++i.chunkSeq,!1,h)}}if(d&&d.length>0)for(const p of d){if(!e.isEventActive(s))return c("ignored: event no longer active");m++;const o=await e.uploadFile(p,t),l=`${x()}_${m}`;e.bridge.sendMedia(s,t,o.access_url,o.file_name,v,l,o.extra),f.info("claude-tools",`File sent: ${o.file_name}`)}e.bridge.sendStreamChunk(s,t,"",++i.chunkSeq,!0,h)}catch(p){if(g&&b.length===0)try{const o=`fallback_${s}_${Date.now()}`,l=e.splitText(g);for(let u=0;u<l.length;u++)e.bridge.sendStreamChunk("",t,l[u],u+1,!1,o);return e.bridge.sendStreamChunk("",t,"",l.length+1,!0,o),e.markReplySent(s),_&&e.finalizeEvent(s,"responded"),c("sent via fallback")}catch{}if(!e.isEventActive(s))return c("ignored: event no longer active");throw e.bridge.sendEventResult(s,"failed",String(p),"send_msg_failed"),p}return e.markReplySent(s),_?e.finalizeEvent(s,"responded"):(i.responded=!0,e.clearActiveEvent("completed")),c("Reply sent")}async function $(n,e){const i=e.getActiveEvent(),r=String(n.event_id??""),t=n.status??"",s=n.code,a=n.msg;if(!r||!t)return{content:[{type:"text",text:"complete requires event_id and status"}],isError:!0};const d=["responded","canceled","failed"];return d.includes(t)?e.isEventActive(r)?(e.bridge.sendEventResult(r,t,a,s),e.clearActiveEvent(t),c("Event completed")):c("ignored: event no longer active"):{content:[{type:"text",text:`status must be one of: ${d.join(", ")}`}],isError:!0}}async function T(n,e){const i=String(n.chat_id??""),r=String(n.message_id??"");if(!i||!r)return{content:[{type:"text",text:"chat_id and message_id are required"}],isError:!0};try{return await e.bridge.agentInvoke("grix_message_unsend",{sessionId:i,msgId:r},y),c(`deleted (${r})`)}catch(t){return{content:[{type:"text",text:`Delete failed: ${t}`}],isError:!0}}}function j(n){const e=n.getStatusInfo();return{content:[{type:"text",text:JSON.stringify({alive:e.alive,active_event:e.activeEvent,pending_approvals:e.pendingPermissions,pending_questions:e.pendingElicitations})}]}}async function M(n,e){const i=String(n.chat_id??""),r=String(n.text??"");if(!i||!r)return{content:[{type:"text",text:"chat_id and text are required"}],isError:!0};try{const t=e.splitText(r),s=`send_${i}_${Date.now()}`;for(let a=0;a<t.length;a++)e.bridge.sendStreamChunk("",i,t[a],a+1,!1,s);return e.bridge.sendStreamChunk("",i,"",t.length+1,!0,s),c("sent")}catch(t){return{content:[{type:"text",text:`Send failed: ${t}`}],isError:!0}}}const C={access_pair:{verb:"pair_approve",payloadKey:"code"},access_deny:{verb:"pair_deny",payloadKey:"code"},allow_sender:{verb:"sender_allow",payloadKey:"sender_id"},remove_sender:{verb:"sender_remove",payloadKey:"sender_id"},access_policy:{verb:"policy_set",payloadKey:"policy"}};async function R(n,e,i){try{const r=C[n];if(!r)throw new Error(`Unknown access control tool: ${n}`);const t={};e.code!=null&&(t.code=e.code),e.sender_id!=null&&(t.sender_id=e.sender_id),e.policy!=null&&(t.policy=e.policy);const s=await i.bridge.agentInvoke("claude_access_control",{verb:r.verb,payload:t},y);return{content:[{type:"text",text:typeof s=="string"?s:JSON.stringify(s)}]}}catch(r){return{content:[{type:"text",text:`${n} failed: ${r}`}],isError:!0}}}async function O(n,e,i){try{const r=k(n,e);if(!E.has(r.action))throw new Error(`Action not allowed: ${r.action}`);const t=await i.bridge.agentInvoke(r.action,r.params,y);if(t&&Number(t.code??0)!==0)throw new Error(String(t.msg??"invoke failed"));return{content:[{type:"text",text:t?.data!=null?typeof t.data=="string"?t.data:JSON.stringify(t.data):JSON.stringify(t)}]}}catch(r){return{content:[{type:"text",text:`${n} failed: ${r}`}],isError:!0}}}function c(n){return{content:[{type:"text",text:n}]}}export{q as registerClaudeTools};
|
|
1
|
+
import{randomUUID as x}from"node:crypto";import{CallToolRequestSchema as S,ListToolsRequestSchema as w}from"@modelcontextprotocol/sdk/types.js";import{log as f}from"../../core/log/index.js";import{toolCallToInvoke as k}from"../../core/mcp/tools.js";const E=new Set(["contact_search","session_search","message_history","message_search","group_create","group_detail_read","group_leave_self","group_member_add","group_member_remove","group_member_role_update","group_all_members_muted_update","group_member_speaking_update","group_dissolve","send_msg","delete_msg","agent_api_create","agent_category_list","agent_category_create","agent_category_update","agent_category_assign","agent_api_key_rotate"]),y=3e4,I=[{name:"reply",description:"Send a visible message back to the chat for this grix-claude event.",inputSchema:{type:"object",properties:{text:{type:"string",description:"The visible reply text to send."},chat_id:{type:"string",description:"The target chat/session id from the <channel> tag."},event_id:{type:"string",description:"The Aibot event_id from the <channel> tag."},reply_to:{type:"string",description:"Optional message_id to quote instead of the inbound trigger message."},files:{type:"array",items:{type:"string"},description:"Optional absolute local file paths. Each file is uploaded through Agent API OSS presign before sending."},final:{type:"boolean",description:"Whether this is the final reply for the event. Defaults to false \u2014 the event stays open while Claude continues working, and auto-completes after inactivity. Set true only when this is definitively the last message for the event."}},required:["chat_id","event_id"]}},{name:"complete",description:"Finish an event without sending a visible reply so the backend does not time out.",inputSchema:{type:"object",properties:{event_id:{type:"string",description:"The Aibot event_id from the <channel> tag."},status:{type:"string",enum:["responded","canceled","failed"]},code:{type:"string"},msg:{type:"string"}},required:["event_id","status"]}},{name:"delete_message",description:"Delete a previously sent message in the same grix-claude chat.",inputSchema:{type:"object",properties:{chat_id:{type:"string"},message_id:{type:"string"}},required:["chat_id","message_id"]}},{name:"status",description:"Show grix-claude runtime status, upstream access state, bridge health, and startup hints.",inputSchema:{type:"object",properties:{}}},{name:"send",description:"Send a message to a chat session proactively, without requiring an inbound event. Use for notifications or scheduled reports.",inputSchema:{type:"object",properties:{chat_id:{type:"string",description:"The target chat/session id."},text:{type:"string",description:"The message text to send."}},required:["chat_id","text"]}},{name:"access_pair",description:"Forward a sender pairing approval code to upstream access control.",inputSchema:{type:"object",properties:{code:{type:"string"}},required:["code"]}},{name:"access_deny",description:"Forward a sender pairing denial code to upstream access control.",inputSchema:{type:"object",properties:{code:{type:"string"}},required:["code"]}},{name:"allow_sender",description:"Ask upstream access control to allow a sender_id.",inputSchema:{type:"object",properties:{sender_id:{type:"string"}},required:["sender_id"]}},{name:"remove_sender",description:"Ask upstream access control to remove a sender_id.",inputSchema:{type:"object",properties:{sender_id:{type:"string"}},required:["sender_id"]}},{name:"access_policy",description:"Ask upstream access control to update the sender access policy.",inputSchema:{type:"object",properties:{policy:{type:"string",enum:["allowlist","open","disabled"]}},required:["policy"]}},{name:"grix_query",description:"Search contacts, sessions, message history, or messages by keyword in the Grix/AIBot platform.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["contact_search","session_search","message_history","message_search"]},keyword:{type:"string"},id:{type:"string"},sessionId:{type:"string"},limit:{type:"number"},offset:{type:"number"},beforeId:{type:"string"}},required:["action"]}},{name:"grix_group",description:"Manage groups in the Grix/AIBot platform: create, get details, leave, dissolve, manage members and permissions.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["create","detail","leave","add_members","remove_members","update_member_role","update_all_members_muted","update_member_speaking","dissolve"]},sessionId:{type:"string"},name:{type:"string"},memberIds:{type:"array",items:{type:"string"}},memberTypes:{type:"array",items:{type:"integer",enum:[1,2]}},memberId:{type:"string"},role:{type:"integer",enum:[1,2]},memberType:{type:"integer",description:"Member type (for update_member_role / update_member_speaking)."},allMembersMuted:{type:"boolean"},isSpeakMuted:{type:"boolean"},canSpeakWhenAllMuted:{type:"boolean",description:"Allow speaking when all muted (for update_member_speaking)."}},required:["action"]}},{name:"grix_message_send",description:"Send a message to a session in the Grix/AIBot platform.",inputSchema:{type:"object",properties:{sessionId:{type:"string"},content:{type:"string"},msgType:{type:"number"},quotedMessageId:{type:"string"},threadId:{type:"string"}},required:["sessionId","content"]}},{name:"grix_message_unsend",description:"Recall/unsend a message in the Grix/AIBot platform.",inputSchema:{type:"object",properties:{sessionId:{type:"string"},msgId:{type:"string"}},required:["sessionId","msgId"]}},{name:"grix_admin",description:"Agent and category management in the Grix/AIBot platform: create agents, manage categories, rotate API keys.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["create_agent","list_categories","create_category","update_category","assign_category","rotate_api_key"]},agentId:{type:"string"},agentName:{type:"string"},introduction:{type:"string"},isMain:{type:"boolean"},categoryId:{type:"string"},name:{type:"string"},parentId:{type:"string"},sortOrder:{type:"number"}},required:["action"]}}];function q(r,e){r.setRequestHandler(w,async()=>({tools:I})),r.setRequestHandler(S,async i=>{const{name:n,arguments:t}=i.params,s=t??{};try{switch(n){case"reply":return await A(s,e);case"complete":return await $(s,e);case"delete_message":return await T(s,e);case"status":return j(e);case"send":return await M(s,e);case"access_pair":case"access_deny":case"allow_sender":case"remove_sender":case"access_policy":return await R(n,s,e);case"grix_query":case"grix_group":case"grix_message_send":case"grix_message_unsend":case"grix_admin":return await O(n,s,e);default:return{content:[{type:"text",text:`Unknown tool: ${n}`}],isError:!0}}}catch(a){return f.error("claude-tools",`Tool ${n} error: ${a}`),{content:[{type:"text",text:`Error: ${a instanceof Error?a.message:String(a)}`}],isError:!0}}})}async function A(r,e){const i=e.getActiveEvent();if(!i)return{content:[{type:"text",text:"No active event to reply to"}],isError:!0};const n=String(r.text??""),t=String(r.chat_id??""),s=String(r.event_id??i.eventId),a=r.reply_to,d=r.files,_=r.final===!0;if(!t||!s)return{content:[{type:"text",text:"reply requires chat_id and event_id"}],isError:!0};if(!n.trim()&&(!d||d.length===0))return{content:[{type:"text",text:"reply requires at least one of text or files"}],isError:!0};const{text:g,quotedMessageId:v}=e.resolveQuotedMessageId(a,n),b=[];let m=0;const h=`reply_${s}_${Date.now()}`;try{if(g){const p=e.splitText(g);for(let o=0;o<p.length;o++){if(!e.isEventActive(s))return c("ignored: event no longer active");m++,e.bridge.sendStreamChunk(s,t,p[o],++i.chunkSeq,!1,h)}}if(d&&d.length>0)for(const p of d){if(!e.isEventActive(s))return c("ignored: event no longer active");m++;const o=await e.uploadFile(p,t),l=`${x()}_${m}`;e.bridge.sendMedia(s,t,o.access_url,o.file_name,v,l,o.extra),f.info("claude-tools",`File sent: ${o.file_name}`)}e.bridge.sendStreamChunk(s,t,"",++i.chunkSeq,!0,h)}catch(p){if(g&&b.length===0)try{const o=`fallback_${s}_${Date.now()}`,l=e.splitText(g);for(let u=0;u<l.length;u++)e.bridge.sendStreamChunk("",t,l[u],u+1,!1,o);return e.bridge.sendStreamChunk("",t,"",l.length+1,!0,o),e.markReplySent(s),_&&e.finalizeEvent(s,"responded"),c("sent via fallback")}catch{}if(!e.isEventActive(s))return c("ignored: event no longer active");throw e.bridge.sendEventResult(s,"failed",String(p),"send_msg_failed"),p}return e.markReplySent(s),_?e.finalizeEvent(s,"responded"):(i.responded=!0,e.clearActiveEvent("completed")),c("Reply sent")}async function $(r,e){const i=e.getActiveEvent(),n=String(r.event_id??""),t=r.status??"",s=r.code,a=r.msg;if(!n||!t)return{content:[{type:"text",text:"complete requires event_id and status"}],isError:!0};const d=["responded","canceled","failed"];return d.includes(t)?e.isEventActive(n)?(e.bridge.sendEventResult(n,t,a,s),e.clearActiveEvent(t),c("Event completed")):c("ignored: event no longer active"):{content:[{type:"text",text:`status must be one of: ${d.join(", ")}`}],isError:!0}}async function T(r,e){const i=String(r.chat_id??""),n=String(r.message_id??"");if(!i||!n)return{content:[{type:"text",text:"chat_id and message_id are required"}],isError:!0};try{return await e.bridge.agentInvoke("grix_message_unsend",{sessionId:i,msgId:n},y),c(`deleted (${n})`)}catch(t){return{content:[{type:"text",text:`Delete failed: ${t}`}],isError:!0}}}function j(r){const e=r.getStatusInfo();return{content:[{type:"text",text:JSON.stringify({alive:e.alive,active_event:e.activeEvent,pending_approvals:e.pendingPermissions,pending_questions:e.pendingElicitations})}]}}async function M(r,e){const i=String(r.chat_id??""),n=String(r.text??"");if(!i||!n)return{content:[{type:"text",text:"chat_id and text are required"}],isError:!0};try{const t=e.splitText(n),s=`send_${i}_${Date.now()}`;for(let a=0;a<t.length;a++)e.bridge.sendStreamChunk("",i,t[a],a+1,!1,s);return e.bridge.sendStreamChunk("",i,"",t.length+1,!0,s),c("sent")}catch(t){return{content:[{type:"text",text:`Send failed: ${t}`}],isError:!0}}}const C={access_pair:{verb:"pair_approve",payloadKey:"code"},access_deny:{verb:"pair_deny",payloadKey:"code"},allow_sender:{verb:"sender_allow",payloadKey:"sender_id"},remove_sender:{verb:"sender_remove",payloadKey:"sender_id"},access_policy:{verb:"policy_set",payloadKey:"policy"}};async function R(r,e,i){try{const n=C[r];if(!n)throw new Error(`Unknown access control tool: ${r}`);const t={};e.code!=null&&(t.code=e.code),e.sender_id!=null&&(t.sender_id=e.sender_id),e.policy!=null&&(t.policy=e.policy);const s=await i.bridge.agentInvoke("claude_access_control",{verb:n.verb,payload:t},y);return{content:[{type:"text",text:typeof s=="string"?s:JSON.stringify(s)}]}}catch(n){return{content:[{type:"text",text:`${r} failed: ${n}`}],isError:!0}}}async function O(r,e,i){try{const n=k(r,e);if(!E.has(n.action))throw new Error(`Action not allowed: ${n.action}`);const t=await i.bridge.agentInvoke(n.action,n.params,y);if(t&&Number(t.code??0)!==0)throw new Error(String(t.msg??"invoke failed"));return{content:[{type:"text",text:t?.data!=null?typeof t.data=="string"?t.data:JSON.stringify(t.data):JSON.stringify(t)}]}}catch(n){return{content:[{type:"text",text:`${r} failed: ${n}`}],isError:!0}}}function c(r){return{content:[{type:"text",text:r}]}}export{q as registerClaudeTools};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{log as l}from"../../core/log/index.js";class c{controlURL="";token="";isConfigured(){return!!(this.controlURL&&this.token)}configure(
|
|
1
|
+
import{log as l}from"../../core/log/index.js";class c{controlURL="";token="";isConfigured(){return!!(this.controlURL&&this.token)}configure(r,e){this.controlURL=r.replace(/\/+$/,""),this.token=e.trim(),l.info("claude-worker-client",`Configured with control URL: ${this.controlURL}`)}async post(r,e,s){if(!this.isConfigured())throw new Error("worker control not configured");const i=new AbortController,o=setTimeout(()=>i.abort(),s);try{const t=await fetch(`${this.controlURL}${r}`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${this.token}`},body:JSON.stringify(e),signal:i.signal}),n=await t.text(),a=n.trim()?JSON.parse(n):{};if(!t.ok)throw new Error(a.error||`worker control failed ${t.status}`);return a}finally{clearTimeout(o)}}isRetryableError(r){const e=r instanceof Error?r.message:String(r);return/fetch failed|network|ECONNRESET|ETIMEDOUT|EAI_AGAIN|socket hang up|aborted/i.test(e)}async postWithRetry(r,e,s,i=1){let o;for(let t=0;t<=i;t++)try{return t>0&&l.info("claude-worker-client",`Retrying ${r} attempt=${t+1}`),await this.post(r,e,s)}catch(n){if(o=n,t>=i||!this.isRetryableError(n))break;await new Promise(a=>setTimeout(a,150))}throw o instanceof Error?o:new Error(String(o))}async deliverEvent(r){return this.postWithRetry("/v1/worker/deliver-event",{payload:r},1e4,1)}async deliverStop(r){return this.postWithRetry("/v1/worker/deliver-stop",{payload:r},1e4,1)}async deliverLocalAction(r){return this.postWithRetry("/v1/worker/deliver-local-action",{payload:r},1e4,1)}async ping(){try{return await this.postWithRetry("/v1/worker/ping",{},5e3,1),!0}catch{return!1}}}export{c as ClaudeWorkerClient};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{spawn as x,execSync as y}from"node:child_process";import{randomUUID as v}from"node:crypto";import{mkdir as S}from"node:fs/promises";import{readFileSync as C}from"node:fs";import{join as d}from"node:path";import{homedir as T,tmpdir as I}from"node:os";import{log as o}from"../../core/log/index.js";import{MCP_HTTP_CHANNEL_NAME as
|
|
2
|
-
`),"utf8"),{expectPath:a,pidPath:i}}function h(
|
|
1
|
+
import{spawn as x,execSync as y}from"node:child_process";import{randomUUID as v}from"node:crypto";import{mkdir as S}from"node:fs/promises";import{readFileSync as C}from"node:fs";import{join as d}from"node:path";import{homedir as T,tmpdir as I}from"node:os";import{log as o}from"../../core/log/index.js";import{MCP_HTTP_CHANNEL_NAME as m}from"./protocol-contract.js";function P(t){let e=null,r=0,n=!1,i=!1;const a=v(),s=t.gatewayUrl??"http://127.0.0.1:19580/mcp";return{async start(){await F(t.command,s,t.env);const c=E(t.grix),u=[...t.args??[],"--name",`grix-mcp-${t.name}`,"--session-id",a];t.fullAuto&&u.push("--dangerously-skip-permissions"),u.push("--dangerously-load-development-channels",`server:${m}`,"--append-system-prompt",c);const f=d(I(),`grix-mcp-claude-${t.name}`);await S(f,{recursive:!0});const{expectPath:$,pidPath:g}=await M(f,t.command,u),_={...process.env,...t.env??{}};e=x("/usr/bin/expect",[$],{cwd:t.cwd,env:_,stdio:["ignore","pipe","pipe"],detached:!0}),o.info("mcp-http-launcher",`\u542F\u52A8 Claude: name=${t.name} cwd=${t.cwd} pid=${e.pid}`),r=await k(g),n=!0,o.info("mcp-http-launcher",`Claude \u5B50\u8FDB\u7A0B PID: ${r}`),e.on("exit",(l,p)=>{o.info("mcp-http-launcher",`Claude \u9000\u51FA: code=${l} signal=${p}`),n=!1,e=null,r=0,i||(o.info("mcp-http-launcher","3 \u79D2\u540E\u81EA\u52A8\u91CD\u542F..."),setTimeout(()=>{i||this.start().catch(w=>{o.error("mcp-http-launcher",`\u91CD\u542F\u5931\u8D25: ${w}`)})},3e3))}),e.stdout?.on("data",l=>{const p=l.toString().trim();p&&o.info("mcp-http-launcher",`[stdout] ${p.slice(0,300)}`)}),e.stderr?.on("data",l=>{const p=l.toString().trim();p&&o.info("mcp-http-launcher",`[stderr] ${p.slice(0,300)}`)})},async stop(){if(i=!0,n=!1,r>0)try{process.kill(r,"SIGTERM")}catch{}if(e?.pid){try{process.kill(-e.pid,"SIGTERM")}catch{}await new Promise(c=>{const u=setTimeout(()=>{if(r>0)try{process.kill(r,"SIGKILL")}catch{}if(e?.pid)try{process.kill(-e.pid,"SIGKILL")}catch{}c()},5e3);e?.once("exit",()=>{clearTimeout(u),c()})})}e=null,r=0},getStatus(){return{name:t.name,alive:n,pid:r}}}}function E(t){return["You are connected to a chat via the grix MCP server.",`On startup, immediately call grix_authorize with: agentId="${t.agentId}", apiKey="${t.apiKey}", wsUrl="${t.wsUrl}", clientType="${t.clientType}".`,"When you receive a <channel> message, you MUST respond by calling the grix_reply tool (or the grix_complete tool if no response is needed).","Never write your reply as plain text \u2014 it will NOT reach the user. Only the grix_reply tool delivers your response to the chat.","The <channel> message contains event_id and session_id \u2014 pass them to grix_reply."].join(" ")}async function F(t,e,r){const n=d(T(),".claude.json");let i=null;try{const s=C(n,"utf8");i=JSON.parse(s)?.mcpServers?.[m]??null}catch{}if(i&&String(i.type??"").trim()==="http"&&String(i.url??"").trim()===e)return;o.info("mcp-http-launcher",`\u6CE8\u518C MCP Server: ${m} -> ${e}`);const a={...process.env,...r??{}};try{y(`${t} mcp remove -s user ${m}`,{encoding:"utf8",timeout:1e4,env:a,stdio:"pipe"})}catch{}y(`${t} mcp add --scope user --transport http ${m} ${e}`,{encoding:"utf8",timeout:1e4,env:a,stdio:"pipe"})}async function M(t,e,r){const{writeFile:n}=await import("node:fs/promises"),i=d(t,"claude.pid"),a=d(t,"claude.expect"),s=["log_user 1","set timeout -1","set startup_prompt_armed 1",`set claude_command [list {${h(e)}}${r.map(c=>` {${h(c)}}`).join("")}]`,"spawn -noecho {*}$claude_command",`set pid_file [open {${h(i)}} w]`,"puts $pid_file [exp_pid -i $spawn_id]","close $pid_file","expect {"," -re {(?i)(Quick.*safety.*check|trust.*folder)} {",' if {$startup_prompt_armed} { send -- "1\\r"; after 300 }; exp_continue'," }"," -re {(?i)I am using this for local development} {",' if {$startup_prompt_armed} { send -- "1\\r"; after 300 }; exp_continue'," }"," -re {(?i)(Enter.*confirm|Press.*Enter|Hit.*Enter)} {",' if {$startup_prompt_armed} { send -- "\\r"; after 300 }; exp_continue'," }"," -re {Listening for channel} {"," set startup_prompt_armed 0"," after 1000",' send -- "Call grix_authorize now as instructed in your system prompt.\\r"'," }"," -re {bypass permissions} {"," set startup_prompt_armed 0"," after 1000",' send -- "Call grix_authorize now as instructed in your system prompt.\\r"'," }"," eof {}","}","expect eof",""];return await n(i,"","utf8"),await n(a,s.join(`
|
|
2
|
+
`),"utf8"),{expectPath:a,pidPath:i}}function h(t){return t.replace(/[\\{}$\[\]"]/g,"\\$&")}async function k(t,e=1e4){const{readFile:r}=await import("node:fs/promises"),n=Math.ceil(e/100);for(let i=0;i<n;i++){try{const a=await r(t,"utf8"),s=parseInt(String(a).trim(),10);if(Number.isFinite(s)&&s>0)return s}catch{}await new Promise(a=>setTimeout(a,100))}return 0}export{P as createMcpHttpLauncher};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
class m{defaultTimeoutMs;onTimeout;timers=new Map;constructor(
|
|
1
|
+
class m{defaultTimeoutMs;onTimeout;timers=new Map;constructor(e){this.defaultTimeoutMs=e.defaultTimeoutMs??9e4,this.onTimeout=e.onTimeout}arm(e,t){this.cancel(e);const s=t?.timeoutMs??this.defaultTimeoutMs,i=Date.now()+s,o=setTimeout(()=>{this.timers.delete(e),this.onTimeout(e).catch(()=>{})},s);return this.timers.set(e,o),i}cancel(e){const t=this.timers.get(e);t&&(clearTimeout(t),this.timers.delete(e))}has(e){return this.timers.has(e)}close(){for(const e of this.timers.values())clearTimeout(e);this.timers.clear()}}export{m as ResultTimeoutManager};
|
|
Binary file
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"bridgeVersion": "4.7.
|
|
4
|
-
"tarball": "grix-dsh-bridge-4.7.
|
|
5
|
-
"size":
|
|
3
|
+
"bridgeVersion": "4.7.1",
|
|
4
|
+
"tarball": "grix-dsh-bridge-4.7.1.tgz",
|
|
5
|
+
"size": 23125,
|
|
6
6
|
"unpackedSize": 92668,
|
|
7
|
-
"shasum": "
|
|
8
|
-
"integrity": "sha512-
|
|
7
|
+
"shasum": "62c8a884bbe1d9a1852eafaa84f0d9759579075c",
|
|
8
|
+
"integrity": "sha512-dqaxuztUfN3WPXSLpWkrMNF8D9hUJ0EP6m5RRbFLcWnkqVtPy8xJ0RPv8Rk3df6oxZnPcSaXtOL3ZvOQ3dJbeg=="
|
|
9
9
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readJSONFile as o,writeJSONFileAtomic as
|
|
1
|
+
import{readJSONFile as o,writeJSONFileAtomic as i}from"../util/json-file.js";function n(t){const r=o(t);return r&&typeof r=="object"&&"owners"in r&&Array.isArray(r.owners)?r.owners.filter(e=>typeof e=="string"&&e.trim().length>0):[]}async function s(t,r){await i(t,{owners:r})}export{n as readAllowlist,s as writeAllowlist};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readdir as r,stat as m}from"node:fs/promises";import{join as l,extname as d}from"node:path";const x={pdf:"application/pdf",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xls:"application/vnd.ms-excel",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",ppt:"application/vnd.ms-powerpoint",pptx:"application/vnd.openxmlformats-officedocument.presentationml.presentation",txt:"text/plain",md:"text/markdown",csv:"text/csv",json:"application/json",xml:"application/xml",yaml:"text/yaml",yml:"text/yaml",html:"text/html",css:"text/css",js:"text/javascript",ts:"text/typescript",zip:"application/zip",rar:"application/x-rar-compressed","7z":"application/x-7z-compressed",tar:"application/x-tar",gz:"application/gzip",jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",gif:"image/gif",webp:"image/webp",svg:"image/svg+xml",mp4:"video/mp4",mov:"video/quicktime",avi:"video/x-msvideo",mkv:"video/x-matroska",webm:"video/webm",mp3:"audio/mpeg",wav:"audio/wav",flac:"audio/flac",aac:"audio/aac"};function n(a){const p=d(a).slice(1).toLowerCase();return x[p]}async function f(a,p=!1){const c=await r(a,{withFileTypes:!0}),s=[];for(const
|
|
1
|
+
import{readdir as r,stat as m}from"node:fs/promises";import{join as l,extname as d}from"node:path";const x={pdf:"application/pdf",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",xls:"application/vnd.ms-excel",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",ppt:"application/vnd.ms-powerpoint",pptx:"application/vnd.openxmlformats-officedocument.presentationml.presentation",txt:"text/plain",md:"text/markdown",csv:"text/csv",json:"application/json",xml:"application/xml",yaml:"text/yaml",yml:"text/yaml",html:"text/html",css:"text/css",js:"text/javascript",ts:"text/typescript",zip:"application/zip",rar:"application/x-rar-compressed","7z":"application/x-7z-compressed",tar:"application/x-tar",gz:"application/gzip",jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",gif:"image/gif",webp:"image/webp",svg:"image/svg+xml",mp4:"video/mp4",mov:"video/quicktime",avi:"video/x-msvideo",mkv:"video/x-matroska",webm:"video/webm",mp3:"audio/mpeg",wav:"audio/wav",flac:"audio/flac",aac:"audio/aac"};function n(a){const p=d(a).slice(1).toLowerCase();return x[p]}async function f(a,p=!1){const c=await r(a,{withFileTypes:!0}),s=[];for(const i of c){if(!p&&i.name.startsWith("."))continue;const t=l(a,i.name),e={id:t,name:i.name,is_directory:i.isDirectory()};try{if(i.isDirectory()){const o=await m(t);e.modified_at=o.mtime.toISOString()}else{const o=await m(t);e.size=o.size,e.modified_at=o.mtime.toISOString(),e.mime_type=n(i.name)}}catch{}s.push(e)}return s.sort((i,t)=>i.is_directory!==t.is_directory?i.is_directory?-1:1:i.name.localeCompare(t.name)),s}export{f as listFiles,n as resolveMimeType};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{execFile as
|
|
2
|
-
[${
|
|
3
|
-
${
|
|
4
|
-
${
|
|
1
|
+
import{execFile as b,execFileSync as C}from"node:child_process";import{existsSync as $,mkdirSync as k}from"node:fs";import{basename as O,dirname as x,join as y}from"node:path";import{promisify as A}from"node:util";import{resolveRuntimePaths as P}from"../config/paths.js";import{log as I}from"../log/logger.js";import{probeUrls as D}from"./speed-test.js";const M=A(b),U=1e4,N=2,j=3e3;function L(e){if(!e)return!1;const t=e.replace(/\\/g,"/").toLowerCase();return O(t)==="npm-cli.js"||t.includes("/node_modules/npm/")}function F(){try{const e=y(P().rootDir,"npm-cache");return k(e,{recursive:!0}),e}catch{return}}function R(e,t={}){if((t.platform??process.platform)!=="win32")return{command:"npm",args:e};const i=t.env??process.env,n=t.nodePath??process.execPath,u=typeof i.npm_execpath=="string"?i.npm_execpath:"",c=[L(u)?u:"",y(x(n),"node_modules","npm","bin","npm-cli.js")];try{const s=C("where.exe",["npm.cmd"],{encoding:"utf-8",timeout:3e3,windowsHide:!0}).split(/\r?\n/).map(l=>l.trim()).filter(Boolean);for(const l of s)c.push(y(x(l),"node_modules","npm","bin","npm-cli.js"))}catch{}const o=c.find(s=>s&&$(s));if(!o)throw new Error("Unable to locate npm-cli.js for safe Windows execution");return{command:n,args:[o,...e]}}class T extends Error{output;constructor(t,r){super(t),this.name="NpmInstallError",this.output=r}}const p=[{id:"official",label:"npm \u5B98\u65B9",url:"https://registry.npmjs.org"},{id:"npmmirror",label:"npmmirror (\u6DD8\u5B9D\u955C\u50CF)",url:"https://registry.npmmirror.com"}];async function G(){const e=await D(p.map(r=>({url:r.url,label:r.label})),5e3),t=[];for(const r of e)if(r.reachable){const i=p.find(n=>n.url===r.url);i&&t.push(i)}for(const r of e)if(!r.reachable){const i=p.find(n=>n.url===r.url);i&&!t.includes(i)&&t.push(i)}for(const r of p)t.includes(r)||t.push(r);return t}async function te(){try{const e=R(["config","get","registry"]),{stdout:t}=await M(e.command,e.args,{timeout:U,encoding:"utf-8"});return t.trim()}catch{return"https://registry.npmjs.org"}}async function re(e,t,r,i){const n=await G();if(n.length===0)throw new Error("All npm registries are unreachable. Check your network connection.");let u="",c="";for(const o of n)for(let s=0;s<=N;s++)try{return I.info("installer",`npm install ${e} using ${o.label} (${o.url})`),{output:await W(e,o.url,t,r,i),registry:o.label,registryUrl:o.url}}catch(l){const a=l instanceof Error?l.message:String(l),f=Y(l);if(u=a,c=z(`${c}
|
|
2
|
+
[${o.label}] ${a}
|
|
3
|
+
${f}`.trim(),r),I.info("installer",`${o.label} failed: ${a.slice(0,200)}`),K(a)&&s<N){await new Promise(d=>setTimeout(d,j));continue}if(!H(a))throw new T(a,c);break}throw new T(`npm install failed on all registries. Last error: ${u}`,c)}function H(e){return/ECONNRESET|ETIMEDOUT|ECONNREFUSED|ENOTFOUND|EAI_AGAIN|ERR_SOCKET_TIMEOUT|getaddrinfo|socket hang up|network|fetch failed|timed out|tunneling socket|self.signed|404|ETARGET|No matching version|notarget/i.test(e)}function K(e){return/\bEBUSY\b|resource busy or locked|EPERM[^\n]*\brename\b|\bELOCKED\b/i.test(e)}function W(e,t,r,i,n){return new Promise((u,c)=>{const o=["install","-g",e,"--registry",t,"--prefer-online","--no-audit","--no-fund"],s=F();s&&o.push("--cache",s),n?.prefix&&o.push("--prefix",n.prefix),n?.ignoreScripts&&o.push("--ignore-scripts");const l=process.platform==="win32",a=R(o,{env:n?.env});let f=!1,d=Promise.resolve(),E;const g=b(a.command,a.args,{maxBuffer:i,windowsHide:!0,env:n?.env},async(m,_,S)=>{clearTimeout(E),await d;const h=`${_??""}
|
|
4
|
+
${S??""}`.trim();if(m){const w=h||m.message,v=f||m.killed===!0?`ETIMEDOUT: npm install exceeded ${r}ms (registry likely unreachable): ${w}`:w;c(new T(v,h||w));return}u(h)});E=setTimeout(()=>{f=!0,l&&g.pid?d=new Promise(m=>{b("taskkill",["/PID",String(g.pid),"/T","/F"],{windowsHide:!0,timeout:1e4},()=>{g.kill("SIGTERM"),m()})}):g.kill("SIGTERM")},r),E.unref?.()})}function Y(e){if(e&&typeof e=="object"&&"output"in e){const t=e.output;return typeof t=="string"?t:""}return""}function z(e,t){return e.length<=t?e:e.slice(-t)}function ne(e){return p.map(t=>({label:t.label,command:`npm install -g ${e} --registry ${t.url}`}))}export{p as NPM_REGISTRIES,T as NpmInstallError,te as getCurrentRegistry,ne as getMirrorInstallCommands,L as isNpmCliEntry,H as isRetriableRegistryError,K as isTransientInstallError,re as npmInstallWithMirror,G as probeRegistries,F as resolveNpmCacheDir,R as resolveNpmInvocation};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{execFile as wt,execFileSync as R}from"node:child_process";import{randomUUID as Q}from"node:crypto";import{promisify as yt}from"node:util";import{uptime as St}from"node:os";import{closeSync as Et,copyFileSync as kt,cpSync as It,existsSync as d,linkSync as Pt,mkdirSync as E,mkdtempSync as tt,openSync as vt,readFileSync as P,renameSync as h,rmSync as p,statfsSync as xt,symlinkSync as $t,unlinkSync as H,writeFileSync as x}from"node:fs";import{basename as v,dirname as w,join as l,relative as rt,resolve as u,sep as b}from"node:path";import{GRIX_PATHS as $}from"../log/index.js";import{appendRotatingFileSync as Dt}from"../log/rotation.js";import{getMachineName as Nt}from"../util/host-info.js";import{resolveInstallId as At}from"../util/install-id.js";import{NPM_REGISTRIES as Rt,npmInstallWithMirror as et,probeRegistries as bt,resolveNpmInvocation as M}from"../installer/npm-registry.js";import{resolveWindowsServiceRuntimeDir as nt}from"../../service/service-paths.js";const it=yt(wt);class f extends Error{code;constructor(r,e){super(e),this.name="UpgradeError",this.code=r}}const Ut=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;function O(t){const r=String(t??"").trim().replace(/^v(?=\d)/,"");if(!Ut.test(r))throw new f("INVALID_VERSION",`Invalid connector upgrade version: ${String(t)}`);return r}const Y=".grix-upgrade-backup",Ft=".grix-upgrade-failed",ot=".grix-upgrade-backup",at=".grix-upgrade-next",Lt="upgrade-wrapper.pause.json",Tt="upgrade-rollback.intent.json",Mt=".grix-connector-upgrade.lock",ct=[250,750],C=[100,250,750,1500];function st(){return l($.log,"upgrade.log")}function I(){return l($.data,"upgrade-pending.json")}function lr(){let t=null;try{t=_()}catch{return{in_progress:!1}}if(!t)return{in_progress:!1};const r=t.phase??"staged";return{in_progress:!(r==="failed"||r==="rolled_back"),phase:r,from:t.from_version,target:t.target_version}}function dr(){return d(I())}function gr(t,r="failed"){const e=new Date().toISOString().replace(/[:.]/g,""),n=l($.data,`upgrade-pending.${r}-${e}.json`);try{return x(n,JSON.stringify(t,null,2),"utf-8"),n}catch{return null}}function _(){const t=I();if(!d(t))return null;try{return JSON.parse(P(t,"utf-8"))}catch{return null}}function pr(t,r,e){const n={from_version:t,target_version:r,upgraded_at:new Date().toISOString(),crash_count:0,transaction_id:Q(),...e?{phase:e}:{}},i=I();E(w(i),{recursive:!0});let a;try{a=vt(i,"wx",384)}catch(o){throw o?.code==="EEXIST"?new f("UPGRADE_IN_PROGRESS","Another connector upgrade transaction is already active"):o}try{x(a,JSON.stringify(n),"utf-8")}catch(o){try{H(i)}catch{}throw o}finally{Et(a)}return n}function _r(t){const r=t.package_dir;if(!r)return null;const e=u(r);if(!e.includes(`${b}node_modules${b}`))return null;try{const n=JSON.parse(P(l(e,"package.json"),"utf-8"));return n.name!=="grix-connector"||typeof n.version!="string"?null:n.version.trim().replace(/^v/,"")||null}catch{return null}}function Ot(t,r){E(w(t),{recursive:!0});const e=`${t}.tmp-${process.pid}`;x(e,JSON.stringify(r),"utf-8"),h(e,t)}function D(t,r){const e=_();if(!e)throw new f("PENDING_MISSING","Upgrade transaction is missing");if(r&&e.transaction_id!==r)throw new f("UPGRADE_TRANSACTION_CHANGED","Upgrade transaction ownership changed");const n={...e,...t};return Ot(I(),n),n}function j(){return l($.data,Lt)}function Ct(){return l($.data,Tt)}function mr(t,r){const e=_();if(!e?.transaction_id||e.phase!=="staged"||r&&e.transaction_id!==r)throw new f("INVALID_UPGRADE_STATE","Windows upgrade is not staged for activation");const n=j();E(w(n),{recursive:!0});const i=`${n}.tmp-${process.pid}`;return x(i,JSON.stringify({transaction_id:e.transaction_id}),"utf-8"),h(i,n),D({phase:"handoff_ready",old_pid:t,old_command_line:Gt(t)??void 0,old_boot_time:Date.now()-St()*1e3,activation_started_at:new Date().toISOString(),wrapper_pause_file:n},e.transaction_id)}function Gt(t){if(process.platform!=="win32"||!Number.isInteger(t)||t<=0)return null;try{const r=`${process.env.SystemRoot||"C:\\Windows"}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`;return R(r,["-NoProfile","-NonInteractive","-WindowStyle","Hidden","-Command",`(Get-CimInstance Win32_Process -Filter 'ProcessId=${t}').CommandLine`],{encoding:"utf-8",timeout:3e3,windowsHide:!0}).trim()||null}catch{return null}}function hr(t,r){const e=_();if(!e?.transaction_id||e.transaction_id!==t||e.phase!=="verifying")throw new f("INVALID_UPGRADE_STATE","Windows upgrade is not awaiting verification");const n=Ct();E(w(n),{recursive:!0});const i=`${n}.tmp-${process.pid}`;x(i,JSON.stringify({transaction_id:t,message:r}),"utf-8"),h(i,n);const a=j();E(w(a),{recursive:!0});const o=`${a}.tmp-${process.pid}`;return x(o,JSON.stringify({transaction_id:t}),"utf-8"),h(o,a),D({phase:"rolling_back",guardian_pid:void 0,error_code:"STARTUP_CRASH",error_msg:r,wrapper_pause_file:a},t)}function wr(){try{p(j(),{force:!0})}catch{}}function Vt(t=_()){if(z(t)){try{p(u(t.staging_prefix),{recursive:!0,force:!0})}catch{}if(ut(t))try{p(u(t.runtime_next_dir),{recursive:!0,force:!0})}catch{}}}function ut(t){if(!t?.runtime_dir||!t.runtime_backup_dir||!t.runtime_next_dir)return!1;const r=u(t.runtime_dir),e=nt($.base),n=l(w(w(e)),"runtime"),i=r===u(n),a=r===u(e)&&/^GrixConnectorDaemon-[0-9a-f]{12}$/.test(v(r))&&v(w(r))==="runtimes"&&v(w(w(r)))==="grix-connector";return(i||a)&&u(t.runtime_backup_dir)===`${r}${ot}`&&u(t.runtime_next_dir)===`${r}${at}`}function J(t){return l(u(t),Mt)}function K(t){try{const r=d(t)&&!d(l(t,"owner.json"))?t:l(t,"owner.json"),e=JSON.parse(P(r,"utf-8"));return typeof e.transaction_id=="string"&&typeof e.pending_file=="string"?e:null}catch{return null}}function ft(t){if(!t||!d(t.pending_file))return!1;try{return JSON.parse(P(t.pending_file,"utf-8")).transaction_id===t.transaction_id}catch{return!0}}function Wt(t){const r=_();if(!r?.transaction_id)throw new f("PENDING_MISSING","Upgrade transaction disappeared before npm staging");const e=J(t),n={transaction_id:r.transaction_id,pending_file:I()};D({npm_prefix:u(t),npm_lock_file:e},r.transaction_id);const i=`${e}.candidate-${r.transaction_id}-${Q()}`;try{x(i,JSON.stringify(n),{encoding:"utf-8",flag:"wx"}),Pt(i,e),p(i,{force:!0})}catch(a){try{p(i,{force:!0})}catch{}if(!d(e))throw a;const o=K(e);if(o?.transaction_id===r.transaction_id&&u(o.pending_file)===u(I()))return;throw new f(ft(o)?"UPGRADE_IN_PROGRESS":"UPGRADE_LOCK_RECOVERY_REQUIRED",ft(o)?`Another Windows service root is upgrading the shared npm prefix ${u(t)}`:`A stale or incomplete Windows upgrade lock requires recovery at ${e}`)}}function Bt(t=_(),r={}){if(!t?.transaction_id||!t.npm_prefix||!t.npm_lock_file)return!0;const e=J(t.npm_prefix);if(u(t.npm_lock_file)!==e)return!1;if(!d(e))return!0;const n=K(e);if(!n)return!1;if(n.transaction_id!==t.transaction_id||u(n.pending_file)!==u(I()))return!0;const i=r.remove??p,a=r.sleep??(o=>{Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,o)});for(let o=0;;o+=1)try{return i(e,{recursive:!0,force:!0}),!d(e)}catch(c){const s=c?.code;if((s==="EBUSY"||s==="EPERM"||s==="EACCES")&&o<C.length){a(C[o]);continue}return m(`shared npm-prefix lock release failed at ${e}: ${c instanceof Error?c.message:String(c)}`),!1}}function G(t,r){const e=u(t);return u(r)===`${e}${Y}`&&e.includes(`${b}node_modules${b}`)&&v(e)==="grix-connector"}function Ht(t,r){const e=rt(u(t),u(r));return e!==""&&e!==".."&&!e.startsWith(`..${b}`)}function z(t){if(!t?.npm_prefix||!t.staging_prefix||!t.staged_package_dir)return!1;const r=u(t.npm_prefix),e=u(t.staging_prefix),n=u(t.staged_package_dir);return w(e)===r&&v(e).startsWith(".grix-upgrade-stage-")&&Ht(e,n)&&v(w(n))==="node_modules"&&v(n)==="grix-connector"}function Yt(t,r){const e=_();!e||!G(t,r)||D({package_dir:u(t),backup_dir:u(r)},e.transaction_id)}function jt(t){if(!G(t.packageDir,t.backupDir))throw new f("UNSAFE_UPGRADE_PATH","Refusing to record an unsafe global package path");if(!z({npm_prefix:t.npmPrefix,staging_prefix:t.stagingPrefix,staged_package_dir:t.stagedPackageDir}))throw new f("UNSAFE_UPGRADE_PATH","Refusing to record an unsafe npm staging path");const r=_();if(!r)throw new f("PENDING_MISSING","Upgrade transaction disappeared during staging");let e;try{const n=JSON.parse(P(l(t.packageDir,"package.json"),"utf-8"));if(n.name!=="grix-connector"||typeof n.version!="string")throw new Error("invalid metadata");e=O(n.version)}catch(n){throw new f("VERSION_VERIFY_FAILED",`Unable to identify the active global package before staging: ${n instanceof Error?n.message:String(n)}`)}D({phase:"staged",activation_strategy:t.activationStrategy,package_from_version:e,npm_prefix:u(t.npmPrefix),package_dir:u(t.packageDir),backup_dir:u(t.backupDir),staged_package_dir:u(t.stagedPackageDir),staging_prefix:u(t.stagingPrefix)},r.transaction_id)}function Jt(t,r,e={}){const n=_();if(!n?.transaction_id)throw new f("PENDING_MISSING","Upgrade transaction disappeared before runtime staging");const i=nt($.base),a=`${i}${ot}`,o=`${i}${at}`;D({runtime_dir:i,runtime_backup_dir:a,runtime_next_dir:o},n.transaction_id);const c=e.copyTree??It,s=e.copyFile??kt,g=e.sleep??(k=>{Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,k)});for(let k=0;;k+=1)try{E(w(i),{recursive:!0}),p(o,{recursive:!0,force:!0}),E(o,{recursive:!0}),c(l(t.stagedPackageDir,"dist"),l(o,"dist"),{recursive:!0,force:!0}),s(l(t.stagedPackageDir,"package.json"),l(o,"package.json"));const y=l(t.stagedPackageDir,"node_modules");d(y)&&c(y,l(o,"node_modules"),{recursive:!0,force:!0});const S=F(o,"grix-connector",r);L(o,S);return}catch(y){try{p(o,{recursive:!0,force:!0})}catch{}const S=y?.code;if(S==="ENOSPC")throw new f("DISK_FULL",`Insufficient space for the isolated Windows runtime: ${y.message}`);if((S==="EBUSY"||S==="EPERM"||S==="EACCES"||S==="ENOTEMPTY")&&k<ct.length){g(ct[k]);continue}throw new f("RUNTIME_STAGE_FAILED",`Could not prepare the isolated Windows runtime before shutdown: ${y instanceof Error?y.message:String(y)}`)}}function V(t,r){if(!d(t))return!0;const e=r.remove??p,n=r.sleep??(i=>{Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,i)});for(let i=0;;i+=1)try{if(e(t,{recursive:!0,force:!0}),!d(t))return!0;throw Object.assign(new Error(`path still exists after removal: ${t}`),{code:"EBUSY"})}catch(a){const o=a?.code;if((o==="EBUSY"||o==="EPERM"||o==="EACCES"||o==="ENOTEMPTY")&&i<C.length){n(C[i]);continue}return m(`upgrade artifact cleanup failed at ${t}: ${a instanceof Error?a.message:String(a)}`),!1}}function yr(t=_(),r={}){if(t?.transaction_id&&_()?.transaction_id!==t.transaction_id)return!1;let e=!0,n=process.platform!=="win32";if(t?.npm_lock_file||t?.npm_prefix){if(!t.transaction_id||!t.npm_lock_file||!t.npm_prefix)return!1;const o=J(t.npm_prefix);if(u(t.npm_lock_file)!==o)return!1;if(d(o)){const c=K(o);if(c?.transaction_id!==t.transaction_id||u(c.pending_file)!==u(I()))return!1;n=!0}else{if(t.backup_dir&&d(t.backup_dir))return!1;n=!1}}const i=t?.package_dir,a=t?.backup_dir;return n&&i&&a&&G(i,a)&&(e=V(a,r)&&e),z(t)&&(e=V(u(t.staging_prefix),r)&&e),ut(t)&&(e=V(u(t.runtime_backup_dir),r)&&e,e=V(u(t.runtime_next_dir),r)&&e),e}function Sr(t=_()){const r=t?.package_dir,e=t?.backup_dir;if(!r||!e||!G(r,e)||!d(e))return!1;const n=`${r}${Ft}`;try{return p(n,{recursive:!0,force:!0}),d(r)&&h(r,n),h(e,r),p(n,{recursive:!0,force:!0}),m(`atomic rollback restored ${r}`),!0}catch(i){try{!d(r)&&d(n)&&h(n,r)}catch{}return m(`atomic rollback failed: ${i instanceof Error?i.message:String(i)}`),!1}}function lt(t,r={}){const e=I();if(t){const n=_();if(!n)return!0;if(n.transaction_id!==t)return!1}if(d(e))try{(r.unlink??H)(e)}catch{return!1}return!d(e)}function Er(t=_(),r={}){if(!t?.transaction_id)return lt(void 0,{unlink:r.unlinkPending});const e=_();if(e?.transaction_id!==t.transaction_id)return!1;const n=e.phase==="finalizing"?e:D({phase:"finalizing"},t.transaction_id);return Bt(n,{remove:r.removeLock,sleep:r.sleep})?lt(t.transaction_id,{unlink:r.unlinkPending}):!1}function m(t){const r=`[${new Date().toISOString()}] ${t}
|
|
2
|
-
`;try{
|
|
1
|
+
import{execFile as yt,execFileSync as R}from"node:child_process";import{randomUUID as Q}from"node:crypto";import{promisify as Et}from"node:util";import{uptime as kt}from"node:os";import{closeSync as It,copyFileSync as Pt,cpSync as vt,existsSync as d,linkSync as xt,mkdirSync as E,mkdtempSync as tt,openSync as $t,readFileSync as P,renameSync as h,rmSync as g,statfsSync as Dt,symlinkSync as Nt,unlinkSync as H,writeFileSync as x}from"node:fs";import{basename as v,dirname as w,join as l,relative as et,resolve as u,sep as b}from"node:path";import{GRIX_PATHS as $}from"../log/index.js";import{appendRotatingFileSync as At}from"../log/rotation.js";import{getMachineName as Rt}from"../util/host-info.js";import{resolveInstallId as bt}from"../util/install-id.js";import{NPM_REGISTRIES as Tt,npmInstallWithMirror as rt,probeRegistries as Ut,resolveNpmCacheDir as nt,resolveNpmInvocation as M}from"../installer/npm-registry.js";import{resolveWindowsServiceRuntimeDir as it}from"../../service/service-paths.js";const ot=Et(yt);class f extends Error{code;constructor(e,r){super(r),this.name="UpgradeError",this.code=e}}const Lt=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;function O(t){const e=String(t??"").trim().replace(/^v(?=\d)/,"");if(!Lt.test(e))throw new f("INVALID_VERSION",`Invalid connector upgrade version: ${String(t)}`);return e}const Y=".grix-upgrade-backup",Ft=".grix-upgrade-failed",at=".grix-upgrade-backup",ct=".grix-upgrade-next",Mt="upgrade-wrapper.pause.json",Ot="upgrade-rollback.intent.json",Ct=".grix-connector-upgrade.lock",st=[250,750],C=[100,250,750,1500];function ut(){return l($.log,"upgrade.log")}function I(){return l($.data,"upgrade-pending.json")}function pe(){let t=null;try{t=_()}catch{return{in_progress:!1}}if(!t)return{in_progress:!1};const e=t.phase??"staged";return{in_progress:!(e==="failed"||e==="rolled_back"),phase:e,from:t.from_version,target:t.target_version}}function ge(){return d(I())}function _e(t,e="failed"){const r=new Date().toISOString().replace(/[:.]/g,""),n=l($.data,`upgrade-pending.${e}-${r}.json`);try{return x(n,JSON.stringify(t,null,2),"utf-8"),n}catch{return null}}function _(){const t=I();if(!d(t))return null;try{return JSON.parse(P(t,"utf-8"))}catch{return null}}function me(t,e,r){const n={from_version:t,target_version:e,upgraded_at:new Date().toISOString(),crash_count:0,transaction_id:Q(),...r?{phase:r}:{}},i=I();E(w(i),{recursive:!0});let a;try{a=$t(i,"wx",384)}catch(o){throw o?.code==="EEXIST"?new f("UPGRADE_IN_PROGRESS","Another connector upgrade transaction is already active"):o}try{x(a,JSON.stringify(n),"utf-8")}catch(o){try{H(i)}catch{}throw o}finally{It(a)}return n}function he(t){const e=t.package_dir;if(!e)return null;const r=u(e);if(!r.includes(`${b}node_modules${b}`))return null;try{const n=JSON.parse(P(l(r,"package.json"),"utf-8"));return n.name!=="grix-connector"||typeof n.version!="string"?null:n.version.trim().replace(/^v/,"")||null}catch{return null}}function Gt(t,e){E(w(t),{recursive:!0});const r=`${t}.tmp-${process.pid}`;x(r,JSON.stringify(e),"utf-8"),h(r,t)}function D(t,e){const r=_();if(!r)throw new f("PENDING_MISSING","Upgrade transaction is missing");if(e&&r.transaction_id!==e)throw new f("UPGRADE_TRANSACTION_CHANGED","Upgrade transaction ownership changed");const n={...r,...t};return Gt(I(),n),n}function j(){return l($.data,Mt)}function Vt(){return l($.data,Ot)}function we(t,e){const r=_();if(!r?.transaction_id||r.phase!=="staged"||e&&r.transaction_id!==e)throw new f("INVALID_UPGRADE_STATE","Windows upgrade is not staged for activation");const n=j();E(w(n),{recursive:!0});const i=`${n}.tmp-${process.pid}`;return x(i,JSON.stringify({transaction_id:r.transaction_id}),"utf-8"),h(i,n),D({phase:"handoff_ready",old_pid:t,old_command_line:Wt(t)??void 0,old_boot_time:Date.now()-kt()*1e3,activation_started_at:new Date().toISOString(),wrapper_pause_file:n},r.transaction_id)}function Wt(t){if(process.platform!=="win32"||!Number.isInteger(t)||t<=0)return null;try{const e=`${process.env.SystemRoot||"C:\\Windows"}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`;return R(e,["-NoProfile","-NonInteractive","-WindowStyle","Hidden","-Command",`(Get-CimInstance Win32_Process -Filter 'ProcessId=${t}').CommandLine`],{encoding:"utf-8",timeout:3e3,windowsHide:!0}).trim()||null}catch{return null}}function Se(t,e){const r=_();if(!r?.transaction_id||r.transaction_id!==t||r.phase!=="verifying")throw new f("INVALID_UPGRADE_STATE","Windows upgrade is not awaiting verification");const n=Vt();E(w(n),{recursive:!0});const i=`${n}.tmp-${process.pid}`;x(i,JSON.stringify({transaction_id:t,message:e}),"utf-8"),h(i,n);const a=j();E(w(a),{recursive:!0});const o=`${a}.tmp-${process.pid}`;return x(o,JSON.stringify({transaction_id:t}),"utf-8"),h(o,a),D({phase:"rolling_back",guardian_pid:void 0,error_code:"STARTUP_CRASH",error_msg:e,wrapper_pause_file:a},t)}function ye(){try{g(j(),{force:!0})}catch{}}function Bt(t=_()){if(z(t)){try{g(u(t.staging_prefix),{recursive:!0,force:!0})}catch{}if(ft(t))try{g(u(t.runtime_next_dir),{recursive:!0,force:!0})}catch{}}}function ft(t){if(!t?.runtime_dir||!t.runtime_backup_dir||!t.runtime_next_dir)return!1;const e=u(t.runtime_dir),r=it($.base),n=l(w(w(r)),"runtime"),i=e===u(n),a=e===u(r)&&/^GrixConnectorDaemon-[0-9a-f]{12}$/.test(v(e))&&v(w(e))==="runtimes"&&v(w(w(e)))==="grix-connector";return(i||a)&&u(t.runtime_backup_dir)===`${e}${at}`&&u(t.runtime_next_dir)===`${e}${ct}`}function J(t){return l(u(t),Ct)}function K(t){try{const e=d(t)&&!d(l(t,"owner.json"))?t:l(t,"owner.json"),r=JSON.parse(P(e,"utf-8"));return typeof r.transaction_id=="string"&&typeof r.pending_file=="string"?r:null}catch{return null}}function lt(t){if(!t||!d(t.pending_file))return!1;try{return JSON.parse(P(t.pending_file,"utf-8")).transaction_id===t.transaction_id}catch{return!0}}function Ht(t){const e=_();if(!e?.transaction_id)throw new f("PENDING_MISSING","Upgrade transaction disappeared before npm staging");const r=J(t),n={transaction_id:e.transaction_id,pending_file:I()};D({npm_prefix:u(t),npm_lock_file:r},e.transaction_id);const i=`${r}.candidate-${e.transaction_id}-${Q()}`;try{x(i,JSON.stringify(n),{encoding:"utf-8",flag:"wx"}),xt(i,r),g(i,{force:!0})}catch(a){try{g(i,{force:!0})}catch{}if(!d(r))throw a;const o=K(r);if(o?.transaction_id===e.transaction_id&&u(o.pending_file)===u(I()))return;throw new f(lt(o)?"UPGRADE_IN_PROGRESS":"UPGRADE_LOCK_RECOVERY_REQUIRED",lt(o)?`Another Windows service root is upgrading the shared npm prefix ${u(t)}`:`A stale or incomplete Windows upgrade lock requires recovery at ${r}`)}}function Yt(t=_(),e={}){if(!t?.transaction_id||!t.npm_prefix||!t.npm_lock_file)return!0;const r=J(t.npm_prefix);if(u(t.npm_lock_file)!==r)return!1;if(!d(r))return!0;const n=K(r);if(!n)return!1;if(n.transaction_id!==t.transaction_id||u(n.pending_file)!==u(I()))return!0;const i=e.remove??g,a=e.sleep??(o=>{Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,o)});for(let o=0;;o+=1)try{return i(r,{recursive:!0,force:!0}),!d(r)}catch(c){const s=c?.code;if((s==="EBUSY"||s==="EPERM"||s==="EACCES")&&o<C.length){a(C[o]);continue}return m(`shared npm-prefix lock release failed at ${r}: ${c instanceof Error?c.message:String(c)}`),!1}}function G(t,e){const r=u(t);return u(e)===`${r}${Y}`&&r.includes(`${b}node_modules${b}`)&&v(r)==="grix-connector"}function jt(t,e){const r=et(u(t),u(e));return r!==""&&r!==".."&&!r.startsWith(`..${b}`)}function z(t){if(!t?.npm_prefix||!t.staging_prefix||!t.staged_package_dir)return!1;const e=u(t.npm_prefix),r=u(t.staging_prefix),n=u(t.staged_package_dir);return w(r)===e&&v(r).startsWith(".grix-upgrade-stage-")&&jt(r,n)&&v(w(n))==="node_modules"&&v(n)==="grix-connector"}function Jt(t,e){const r=_();!r||!G(t,e)||D({package_dir:u(t),backup_dir:u(e)},r.transaction_id)}function Kt(t){if(!G(t.packageDir,t.backupDir))throw new f("UNSAFE_UPGRADE_PATH","Refusing to record an unsafe global package path");if(!z({npm_prefix:t.npmPrefix,staging_prefix:t.stagingPrefix,staged_package_dir:t.stagedPackageDir}))throw new f("UNSAFE_UPGRADE_PATH","Refusing to record an unsafe npm staging path");const e=_();if(!e)throw new f("PENDING_MISSING","Upgrade transaction disappeared during staging");let r;try{const n=JSON.parse(P(l(t.packageDir,"package.json"),"utf-8"));if(n.name!=="grix-connector"||typeof n.version!="string")throw new Error("invalid metadata");r=O(n.version)}catch(n){throw new f("VERSION_VERIFY_FAILED",`Unable to identify the active global package before staging: ${n instanceof Error?n.message:String(n)}`)}D({phase:"staged",activation_strategy:t.activationStrategy,package_from_version:r,npm_prefix:u(t.npmPrefix),package_dir:u(t.packageDir),backup_dir:u(t.backupDir),staged_package_dir:u(t.stagedPackageDir),staging_prefix:u(t.stagingPrefix)},e.transaction_id)}function zt(t,e,r={}){const n=_();if(!n?.transaction_id)throw new f("PENDING_MISSING","Upgrade transaction disappeared before runtime staging");const i=it($.base),a=`${i}${at}`,o=`${i}${ct}`;D({runtime_dir:i,runtime_backup_dir:a,runtime_next_dir:o},n.transaction_id);const c=r.copyTree??vt,s=r.copyFile??Pt,p=r.sleep??(k=>{Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,k)});for(let k=0;;k+=1)try{E(w(i),{recursive:!0}),g(o,{recursive:!0,force:!0}),E(o,{recursive:!0}),c(l(t.stagedPackageDir,"dist"),l(o,"dist"),{recursive:!0,force:!0}),s(l(t.stagedPackageDir,"package.json"),l(o,"package.json"));const S=l(t.stagedPackageDir,"node_modules");d(S)&&c(S,l(o,"node_modules"),{recursive:!0,force:!0});const y=U(o,"grix-connector",e);L(o,y);return}catch(S){try{g(o,{recursive:!0,force:!0})}catch{}const y=S?.code;if(y==="ENOSPC")throw new f("DISK_FULL",`Insufficient space for the isolated Windows runtime: ${S.message}`);if((y==="EBUSY"||y==="EPERM"||y==="EACCES"||y==="ENOTEMPTY")&&k<st.length){p(st[k]);continue}throw new f("RUNTIME_STAGE_FAILED",`Could not prepare the isolated Windows runtime before shutdown: ${S instanceof Error?S.message:String(S)}`)}}function V(t,e){if(!d(t))return!0;const r=e.remove??g,n=e.sleep??(i=>{Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,i)});for(let i=0;;i+=1)try{if(r(t,{recursive:!0,force:!0}),!d(t))return!0;throw Object.assign(new Error(`path still exists after removal: ${t}`),{code:"EBUSY"})}catch(a){const o=a?.code;if((o==="EBUSY"||o==="EPERM"||o==="EACCES"||o==="ENOTEMPTY")&&i<C.length){n(C[i]);continue}return m(`upgrade artifact cleanup failed at ${t}: ${a instanceof Error?a.message:String(a)}`),!1}}function Ee(t=_(),e={}){if(t?.transaction_id&&_()?.transaction_id!==t.transaction_id)return!1;let r=!0,n=process.platform!=="win32";if(t?.npm_lock_file||t?.npm_prefix){if(!t.transaction_id||!t.npm_lock_file||!t.npm_prefix)return!1;const o=J(t.npm_prefix);if(u(t.npm_lock_file)!==o)return!1;if(d(o)){const c=K(o);if(c?.transaction_id!==t.transaction_id||u(c.pending_file)!==u(I()))return!1;n=!0}else{if(t.backup_dir&&d(t.backup_dir))return!1;n=!1}}const i=t?.package_dir,a=t?.backup_dir;return n&&i&&a&&G(i,a)&&(r=V(a,e)&&r),z(t)&&(r=V(u(t.staging_prefix),e)&&r),ft(t)&&(r=V(u(t.runtime_backup_dir),e)&&r,r=V(u(t.runtime_next_dir),e)&&r),r}function ke(t=_()){const e=t?.package_dir,r=t?.backup_dir;if(!e||!r||!G(e,r)||!d(r))return!1;const n=`${e}${Ft}`;try{return g(n,{recursive:!0,force:!0}),d(e)&&h(e,n),h(r,e),g(n,{recursive:!0,force:!0}),m(`atomic rollback restored ${e}`),!0}catch(i){try{!d(e)&&d(n)&&h(n,e)}catch{}return m(`atomic rollback failed: ${i instanceof Error?i.message:String(i)}`),!1}}function dt(t,e={}){const r=I();if(t){const n=_();if(!n)return!0;if(n.transaction_id!==t)return!1}if(d(r))try{(e.unlink??H)(r)}catch{return!1}return!d(r)}function Ie(t=_(),e={}){if(!t?.transaction_id)return dt(void 0,{unlink:e.unlinkPending});const r=_();if(r?.transaction_id!==t.transaction_id)return!1;const n=r.phase==="finalizing"?r:D({phase:"finalizing"},t.transaction_id);return Yt(n,{remove:e.removeLock,sleep:e.sleep})?dt(t.transaction_id,{unlink:e.unlinkPending}):!1}function m(t){const e=`[${new Date().toISOString()}] ${t}
|
|
2
|
+
`;try{At(ut(),e)}catch{}}function Pe(t=4096){const e=ut();if(!d(e))return"";try{const r=P(e,"utf-8");return r.length<=t?r:r.slice(-t)}catch{return""}}function pt(){try{const t=M(["--version"]);return R(t.command,t.args,{encoding:"utf-8",timeout:1e4,windowsHide:!0}).trim()}catch{throw new f("NPM_NOT_FOUND","npm is not available or timed out")}}const T=1e6;function gt(){let t;try{t=X(["prefix","-g"])}catch{return T}try{const e=Dt(t),r=Math.floor(Number(e.bavail)*Number(e.bsize)/(1024*1024));return!Number.isFinite(r)||r<0?T:Math.min(r,T)}catch{return T}}function ve(){let t;try{t=pt()}catch(r){return{ok:!1,errorCode:"NPM_NOT_FOUND",errorMsg:r instanceof Error?r.message:"npm not available"}}const e=gt();return e<100?{ok:!1,errorCode:"DISK_FULL",errorMsg:`Only ${e}MB free disk space (need >= 100MB)`,npmVersion:t,diskFreeMb:e}:{ok:!0,npmVersion:t,diskFreeMb:e}}function xe(){let t="";try{t=pt()}catch{}let e=T;try{e=gt()}catch{}return{npm_version:t,node_version:process.version,disk_free_mb:e,platform:process.platform,arch:process.arch,host_name:Rt(),install_id:bt()}}function U(t,e,r){const n=l(t,"package.json");let i;try{i=JSON.parse(P(n,"utf-8"))}catch{throw new f("VERSION_VERIFY_FAILED",`Unable to read staged package metadata: ${n}`)}if(i.name!==e||i.version?.replace(/^v(?=\d)/,"")!==r)throw new f("VERSION_MISMATCH",`Staged package ${String(i.name)}@${String(i.version)} does not match ${e}@${r}`);return i}function Xt(t){return typeof t.bin=="string"?[[v(t.name),t.bin]]:!t.bin||typeof t.bin!="object"?[]:Object.entries(t.bin).filter(e=>typeof e[1]=="string")}function L(t,e){const r=Xt(e);if(r.length===0)throw new f("VERSION_VERIFY_FAILED",`Staged package ${e.name} has no executable bin`);for(const[,n]of r){const i=l(t,n);if(!d(i))throw new f("VERSION_VERIFY_FAILED",`Staged package entrypoint is missing: ${i}`)}return r}function qt(t,e,r){if(process.platform==="win32")return;const n=l(t,"bin");E(n,{recursive:!0});for(const[i,a]of r){const o=l(n,i);if(d(o))continue;const c=`${o}.grix-upgrade-${process.pid}`;try{H(c)}catch{}Nt(et(n,l(e,a)),c),h(c,o)}}function Zt(t){const e=u(t.activePackageDir),r=u(t.stagedPackageDir),n=`${e}${Y}`,i=U(r,t.packageName,t.version),a=L(r,i);d(n)&&(d(e)?g(n,{recursive:!0,force:!0}):h(n,e)),Jt(e,n);let o=!1;try{d(e)&&(h(e,n),o=!0),h(r,e);const c=U(e,t.packageName,t.version),s=L(e,c);return qt(t.npmPrefix,e,s),{packageDir:e,backupDir:n}}catch(c){try{d(e)&&g(e,{recursive:!0,force:!0}),o&&d(n)&&h(n,e)}catch{}throw c}}function X(t,e=1e4){try{const r=M(t);return R(r.command,r.args,{encoding:"utf-8",timeout:e,windowsHide:!0}).trim()}catch{throw new f("NPM_NOT_FOUND",`Unable to resolve npm ${t.join(" ")}`)}}function W(t){return X(t)}const _t=3e5,mt=Tt.find(t=>t.id==="official")?.url??"https://registry.npmjs.org";async function Qt(t,e,r){const n=["view",`${t}@${e}`,"dist.integrity","--registry",r,"--no-audit","--no-fund"],i=nt();i&&n.push("--cache",i);const a=M(n),{stdout:o}=await ot(a.command,a.args,{timeout:1e4,windowsHide:!0});return o.trim()}async function ht(t,e,r,n={}){if(!r)return;let i;try{i=new URL(r).origin}catch{return}if(i===new URL(mt).origin)return;const a=n.fetchIntegrity??Qt;let o;try{o=await a(t,e,mt)}catch(s){m(`integrity cross-check skipped: official registry unreachable (${s instanceof Error?s.message:String(s)})`);return}if(!o){m("integrity cross-check skipped: official registry returned no dist.integrity");return}let c;try{c=await a(t,e,r)}catch(s){m(`integrity cross-check skipped: mirror metadata unreadable (${s instanceof Error?s.message:String(s)})`);return}if(!c){m("integrity cross-check skipped: mirror returned no dist.integrity");return}if(c!==o)throw new f("INTEGRITY_MISMATCH",`Mirror ${r} reports dist.integrity ${c} but official npm reports ${o} for ${t}@${e}`);m(`integrity cross-check passed for ${t}@${e} via ${r}`)}async function wt(t,e,r,n={},i=process.platform==="win32"?"staged":"atomic"){const a=`${t}@${e}`,o=W(["prefix","-g"]),c=W(["root","-g"]);E(o,{recursive:!0}),i==="staged"&&Ht(o);const s=tt(l(o,".grix-upgrade-stage-"));try{m(`staging npm install ${a} under ${s}`);const p=n.installWithMirror??rt,{registry:k,registryUrl:S}=await p(a,r,10*1024*1024,{prefix:s,...i==="staged"?{env:{...process.env,GRIX_UPGRADE_STAGING:"1"}}:{}});await(n.verifyIntegrityConsensus??ht)(t,e,S);const N=W(["root","-g","--prefix",s]),A=l(N,t),B=U(A,t,e),F=L(A,B),St=l(A,F[0][1]),q=R(process.execPath,[St,"--version"],{encoding:"utf-8",timeout:15e3,maxBuffer:2*1024*1024,windowsHide:!0}).trim().replace(/^v(?=\d)/,"");if(q!==e)throw new f("VERSION_MISMATCH",`Staged CLI reported ${q||"<empty>"}, expected ${e}`);const Z=l(c,t);return{npmPrefix:o,packageDir:Z,backupDir:`${u(Z)}${Y}`,stagedPackageDir:A,stagingPrefix:s,registry:k}}catch(p){try{g(s,{recursive:!0,force:!0})}catch{}throw p}}async function te(t,e,r,n){const i=await wt(t,e,r,n,"atomic");try{const a=Zt({packageName:t,version:e,npmPrefix:i.npmPrefix,activePackageDir:i.packageDir,stagedPackageDir:i.stagedPackageDir});m(`atomic package switch succeeded via ${i.registry}; backup=${a.backupDir}`)}finally{try{g(i.stagingPrefix,{recursive:!0,force:!0})}catch{}}}async function $e(t,e,r=_t,n={}){e=O(e);const i=_()?.transaction_id,a=`${t}@${e}`,o=n.activationMode??(process.platform==="win32"?"staged":"atomic");m(`npm install -g ${a} starting (${o} staging with mirror fallback)`);try{if(o==="staged"){const c=await wt(t,e,r,n,o);try{Kt({...c,activationStrategy:process.platform==="win32"?"wrapper-runtime":"service-start"}),process.platform==="win32"&&zt(c,e)}catch(s){try{g(c.stagingPrefix,{recursive:!0,force:!0})}catch{}throw s}return m(`staged package verified via ${c.registry}; waiting for guardian activation`),{activationRequired:!0,packageDir:c.packageDir,backupDir:c.backupDir,stagedPackageDir:c.stagedPackageDir,stagingPrefix:c.stagingPrefix}}else return await te(t,e,r,n),{activationRequired:!1}}catch(c){if(o==="staged"){const p=_();i&&p?.transaction_id===i&&Bt(p)}if(c instanceof f)throw c;const s=c instanceof Error?c.message:String(c);throw m(`npm install failed: ${s}`),/timed out|ETIMEDOUT/i.test(s)?new f("NPM_TIMEOUT",`npm install timed out after ${r/1e3}s (tried all mirrors): ${s}`):s.includes("EACCES")||s.includes("permission denied")?new f("NPM_INSTALL_FAILED",`Permission denied: ${s}`):s.includes("ENOSPC")||s.includes("no space left")?new f("DISK_FULL",`Disk full: ${s}`):s.includes("404")||s.includes("not found")?new f("NPM_INSTALL_FAILED",`Package not found: ${s}`):new f("NPM_INSTALL_FAILED",s)}}function De(t){let e;try{e=X(["root","-g"])}catch{throw new f("VERSION_VERIFY_FAILED","Unable to resolve the global npm package directory")}let r;try{const n=l(e,"grix-connector","package.json"),i=JSON.parse(P(n,"utf-8"));if(i.name!=="grix-connector"||typeof i.version!="string"||!i.version.trim())throw new Error("invalid package metadata");r=i.version.trim().replace(/^v(?=\d)/,"")}catch{throw new f("VERSION_VERIFY_FAILED","Unable to read the installed grix-connector version")}if(r!==t)throw new f("VERSION_MISMATCH",`Installed version ${r} does not match expected ${t}`);return r}async function Ne(t,e){e=O(e);let r=!1;for(const n of await Ut())try{const i=["view",`${t}@${e}`,"version","--registry",n.url,"--no-audit","--no-fund"],a=nt();a&&i.push("--cache",a);const o=M(i),{stdout:c}=await ot(o.command,o.args,{timeout:8e3,windowsHide:!0});if(c.trim())return!0}catch(i){const a=i,o=a.stderr||a.message||String(i);/ETARGET|No matching version|notarget|E404/i.test(o)&&(r=!0)}return!r}async function Ae(t,e,r,n=_t,i={}){r=O(r);const a=`${e}@${r}`,o=l(t,"versions",r);E(l(t,"versions"),{recursive:!0});const c=tt(l(t,"versions",`.stage-${r}-`));m(`installing ${a} into version store under ${c}`);try{const s=i.installWithMirror??rt,{registry:p,registryUrl:k}=await s(a,n,10*1024*1024,{prefix:c,env:{...process.env,GRIX_UPGRADE_STAGING:"1"},ignoreScripts:!0});await(i.verifyIntegrityConsensus??ht)(e,r,k);const y=W(["root","-g","--prefix",c]),N=l(y,e),A=U(N,e,r),B=L(N,A),F=R(process.execPath,[l(N,B[0][1]),"--version"],{encoding:"utf-8",timeout:15e3,maxBuffer:2*1024*1024,windowsHide:!0}).trim().replace(/^v(?=\d)/,"");if(F!==r)throw new f("VERSION_MISMATCH",`Installed CLI reported ${F||"<empty>"}, expected ${r}`);return g(o,{recursive:!0,force:!0}),h(N,o),m(`${a} verified via ${p}; placed at ${o}`),{registry:p,versionDir:o}}catch(s){if(s instanceof f)throw s;const p=s instanceof Error?s.message:String(s);throw m(`version store install failed: ${p}`),/timed out|ETIMEDOUT/i.test(p)?new f("NPM_TIMEOUT",`npm install timed out after ${n/1e3}s (tried all mirrors): ${p}`):p.includes("ENOSPC")||p.includes("no space left")?new f("DISK_FULL",`Disk full: ${p}`):new f("NPM_INSTALL_FAILED",p)}finally{try{g(c,{recursive:!0,force:!0})}catch{}}}export{_t as NPM_INSTALL_TIMEOUT_MS,f as UpgradeError,Ht as acquireNpmPrefixUpgradeLock,_e as archivePendingJournal,we as armWindowsUpgradeHandoff,Se as armWindowsUpgradeRollback,gt as checkDiskSpace,pt as checkNpmAvailable,Ee as cleanupPendingBackup,xe as collectEnvInfo,Zt as commitStagedGlobalPackage,Bt as discardPendingStaging,Ie as finalizePendingTransaction,Pe as getUpgradeLogTail,Ae as installVersionIntoStore,Ne as isVersionAvailable,O as normalizeUpgradeVersion,$e as npmInstall,ge as pendingExists,ve as preflightCheck,zt as prepareStagedWindowsRuntime,_ as readPending,he as readPendingPackageVersion,Yt as releasePendingUpgradeLock,dt as removePending,ye as removeWindowsHandoffFiles,ke as rollbackPendingInstall,D as updatePending,m as upgradeLog,pe as upgradeStatusSnapshot,De as verifyInstalledVersion,ht as verifyMirrorIntegrityConsensus,Vt as windowsRollbackIntentPath,j as windowsWrapperPausePath,me as writePending,Gt as writePendingData};
|
package/dist/log.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{createWriteStream as g,mkdirSync as l,existsSync as f}from"node:fs";import{join as
|
|
2
|
-
`)},error(o,r,...
|
|
1
|
+
import{createWriteStream as g,mkdirSync as l,existsSync as f}from"node:fs";import{join as i}from"node:path";import{homedir as m}from"node:os";const n=i(m(),".grix"),s={base:n,config:i(n,"config"),log:i(n,"log"),data:i(n,"data")};function S(){for(const o of Object.values(s))f(o)||l(o,{recursive:!0})}let a=null;function $(){const o=new Date().toISOString().slice(0,10),r=i(s.log,`grix-acp-${o}.log`);a=g(r,{flags:"a"})}function c(){return new Date().toISOString().slice(11,19)}const u={info(o,r,...t){const e=`${c()} [${o}] ${r}${t.length?" "+t.map(String).join(" "):""}`;console.log(e),a?.write(e+`
|
|
2
|
+
`)},error(o,r,...t){const e=`${c()} [${o}] ERROR ${r}${t.length?" "+t.map(String).join(" "):""}`;console.error(e),a?.write(e+`
|
|
3
3
|
`)}};export{s as GRIX_PATHS,S as ensureGrixDirs,$ as initLogger,u as log};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import*as
|
|
1
|
+
import*as n from"node:net";const i={bind:"127.0.0.1",port:0,endpoint:"/mcp",sessionTimeoutMs:18e5,invokeTimeoutMs:3e4};function s(u){const e={bind:u?.bind??i.bind,port:u?.port??i.port,endpoint:u?.endpoint??i.endpoint,sessionTimeoutMs:u?.sessionTimeoutMs??i.sessionTimeoutMs,invokeTimeoutMs:u?.invokeTimeoutMs??i.invokeTimeoutMs,allowedOrigins:u?.allowedOrigins,allowedHosts:u?.allowedHosts};return t(e.bind),e.port!==0&&o(e.port),r(e.sessionTimeoutMs),e}function t(u){if(!u||!n.isIPv4(u)&&!n.isIPv6(u))throw new Error(`\u914D\u7F6E\u6821\u9A8C\u5931\u8D25: bind \u5730\u5740 "${u}" \u4E0D\u662F\u5408\u6CD5\u7684 IPv4 \u6216 IPv6 \u5730\u5740`)}function o(u){if(!Number.isInteger(u)||u<1||u>65535)throw new Error(`\u914D\u7F6E\u6821\u9A8C\u5931\u8D25: port \u503C ${u} \u4E0D\u5728\u5408\u6CD5\u8303\u56F4 1-65535 \u5185\u6216\u4E0D\u662F\u6574\u6570`)}function r(u){if(!Number.isInteger(u)||u<1e3||u>864e5)throw new Error(`\u914D\u7F6E\u6821\u9A8C\u5931\u8D25: session_timeout_ms \u503C ${u} \u4E0D\u5728\u5408\u6CD5\u8303\u56F4 1000-86400000 \u5185`)}export{s as createDefaultGatewayConfig};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
const a=3e4;class c{connectionManager;onDisconnected;bindings=new Map;constructor(n,i){this.connectionManager=n,this.onDisconnected=i}async bind(n,i){if(this.bindings.has(n))throw new Error(`Session ${n} is already bound to a connection`);const e=await this.connectWithTimeout(i),t=[],s=e.onDisconnected(()=>{this.removeBinding(n),this.onDisconnected(n)});return t.push(s),this.bindings.set(n,{sessionId:n,handle:e,subscriptions:t}),e}getHandle(n){return this.bindings.get(n)?.handle}unbind(n){const i=this.bindings.get(n);if(i){this.bindings.delete(n);for(const e of i.subscriptions)e();i.handle.disconnect()}}unbindAll(){const n=[...this.bindings.keys()];for(const i of n)this.unbind(i)}connectWithTimeout(n){return new Promise((i,e)=>{let t=!1;const s=setTimeout(()=>{t||(t=!0,e(new Error("Connection bind timeout after 30000ms")))},3e4);this.connectionManager.connect({agentId:n.agentId,apiKey:n.apiKey,url:n.wsUrl,clientType:n.clientType,capabilities:["agent_invoke"],adapterHint:`${n.clientType}/base`},{maxRetries:0}).then(o=>{t?o.disconnect():(t=!0,clearTimeout(s),i(o))}).catch(o=>{t||(t=!0,clearTimeout(s),e(o))})})}removeBinding(n){const i=this.bindings.get(n);if(i){this.bindings.delete(n);for(const e of i.subscriptions)e()}}}export{c as ConnectionBindingImpl};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function a(
|
|
1
|
+
function a(e){const t=new Set([`http://127.0.0.1:${e.serverPort}`,`http://localhost:${e.serverPort}`,...e.allowedOrigins]),o=new Set([`127.0.0.1:${e.serverPort}`,`localhost:${e.serverPort}`,...e.allowedHosts]);return{validateRequest(s){const r=i(s,t);if(!r.ok)return r;const n=l(s,o);return n.ok?{ok:!0}:n}}}function i(e,t){const o=e.headers.origin;return o?t.has(o)?{ok:!0}:{ok:!1,statusCode:403,message:`Origin not allowed: ${o}`}:{ok:!0}}function l(e,t){const o=e.headers.host;return o?t.has(o)?{ok:!0}:{ok:!1,statusCode:403,message:`Host not allowed: ${o}`}:{ok:!1,statusCode:403,message:"Missing Host header"}}export{a as createSecurityPolicy};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{toolCallToInvoke as i}from"../../core/mcp/tools.js";import{ToolRegistryImpl as l}from"./tool-registry.js";import{validateToolArgs as a}from"./tool-schemas.js";import{isEventTool as p,executeEventTool as d}from"./event-tool-executor.js";class y{registry;constructor(){this.registry=new l}async execute(
|
|
1
|
+
import{toolCallToInvoke as i}from"../../core/mcp/tools.js";import{ToolRegistryImpl as l}from"./tool-registry.js";import{validateToolArgs as a}from"./tool-schemas.js";import{isEventTool as p,executeEventTool as d}from"./event-tool-executor.js";class y{registry;constructor(){this.registry=new l}async execute(r,e,t,n){if(!this.registry.hasTool(e))return this.errorResult(`\u672A\u77E5\u5DE5\u5177: ${e}`);const s=a(e,t);if(!s.valid)return this.errorResult(`\u53C2\u6570\u6821\u9A8C\u5931\u8D25: ${s.error}`);if(r.status!=="ready")return this.errorResult(`\u8FDE\u63A5\u4E0D\u53EF\u7528: \u5F53\u524D\u72B6\u6001\u4E3A ${r.status}`);if(p(e))return this.executeEventTool(r,e,t);const o=i(e,t);try{const u=await r.agentInvoke(o.action,o.params,n);return this.normalizeResult(u)}catch(u){const c=u instanceof Error?u.message:String(u);return c.toLowerCase().includes("timeout")?this.errorResult(`\u8C03\u7528\u8D85\u65F6: ${c}`):this.errorResult(`\u8C03\u7528\u5931\u8D25: ${c}`)}}normalizeResult(r){if(r==null||typeof r!="object")return this.successResult(r??null);const e=r,t=typeof e.code=="number"?e.code:0;if(t===0){const s="data"in e?e.data:null;return this.successResult(s??null)}const n=typeof e.msg=="string"?e.msg:"\u672A\u77E5\u9519\u8BEF";return this.errorResult(`\u4E0A\u6E38\u9519\u8BEF [code=${t}]: ${n}`)}successResult(r){return{content:[{type:"text",text:JSON.stringify(r)}],isError:!1}}errorResult(r){return{content:[{type:"text",text:r}],isError:!0}}async executeEventTool(r,e,t){return e==="grix_access_control"?this.executeAccessControl(r,t):d(r,e,t)}async executeAccessControl(r,e){const t=String(e.action??""),n={pair_approve:"pair_approve",pair_deny:"pair_deny",allow_sender:"sender_allow",remove_sender:"sender_remove",set_policy:"policy_set"}[t];if(!n)return this.errorResult(`\u672A\u77E5 access_control action: ${t}`);const s={};e.code!=null&&(s.code=e.code),e.sender_id!=null&&(s.sender_id=e.sender_id),e.policy!=null&&(s.policy=e.policy);try{const o=await r.agentInvoke("claude_access_control",{verb:n,payload:s},3e4);return this.successResult(o)}catch(o){const u=o instanceof Error?o.message:String(o);return this.errorResult(`access_control \u8C03\u7528\u5931\u8D25: ${u}`)}}}export{y as ToolExecutorImpl};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{TOOLS as
|
|
1
|
+
import{TOOLS as o,EVENT_TOOLS as s}from"../../core/mcp/tools.js";const e=new Set(["grix_query","grix_group","grix_message_send","grix_message_unsend","grix_admin"]),r=new Set(["grix_reply","grix_complete","grix_event_ack","grix_composing","grix_access_control","grix_status"]);class a{tools;toolMap;constructor(){this.tools=[...o.filter(t=>e.has(t.name)),...s.filter(t=>r.has(t.name))],this.toolMap=new Map(this.tools.map(t=>[t.name,t]))}getTools(){return this.tools}getTool(t){return this.toolMap.get(t)}hasTool(t){return this.toolMap.has(t)}}export{a as ToolRegistryImpl};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const o={required:["action"],properties:{action:{type:"string",enum:["contact_search","session_search","message_history","message_search"]},id:{type:"string"},keyword:{type:"string",maxLength:200},limit:{type:"integer",minimum:1,maximum:100},offset:{type:"integer",minimum:0},sessionId:{type:"string"},beforeId:{type:"string"}}},a={required:["action"],properties:{action:{type:"string",enum:["create","detail","leave","add_members","remove_members","update_member_role","update_all_members_muted","update_member_speaking","dissolve"]},sessionId:{type:"string"},name:{type:"string",maxLength:128},memberIds:{type:"array",items:{type:"string"},maxItems:100},memberTypes:{type:"array",items:{type:"integer",enum:[1,2]}},memberId:{type:"string"},role:{type:"integer",enum:[1,2]},memberType:{type:"integer"},allMembersMuted:{type:"boolean"},isSpeakMuted:{type:"boolean"},canSpeakWhenAllMuted:{type:"boolean"}}},p={required:["sessionId","content"],properties:{sessionId:{type:"string"},content:{type:"string",maxLength:1e4},msgType:{type:"integer"},quotedMessageId:{type:"string"},threadId:{type:"string"}}},m={required:["sessionId","msgId"],properties:{sessionId:{type:"string"},msgId:{type:"string"}}},g={required:["action"],properties:{action:{type:"string",enum:["create_agent","list_categories","create_category","update_category","assign_category","rotate_api_key"]},agentName:{type:"string"},introduction:{type:"string"},isMain:{type:"boolean"},agentId:{type:"string"},categoryId:{type:"string"},name:{type:"string"},parentId:{type:"string"},sortOrder:{type:"integer"}}},y={required:["session_id","text"],properties:{event_id:{type:"string"},session_id:{type:"string"},text:{type:"string",maxLength:5e4},quoted_message_id:{type:"string"},is_final:{type:"boolean"}}},d={required:["event_id","status"],properties:{event_id:{type:"string"},status:{type:"string",enum:["responded","canceled","failed"]},msg:{type:"string",maxLength:500}}},c={required:["event_id"],properties:{event_id:{type:"string"},session_id:{type:"string"}}},l={required:["session_id","active"],properties:{session_id:{type:"string"},active:{type:"boolean"},event_id:{type:"string"}}},_={required:["action"],properties:{action:{type:"string",enum:["pair_approve","pair_deny","allow_sender","remove_sender","set_policy"]},code:{type:"string"},sender_id:{type:"string"},policy:{type:"string",enum:["allowlist","open","disabled"]}}},f={required:[],properties:{}},C={grix_query:o,grix_group:a,grix_message_send:p,grix_message_unsend:m,grix_admin:g,grix_reply:y,grix_complete:d,grix_event_ack:c,grix_composing:l,grix_access_control:_,grix_status:f};function B(
|
|
1
|
+
const o={required:["action"],properties:{action:{type:"string",enum:["contact_search","session_search","message_history","message_search"]},id:{type:"string"},keyword:{type:"string",maxLength:200},limit:{type:"integer",minimum:1,maximum:100},offset:{type:"integer",minimum:0},sessionId:{type:"string"},beforeId:{type:"string"}}},a={required:["action"],properties:{action:{type:"string",enum:["create","detail","leave","add_members","remove_members","update_member_role","update_all_members_muted","update_member_speaking","dissolve"]},sessionId:{type:"string"},name:{type:"string",maxLength:128},memberIds:{type:"array",items:{type:"string"},maxItems:100},memberTypes:{type:"array",items:{type:"integer",enum:[1,2]}},memberId:{type:"string"},role:{type:"integer",enum:[1,2]},memberType:{type:"integer"},allMembersMuted:{type:"boolean"},isSpeakMuted:{type:"boolean"},canSpeakWhenAllMuted:{type:"boolean"}}},p={required:["sessionId","content"],properties:{sessionId:{type:"string"},content:{type:"string",maxLength:1e4},msgType:{type:"integer"},quotedMessageId:{type:"string"},threadId:{type:"string"}}},m={required:["sessionId","msgId"],properties:{sessionId:{type:"string"},msgId:{type:"string"}}},g={required:["action"],properties:{action:{type:"string",enum:["create_agent","list_categories","create_category","update_category","assign_category","rotate_api_key"]},agentName:{type:"string"},introduction:{type:"string"},isMain:{type:"boolean"},agentId:{type:"string"},categoryId:{type:"string"},name:{type:"string"},parentId:{type:"string"},sortOrder:{type:"integer"}}},y={required:["session_id","text"],properties:{event_id:{type:"string"},session_id:{type:"string"},text:{type:"string",maxLength:5e4},quoted_message_id:{type:"string"},is_final:{type:"boolean"}}},d={required:["event_id","status"],properties:{event_id:{type:"string"},status:{type:"string",enum:["responded","canceled","failed"]},msg:{type:"string",maxLength:500}}},c={required:["event_id"],properties:{event_id:{type:"string"},session_id:{type:"string"}}},l={required:["session_id","active"],properties:{session_id:{type:"string"},active:{type:"boolean"},event_id:{type:"string"}}},_={required:["action"],properties:{action:{type:"string",enum:["pair_approve","pair_deny","allow_sender","remove_sender","set_policy"]},code:{type:"string"},sender_id:{type:"string"},policy:{type:"string",enum:["allowlist","open","disabled"]}}},f={required:[],properties:{}},C={grix_query:o,grix_group:a,grix_message_send:p,grix_message_unsend:m,grix_admin:g,grix_reply:y,grix_complete:d,grix_event_ack:c,grix_composing:l,grix_access_control:_,grix_status:f};function B(r,t){const e=C[r];if(!e)return{valid:!1,error:`\u672A\u77E5\u5DE5\u5177: ${r}`};for(const i of e.required)if(t[i]===void 0||t[i]===null)return{valid:!1,error:`\u7F3A\u5C11\u5FC5\u586B\u53C2\u6570: ${i}`};for(const[i,u]of Object.entries(t)){if(u==null)continue;const n=e.properties[i];if(!n)continue;const s=$(i,u,n);if(s)return{valid:!1,error:s}}return{valid:!0}}function $(r,t,e){switch(e.type){case"string":if(typeof t!="string")return`\u53C2\u6570 ${r} \u7C7B\u578B\u9519\u8BEF: \u671F\u671B string\uFF0C\u5B9E\u9645 ${typeof t}`;if(e.maxLength!==void 0&&t.length>e.maxLength)return`\u53C2\u6570 ${r} \u8D85\u8FC7\u6700\u5927\u957F\u5EA6 ${e.maxLength}\uFF0C\u5B9E\u9645 ${t.length}`;if(e.enum&&!e.enum.includes(t))return`\u53C2\u6570 ${r} \u503C "${t}" \u4E0D\u5728\u5141\u8BB8\u8303\u56F4 [${e.enum.join(", ")}]`;break;case"integer":if(typeof t!="number"||!Number.isInteger(t))return`\u53C2\u6570 ${r} \u7C7B\u578B\u9519\u8BEF: \u671F\u671B integer\uFF0C\u5B9E\u9645 ${typeof t=="number"?"\u6D6E\u70B9\u6570":typeof t}`;if(e.minimum!==void 0&&t<e.minimum)return`\u53C2\u6570 ${r} \u503C ${t} \u5C0F\u4E8E\u6700\u5C0F\u503C ${e.minimum}`;if(e.maximum!==void 0&&t>e.maximum)return`\u53C2\u6570 ${r} \u503C ${t} \u5927\u4E8E\u6700\u5927\u503C ${e.maximum}`;if(e.enum&&!e.enum.includes(t))return`\u53C2\u6570 ${r} \u503C ${t} \u4E0D\u5728\u5141\u8BB8\u8303\u56F4 [${e.enum.join(", ")}]`;break;case"boolean":if(typeof t!="boolean")return`\u53C2\u6570 ${r} \u7C7B\u578B\u9519\u8BEF: \u671F\u671B boolean\uFF0C\u5B9E\u9645 ${typeof t}`;break;case"array":if(!Array.isArray(t))return`\u53C2\u6570 ${r} \u7C7B\u578B\u9519\u8BEF: \u671F\u671B array\uFF0C\u5B9E\u9645 ${typeof t}`;if(e.maxItems!==void 0&&t.length>e.maxItems)return`\u53C2\u6570 ${r} \u8D85\u8FC7\u6700\u5927\u5143\u7D20\u6570 ${e.maxItems}\uFF0C\u5B9E\u9645 ${t.length}`;if(e.items)for(let i=0;i<t.length;i++){const u=t[i];if(e.items.type==="string"&&typeof u!="string")return`\u53C2\u6570 ${r}[${i}] \u7C7B\u578B\u9519\u8BEF: \u671F\u671B string\uFF0C\u5B9E\u9645 ${typeof u}`;if(e.items.type==="integer"){if(typeof u!="number"||!Number.isInteger(u))return`\u53C2\u6570 ${r}[${i}] \u7C7B\u578B\u9519\u8BEF: \u671F\u671B integer\uFF0C\u5B9E\u9645 ${typeof u}`;if(e.items.enum&&!e.items.enum.includes(u))return`\u53C2\u6570 ${r}[${i}] \u503C ${u} \u4E0D\u5728\u5141\u8BB8\u8303\u56F4 [${e.items.enum.join(", ")}]`}}break}}export{B as validateToolArgs};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "grix-connector",
|
|
3
|
-
"version": "4.7.
|
|
3
|
+
"version": "4.7.1",
|
|
4
4
|
"description": "Connect local AI coding agents (Claude, Codex, Gemini, Qwen, DeepSeek, Cursor, OpenCode, Pi, OpenHuman, Reasonix) to the Grix scheduling platform. Also serves as an OpenClaw plugin for Grix channel transport.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|