grix-connector 4.2.6 → 4.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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 n of t)e.push(n);const r=Buffer.concat(e).toString("utf8").trim();return r?JSON.parse(r):{}}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,r)=>{try{await this.handleRequest(e,r)}catch(n){h(r,n instanceof Error?n.message:String(n))}}),await new Promise((e,r)=>{this.server.once("error",r),this.server.listen(this.port,this.host,()=>{this.server.off("error",r),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((r,n)=>{e.close(s=>s?n(s):r())})}async handleRequest(e,r){if(k(e)!==this.token){l(r);return}if(e.method!=="POST"){r.writeHead(405,{"content-type":"application/json"}),r.end(JSON.stringify({error:"method_not_allowed"}));return}const n=new URL(e.url,"http://localhost").pathname,s=await v(e),i=f.get(n);if(!i){u(r);return}const a=await i(this.callbacks,s);p(r,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
+ 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(t,e){this.controlURL=t.replace(/\/+$/,""),this.token=e.trim(),l.info("claude-worker-client",`Configured with control URL: ${this.controlURL}`)}async post(t,e,s){if(!this.isConfigured())throw new Error("worker control not configured");const i=new AbortController,o=setTimeout(()=>i.abort(),s);try{const r=await fetch(`${this.controlURL}${t}`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${this.token}`},body:JSON.stringify(e),signal:i.signal}),n=await r.text(),a=n.trim()?JSON.parse(n):{};if(!r.ok)throw new Error(a.error||`worker control failed ${r.status}`);return a}finally{clearTimeout(o)}}isRetryableError(t){const e=t instanceof Error?t.message:String(t);return/fetch failed|network|ECONNRESET|ETIMEDOUT|EAI_AGAIN|socket hang up|aborted/i.test(e)}async postWithRetry(t,e,s,i=1){let o;for(let r=0;r<=i;r++)try{return r>0&&l.info("claude-worker-client",`Retrying ${t} attempt=${r+1}`),await this.post(t,e,s)}catch(n){if(o=n,r>=i||!this.isRetryableError(n))break;await new Promise(a=>setTimeout(a,150))}throw o instanceof Error?o:new Error(String(o))}async deliverEvent(t){return this.postWithRetry("/v1/worker/deliver-event",{payload:t},1e4,1)}async deliverStop(t){return this.postWithRetry("/v1/worker/deliver-stop",{payload:t},1e4,1)}async deliverLocalAction(t){return this.postWithRetry("/v1/worker/deliver-local-action",{payload:t},1e4,1)}async ping(){try{return await this.postWithRetry("/v1/worker/ping",{},5e3,1),!0}catch{return!1}}}export{c as ClaudeWorkerClient};
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 l}from"./protocol-contract.js";function P(e){let t=null,r=0,n=!1,i=!1;const a=v(),s=e.gatewayUrl??"http://127.0.0.1:19580/mcp";return{async start(){await F(e.command,s,e.env);const c=E(e.grix),u=[...e.args??[],"--name",`grix-mcp-${e.name}`,"--session-id",a];e.fullAuto&&u.push("--dangerously-skip-permissions"),u.push("--dangerously-load-development-channels",`server:${l}`,"--append-system-prompt",c);const f=d(I(),`grix-mcp-claude-${e.name}`);await S(f,{recursive:!0});const{expectPath:$,pidPath:g}=await M(f,e.command,u),_={...process.env,...e.env??{}};t=x("/usr/bin/expect",[$],{cwd:e.cwd,env:_,stdio:["ignore","pipe","pipe"],detached:!0}),o.info("mcp-http-launcher",`\u542F\u52A8 Claude: name=${e.name} cwd=${e.cwd} pid=${t.pid}`),r=await k(g),n=!0,o.info("mcp-http-launcher",`Claude \u5B50\u8FDB\u7A0B PID: ${r}`),t.on("exit",(m,p)=>{o.info("mcp-http-launcher",`Claude \u9000\u51FA: code=${m} signal=${p}`),n=!1,t=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))}),t.stdout?.on("data",m=>{const p=m.toString().trim();p&&o.info("mcp-http-launcher",`[stdout] ${p.slice(0,300)}`)}),t.stderr?.on("data",m=>{const p=m.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(t?.pid){try{process.kill(-t.pid,"SIGTERM")}catch{}await new Promise(c=>{const u=setTimeout(()=>{if(r>0)try{process.kill(r,"SIGKILL")}catch{}if(t?.pid)try{process.kill(-t.pid,"SIGKILL")}catch{}c()},5e3);t?.once("exit",()=>{clearTimeout(u),c()})})}t=null,r=0},getStatus(){return{name:e.name,alive:n,pid:r}}}}function E(e){return["You are connected to a chat via the grix MCP server.",`On startup, immediately call grix_authorize with: agentId="${e.agentId}", apiKey="${e.apiKey}", wsUrl="${e.wsUrl}", clientType="${e.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(e,t,r){const n=d(T(),".claude.json");let i=null;try{const s=C(n,"utf8");i=JSON.parse(s)?.mcpServers?.[l]??null}catch{}if(i&&String(i.type??"").trim()==="http"&&String(i.url??"").trim()===t)return;o.info("mcp-http-launcher",`\u6CE8\u518C MCP Server: ${l} -> ${t}`);const a={...process.env,...r??{}};try{y(`${e} mcp remove -s user ${l}`,{encoding:"utf8",timeout:1e4,env:a,stdio:"pipe"})}catch{}y(`${e} mcp add --scope user --transport http ${l} ${t}`,{encoding:"utf8",timeout:1e4,env:a,stdio:"pipe"})}async function M(e,t,r){const{writeFile:n}=await import("node:fs/promises"),i=d(e,"claude.pid"),a=d(e,"claude.expect"),s=["log_user 1","set timeout -1","set startup_prompt_armed 1",`set claude_command [list {${h(t)}}${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(e){return e.replace(/[\\{}$\[\]"]/g,"\\$&")}async function k(e,t=1e4){const{readFile:r}=await import("node:fs/promises"),n=Math.ceil(t/100);for(let i=0;i<n;i++){try{const a=await r(e,"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
+ 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(t){this.defaultTimeoutMs=t.defaultTimeoutMs??9e4,this.onTimeout=t.onTimeout}arm(t,e){this.cancel(t);const s=e?.timeoutMs??this.defaultTimeoutMs,i=Date.now()+s,o=setTimeout(()=>{this.timers.delete(t),this.onTimeout(t).catch(()=>{})},s);return this.timers.set(t,o),i}cancel(t){const e=this.timers.get(t);e&&(clearTimeout(e),this.timers.delete(t))}has(t){return this.timers.has(t)}close(){for(const t of this.timers.values())clearTimeout(t);this.timers.clear()}}export{m as ResultTimeoutManager};
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};
@@ -1,2 +1,2 @@
1
- import{readdirSync as y,readFileSync as g,existsSync as h,statSync as j}from"node:fs";import{dirname as x,join as i,resolve as H}from"node:path";import{homedir as _}from"node:os";import{log as O}from"../../core/log/index.js";import{findGitProjectRoot as b}from"../../core/util/git-project-root.js";const M=".grix-managed";function S(r){const e=r.trim();if(!e.startsWith("---"))return{name:"",description:""};const t=e.indexOf("---",3);if(t===-1)return{name:"",description:""};const n=e.slice(3,t).trim();let c="",o="",l;for(const p of n.split(`
2
- `)){const u=p.indexOf(":");if(u===-1)continue;const f=p.slice(0,u).trim();let a=p.slice(u+1).trim();(a.startsWith('"')&&a.endsWith('"')||a.startsWith("'")&&a.endsWith("'"))&&(a=a.slice(1,-1)),f==="name"?c=a:f==="description"?o=a:f==="trigger"&&(l=a)}return{name:c,description:o,trigger:l}}function F(r,e,t){if(!h(r))return[];const n=[];try{for(const c of y(r,{withFileTypes:!0})){const o=i(r,c.name);if(!E(c,o)||c.name.startsWith("."))continue;const l=i(o,"SKILL.md");if(h(l))try{const p=g(l,"utf-8"),u=S(p);u.name&&n.push({name:u.name,description:u.description,trigger:u.trigger,source:e,pluginName:t,filePath:l,managed:h(i(o,M))})}catch{}}}catch{}return n}function s(r,e,t){if(!h(r))return[];const n=t?.maxDepth??6,c=t?.includeHiddenDirs??!1,o=[],l=(p,u)=>{if(u>n)return;let f;try{f=y(p,{withFileTypes:!0,encoding:"utf8"})}catch{return}for(const a of f){const m=i(p,a.name);if(t?.rootMarkdownFiles&&u===0&&a.name.endsWith(".md")){if(!c&&a.name.startsWith(".")||!v(a,m))continue;try{const D=g(m,"utf-8"),d=S(D);d.name&&o.push({name:d.name,description:d.description,trigger:d.trigger,source:e,pluginName:t?.pluginName,filePath:m})}catch{}continue}if(!E(a,m)||!c&&a.name.startsWith("."))continue;const k=i(m,"SKILL.md");if(h(k))try{const D=g(k,"utf-8"),d=S(D);d.name&&o.push({name:d.name,description:d.description,trigger:d.trigger,source:e,pluginName:t?.pluginName,filePath:k,managed:h(i(m,M))})}catch{}l(m,u+1)}};return l(r,0),o}function w(r){return r.map(e=>({...e,managed:!0}))}function E(r,e){if(r.isDirectory())return!0;if(!r.isSymbolicLink())return!1;try{return j(e).isDirectory()}catch{return!1}}function v(r,e){if(r.isFile())return!0;if(!r.isSymbolicLink())return!1;try{return j(e).isFile()}catch{return!1}}function L(r){const e=[],t=new Set;for(const n of r){const c=n.name.trim().toLowerCase();t.has(c)||(t.add(c),e.push(n))}return e}function A(r){const e=r.filePath?.trim();if(!e)return 0;try{const t=j(e).mtimeMs,n=j(x(e)).mtimeMs;return Math.max(t,n)}catch{return 0}}function I(r){return r.map((e,t)=>({entry:e,index:t,timeMs:A(e)})).sort((e,t)=>e.timeMs!==t.timeMs?t.timeMs-e.timeMs:e.index-t.index).map(e=>e.entry)}function N(r){const e=[],t=new Set;let n=H(r);for(;;){t.has(n)||(e.push(n),t.add(n));const c=x(n);if(c===n)break;n=c}return e}function R(r){const e=i(r,".claude","plugins","installed_plugins.json");if(!h(e))return[];const t=[];try{const n=g(e,"utf-8"),o=JSON.parse(n)?.plugins;if(!o||typeof o!="object")return t;for(const[l,p]of Object.entries(o))if(Array.isArray(p))for(const u of p){const f=u?.installPath;if(!f||!h(f))continue;const a=i(f,"skills"),m=l.split("@")[0],k=w(F(a,"plugin",m));t.push(...k)}}catch{}return t}function K(r,e){const t=(r??"").trim().toLowerCase(),n=(e??"").trim().toLowerCase();return t==="claude"?"claude":t==="codex"?"codex":t==="pi"?"pi":t==="cursor"?"cursor":t==="codewhale"?"codewhale":t==="opencode"?"opencode":t==="agy"?"gemini":t==="openhuman"?"none":t==="deepseek-harness"?"deepseek":n==="kiro"?"kiro":n==="qwen"?"qwen":n==="reasonix"?"reasonix":n==="kimi"?"kimi":n==="hermes"?"hermes":n==="copilot"?"copilot":"gemini"}function q(r){const e=[],t=r.homeDir??_();switch(r.mode){case"claude":{r.projectDir&&e.push(...s(i(r.projectDir,".claude","skills"),"project"));const c=i(t,".claude","skills");e.push(...s(c,"global")),e.push(...R(t));break}case"codex":{const c=process.env.CODEX_HOME?.trim()||i(t,".codex"),o=r.includeSharedAgentSkills??/^(1|true|yes|on)$/i.test(process.env.GRIX_CODEX_INCLUDE_SHARED_AGENT_SKILLS??"");if(r.projectDir)for(const l of N(r.projectDir))e.push(...s(i(l,".agents","skills"),"project")),e.push(...s(i(l,".codex","skills"),"project"));o&&e.push(...s(i(t,".agents","skills"),"codex")),e.push(...s(i(c,"skills"),"codex")),e.push(...w(s(i(c,"skills",".system"),"codex")));break}case"gemini":{r.projectDir&&(e.push(...s(i(r.projectDir,".gemini","skills"),"project")),e.push(...s(i(r.projectDir,".agents","skills"),"project"))),e.push(...s(i(t,".gemini","skills"),"gemini")),e.push(...s(i(t,".agents","skills"),"gemini"));break}case"pi":{r.projectDir&&e.push(...s(i(r.projectDir,".pi","skills"),"project")),e.push(...s(i(t,".pi","agent","skills"),"pi"));break}case"kiro":{r.projectDir&&e.push(...s(i(r.projectDir,".kiro","skills"),"project")),e.push(...s(i(t,".kiro","skills"),"kiro"));break}case"qwen":{r.projectDir&&e.push(...s(i(r.projectDir,".qwen","skills"),"project")),e.push(...s(i(t,".qwen","skills"),"global"));break}case"cursor":{r.projectDir&&(e.push(...s(i(r.projectDir,".agents","skills"),"project")),e.push(...s(i(r.projectDir,".cursor","skills"),"project"))),e.push(...s(i(t,".cursor","skills"),"global"));break}case"codewhale":{r.projectDir&&e.push(...s(i(r.projectDir,".codewhale","skills"),"project")),e.push(...s(i(t,".codewhale","skills"),"global"));break}case"opencode":{const c=process.env.XDG_CONFIG_HOME?.trim()||i(t,".config");e.push(...s(i(c,"opencode","skills"),"global"));break}case"reasonix":{e.push(...s(i(t,".reasonix","skills"),"global"));break}case"kimi":{const c=process.env.KIMI_CODE_HOME?.trim()||i(t,".kimi-code");e.push(...s(i(c,"skills"),"global"));break}case"deepseek":{const c=r.env??process.env,o=c.DSH_HOME?.trim()||i(t,".dsh"),l=c.DSH_AGENTS_HOME?.trim()||i(t,".agents"),p={rootMarkdownFiles:!0};if(r.projectDir){const u=b(r.projectDir);e.push(...s(i(u,".dsh","skills"),"project",p)),e.push(...s(i(u,".agents","skills"),"project",p))}e.push(...s(i(o,"skills"),"global",p)),e.push(...s(i(l,"skills"),"global",p));break}case"hermes":{const c=r.env??process.env,o=c.HERMES_HOME?.trim()||c.GRIX_HERMES_HOME?.trim()||i(t,".hermes");if(r.projectDir){const l=b(r.projectDir);e.push(...s(i(l,".hermes","skills"),"project")),e.push(...s(i(l,".agents","skills"),"project"))}e.push(...s(i(o,"skills"),"global"));break}case"copilot":{r.projectDir&&(e.push(...s(i(r.projectDir,".github","skills"),"project")),e.push(...s(i(r.projectDir,".claude","skills"),"project")),e.push(...s(i(r.projectDir,".agents","skills"),"project"))),e.push(...s(i(t,".copilot","skills"),"global")),e.push(...s(i(t,".agents","skills"),"global"));break}case"none":break}const n=I(L(e));return O.info("skill-scanner",`Scanned skills: mode=${r.mode} count=${n.length}`),n}export{M as MANAGED_MARKER,L as dedupeSkills,w as markManaged,S as parseSkillFrontmatter,K as resolveSkillScanMode,s as scanSkillTree,q as scanSkills,I as sortSkillsByRecentTime};
1
+ import{readdirSync as x,readFileSync as j,existsSync as h,statSync as D}from"node:fs";import{dirname as S,join as s,resolve as y}from"node:path";import{homedir as L}from"node:os";import{log as F}from"../../core/log/index.js";import{findGitProjectRoot as M}from"../../core/util/git-project-root.js";const w=".grix-managed";function b(t){const e=t.trim();if(!e.startsWith("---"))return{name:"",description:""};const r=e.indexOf("---",3);if(r===-1)return{name:"",description:""};const c=e.slice(3,r).trim();let i="",o="",l;for(const p of c.split(`
2
+ `)){const a=p.indexOf(":");if(a===-1)continue;const d=p.slice(0,a).trim();let u=p.slice(a+1).trim();(u.startsWith('"')&&u.endsWith('"')||u.startsWith("'")&&u.endsWith("'"))&&(u=u.slice(1,-1)),d==="name"?i=u:d==="description"?o=u:d==="trigger"&&(l=u)}return{name:i,description:o,trigger:l}}function P(t,e,r){if(!h(t))return[];const c=[];try{for(const i of x(t,{withFileTypes:!0})){const o=s(t,i.name);if(!H(i,o)||i.name.startsWith("."))continue;const l=s(o,"SKILL.md");if(h(l))try{const p=j(l,"utf-8"),a=b(p);a.name&&c.push({name:a.name,description:a.description,trigger:a.trigger,source:e,pluginName:r,filePath:l,managed:h(s(o,w))})}catch{}}}catch{}return c}function n(t,e,r){if(!h(t))return[];const c=r?.maxDepth??6,i=r?.includeHiddenDirs??!1,o=[],l=(p,a)=>{if(a>c)return;let d;try{d=x(p,{withFileTypes:!0,encoding:"utf8"})}catch{return}for(const u of d){const f=s(p,u.name);if(r?.rootMarkdownFiles&&a===0&&u.name.endsWith(".md")){if(!i&&u.name.startsWith(".")||!v(u,f))continue;try{const g=j(f,"utf-8"),m=b(g);m.name&&o.push({name:m.name,description:m.description,trigger:m.trigger,source:e,pluginName:r?.pluginName,filePath:f})}catch{}continue}if(!H(u,f)||!i&&u.name.startsWith(".")||u.name==="node_modules")continue;const k=s(f,"SKILL.md");if(h(k))try{const g=j(k,"utf-8"),m=b(g);m.name&&o.push({name:m.name,description:m.description,trigger:m.trigger,source:e,pluginName:r?.pluginName,filePath:k,managed:h(s(f,w))})}catch{}l(f,a+1)}};return l(t,0),o}function E(t){return t.map(e=>({...e,managed:!0}))}function H(t,e){if(t.isDirectory())return!0;if(!t.isSymbolicLink())return!1;try{return D(e).isDirectory()}catch{return!1}}function v(t,e){if(t.isFile())return!0;if(!t.isSymbolicLink())return!1;try{return D(e).isFile()}catch{return!1}}function N(t){const e=[],r=new Set;for(const c of t){const i=c.name.trim().toLowerCase();r.has(i)||(r.add(i),e.push(c))}return e}function R(t){const e=t.filePath?.trim();if(!e)return 0;try{const r=D(e).mtimeMs,c=D(S(e)).mtimeMs;return Math.max(r,c)}catch{return 0}}function A(t){return t.map((e,r)=>({entry:e,index:r,timeMs:R(e)})).sort((e,r)=>e.timeMs!==r.timeMs?r.timeMs-e.timeMs:e.index-r.index).map(e=>e.entry)}function I(t){const e=[],r=new Set;let c=y(t);for(;;){r.has(c)||(e.push(c),r.add(c));const i=S(c);if(i===c)break;c=i}return e}function T(t,e){const r=[s(t,".claude","settings.json")];e&&(r.push(s(e,".claude","settings.json")),r.push(s(e,".claude","settings.local.json")));const c=new Map;for(const i of r)if(h(i))try{const l=JSON.parse(j(i,"utf-8"))?.enabledPlugins;if(!l||typeof l!="object")continue;for(const[p,a]of Object.entries(l))typeof a=="boolean"&&c.set(p,a)}catch{}return c}function C(t,e){const r=s(t,".claude","plugins","installed_plugins.json");if(!h(r))return[];const c=[];try{const i=j(r,"utf-8"),l=JSON.parse(i)?.plugins;if(!l||typeof l!="object")return c;const p=T(t,e),a=e?y(e):void 0;for(const[d,u]of Object.entries(l))if(Array.isArray(u)&&p.get(d)===!0)for(const f of u){const k=f?.installPath;if(!k||!h(k))continue;if(f?.scope==="local"){const _=typeof f?.projectPath=="string"?y(f.projectPath):void 0;if(!a||_!==a)continue}const g=s(k,"skills"),m=d.split("@")[0],O=E(P(g,"plugin",m));c.push(...O)}}catch{}return c}function $(t,e){const r=(t??"").trim().toLowerCase(),c=(e??"").trim().toLowerCase();return r==="claude"?"claude":r==="codex"?"codex":r==="pi"?"pi":r==="cursor"?"cursor":r==="codewhale"?"codewhale":r==="opencode"?"opencode":r==="agy"?"gemini":r==="openhuman"?"none":r==="deepseek-harness"?"deepseek":c==="kiro"?"kiro":c==="qwen"?"qwen":c==="reasonix"?"reasonix":c==="kimi"?"kimi":c==="hermes"?"hermes":c==="copilot"?"copilot":"gemini"}function J(t){const e=[],r=t.homeDir??L();switch(t.mode){case"claude":{const i={maxDepth:0};t.projectDir&&e.push(...n(s(t.projectDir,".claude","skills"),"project",i));const o=s(r,".claude","skills");e.push(...n(o,"global",i)),e.push(...C(r,t.projectDir));break}case"codex":{const i=process.env.CODEX_HOME?.trim()||s(r,".codex"),o=t.includeSharedAgentSkills??/^(1|true|yes|on)$/i.test(process.env.GRIX_CODEX_INCLUDE_SHARED_AGENT_SKILLS??"");if(t.projectDir)for(const l of I(t.projectDir))e.push(...n(s(l,".agents","skills"),"project")),e.push(...n(s(l,".codex","skills"),"project"));o&&e.push(...n(s(r,".agents","skills"),"codex")),e.push(...n(s(i,"skills"),"codex")),e.push(...E(n(s(i,"skills",".system"),"codex")));break}case"gemini":{const i={maxDepth:0};t.projectDir&&(e.push(...n(s(t.projectDir,".gemini","skills"),"project",i)),e.push(...n(s(t.projectDir,".agents","skills"),"project",i))),e.push(...n(s(r,".gemini","skills"),"gemini",i)),e.push(...n(s(r,".agents","skills"),"gemini",i));break}case"pi":{t.projectDir&&e.push(...n(s(t.projectDir,".pi","skills"),"project")),e.push(...n(s(r,".pi","agent","skills"),"pi"));break}case"kiro":{t.projectDir&&e.push(...n(s(t.projectDir,".kiro","skills"),"project")),e.push(...n(s(r,".kiro","skills"),"kiro"));break}case"qwen":{const i={maxDepth:0};t.projectDir&&(e.push(...n(s(t.projectDir,".qwen","skills"),"project",i)),e.push(...n(s(t.projectDir,".agents","skills"),"project",i))),e.push(...n(s(r,".qwen","skills"),"global",i)),e.push(...n(s(r,".agents","skills"),"global",i));break}case"cursor":{const i={maxDepth:0};t.projectDir&&(e.push(...n(s(t.projectDir,".agents","skills"),"project",i)),e.push(...n(s(t.projectDir,".cursor","skills"),"project",i))),e.push(...n(s(r,".agents","skills"),"global",i)),e.push(...n(s(r,".cursor","skills"),"global",i));break}case"codewhale":{t.projectDir&&e.push(...n(s(t.projectDir,".codewhale","skills"),"project")),e.push(...n(s(r,".codewhale","skills"),"global"));break}case"opencode":{const i=process.env.XDG_CONFIG_HOME?.trim()||s(r,".config");t.projectDir&&(e.push(...n(s(t.projectDir,".opencode","skills"),"project")),e.push(...n(s(t.projectDir,".opencode","skill"),"project"))),e.push(...n(s(i,"opencode","skills"),"global")),e.push(...n(s(i,"opencode","skill"),"global")),e.push(...n(s(r,".claude","skills"),"global")),e.push(...n(s(r,".agents","skills"),"global"));break}case"reasonix":{e.push(...n(s(r,".reasonix","skills"),"global"));break}case"kimi":{const i=process.env.KIMI_CODE_HOME?.trim()||s(r,".kimi-code"),o={rootMarkdownFiles:!0};if(t.projectDir){const l=M(t.projectDir);e.push(...n(s(l,".kimi-code","skills"),"project",o)),e.push(...n(s(l,".agents","skills"),"project",o))}e.push(...n(s(i,"skills"),"global",o)),e.push(...n(s(r,".agents","skills"),"global",o));break}case"deepseek":{const i=t.env??process.env,o=i.DSH_HOME?.trim()||s(r,".dsh"),l=i.DSH_AGENTS_HOME?.trim()||s(r,".agents"),p={rootMarkdownFiles:!0,maxDepth:0};if(t.projectDir){const a=M(t.projectDir);e.push(...n(s(a,".dsh","skills"),"project",p)),e.push(...n(s(a,".agents","skills"),"project",p))}e.push(...n(s(o,"skills"),"global",p)),e.push(...n(s(l,"skills"),"global",p));break}case"hermes":{const i=t.env??process.env,o=i.HERMES_HOME?.trim()||i.GRIX_HERMES_HOME?.trim()||s(r,".hermes");e.push(...n(s(o,"skills"),"global"));break}case"copilot":{t.projectDir&&(e.push(...n(s(t.projectDir,".github","skills"),"project")),e.push(...n(s(t.projectDir,".claude","skills"),"project")),e.push(...n(s(t.projectDir,".agents","skills"),"project"))),e.push(...n(s(r,".copilot","skills"),"global")),e.push(...n(s(r,".agents","skills"),"global"));break}case"none":break}const c=A(N(e));return F.info("skill-scanner",`Scanned skills: mode=${t.mode} count=${c.length}`),c}export{w as MANAGED_MARKER,N as dedupeSkills,E as markManaged,b as parseSkillFrontmatter,$ as resolveSkillScanMode,n as scanSkillTree,J as scanSkills,A as sortSkillsByRecentTime};
@@ -1,3 +1,3 @@
1
- import{execFileSync as I}from"node:child_process";import{stat as A}from"node:fs/promises";import{resolveCommandPath as w,spawnCommand as M,killProcessGroup as b}from"../../core/runtime/spawn.js";import{createInterface as C}from"node:readline";import{EventEmitter as k}from"node:events";import{join as _,resolve as E}from"node:path";import{homedir as P}from"node:os";import{fileURLToPath as T}from"node:url";import{InternalApiServer as x}from"../../core/mcp/internal-api-server.js";import{resolveMcpServerName as $,LEGACY_MCP_SERVER_NAMES as N}from"../../core/mcp/server-name.js";import{InboundMessageIdInjector as R}from"../shared/inbound-message-id-injector.js";import{insertBeforeTrailingMessageReferences as B}from"../../core/protocol/message-reference.js";import{IdentityInjector as D}from"../shared/identity-injector.js";import{compactToolInputForWire as L}from"../shared/tool-wire-payload.js";import{syncDefaultSkillsToDir as U}from"../../default-skills/index.js";import{buildSimpleProbeReport as j}from"../shared/probe-util.js";import{getCachedCodeWhaleModels as O,primeCodeWhaleModels as G}from"./model-list.js";import{writeCodeWhaleGrixConfig as H}from"./codewhale-provider-config.js";import{log as o}from"../../core/log/index.js";import{SessionBindingStore as W}from"../../core/persistence/session-binding-store.js";const q=120*1e3,f=1800*1e3,F=5*1e3;function J(g){try{return process.kill(g,0),!0}catch(e){return e.code==="EPERM"}}class me extends k{type="codewhale";config;callbacks;alive=!1;stopped=!1;internalApi=null;deepSeekSessionId=null;activeEventId=null;activeSessionId=null;chunkSeq=0;activeClientMsgId=null;idleTimer=null;lastProgressAt=0;activeProcess=null;identity;inboundMessageIds=new R;bindingStore=null;aibotSessionId="";cwd;provider;agentName="";grixConfigPath="";lastUsage=null;currentModel=null;toolNamesById=new Map;auditCaptures=new Map;completedAuditBoundaries=new Map;constructor(e,t){super(),this.config=e,this.callbacks=t,this.identity=new D("codewhale-adapter",t.getAgentProfile);const i=e.options??{};if(this.aibotSessionId=String(i.aibotSessionId??"").trim(),this.bindingStore=i.bindingStore instanceof W?i.bindingStore:null,this.provider=i.provider,this.agentName=String(i.agentName??"").trim(),this.cwd=this.resolveCwd(),this.bindingStore&&this.aibotSessionId){const n=this.bindingStore.getCodeWhaleThreadId(this.aibotSessionId);n&&(this.deepSeekSessionId=n)}}resolveCwd(){if(this.bindingStore&&this.aibotSessionId){const e=this.bindingStore.get(this.aibotSessionId);if(e?.cwd)return e.cwd}return process.cwd()}async start(){this.alive=!0,await this.applyGrixProviderConfig(),await this.startInternalApiAndRegisterMcp(),G(this.config.command||"codewhale"),this.notifyBindingReady(),o.info("codewhale-adapter","Ready (exec mode)")}async applyGrixProviderConfig(){if(!this.provider){this.grixConfigPath="";return}try{this.grixConfigPath=await H(this.agentName,this.provider)??"",this.grixConfigPath?o.info("codewhale-adapter",`Grix provider config written to ${this.grixConfigPath}`):o.warn("codewhale-adapter","provider config incomplete (baseUrl/model required); Grix provider not applied")}catch(e){this.grixConfigPath="",o.warn("codewhale-adapter",`Failed to write Grix provider config: ${e instanceof Error?e.message:String(e)}`)}}async stop(){this.stopped=!0,this.alive=!1,this.stopComposing(),this.clearIdleTimer(),this.killActiveProcess(),this.activeEventId&&this.snapshotAuditBoundary(this.activeEventId),this.internalApi&&(await this.internalApi.stop(),this.internalApi=null)}isAlive(){return this.alive}async createSession(e){const t=this.deepSeekSessionId??`ds-${Date.now()}`;return this.notifyBindingReady(),t}async resumeSession(e,t){}onAgentProfileChanged(){this.identity.onProfileChanged()}async destroySession(e){this.identity.forgetSession(e),this.inboundMessageIds.forgetSession(e),this.deepSeekSessionId=null,this.persistSessionId(void 0)}sendPrompt(e){const t=new y(e.adapterSessionId);return this.runMessage(e,t).catch(i=>{t.emitError(i instanceof Error?i:new Error(String(i)))}),t}async cancel(e){this.killActiveProcess()}setPermissionHandler(e){}async ping(e){if(this.stopped||!this.alive)return!1;const t=this.activeProcess;return!(t?.pid&&!J(t.pid))}getStatus(){return{alive:this.alive,busy:this.activeEventId!==null,sessions:this.deepSeekSessionId?1:0}}getActiveEventIds(){return this.activeEventId?[this.activeEventId]:[]}clearActiveEventForShutdown(){this.clearIdleTimer(),this.killActiveProcess(),this.activeEventId&&this.snapshotAuditBoundary(this.activeEventId),this.activeEventId=null}takeAuditBoundary(e){const t=this.completedAuditBoundaries.get(e);return t&&this.completedAuditBoundaries.delete(e),t}getMcpConfig(){if(!this.internalApi)return null;const e=E(T(import.meta.url),"../../../mcp/acp-mcp-server.js");return{name:$(this.callbacks.getAgentId?.()),command:process.execPath,args:[e,"--api-url",this.internalApi.url]}}async probe(e){const t=this.getStatus();return j(this.config.command||"codewhale",{alive:t.alive,busy:t.busy,started:this.alive},e)}getUsageSnapshot(){return this.lastUsage}async startInternalApiAndRegisterMcp(){try{this.internalApi=new x,this.internalApi.setInvokeHandler(async(a,p,h,c)=>this.callbacks.agentInvoke(a,p,c)),await this.internalApi.start(0),o.info("codewhale-adapter",`Internal API started at ${this.internalApi.url}`);const e=this.getMcpConfig(),t={...process.env,...this.config.env},i=typeof t.PATH=="string"?t.PATH:void 0,n=w(this.config.command||"codewhale",i);for(const a of[...N,e.name])try{I(n,["mcp","remove",a],{env:t,timeout:1e4,stdio:"ignore",windowsHide:!0})}catch{}const s=["mcp","add",e.name,"--command",e.command];for(const a of e.args)s.push("--arg",a);I(n,s,{env:t,timeout:1e4,stdio:"ignore",windowsHide:!0}),o.info("codewhale-adapter",`Registered MCP server: ${e.name}`);const d=_(P(),".codewhale","skills"),r=U(d);r.length>0&&o.info("codewhale-adapter",`Synced connector skills to ${d}: [${r.join(", ")}]`)}catch(e){o.warn("codewhale-adapter",`Failed to register MCP tools (non-fatal): ${e instanceof Error?e.message:String(e)}`)}}getSupportedCommands(){return[{name:"status",description:"Show session and working directory status"}]}async execCommand(e,t,i){return e==="status"?{status:"ok",message:`Session: ${this.deepSeekSessionId??"none"}, CWD: ${this.cwd}`,data:{sessionId:this.deepSeekSessionId,cwd:this.cwd,alive:this.alive}}:{status:"unsupported",message:`Unknown command: ${e}`}}async handleLocalAction(e){const t=e.action_type??"",i=e.params??{};switch(t){case"get_context":return this.callbacks.sendLocalActionResult(e.action_id,"ok",{sessionId:this.deepSeekSessionId,cwd:this.cwd,model:this.currentModel,model_id:this.currentModel,available_models:this.availableModelsMeta()}),{handled:!0,kind:"get_context"};case"set_model":{const n=String(i.model_id??"").trim();return n?(this.currentModel=n,this.callbacks.sendLocalActionResult(e.action_id,"ok",{outcome:"model_set",modelId:n,model_id:n,available_models:this.availableModelsMeta()}),o.info("codewhale-adapter",`Model set to: ${n}`),{handled:!0,kind:"set_model"}):(this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,"invalid_params","model_id is required"),{handled:!0,kind:"set_model"})}default:return{handled:!1,kind:""}}}availableModelsMeta(){return O(this.config.command||"codewhale").map(e=>({id:e.id,displayName:e.displayName}))}deliverInboundEvent(e){if(this.activeEventId){o.info("codewhale-adapter",`Event ${e.event_id}: rejected, busy with ${this.activeEventId}`),this.callbacks.sendEventResult(e.event_id,"failed","agent busy");return}const t=this.inboundMessageIds.inject(e.session_id,e.content,e.msg_id);this.startNewMessage(e,t)}deliverStopEvent(e,t){this.activeEventId===e&&(this.killActiveProcess(),this.callbacks.sendEventResult(e,"canceled","stopped by user"),this.clearActive())}startNewMessage(e,t){this.activeEventId=e.event_id,this.activeSessionId=e.session_id,this.chunkSeq=0,this.activeClientMsgId=`ds-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,this.beginAuditCapture(e),this.startComposing();const i={adapterSessionId:this.deepSeekSessionId??"",text:t,contextMessages:e.context_messages_json?JSON.parse(e.context_messages_json).map(s=>({senderId:s.sender_id??"unknown",content:s.content})):void 0},n=new y(this.deepSeekSessionId??"");this.runMessage(i,n,e.event_id,e.session_id).catch(s=>{o.error("codewhale-adapter",`Message failed: ${s}`),this.callbacks.sendEventResult(e.event_id,"failed",s instanceof Error?s.message:String(s)),this.clearActive()}),this.resetIdleTimer(e.event_id)}buildExecArgs(e){const t=[];if(this.grixConfigPath){t.push("--config",this.grixConfigPath);const n=this.provider?.baseUrl?.trim();n&&t.push("--base-url",n)}const i=[...this.config.args??[]];return t.push("exec"),i.includes("--output-format")||t.push("--output-format","stream-json"),t.push(...i),this.currentModel&&t.push("--model",this.currentModel),this.deepSeekSessionId&&t.push("--resume",this.deepSeekSessionId),t.push("--",e),t}async runMessage(e,t,i,n){let s=e.text;if(e.contextMessages&&e.contextMessages.length>0){const c=e.contextMessages.map(l=>`[${l.senderId??"unknown"}]: ${l.content}`).join(`
1
+ import{execFileSync as I}from"node:child_process";import{stat as M}from"node:fs/promises";import{resolveCommandPath as w,spawnCommand as A,killProcessGroup as b}from"../../core/runtime/spawn.js";import{createInterface as C}from"node:readline";import{EventEmitter as k}from"node:events";import{join as _,resolve as E}from"node:path";import{homedir as P}from"node:os";import{fileURLToPath as T}from"node:url";import{InternalApiServer as x}from"../../core/mcp/internal-api-server.js";import{resolveMcpServerName as $,LEGACY_MCP_SERVER_NAMES as N}from"../../core/mcp/server-name.js";import{InboundMessageIdInjector as R}from"../shared/inbound-message-id-injector.js";import{insertBeforeTrailingMessageReferences as B}from"../../core/protocol/message-reference.js";import{IdentityInjector as D}from"../shared/identity-injector.js";import{compactToolInputForWire as L}from"../shared/tool-wire-payload.js";import{syncDefaultSkillsToDir as U}from"../../default-skills/index.js";import{buildSimpleProbeReport as j}from"../shared/probe-util.js";import{getCachedCodeWhaleModels as O,primeCodeWhaleModels as G}from"./model-list.js";import{writeCodeWhaleGrixConfig as H}from"./codewhale-provider-config.js";import{log as o}from"../../core/log/index.js";import{SessionBindingStore as W}from"../../core/persistence/session-binding-store.js";const q=120*1e3,f=1800*1e3,F=5*1e3;function J(g){try{return process.kill(g,0),!0}catch(e){return e.code==="EPERM"}}class me extends k{type="codewhale";config;callbacks;alive=!1;stopped=!1;internalApi=null;deepSeekSessionId=null;activeEventId=null;activeSessionId=null;chunkSeq=0;activeClientMsgId=null;idleTimer=null;lastProgressAt=0;activeProcess=null;identity;inboundMessageIds=new R;bindingStore=null;aibotSessionId="";cwd;provider;agentName="";grixConfigPath="";lastUsage=null;currentModel=null;toolNamesById=new Map;auditCaptures=new Map;completedAuditBoundaries=new Map;constructor(e,t){super(),this.config=e,this.callbacks=t,this.identity=new D("codewhale-adapter",t.getAgentProfile);const i=e.options??{};this.aibotSessionId=String(i.aibotSessionId??"").trim(),this.bindingStore=i.bindingStore instanceof W?i.bindingStore:null;const n=String(i.model??"").trim();if(n&&(this.currentModel=n),this.provider=i.provider,this.agentName=String(i.agentName??"").trim(),this.cwd=this.resolveCwd(),this.bindingStore&&this.aibotSessionId){const s=this.bindingStore.getCodeWhaleThreadId(this.aibotSessionId);s&&(this.deepSeekSessionId=s)}}resolveCwd(){if(this.bindingStore&&this.aibotSessionId){const e=this.bindingStore.get(this.aibotSessionId);if(e?.cwd)return e.cwd}return process.cwd()}async start(){this.alive=!0,await this.applyGrixProviderConfig(),await this.startInternalApiAndRegisterMcp(),G(this.config.command||"codewhale"),this.notifyBindingReady(),o.info("codewhale-adapter","Ready (exec mode)")}async applyGrixProviderConfig(){if(!this.provider){this.grixConfigPath="";return}try{this.grixConfigPath=await H(this.agentName,this.provider)??"",this.grixConfigPath?o.info("codewhale-adapter",`Grix provider config written to ${this.grixConfigPath}`):o.warn("codewhale-adapter","provider config incomplete (baseUrl/model required); Grix provider not applied")}catch(e){this.grixConfigPath="",o.warn("codewhale-adapter",`Failed to write Grix provider config: ${e instanceof Error?e.message:String(e)}`)}}async stop(){this.stopped=!0,this.alive=!1,this.stopComposing(),this.clearIdleTimer(),this.killActiveProcess(),this.activeEventId&&this.snapshotAuditBoundary(this.activeEventId),this.internalApi&&(await this.internalApi.stop(),this.internalApi=null)}isAlive(){return this.alive}async createSession(e){const t=this.deepSeekSessionId??`ds-${Date.now()}`;return this.notifyBindingReady(),t}async resumeSession(e,t){}onAgentProfileChanged(){this.identity.onProfileChanged()}async destroySession(e){this.identity.forgetSession(e),this.inboundMessageIds.forgetSession(e),this.deepSeekSessionId=null,this.persistSessionId(void 0)}sendPrompt(e){const t=new y(e.adapterSessionId);return this.runMessage(e,t).catch(i=>{t.emitError(i instanceof Error?i:new Error(String(i)))}),t}async cancel(e){this.killActiveProcess()}setPermissionHandler(e){}async ping(e){if(this.stopped||!this.alive)return!1;const t=this.activeProcess;return!(t?.pid&&!J(t.pid))}getStatus(){return{alive:this.alive,busy:this.activeEventId!==null,sessions:this.deepSeekSessionId?1:0}}getActiveEventIds(){return this.activeEventId?[this.activeEventId]:[]}clearActiveEventForShutdown(){this.clearIdleTimer(),this.killActiveProcess(),this.activeEventId&&this.snapshotAuditBoundary(this.activeEventId),this.activeEventId=null}takeAuditBoundary(e){const t=this.completedAuditBoundaries.get(e);return t&&this.completedAuditBoundaries.delete(e),t}getMcpConfig(){if(!this.internalApi)return null;const e=E(T(import.meta.url),"../../../mcp/acp-mcp-server.js");return{name:$(this.callbacks.getAgentId?.()),command:process.execPath,args:[e,"--api-url",this.internalApi.url]}}async probe(e){const t=this.getStatus();return j(this.config.command||"codewhale",{alive:t.alive,busy:t.busy,started:this.alive},e)}getUsageSnapshot(){return this.lastUsage}async startInternalApiAndRegisterMcp(){try{this.internalApi=new x,this.internalApi.setInvokeHandler(async(a,p,h,c)=>this.callbacks.agentInvoke(a,p,c)),await this.internalApi.start(0),o.info("codewhale-adapter",`Internal API started at ${this.internalApi.url}`);const e=this.getMcpConfig(),t={...process.env,...this.config.env},i=typeof t.PATH=="string"?t.PATH:void 0,n=w(this.config.command||"codewhale",i);for(const a of[...N,e.name])try{I(n,["mcp","remove",a],{env:t,timeout:1e4,stdio:"ignore",windowsHide:!0})}catch{}const s=["mcp","add",e.name,"--command",e.command];for(const a of e.args)s.push("--arg",a);I(n,s,{env:t,timeout:1e4,stdio:"ignore",windowsHide:!0}),o.info("codewhale-adapter",`Registered MCP server: ${e.name}`);const d=_(P(),".codewhale","skills"),r=U(d);r.length>0&&o.info("codewhale-adapter",`Synced connector skills to ${d}: [${r.join(", ")}]`)}catch(e){o.warn("codewhale-adapter",`Failed to register MCP tools (non-fatal): ${e instanceof Error?e.message:String(e)}`)}}getSupportedCommands(){return[{name:"status",description:"Show session and working directory status"}]}async execCommand(e,t,i){return e==="status"?{status:"ok",message:`Session: ${this.deepSeekSessionId??"none"}, CWD: ${this.cwd}`,data:{sessionId:this.deepSeekSessionId,cwd:this.cwd,alive:this.alive}}:{status:"unsupported",message:`Unknown command: ${e}`}}async handleLocalAction(e){const t=e.action_type??"",i=e.params??{};switch(t){case"get_context":return this.callbacks.sendLocalActionResult(e.action_id,"ok",{sessionId:this.deepSeekSessionId,cwd:this.cwd,model:this.currentModel,model_id:this.currentModel,available_models:this.availableModelsMeta()}),{handled:!0,kind:"get_context"};case"set_model":{const n=String(i.model_id??"").trim();return n?(this.currentModel=n,this.callbacks.sendLocalActionResult(e.action_id,"ok",{outcome:"model_set",modelId:n,model_id:n,available_models:this.availableModelsMeta()}),o.info("codewhale-adapter",`Model set to: ${n}`),{handled:!0,kind:"set_model"}):(this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,"invalid_params","model_id is required"),{handled:!0,kind:"set_model"})}default:return{handled:!1,kind:""}}}availableModelsMeta(){return O(this.config.command||"codewhale").map(e=>({id:e.id,displayName:e.displayName}))}deliverInboundEvent(e){if(this.activeEventId){o.info("codewhale-adapter",`Event ${e.event_id}: rejected, busy with ${this.activeEventId}`),this.callbacks.sendEventResult(e.event_id,"failed","agent busy");return}const t=this.inboundMessageIds.inject(e.session_id,e.content,e.msg_id);this.startNewMessage(e,t)}deliverStopEvent(e,t){this.activeEventId===e&&(this.killActiveProcess(),this.callbacks.sendEventResult(e,"canceled","stopped by user"),this.clearActive())}startNewMessage(e,t){this.activeEventId=e.event_id,this.activeSessionId=e.session_id,this.chunkSeq=0,this.activeClientMsgId=`ds-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,this.beginAuditCapture(e),this.startComposing();const i={adapterSessionId:this.deepSeekSessionId??"",text:t,contextMessages:e.context_messages_json?JSON.parse(e.context_messages_json).map(s=>({senderId:s.sender_id??"unknown",content:s.content})):void 0},n=new y(this.deepSeekSessionId??"");this.runMessage(i,n,e.event_id,e.session_id).catch(s=>{o.error("codewhale-adapter",`Message failed: ${s}`),this.callbacks.sendEventResult(e.event_id,"failed",s instanceof Error?s.message:String(s)),this.clearActive()}),this.resetIdleTimer(e.event_id)}buildExecArgs(e){const t=[];if(this.grixConfigPath){t.push("--config",this.grixConfigPath);const n=this.provider?.baseUrl?.trim();n&&t.push("--base-url",n)}const i=[...this.config.args??[]];return t.push("exec"),i.includes("--output-format")||t.push("--output-format","stream-json"),t.push(...i),this.currentModel&&t.push("--model",this.currentModel),this.deepSeekSessionId&&t.push("--resume",this.deepSeekSessionId),t.push("--",e),t}async runMessage(e,t,i,n){let s=e.text;if(e.contextMessages&&e.contextMessages.length>0){const c=e.contextMessages.map(l=>`[${l.senderId??"unknown"}]: ${l.content}`).join(`
2
2
  `);s=B(s,`[Conversation context]
3
- ${c}`)}s=this.identity.injectOnce(n??e.adapterSessionId,s);const d=this.config.command||"codewhale",r=this.buildExecArgs(s),a={...process.env,...this.config.env},p=w(d,typeof a.PATH=="string"?a.PATH:void 0);o.info("codewhale-adapter",`Spawning: ${p} ${r.slice(0,5).join(" ")}...`);try{if(!(await A(this.cwd)).isDirectory())throw new Error(`Bound path is not a directory: ${this.cwd}`)}catch(c){throw String(c?.code??"")==="ENOENT"?new Error(`Bound directory does not exist: ${this.cwd}. Please rebind with /grix open <valid-directory>.`):c}const h=M(p,r,{cwd:this.cwd,env:a}).process;return this.activeProcess=h,h.stderr?.on("data",c=>{const l=c.toString().trim();l&&o.info("codewhale-adapter",`[codewhale stderr] ${l}`)}),new Promise((c,l)=>{let m=!1,v="";const S=()=>{this.activeProcess=null};h.on("error",u=>{m||(m=!0,S(),l(u))}),h.on("exit",u=>{if(v.trim()&&this.handleOutputLine(v.trim(),i),v="",m){S();return}if(m=!0,S(),u!==0&&i&&this.activeEventId===i){l(new Error(`codewhale exec exited with code ${u}`));return}t.emitDone({status:"completed"}),c()}),C({input:h.stdout}).on("line",u=>{u.trim()&&this.handleOutputLine(u.trim(),i)}),h.stdin?.end()})}handleOutputLine(e,t){let i;try{i=JSON.parse(e)}catch{o.error("codewhale-adapter",`Invalid JSON: ${e.slice(0,200)}`);return}switch(t&&this.captureAuditEvent(t,e,i),i.type){case"content":{const s=i.content;s&&t&&this.activeEventId===t&&this.activeSessionId&&(this.chunkSeq++,this.callbacks.sendStreamChunk(t,this.activeSessionId,s,this.chunkSeq,!1,this.activeClientMsgId??void 0),this.startComposing(),this.resetIdleTimer(t));break}case"session_capture":{const s=i.content;s&&(this.deepSeekSessionId=s,this.persistSessionId(s),o.info("codewhale-adapter",`Session captured: ${s}`));break}case"metadata":{const s=i.meta;if(s){o.info("codewhale-adapter",`Metadata: model=${s.model}, tokens_in=${s.input_tokens}, tokens_out=${s.output_tokens}`);const d=Number(s.input_tokens??0),r=Number(s.output_tokens??0);if(d>0||r>0){const a=this.lastUsage;this.lastUsage={sampledAt:new Date().toISOString(),turns:(a?.turns??0)+1,total:{input:(a?.total.input??0)+d,output:(a?.total.output??0)+r}}}}break}case"tool_use":{const s=typeof i.name=="string"?i.name.trim():"",d=typeof i.id=="string"?i.id.trim():"",r=L(i.input);s&&t&&this.activeEventId===t&&this.activeSessionId&&(d&&this.toolNamesById.set(d,s),o.info("codewhale-adapter",`Tool use: ${s}`),this.callbacks.sendToolUse(t,this.activeSessionId,s,r),this.resetIdleTimer(t));break}case"tool_result":{const s=typeof i.id=="string"?i.id.trim():"",r=(typeof i.name=="string"?i.name.trim():"")||(s?this.toolNamesById.get(s):void 0)||"tool";s&&this.toolNamesById.delete(s);const a=typeof i.status=="string"?i.status.trim().toLowerCase():"",p=a==="failed"||a==="failure"||a==="error";t&&this.activeEventId===t&&this.activeSessionId&&(p&&this.callbacks.sendToolResult(t,this.activeSessionId,r,"(failed)"),this.resetIdleTimer(t));break}case"done":{this.handleMessageCompleted(t);break}default:break}}handleMessageCompleted(e){if(this.stopComposing(),e&&this.activeEventId===e){const t=this.activeSessionId??"",i=this.activeClientMsgId??void 0;t&&(this.chunkSeq++,this.callbacks.sendStreamChunk(e,t,"",this.chunkSeq,!0,i)),this.callbacks.sendEventResult(e,"responded"),this.clearActive()}}killActiveProcess(){const e=this.activeProcess;this.activeProcess=null,e?.pid&&(b(e,"SIGTERM"),setTimeout(()=>{if(e.exitCode===null&&e.signalCode===null)try{b(e,"SIGKILL")}catch{}},5e3).unref())}notifyBindingReady(){if(!this.aibotSessionId||!this.cwd)return;const e=this.availableModelsMeta(),t=this.currentModel??e[0]?.id??"";this.callbacks.sendUpdateBindingCard(this.aibotSessionId,"ready",this.cwd,{model_id:t,available_models:e})}persistSessionId(e){!this.bindingStore||!this.aibotSessionId||this.bindingStore.setCodeWhaleThreadId(this.aibotSessionId,e)}startComposing(){}stopComposing(){}resetIdleTimer(e){this.lastProgressAt=Date.now(),this.armIdleTimer(e)}armIdleTimer(e){this.clearIdleTimer();const t=this.lastProgressAt+f-Date.now(),i=Math.max(0,Math.min(q,t));this.idleTimer=setTimeout(()=>{this.onIdleTimeout(e)},i)}async onIdleTimeout(e){if(this.activeEventId!==e)return;if(Date.now()-this.lastProgressAt>=f){this.failIdleRun(e,`liveness budget exhausted after ${f/6e4}min`);return}let i=!1;try{i=await this.ping(F)}catch{i=!1}if(this.activeEventId===e){if(i){o.info("codewhale-adapter",`Idle timer: process alive, extending until liveness cap (${f/6e4}min): ${e}`),this.armIdleTimer(e);return}this.failIdleRun(e,"process not alive")}}failIdleRun(e,t){this.activeEventId===e&&(o.error("codewhale-adapter",`Idle timeout (${t}): ${e}`),this.killActiveProcess(),this.callbacks.sendEventResult(e,"failed",`idle timeout: ${t}`),this.clearActive(),this.emit("stuck"))}clearIdleTimer(){this.idleTimer&&(clearTimeout(this.idleTimer),this.idleTimer=null)}clearActive(){const e=this.activeEventId;e&&this.snapshotAuditBoundary(e),this.stopComposing(),this.activeEventId=null,this.activeSessionId=null,this.chunkSeq=0,this.activeClientMsgId=null,this.toolNamesById.clear(),this.lastProgressAt=0,this.clearIdleTimer(),e&&this.emit("eventDone",e)}beginAuditCapture(e){!e.audit?.enabled||this.auditCaptures.has(e.event_id)||this.auditCaptures.set(e.event_id,{events:[]})}captureAuditEvent(e,t,i){const n=this.auditCaptures.get(e);n&&n.events.push({sequence:n.events.length,observedAt:new Date().toISOString(),rawLine:t,event:structuredClone(i)})}snapshotAuditBoundary(e){const t=this.auditCaptures.get(e);t&&(this.completedAuditBoundaries.set(e,{adapterType:"codewhale",providerSessionId:this.deepSeekSessionId??void 0,codeWhaleEvidence:{events:t.events}}),this.auditCaptures.delete(e))}}class y extends k{adapterSessionId;constructor(e){super(),this.adapterSessionId=e}emitDone(e){this.emit("done",e)}emitError(e){if(this.listenerCount("error")===0){o.warn("codewhale-adapter",`Prompt handle error (no listeners): ${e.message}`);return}this.emit("error",e)}async cancel(){}}export{me as CodeWhaleAdapter};
3
+ ${c}`)}s=this.identity.injectOnce(n??e.adapterSessionId,s);const d=this.config.command||"codewhale",r=this.buildExecArgs(s),a={...process.env,...this.config.env},p=w(d,typeof a.PATH=="string"?a.PATH:void 0);o.info("codewhale-adapter",`Spawning: ${p} ${r.slice(0,5).join(" ")}...`);try{if(!(await M(this.cwd)).isDirectory())throw new Error(`Bound path is not a directory: ${this.cwd}`)}catch(c){throw String(c?.code??"")==="ENOENT"?new Error(`Bound directory does not exist: ${this.cwd}. Please rebind with /grix open <valid-directory>.`):c}const h=A(p,r,{cwd:this.cwd,env:a}).process;return this.activeProcess=h,h.stderr?.on("data",c=>{const l=c.toString().trim();l&&o.info("codewhale-adapter",`[codewhale stderr] ${l}`)}),new Promise((c,l)=>{let m=!1,v="";const S=()=>{this.activeProcess=null};h.on("error",u=>{m||(m=!0,S(),l(u))}),h.on("exit",u=>{if(v.trim()&&this.handleOutputLine(v.trim(),i),v="",m){S();return}if(m=!0,S(),u!==0&&i&&this.activeEventId===i){l(new Error(`codewhale exec exited with code ${u}`));return}t.emitDone({status:"completed"}),c()}),C({input:h.stdout}).on("line",u=>{u.trim()&&this.handleOutputLine(u.trim(),i)}),h.stdin?.end()})}handleOutputLine(e,t){let i;try{i=JSON.parse(e)}catch{o.error("codewhale-adapter",`Invalid JSON: ${e.slice(0,200)}`);return}switch(t&&this.captureAuditEvent(t,e,i),i.type){case"content":{const s=i.content;s&&t&&this.activeEventId===t&&this.activeSessionId&&(this.chunkSeq++,this.callbacks.sendStreamChunk(t,this.activeSessionId,s,this.chunkSeq,!1,this.activeClientMsgId??void 0),this.startComposing(),this.resetIdleTimer(t));break}case"session_capture":{const s=i.content;s&&(this.deepSeekSessionId=s,this.persistSessionId(s),o.info("codewhale-adapter",`Session captured: ${s}`));break}case"metadata":{const s=i.meta;if(s){o.info("codewhale-adapter",`Metadata: model=${s.model}, tokens_in=${s.input_tokens}, tokens_out=${s.output_tokens}`);const d=Number(s.input_tokens??0),r=Number(s.output_tokens??0);if(d>0||r>0){const a=this.lastUsage;this.lastUsage={sampledAt:new Date().toISOString(),turns:(a?.turns??0)+1,total:{input:(a?.total.input??0)+d,output:(a?.total.output??0)+r}}}}break}case"tool_use":{const s=typeof i.name=="string"?i.name.trim():"",d=typeof i.id=="string"?i.id.trim():"",r=L(i.input);s&&t&&this.activeEventId===t&&this.activeSessionId&&(d&&this.toolNamesById.set(d,s),o.info("codewhale-adapter",`Tool use: ${s}`),this.callbacks.sendToolUse(t,this.activeSessionId,s,r),this.resetIdleTimer(t));break}case"tool_result":{const s=typeof i.id=="string"?i.id.trim():"",r=(typeof i.name=="string"?i.name.trim():"")||(s?this.toolNamesById.get(s):void 0)||"tool";s&&this.toolNamesById.delete(s);const a=typeof i.status=="string"?i.status.trim().toLowerCase():"",p=a==="failed"||a==="failure"||a==="error";t&&this.activeEventId===t&&this.activeSessionId&&(p&&this.callbacks.sendToolResult(t,this.activeSessionId,r,"(failed)"),this.resetIdleTimer(t));break}case"done":{this.handleMessageCompleted(t);break}default:break}}handleMessageCompleted(e){if(this.stopComposing(),e&&this.activeEventId===e){const t=this.activeSessionId??"",i=this.activeClientMsgId??void 0;t&&(this.chunkSeq++,this.callbacks.sendStreamChunk(e,t,"",this.chunkSeq,!0,i)),this.callbacks.sendEventResult(e,"responded"),this.clearActive()}}killActiveProcess(){const e=this.activeProcess;this.activeProcess=null,e?.pid&&(b(e,"SIGTERM"),setTimeout(()=>{if(e.exitCode===null&&e.signalCode===null)try{b(e,"SIGKILL")}catch{}},5e3).unref())}notifyBindingReady(){if(!this.aibotSessionId||!this.cwd)return;const e=this.availableModelsMeta(),t=this.currentModel??e[0]?.id??"";this.callbacks.sendUpdateBindingCard(this.aibotSessionId,"ready",this.cwd,{model_id:t,available_models:e})}persistSessionId(e){!this.bindingStore||!this.aibotSessionId||this.bindingStore.setCodeWhaleThreadId(this.aibotSessionId,e)}startComposing(){}stopComposing(){}resetIdleTimer(e){this.lastProgressAt=Date.now(),this.armIdleTimer(e)}armIdleTimer(e){this.clearIdleTimer();const t=this.lastProgressAt+f-Date.now(),i=Math.max(0,Math.min(q,t));this.idleTimer=setTimeout(()=>{this.onIdleTimeout(e)},i)}async onIdleTimeout(e){if(this.activeEventId!==e)return;if(Date.now()-this.lastProgressAt>=f){this.failIdleRun(e,`liveness budget exhausted after ${f/6e4}min`);return}let i=!1;try{i=await this.ping(F)}catch{i=!1}if(this.activeEventId===e){if(i){o.info("codewhale-adapter",`Idle timer: process alive, extending until liveness cap (${f/6e4}min): ${e}`),this.armIdleTimer(e);return}this.failIdleRun(e,"process not alive")}}failIdleRun(e,t){this.activeEventId===e&&(o.error("codewhale-adapter",`Idle timeout (${t}): ${e}`),this.killActiveProcess(),this.callbacks.sendEventResult(e,"failed",`idle timeout: ${t}`),this.clearActive(),this.emit("stuck"))}clearIdleTimer(){this.idleTimer&&(clearTimeout(this.idleTimer),this.idleTimer=null)}clearActive(){const e=this.activeEventId;e&&this.snapshotAuditBoundary(e),this.stopComposing(),this.activeEventId=null,this.activeSessionId=null,this.chunkSeq=0,this.activeClientMsgId=null,this.toolNamesById.clear(),this.lastProgressAt=0,this.clearIdleTimer(),e&&this.emit("eventDone",e)}beginAuditCapture(e){!e.audit?.enabled||this.auditCaptures.has(e.event_id)||this.auditCaptures.set(e.event_id,{events:[]})}captureAuditEvent(e,t,i){const n=this.auditCaptures.get(e);n&&n.events.push({sequence:n.events.length,observedAt:new Date().toISOString(),rawLine:t,event:structuredClone(i)})}snapshotAuditBoundary(e){const t=this.auditCaptures.get(e);t&&(this.completedAuditBoundaries.set(e,{adapterType:"codewhale",providerSessionId:this.deepSeekSessionId??void 0,codeWhaleEvidence:{events:t.events}}),this.auditCaptures.delete(e))}}class y extends k{adapterSessionId;constructor(e){super(),this.adapterSessionId=e}emitDone(e){this.emit("done",e)}emitError(e){if(this.listenerCount("error")===0){o.warn("codewhale-adapter",`Prompt handle error (no listeners): ${e.message}`);return}this.emit("error",e)}async cancel(){}}export{me as CodeWhaleAdapter};
@@ -1,8 +1,8 @@
1
- import{mkdir as Y,readFile as F,writeFile as w}from"node:fs/promises";import{join as y}from"node:path";import{log as E}from"../../core/log/index.js";import{DEFAULT_DSH_MODELS as K}from"./toolbar-state.js";const M="grix",g="GRIX_PROVIDER_API_KEY",O="settings.yaml",W=".credentials.yaml",A="dsh-provider",x="llm-pi-ai",j=new Map;function _(t,n){const r=(j.get(t)??Promise.resolve()).then(n,n);return j.set(t,r.catch(()=>{})),r}function l(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}class p extends Error{code="yaml_incomplete";constructor(n){super(n),this.name="IncompleteYamlError"}}async function $(t){try{return l(G(await F(t,"utf8")))}catch(n){if(n.code==="ENOENT")return{};throw n}}async function z(t){return _(y(t,W),()=>$(y(t,W)))}function P(t){const n=t.baseUrl?.trim(),r=t.model?.trim();if(!n||!r)return;const o=new Map;o.set(r,{id:r,name:r,contextWindow:1e6});for(const e of K)o.has(e.id)||o.set(e.id,{id:e.id,name:e.displayName,contextWindow:e.contextWindow});return{displayName:"Grix",apiKeyEnv:g,api:"openai-completions",baseURL:n,compat:{thinkingFormat:"deepseek"},models:[...o.values()]}}function D(t){return l(t).apiKeyEnv===g}function k(t,n){const r=l(t);if(r.displayName!==n.displayName||r.apiKeyEnv!==n.apiKeyEnv||r.api!==n.api||r.baseURL!==n.baseURL||l(r.compat).thinkingFormat!==l(n.compat).thinkingFormat)return!1;const o=Array.isArray(n.models)?n.models:[],e=Array.isArray(r.models)?r.models:[];if(o.length!==e.length)return!1;const s=new Map(e.map(i=>[String(i.id??""),i]));return o.every(i=>{const c=s.get(String(i.id??""));return!!c&&c.name===i.name&&Number(c.contextWindow)===Number(i.contextWindow)})}function B(t){const n=P(t),r=t.apiKey?.trim();if(!n||!r)return;const o=Array.isArray(n.models)?n.models:[];return{id:M,displayName:String(n.displayName??"Grix"),baseURL:String(n.baseURL),apiKey:r,models:o}}async function q(t,n,r){const o=P(r),e=r.apiKey?.trim();if(!o||!e||!n.trim())return"skipped";const s=y(t,O),i=y(t,W);return _(s,async()=>{let c,a;try{c=await $(s),a=await $(i)}catch(f){if(f instanceof p)return E.warn(A,`Refusing to rewrite incomplete DSH YAML: ${f.message}`),"skipped";throw f}const d=l(c[x]),h=l(d.providers),u=h[n];return u!==void 0&&!D(u)?"skipped":D(u)&&k(u,o)&&a[g]===e?"unchanged":(h[n]=o,d.providers=h,c[x]=d,a[g]=e,await Y(t,{recursive:!0,mode:448}),await w(s,b(c),{encoding:"utf8",mode:384}),await w(i,b(a),{encoding:"utf8",mode:384}),E.info(A,`Wrote Grix provider providerId=${n} baseURL=${o.baseURL} api=openai-completions apiKeyEnv=${g} path=${s}`),"written")})}async function J(t,n){const r=y(t,O),o=y(t,W);return _(r,async()=>{let e,s;try{e=await $(r),s=await $(o)}catch(a){if(a instanceof p)return E.warn(A,`Refusing to rewrite incomplete DSH YAML: ${a.message}`),!1;throw a}const i=l(e[x]),c=l(i.providers);return D(c[n])?(delete c[n],i.providers=c,e[x]=i,delete s[g],await w(r,b(e),{encoding:"utf8",mode:384}),await w(o,b(s),{encoding:"utf8",mode:384}),!0):!1})}function G(t){const n=t.replace(/^\uFEFF/,"");U(n);const r=T(n,0);return l(r.value)}function U(t){const n=t.split(/\r?\n/);for(let r=0;r<n.length;r++){const o=n[r]??"";if(o.includes(" "))throw new p(`tab indent at line ${r+1}`);const e=o.trim();if(!e||e.startsWith("#"))continue;if(e==="---"||e==="..."||e.startsWith("%"))throw new p(`document marker at line ${r+1}`);if((o.length-o.trimStart().length)%2!==0)throw new p(`odd indent at line ${r+1}`);const i=e.startsWith("- ")?e.slice(2):e;if(i.startsWith("&")||i.startsWith("*")||i.startsWith("!!")||i.startsWith("|")||i.startsWith(">"))throw new p(`unsupported yaml construct at line ${r+1}`);const c=i.indexOf(":");if(!e.startsWith("- ")&&c===-1)throw new p(`non-mapping line ${r+1}`);const a=c===-1?i:i.slice(c+1).trim();if(a&&a!=="[]"&&a!=="{}"&&!(a.startsWith('"')&&a.endsWith('"')||a.startsWith("'")&&a.endsWith("'"))&&(a.startsWith("{")||a.startsWith("[")||a.startsWith("|")||a.startsWith(">")||a.startsWith("&")||a.startsWith("*")||a.startsWith("!!")))throw new p(`unsupported inline yaml at line ${r+1}`)}}function b(t){const n=m(t,0);return n?`${n}
2
- `:""}function T(t,n){const r=t.split(/\r?\n/),o=[];for(let s=n;s<r.length;s++){const i=r[s]??"";if(!i.trim()||i.trimStart().startsWith("#"))continue;const c=i.length-i.trimStart().length;o.push({indent:c,content:i.trim()})}if(o.length===0)return{value:{},nextLine:r.length};const e=S(o,0,o[0].indent);if(e.next<o.length)throw new p("unconsumed yaml lines");return{value:e.value,nextLine:r.length}}function S(t,n,r){if(n>=t.length||t[n].indent<r)return{value:{},next:n};if(t[n].content.startsWith("- ")){const s=[];let i=n;for(;i<t.length&&t[i].indent===r&&t[i].content.startsWith("- ");){const c=t[i].content.slice(2),a=c.indexOf(":");if(a===-1){s.push(I(c)),i+=1;continue}const d=c.slice(0,a).trim(),h=c.slice(a+1).trim(),u=r+2;if(h){const R=S(t,i+1,u),L=l(R.value);L[d]=I(h),s.push(L),i=R.next;continue}const f=S(t,i+1,u);s.push({[d]:f.value}),i=f.next}return{value:s,next:i}}const o={};let e=n;for(;e<t.length&&t[e].indent===r&&!t[e].content.startsWith("- ");){const s=t[e].content.indexOf(":");if(s===-1)throw new p(`non-mapping entry: ${t[e].content}`);const i=t[e].content.slice(0,s).trim(),c=t[e].content.slice(s+1).trim();if(c){o[i]=I(c),e+=1;continue}const a=S(t,e+1,r+2);o[i]=a.value,e=a.next}return{value:o,next:e}}function I(t){return t==="~"||t==="null"?null:t==="true"?!0:t==="false"?!1:t==="[]"?[]:t==="{}"?{}:t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1).replace(/\\"/g,'"'):/^-?\d+(?:\.\d+)?$/.test(t)?Number(t):t}function m(t,n){if(t==null)return"null";if(typeof t=="boolean"||typeof t=="number")return String(t);if(typeof t=="string")return V(t);if(Array.isArray(t))return t.length===0?"[]":t.map(e=>{if(e&&typeof e=="object"&&!Array.isArray(e)){const s=Object.entries(e);if(s.length===0)return`${" ".repeat(n)}- {}`;const[i,c]=s[0],d=N(c)?`${" ".repeat(n)}- ${i}: ${m(c,0)}`:`${" ".repeat(n)}- ${i}:
3
- ${m(c,n+4)}`,h=s.slice(1).map(([u,f])=>N(f)?`${" ".repeat(n+2)}${u}: ${m(f,0)}`:`${" ".repeat(n+2)}${u}:
4
- ${m(f,n+4)}`);return[d,...h].join(`
1
+ import{mkdir as k,readFile as F,writeFile as W}from"node:fs/promises";import{join as $}from"node:path";import{log as S}from"../../core/log/index.js";import{DEFAULT_DSH_MODELS as G}from"./toolbar-state.js";const B="grix",g="GRIX_PROVIDER_API_KEY",j="settings.yaml",A=".credentials.yaml",_="dsh-provider",x="llm-pi-ai",L=new Map;function D(t,n){const r=(L.get(t)??Promise.resolve()).then(n,n);return L.set(t,r.catch(()=>{})),r}function l(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}class p extends Error{code="yaml_incomplete";constructor(n){super(n),this.name="IncompleteYamlError"}}async function w(t){try{return l(T(await F(t,"utf8")))}catch(n){if(n.code==="ENOENT")return{};throw n}}async function q(t){const n=$(t,A);return D(n,async()=>l((await w(n)).refs))}const K=1;function P(t){t.version===void 0&&(t.version=K);const n=l(t.refs);return t.refs=n,n}function Y(t){const n=t.baseUrl?.trim(),r=t.model?.trim();if(!n||!r)return;const s=new Map;s.set(r,{id:r,name:r,contextWindow:1e6});for(const e of G)s.has(e.id)||s.set(e.id,{id:e.id,name:e.displayName,contextWindow:e.contextWindow});return{displayName:"Grix",apiKeyEnv:g,api:"openai-completions",baseURL:n,compat:{thinkingFormat:"deepseek"},models:[...s.values()]}}function I(t){return l(t).apiKeyEnv===g}function M(t,n){const r=l(t);if(r.displayName!==n.displayName||r.apiKeyEnv!==n.apiKeyEnv||r.api!==n.api||r.baseURL!==n.baseURL||l(r.compat).thinkingFormat!==l(n.compat).thinkingFormat)return!1;const s=Array.isArray(n.models)?n.models:[],e=Array.isArray(r.models)?r.models:[];if(s.length!==e.length)return!1;const o=new Map(e.map(i=>[String(i.id??""),i]));return s.every(i=>{const c=o.get(String(i.id??""));return!!c&&c.name===i.name&&Number(c.contextWindow)===Number(i.contextWindow)})}function J(t){return!!t&&!!Y(t)&&!!t.apiKey?.trim()}async function Q(t,n,r){const s=Y(r),e=r.apiKey?.trim();if(!s||!e||!n.trim())return"skipped";const o=$(t,j),i=$(t,A);return D(o,async()=>{let c,a;try{c=await w(o),a=await w(i)}catch(y){if(y instanceof p)return S.warn(_,`Refusing to rewrite incomplete DSH YAML: ${y.message}`),"skipped";throw y}const f=l(c[x]),d=l(f.providers),u=d[n];if(u!==void 0&&!I(u))return"skipped";const h=P(a);return I(u)&&M(u,s)&&h[g]===e?"unchanged":(d[n]=s,f.providers=d,c[x]=f,h[g]=e,await k(t,{recursive:!0,mode:448}),await W(o,b(c),{encoding:"utf8",mode:384}),await W(i,b(a),{encoding:"utf8",mode:384}),S.info(_,`Wrote Grix provider providerId=${n} baseURL=${s.baseURL} api=openai-completions apiKeyEnv=${g} path=${o}`),"written")})}async function Z(t,n){const r=$(t,j),s=$(t,A);return D(r,async()=>{let e,o;try{e=await w(r),o=await w(s)}catch(f){if(f instanceof p)return S.warn(_,`Refusing to rewrite incomplete DSH YAML: ${f.message}`),!1;throw f}const i=l(e[x]),c=l(i.providers);if(!I(c[n]))return!1;delete c[n],i.providers=c,e[x]=i;const a=P(o);return delete a[g],Object.keys(a).length===0&&delete o.refs,await W(r,b(e),{encoding:"utf8",mode:384}),await W(s,b(o),{encoding:"utf8",mode:384}),!0})}function T(t){const n=t.replace(/^\uFEFF/,"");U(n);const r=V(n,0);return l(r.value)}function U(t){const n=t.split(/\r?\n/);for(let r=0;r<n.length;r++){const s=n[r]??"";if(s.includes(" "))throw new p(`tab indent at line ${r+1}`);const e=s.trim();if(!e||e.startsWith("#"))continue;if(e==="---"||e==="..."||e.startsWith("%"))throw new p(`document marker at line ${r+1}`);if((s.length-s.trimStart().length)%2!==0)throw new p(`odd indent at line ${r+1}`);const i=e.startsWith("- ")?e.slice(2):e;if(i.startsWith("&")||i.startsWith("*")||i.startsWith("!!")||i.startsWith("|")||i.startsWith(">"))throw new p(`unsupported yaml construct at line ${r+1}`);const c=i.indexOf(":");if(!e.startsWith("- ")&&c===-1)throw new p(`non-mapping line ${r+1}`);const a=c===-1?i:i.slice(c+1).trim();if(a&&a!=="[]"&&a!=="{}"&&!(a.startsWith('"')&&a.endsWith('"')||a.startsWith("'")&&a.endsWith("'"))&&(a.startsWith("{")||a.startsWith("[")||a.startsWith("|")||a.startsWith(">")||a.startsWith("&")||a.startsWith("*")||a.startsWith("!!")))throw new p(`unsupported inline yaml at line ${r+1}`)}}function b(t){const n=m(t,0);return n?`${n}
2
+ `:""}function V(t,n){const r=t.split(/\r?\n/),s=[];for(let o=n;o<r.length;o++){const i=r[o]??"";if(!i.trim()||i.trimStart().startsWith("#"))continue;const c=i.length-i.trimStart().length;s.push({indent:c,content:i.trim()})}if(s.length===0)return{value:{},nextLine:r.length};const e=E(s,0,s[0].indent);if(e.next<s.length)throw new p("unconsumed yaml lines");return{value:e.value,nextLine:r.length}}function E(t,n,r){if(n>=t.length||t[n].indent<r)return{value:{},next:n};if(t[n].content.startsWith("- ")){const o=[];let i=n;for(;i<t.length&&t[i].indent===r&&t[i].content.startsWith("- ");){const c=t[i].content.slice(2),a=c.indexOf(":");if(a===-1){o.push(O(c)),i+=1;continue}const f=c.slice(0,a).trim(),d=c.slice(a+1).trim(),u=r+2;if(d){const y=E(t,i+1,u),N=l(y.value);N[f]=O(d),o.push(N),i=y.next;continue}const h=E(t,i+1,u);o.push({[f]:h.value}),i=h.next}return{value:o,next:i}}const s={};let e=n;for(;e<t.length&&t[e].indent===r&&!t[e].content.startsWith("- ");){const o=t[e].content.indexOf(":");if(o===-1)throw new p(`non-mapping entry: ${t[e].content}`);const i=t[e].content.slice(0,o).trim(),c=t[e].content.slice(o+1).trim();if(c){s[i]=O(c),e+=1;continue}const a=E(t,e+1,r+2);s[i]=a.value,e=a.next}return{value:s,next:e}}function O(t){return t==="~"||t==="null"?null:t==="true"?!0:t==="false"?!1:t==="[]"?[]:t==="{}"?{}:t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1).replace(/\\"/g,'"'):/^-?\d+(?:\.\d+)?$/.test(t)?Number(t):t}function m(t,n){if(t==null)return"null";if(typeof t=="boolean"||typeof t=="number")return String(t);if(typeof t=="string")return C(t);if(Array.isArray(t))return t.length===0?"[]":t.map(e=>{if(e&&typeof e=="object"&&!Array.isArray(e)){const o=Object.entries(e);if(o.length===0)return`${" ".repeat(n)}- {}`;const[i,c]=o[0],f=R(c)?`${" ".repeat(n)}- ${i}: ${m(c,0)}`:`${" ".repeat(n)}- ${i}:
3
+ ${m(c,n+4)}`,d=o.slice(1).map(([u,h])=>R(h)?`${" ".repeat(n+2)}${u}: ${m(h,0)}`:`${" ".repeat(n+2)}${u}:
4
+ ${m(h,n+4)}`);return[f,...d].join(`
5
5
  `)}return`${" ".repeat(n)}- ${m(e,0)}`}).join(`
6
- `);const r=l(t),o=Object.keys(r);return o.length===0?"{}":o.map(e=>{const s=r[e];if(N(s))return`${" ".repeat(n)}${e}: ${m(s,0)}`;const i=m(s,n+2);return`${" ".repeat(n)}${e}:
6
+ `);const r=l(t),s=Object.keys(r);return s.length===0?"{}":s.map(e=>{const o=r[e];if(R(o))return`${" ".repeat(n)}${e}: ${m(o,0)}`;const i=m(o,n+2);return`${" ".repeat(n)}${e}:
7
7
  ${i}`}).join(`
8
- `)}function N(t){return t==null||typeof t=="string"||typeof t=="number"||typeof t=="boolean"||Array.isArray(t)&&t.length===0?!0:!!t&&typeof t=="object"&&!Array.isArray(t)&&Object.keys(t).length===0}function V(t){return t===""||/[:#{}[\],&*!|>'"%@`]|^\s|\s$|^(?:true|false|null|~)$/i.test(t)||/^-?\d+(?:\.\d+)?$/.test(t)?JSON.stringify(t):t}export{W as DSH_CREDENTIALS_FILE,g as DSH_GRIX_API_KEY_ENV,M as DSH_GRIX_PROVIDER_ID,O as DSH_SETTINGS_FILE,p as IncompleteYamlError,B as buildDshManagedProvider,G as parseYamlMapping,z as readDshCredentials,J as removeDshGrixProvider,b as stringifyYamlMapping,q as writeDshGrixProvider};
8
+ `)}function R(t){return t==null||typeof t=="string"||typeof t=="number"||typeof t=="boolean"||Array.isArray(t)&&t.length===0?!0:!!t&&typeof t=="object"&&!Array.isArray(t)&&Object.keys(t).length===0}function C(t){return t===""||/[:#{}[\],&*!|>'"%@`]|^\s|\s$|^(?:true|false|null|~)$/i.test(t)||/^-?\d+(?:\.\d+)?$/.test(t)?JSON.stringify(t):t}export{A as DSH_CREDENTIALS_FILE,g as DSH_GRIX_API_KEY_ENV,B as DSH_GRIX_PROVIDER_ID,j as DSH_SETTINGS_FILE,p as IncompleteYamlError,J as isDshGrixProviderConfigured,T as parseYamlMapping,q as readDshCredentials,Z as removeDshGrixProvider,b as stringifyYamlMapping,Q as writeDshGrixProvider};
@@ -1 +1 @@
1
- import{DSH_RUNTIME_ENSURE_MAX_ATTEMPTS as o,dshRuntimeEnsureBackoffMs as s,isRetryableDshRuntimeError as t}from"./runtime-ensure.js";import{DshJsonRpcAdapter as l}from"./jsonrpc-adapter.js";import{buildDshBindingToolbarMeta as a,DEFAULT_DSH_PRESET_ID as h,DEFAULT_DSH_PRESETS as d,normalizeDshModeId as n,normalizeDshReasoningEffort as m,normalizeDshThinking as f,resolveDshAgentPreset as P,resolveDshModeId as p}from"./toolbar-state.js";import{dshCatalogCachePath as E,readDshCatalogCache as g,resolveDshCatalogForToolbar as u,writeDshCatalogCache as R}from"./catalog-cache.js";import{buildDshSystemPrompt as S,describeDshSystemPrompt as T}from"./system-prompt.js";import{buildDshUserPrompt as c,extractQuotedMessageMarker as v}from"./prompt-builder.js";import{TurnCorrelator as M}from"./turn-correlator.js";import{DshJsonRpcClient as A}from"./jsonrpc-client.js";import{runDshProtocolProbe as U}from"./probe.js";import{DshBridgeInstaller as F,defaultBridgeTarball as k}from"./bridge-installer.js";import{DEFAULT_DSH_PROFILE_NAME as L,discoverDshBridgeEndpoints as N,listDshProfiles as z,resolveDshConnectorProfileDataDir as G,resolveDshHome as w,resolveDshProfileIdentity as J,resolveDshSelectedProfileName as O}from"./profile-resolver.js";import{createDshWebProfile as q}from"./profile-catalog.js";import{DSH_GRIX_PROVIDER_ID as V,buildDshManagedProvider as W,readDshCredentials as j,writeDshGrixProvider as K,removeDshGrixProvider as Y}from"./dsh-provider-config.js";import{disableDshPlugin as $,enableDshPlugin as ee,isDshPluginRestartRequired as re,listDshPlugins as oe}from"./plugin-manager.js";import{listDshSkills as te}from"./skill-manager.js";export{d as DEFAULT_DSH_PRESETS,h as DEFAULT_DSH_PRESET_ID,L as DEFAULT_DSH_PROFILE_NAME,V as DSH_GRIX_PROVIDER_ID,o as DSH_RUNTIME_ENSURE_MAX_ATTEMPTS,F as DshBridgeInstaller,l as DshJsonRpcAdapter,A as DshJsonRpcClient,M as TurnCorrelator,a as buildDshBindingToolbarMeta,W as buildDshManagedProvider,S as buildDshSystemPrompt,c as buildDshUserPrompt,q as createDshWebProfile,k as defaultBridgeTarball,T as describeDshSystemPrompt,$ as disableDshPlugin,N as discoverDshBridgeEndpoints,E as dshCatalogCachePath,s as dshRuntimeEnsureBackoffMs,ee as enableDshPlugin,v as extractQuotedMessageMarker,re as isDshPluginRestartRequired,t as isRetryableDshRuntimeError,oe as listDshPlugins,z as listDshProfiles,te as listDshSkills,n as normalizeDshModeId,m as normalizeDshReasoningEffort,f as normalizeDshThinking,g as readDshCatalogCache,j as readDshCredentials,Y as removeDshGrixProvider,P as resolveDshAgentPreset,u as resolveDshCatalogForToolbar,G as resolveDshConnectorProfileDataDir,w as resolveDshHome,p as resolveDshModeId,J as resolveDshProfileIdentity,O as resolveDshSelectedProfileName,U as runDshProtocolProbe,R as writeDshCatalogCache,K as writeDshGrixProvider};
1
+ import{DSH_RUNTIME_ENSURE_MAX_ATTEMPTS as o,dshRuntimeEnsureBackoffMs as s,isRetryableDshRuntimeError as t}from"./runtime-ensure.js";import{DshJsonRpcAdapter as l}from"./jsonrpc-adapter.js";import{buildDshBindingToolbarMeta as a,DEFAULT_DSH_PRESET_ID as h,DEFAULT_DSH_PRESETS as n,normalizeDshModeId as d,normalizeDshReasoningEffort as m,normalizeDshThinking as f,resolveDshAgentPreset as P,resolveDshModeId as p}from"./toolbar-state.js";import{dshCatalogCachePath as E,readDshCatalogCache as g,resolveDshCatalogForToolbar as u,writeDshCatalogCache as R}from"./catalog-cache.js";import{buildDshSystemPrompt as S,describeDshSystemPrompt as T}from"./system-prompt.js";import{buildDshUserPrompt as b,extractQuotedMessageMarker as v}from"./prompt-builder.js";import{TurnCorrelator as I}from"./turn-correlator.js";import{DshJsonRpcClient as A}from"./jsonrpc-client.js";import{runDshProtocolProbe as U}from"./probe.js";import{DshBridgeInstaller as F,defaultBridgeTarball as k}from"./bridge-installer.js";import{DEFAULT_DSH_PROFILE_NAME as G,discoverDshBridgeEndpoints as L,listDshProfiles as N,resolveDshConnectorProfileDataDir as z,resolveDshHome as w,resolveDshProfileIdentity as J,resolveDshSelectedProfileName as O}from"./profile-resolver.js";import{createDshWebProfile as q}from"./profile-catalog.js";import{DSH_GRIX_PROVIDER_ID as V,isDshGrixProviderConfigured as W,readDshCredentials as j,writeDshGrixProvider as K,removeDshGrixProvider as Y}from"./dsh-provider-config.js";import{disableDshPlugin as $,enableDshPlugin as ee,isDshPluginRestartRequired as re,listDshPlugins as oe}from"./plugin-manager.js";import{listDshSkills as te}from"./skill-manager.js";export{n as DEFAULT_DSH_PRESETS,h as DEFAULT_DSH_PRESET_ID,G as DEFAULT_DSH_PROFILE_NAME,V as DSH_GRIX_PROVIDER_ID,o as DSH_RUNTIME_ENSURE_MAX_ATTEMPTS,F as DshBridgeInstaller,l as DshJsonRpcAdapter,A as DshJsonRpcClient,I as TurnCorrelator,a as buildDshBindingToolbarMeta,S as buildDshSystemPrompt,b as buildDshUserPrompt,q as createDshWebProfile,k as defaultBridgeTarball,T as describeDshSystemPrompt,$ as disableDshPlugin,L as discoverDshBridgeEndpoints,E as dshCatalogCachePath,s as dshRuntimeEnsureBackoffMs,ee as enableDshPlugin,v as extractQuotedMessageMarker,W as isDshGrixProviderConfigured,re as isDshPluginRestartRequired,t as isRetryableDshRuntimeError,oe as listDshPlugins,N as listDshProfiles,te as listDshSkills,d as normalizeDshModeId,m as normalizeDshReasoningEffort,f as normalizeDshThinking,g as readDshCatalogCache,j as readDshCredentials,Y as removeDshGrixProvider,P as resolveDshAgentPreset,u as resolveDshCatalogForToolbar,z as resolveDshConnectorProfileDataDir,w as resolveDshHome,p as resolveDshModeId,J as resolveDshProfileIdentity,O as resolveDshSelectedProfileName,U as runDshProtocolProbe,R as writeDshCatalogCache,K as writeDshGrixProvider};