grix-connector 3.8.2 → 3.9.0

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{EventEmitter as S}from"events";import{log as l}from"../core/log/index.js";import{AgentEventType as c}from"../types/events.js";import{mapSessionUpdate as M}from"./event-mapper.js";class h extends Error{authMethods;constructor(e){super("ACP authentication required"),this.name="AcpAuthRequiredError",this.authMethods=e}}function p(a){if(!a||typeof a!="object")return!1;const e=a;return e.code===-32e3?!0:e.code===-32603&&e.data?.details?/\b(401|token\s*expired|access\s*token)\b/i.test(e.data.details):!1}function m(a){return!a||typeof a!="object"?[{id:"oauth"}]:a.data?.authMethods??[{id:"oauth"}]}class u extends S{acpSessionId="";alive=!1;pendingPermissions=new Map;availableModes=[];availableModels=[];currentMode="";currentModel="";listSupported=!1;loadSupported=!1;_supportsCommandsExecute=!1;_availableCommands=[];transport;settleTimer=null;static SETTLE_MS=3e3;pendingToolCallIds=new Set;settleSuppressedSince=0;static SETTLE_SUPPRESS_MAX_MS=900*1e3;constructor(){super(),this.transport=null}get sessionId(){return this.acpSessionId}get isAlive(){return this.alive}get modes(){return[...this.availableModes]}get mode(){return this.currentMode}get models(){return[...this.availableModels]}get model(){return this.currentModel}get sessionOptions(){return{modes:[...this.availableModes],currentModeId:this.currentMode,models:[...this.availableModels],currentModelId:this.currentModel}}get supportsCommandsExecute(){return this._supportsCommandsExecute}get availableCommands(){return[...this._availableCommands]}async connect(e){this.transport=e.transport,this.transport.on("close",()=>{this.alive&&(this.alive=!1,this.emit("session-lost"))}),this.transport.setHandlers((n,r)=>{n==="session/update"?this.handleSessionUpdate(r):n==="_kiro.dev/metadata"?this.handleKiroMetadata(r):n==="_kiro.dev/commands/available"?this.handleCommandsAvailable(r):n==="_kiro.dev/compaction/status"?this.emit("compactionStatus",r):n==="_kiro.dev/clear/status"&&this.emit("clearStatus",r)},(n,r,d)=>{n==="session/request_permission"?this.handlePermissionRequest(r,d):n.startsWith("cursor/")?this.transport.respondSuccess(r,{}).catch(()=>{}):this.transport.respondError(r,-32601,"method not implemented").catch(()=>{})});const t=await this.initialize();this.listSupported=!!t.agentCapabilities?.sessionCapabilities?.list,this.loadSupported=!!t.agentCapabilities?.loadSession;const i=t.agentCapabilities??{};if(this._supportsCommandsExecute=!!(i.extensions?.["_kiro.dev/commands"]||i.commands),e.authMethod)try{await this.transport.call("authenticate",{methodId:e.authMethod})}catch(n){throw p(n)?new h(m(n)):n}const s=e.sessionId&&e.sessionId!=="__continue__";let o=!1;if(s){if(!this.loadSupported)throw new Error(`session/load not supported by agent, cannot resume session ${e.sessionId}`);try{await this.loadSession(e.sessionId,e)&&(o=!0)}catch(n){throw p(n)?new h(m(n)):n}if(!o)throw new Error(`session/load failed for session ${e.sessionId}`)}else try{await this.newSession(e)}catch(n){throw p(n)?new h(m(n)):n}e.initialMode&&await this.setLiveMode(e.initialMode).catch(()=>{}),e.initialModel&&await this.setModel(e.initialModel).catch(()=>{}),this.alive=!0}async initialize(){return await this.transport.call("initialize",{protocolVersion:1,clientCapabilities:{fs:{readTextFile:!1,writeTextFile:!1},terminal:!1},clientInfo:{name:"grix-connector-acp",version:"0.2.0"}})}buildMcpEntries(e){return(e??[]).map(t=>{const i={name:t.name,command:t.command};return t.args&&(i.args=t.args),t.env&&(i.env=Object.entries(t.env).map(([s,o])=>({name:s,value:o}))),i})}async newSession(e){const t=this.buildMcpEntries(e.mcpServers),i={cwd:e.cwd||process.cwd(),mcpServers:t};e.additionalDirectories&&e.additionalDirectories.length>0&&(i.additionalDirectories=e.additionalDirectories);const s=await this.transport.call("session/new",i);if(!s?.sessionId)throw new Error("session/new returned empty sessionId");this.acpSessionId=s.sessionId,this.absorbModes(s.modes),this.absorbModels(s.models)}async loadSession(e,t){const i=this.buildMcpEntries(t.mcpServers),s={sessionId:e,cwd:t.cwd||process.cwd(),mcpServers:i};t.additionalDirectories&&t.additionalDirectories.length>0&&(s.additionalDirectories=t.additionalDirectories);const o=await this.transport.call("session/load",s);return o?.sessionId?(this.acpSessionId=o.sessionId,this.absorbModes(o.modes),this.absorbModels(o.models),!0):o&&(o.modes||o.models)?(this.acpSessionId=e,this.absorbModes(o.modes),this.absorbModels(o.models),!0):(this.acpSessionId=e,!0)}absorbModes(e){e?.availableModes?.length&&(this.availableModes=[...e.availableModes],e.currentModeId&&(this.currentMode=e.currentModeId))}absorbModels(e){e?.availableModels?.length&&(this.availableModels=[...e.availableModels],e.currentModelId&&(this.currentModel=e.currentModelId))}async send(e,t,i){if(!this.alive)throw new Error("session not active");if(!this.acpSessionId)throw new Error("no agent session id");const s=[{type:"text",text:e}];if(t)for(const o of t)s.push({type:"image",data:o.data.toString("base64"),mimeType:o.mimeType});this.pendingToolCallIds.clear(),this.settleSuppressedSince=0,await this.transport.call("session/prompt",{sessionId:this.acpSessionId,prompt:s,...this.currentModel?{modelId:this.currentModel}:{}}),this.scheduleSettledResult()}scheduleSettledResult(){this.settleTimer&&clearTimeout(this.settleTimer),this.settleTimer=setTimeout(()=>{if(this.settleTimer=null,!!this.alive){if(this.pendingToolCallIds.size>0){if(this.settleSuppressedSince===0&&(this.settleSuppressedSince=Date.now()),Date.now()-this.settleSuppressedSince<u.SETTLE_SUPPRESS_MAX_MS){l.info("acp-client",`settle suppressed: ${this.pendingToolCallIds.size} pending tool call(s) for session ${this.acpSessionId}`),this.scheduleSettledResult();return}l.warn("acp-client",`settle suppression exceeded ${u.SETTLE_SUPPRESS_MAX_MS/6e4}min with ${this.pendingToolCallIds.size} pending tool call(s), emitting Result anyway`)}this.settleSuppressedSince=0,l.info("acp-client",`settle timer fired, emitting Result for session ${this.acpSessionId}`),this.emit("event",{type:c.Result,sessionId:this.acpSessionId,done:!0})}},u.SETTLE_MS),this.settleTimer.unref()}clearSettleTimer(){this.settleTimer&&(clearTimeout(this.settleTimer),this.settleTimer=null),this.settleSuppressedSince=0}async cancel(){if(this.acpSessionId){this.pendingToolCallIds.clear(),this.settleSuppressedSince=0;try{await this.transport.notify("session/cancel",{sessionId:this.acpSessionId})}catch{}}}async authenticate(e){await this.transport.call("authenticate",{methodId:e})}async respondPermission(e,t){const i=this.pendingPermissions.get(e);if(!i)throw new Error(`unknown permission request: ${e}`);this.pendingPermissions.delete(e);const s=this.pickPermissionOptionId(t.behavior,i.options),o=this.buildPermissionResult(t.behavior,s);await this.transport.respondSuccess(i.rpcId,o)}async ping(e=1e4){if(!this.alive)return!1;try{const t=new AbortController,i=setTimeout(()=>t.abort(),e);return await this.transport.call("session/list",{},t.signal),clearTimeout(i),!0}catch(t){return t?.code===-32601}}async setLiveMode(e){if(!this.acpSessionId)return l.warn("acp-client",`setLiveMode("${e}") skipped: no active session`),!1;const t=this.matchAvailableMode(e);if(!t)return l.warn("acp-client",`setLiveMode("${e}") failed: mode not found in available [${this.availableModes.map(i=>i.id).join(",")}]`),!1;try{const i=new AbortController,s=setTimeout(()=>i.abort(),8e3);return await this.transport.call("session/set_mode",{sessionId:this.acpSessionId,modeId:t},i.signal),clearTimeout(s),this.currentMode=t,!0}catch(i){return l.warn("acp-client",`setLiveMode("${t}") RPC failed: ${i instanceof Error?i.message:i}`),!1}}async setModel(e){if(!this.acpSessionId)return l.warn("acp-client",`setModel("${e}") skipped: no active session`),!1;try{const t=new AbortController,i=setTimeout(()=>t.abort(),8e3);return await this.transport.call("session/set_model",{sessionId:this.acpSessionId,modelId:e},t.signal),clearTimeout(i),this.currentModel=e,!0}catch(t){return l.warn("acp-client",`setModel("${e}") RPC failed: ${t instanceof Error?t.message:t}`),!1}}handleSessionUpdate(e){this.emit("activity");const t=e?.update?.sessionUpdate,i=t==="usage_update";if(t==="tool_call"||t==="tool_call_update"){const o=e?.update??{},n=String(o.toolCallId??""),r=String(o.status??"").toLowerCase().trim();n&&(r==="completed"||r==="failed"?this.pendingToolCallIds.delete(n):t==="tool_call"&&this.pendingToolCallIds.add(n))}this.settleTimer&&!i&&this.scheduleSettledResult();const s=M(this.acpSessionId,e);for(const o of s)o.sessionId||(o.sessionId=this.acpSessionId),o.type===c.Result&&(this.pendingToolCallIds.clear(),this.settleTimer&&this.clearSettleTimer()),this.emit("event",o)}handleKiroMetadata(e){const i=e?.contextUsagePercentage;typeof i!="number"||!Number.isFinite(i)||this.emit("event",{type:c.ContextWindowUpdate,sessionId:this.acpSessionId,contextWindow:{usedPercentage:Math.min(100,Math.max(0,i))}})}handleCommandsAvailable(e){const t=e,i=Array.isArray(t?.commands)?t.commands:[];this._availableCommands=i.map(s=>({name:String(s.name??""),description:s.description?String(s.description):void 0,args:s.args?String(s.args):void 0})),this._supportsCommandsExecute=!0,this.emit("commandsAvailable",this._availableCommands)}async executeCommand(e,t){if(!this.alive)throw new Error("session not active");if(!this.acpSessionId)throw new Error("no agent session id");const i=new AbortController,s=setTimeout(()=>i.abort(),2e4);try{const o=await this.transport.call("_kiro.dev/commands/execute",{sessionId:this.acpSessionId,command:e,...t?{args:t}:{}},i.signal);return clearTimeout(s),{status:o?.status??"ok",message:o?.message,options:o?.options,data:o?.data}}catch(o){clearTimeout(s);const n=o instanceof Error?o.message:String(o);if(o?.code===-32601)throw this._supportsCommandsExecute=!1,o;return{status:"failed",message:n}}}handlePermissionRequest(e,t){const i=t,s=i?.toolCall??{},o=String(e),n=Array.isArray(i?.options)?i.options:[];this.pendingPermissions.set(o,{rpcId:e,options:n});const r=s.title||s.kind||"permission",d=s.toolCallId||o,f=s.title||"",w={type:c.PermissionRequest,requestId:o,toolName:r,toolInput:f||d,sessionId:this.acpSessionId,permissionRequest:{requestId:o,toolCallId:d,toolName:r,toolTitle:f,options:n,rawParams:t}};this.emit("event",w)}matchAvailableMode(e){const t=e.toLowerCase();for(const i of this.availableModes)if(i.id.toLowerCase()===t||i.name.toLowerCase()===t)return i.id;return""}pickPermissionOptionId(e,t){if(t.length===0)return"";if(e==="deny"){for(const s of t)if(s.kind==="reject_once"||s.kind==="reject_always")return s.optionId;for(const s of t)if(s.kind.toLowerCase().includes("reject")||s.kind.toLowerCase().includes("deny"))return s.optionId;for(const s of t)if(s.name.toLowerCase().includes("reject")||s.name.toLowerCase().includes("deny"))return s.optionId;return t[t.length-1].optionId}const i=e==="allow-always"?"allow_always":e==="allow-once"?"allow_once":null;if(i){for(const s of t)if(s.kind===i)return s.optionId}for(const s of t)if(s.kind.toLowerCase().includes("allow"))return s.optionId;for(const s of t)if(s.name.toLowerCase().includes("allow"))return s.optionId;return t[0].optionId}buildPermissionResult(e,t){return e==="deny"?t?{outcome:{outcome:"selected",optionId:t}}:{outcome:{outcome:"cancelled"}}:t?{outcome:{outcome:"selected",optionId:t}}:{outcome:{outcome:"cancelled"}}}}export{h as AcpAuthRequiredError,u as AcpClient,p as isAuthRequiredError};
1
+ import{EventEmitter as w}from"events";import{log as a}from"../core/log/index.js";import{AgentEventType as c}from"../types/events.js";import{mapSessionUpdate as M}from"./event-mapper.js";class h extends Error{authMethods;constructor(e){super("ACP authentication required"),this.name="AcpAuthRequiredError",this.authMethods=e}}function p(l){if(!l||typeof l!="object")return!1;const e=l;return e.code===-32e3?!0:e.code===-32603&&e.data?.details?/\b(401|token\s*expired|access\s*token)\b/i.test(e.data.details):!1}function m(l){return!l||typeof l!="object"?[{id:"oauth"}]:l.data?.authMethods??[{id:"oauth"}]}class u extends w{acpSessionId="";alive=!1;pendingPermissions=new Map;availableModes=[];availableModels=[];currentMode="";currentModel="";listSupported=!1;loadSupported=!1;_supportsCommandsExecute=!1;_availableCommands=[];transport;settleTimer=null;static SETTLE_MS=3e3;pendingToolCallIds=new Set;settleSuppressedSince=0;static SETTLE_SUPPRESS_MAX_MS=900*1e3;constructor(){super(),this.transport=null}get sessionId(){return this.acpSessionId}get isAlive(){return this.alive}get modes(){return[...this.availableModes]}get mode(){return this.currentMode}get models(){return[...this.availableModels]}get model(){return this.currentModel}get sessionOptions(){return{modes:[...this.availableModes],currentModeId:this.currentMode,models:[...this.availableModels],currentModelId:this.currentModel}}get supportsCommandsExecute(){return this._supportsCommandsExecute}get availableCommands(){return[...this._availableCommands]}async connect(e){this.transport=e.transport,this.transport.on("close",()=>{this.alive&&(this.alive=!1,this.emit("session-lost"))}),this.transport.setHandlers((n,r)=>{n==="session/update"?this.handleSessionUpdate(r):n==="_kiro.dev/metadata"?this.handleKiroMetadata(r):n==="_kiro.dev/commands/available"?this.handleCommandsAvailable(r):n==="_kiro.dev/compaction/status"?this.emit("compactionStatus",r):n==="_kiro.dev/clear/status"&&this.emit("clearStatus",r)},(n,r,d)=>{n==="session/request_permission"?this.handlePermissionRequest(r,d):n.startsWith("cursor/")?this.transport.respondSuccess(r,{}).catch(()=>{}):this.transport.respondError(r,-32601,"method not implemented").catch(()=>{})});const t=await this.initialize();this.listSupported=!!t.agentCapabilities?.sessionCapabilities?.list,this.loadSupported=!!t.agentCapabilities?.loadSession;const s=t.agentCapabilities??{};if(this._supportsCommandsExecute=!!(s.extensions?.["_kiro.dev/commands"]||s.commands),e.authMethod)try{await this.transport.call("authenticate",{methodId:e.authMethod})}catch(n){throw p(n)?new h(m(n)):n}const i=e.sessionId&&e.sessionId!=="__continue__";let o=!1;if(i){if(!this.loadSupported)throw new Error(`session/load not supported by agent, cannot resume session ${e.sessionId}`);try{await this.loadSession(e.sessionId,e)&&(o=!0)}catch(n){throw p(n)?new h(m(n)):n}if(!o)throw new Error(`session/load failed for session ${e.sessionId}`)}else try{await this.newSession(e)}catch(n){throw p(n)?new h(m(n)):n}e.initialMode&&await this.setLiveMode(e.initialMode).catch(()=>{}),e.initialModel&&await this.setModel(e.initialModel).catch(()=>{}),this.alive=!0}async initialize(){return await this.transport.call("initialize",{protocolVersion:1,clientCapabilities:{fs:{readTextFile:!1,writeTextFile:!1},terminal:!1},clientInfo:{name:"grix-connector-acp",version:"0.2.0"}})}buildMcpEntries(e){return(e??[]).map(t=>{const s={name:t.name,command:t.command};return t.args&&(s.args=t.args),t.env&&(s.env=Object.entries(t.env).map(([i,o])=>({name:i,value:o}))),s})}async newSession(e){const t=this.buildMcpEntries(e.mcpServers),s={cwd:e.cwd||process.cwd(),mcpServers:t};e.additionalDirectories&&e.additionalDirectories.length>0&&(s.additionalDirectories=e.additionalDirectories);const i=await this.transport.call("session/new",s);if(!i?.sessionId)throw new Error("session/new returned empty sessionId");this.acpSessionId=i.sessionId,this.absorbModes(i.modes),a.info("acp-client",`[handshake] session/new models block: ${JSON.stringify(i.models)}`),this.absorbModels(i.models),this.absorbConfigOptions(i.configOptions)}async loadSession(e,t){const s=this.buildMcpEntries(t.mcpServers),i={sessionId:e,cwd:t.cwd||process.cwd(),mcpServers:s};t.additionalDirectories&&t.additionalDirectories.length>0&&(i.additionalDirectories=t.additionalDirectories);const o=await this.transport.call("session/load",i);return o?.sessionId?(this.acpSessionId=o.sessionId,this.absorbModes(o.modes),a.info("acp-client",`[handshake] session/load models block: ${JSON.stringify(o.models)}`),this.absorbModels(o.models),this.absorbConfigOptions(o.configOptions),!0):o&&(o.modes||o.models||o.configOptions)?(this.acpSessionId=e,this.absorbModes(o.modes),a.info("acp-client",`[handshake] session/load (compat) models block: ${JSON.stringify(o.models)}`),this.absorbModels(o.models),this.absorbConfigOptions(o.configOptions),!0):(a.info("acp-client",`[handshake] session/load returned empty result for ${e}`),this.acpSessionId=e,!0)}absorbModes(e){e?.availableModes?.length&&(this.availableModes=[...e.availableModes],e.currentModeId&&(this.currentMode=e.currentModeId))}absorbConfigOptions(e){if(Array.isArray(e))for(const t of e){const s=t,i=Array.isArray(s?.options)?s.options.filter(n=>typeof n?.value=="string"&&n.value):[];if(i.length===0)continue;const o=s.category||s.id;o==="mode"&&this.availableModes.length===0?(this.availableModes=i.map(n=>({id:n.value,name:n.name||n.value,...n.description?{description:n.description}:{}})),typeof s.currentValue=="string"&&s.currentValue&&(this.currentMode=s.currentValue),a.info("acp-client",`[handshake] absorbConfigOptions modes: count=${this.availableModes.length} ids=${JSON.stringify(this.availableModes.map(n=>n.id))} current=${s.currentValue??"<none>"}`)):o==="model"&&this.availableModels.length===0&&(this.availableModels=i.map(n=>({modelId:n.value,name:n.name||n.value})),typeof s.currentValue=="string"&&s.currentValue&&(this.currentModel=s.currentValue),a.info("acp-client",`[handshake] absorbConfigOptions models: count=${this.availableModels.length} ids=${JSON.stringify(this.availableModels.map(n=>n.modelId))} current=${s.currentValue??"<none>"}`))}}absorbModels(e){if(!e?.availableModels?.length){a.info("acp-client","[handshake] absorbModels skipped: block empty");return}this.availableModels=[...e.availableModels],a.info("acp-client",`[handshake] absorbModels: count=${this.availableModels.length} ids=${JSON.stringify(this.availableModels.map(t=>t.modelId))} current=${e.currentModelId??"<none>"}`),e.currentModelId&&(this.currentModel=e.currentModelId)}async send(e,t,s){if(!this.alive)throw new Error("session not active");if(!this.acpSessionId)throw new Error("no agent session id");const i=[{type:"text",text:e}];if(t)for(const o of t)i.push({type:"image",data:o.data.toString("base64"),mimeType:o.mimeType});this.pendingToolCallIds.clear(),this.settleSuppressedSince=0,await this.transport.call("session/prompt",{sessionId:this.acpSessionId,prompt:i,...this.currentModel?{modelId:this.currentModel}:{}}),this.scheduleSettledResult()}scheduleSettledResult(){this.settleTimer&&clearTimeout(this.settleTimer),this.settleTimer=setTimeout(()=>{if(this.settleTimer=null,!!this.alive){if(this.pendingToolCallIds.size>0){if(this.settleSuppressedSince===0&&(this.settleSuppressedSince=Date.now()),Date.now()-this.settleSuppressedSince<u.SETTLE_SUPPRESS_MAX_MS){a.info("acp-client",`settle suppressed: ${this.pendingToolCallIds.size} pending tool call(s) for session ${this.acpSessionId}`),this.scheduleSettledResult();return}a.warn("acp-client",`settle suppression exceeded ${u.SETTLE_SUPPRESS_MAX_MS/6e4}min with ${this.pendingToolCallIds.size} pending tool call(s), emitting Result anyway`)}this.settleSuppressedSince=0,a.info("acp-client",`settle timer fired, emitting Result for session ${this.acpSessionId}`),this.emit("event",{type:c.Result,sessionId:this.acpSessionId,done:!0})}},u.SETTLE_MS),this.settleTimer.unref()}clearSettleTimer(){this.settleTimer&&(clearTimeout(this.settleTimer),this.settleTimer=null),this.settleSuppressedSince=0}async cancel(){if(this.acpSessionId){this.pendingToolCallIds.clear(),this.settleSuppressedSince=0;try{await this.transport.notify("session/cancel",{sessionId:this.acpSessionId})}catch{}}}async authenticate(e){await this.transport.call("authenticate",{methodId:e})}async respondPermission(e,t){const s=this.pendingPermissions.get(e);if(!s)throw new Error(`unknown permission request: ${e}`);this.pendingPermissions.delete(e);const i=this.pickPermissionOptionId(t.behavior,s.options),o=this.buildPermissionResult(t.behavior,i);await this.transport.respondSuccess(s.rpcId,o)}async ping(e=1e4){if(!this.alive)return!1;try{const t=new AbortController,s=setTimeout(()=>t.abort(),e);return await this.transport.call("session/list",{},t.signal),clearTimeout(s),!0}catch(t){return t?.code===-32601}}async setLiveMode(e){if(!this.acpSessionId)return a.warn("acp-client",`setLiveMode("${e}") skipped: no active session`),!1;const t=this.matchAvailableMode(e);if(!t)return a.warn("acp-client",`setLiveMode("${e}") failed: mode not found in available [${this.availableModes.map(s=>s.id).join(",")}]`),!1;try{const s=new AbortController,i=setTimeout(()=>s.abort(),8e3);return await this.transport.call("session/set_mode",{sessionId:this.acpSessionId,modeId:t},s.signal),clearTimeout(i),this.currentMode=t,!0}catch(s){return a.warn("acp-client",`setLiveMode("${t}") RPC failed: ${s instanceof Error?s.message:s}`),!1}}async setModel(e){if(!this.acpSessionId)return a.warn("acp-client",`setModel("${e}") skipped: no active session`),!1;try{const t=new AbortController,s=setTimeout(()=>t.abort(),8e3);return await this.transport.call("session/set_model",{sessionId:this.acpSessionId,modelId:e},t.signal),clearTimeout(s),this.currentModel=e,!0}catch(t){return a.warn("acp-client",`setModel("${e}") RPC failed: ${t instanceof Error?t.message:t}`),!1}}handleSessionUpdate(e){this.emit("activity");const t=e?.update?.sessionUpdate,s=t==="usage_update";if(t==="tool_call"||t==="tool_call_update"){const o=e?.update??{},n=String(o.toolCallId??""),r=String(o.status??"").toLowerCase().trim();n&&(r==="completed"||r==="failed"?this.pendingToolCallIds.delete(n):t==="tool_call"&&this.pendingToolCallIds.add(n))}this.settleTimer&&!s&&this.scheduleSettledResult();const i=M(this.acpSessionId,e);for(const o of i)o.sessionId||(o.sessionId=this.acpSessionId),o.type===c.Result&&(this.pendingToolCallIds.clear(),this.settleTimer&&this.clearSettleTimer()),this.emit("event",o)}handleKiroMetadata(e){const s=e?.contextUsagePercentage;typeof s!="number"||!Number.isFinite(s)||this.emit("event",{type:c.ContextWindowUpdate,sessionId:this.acpSessionId,contextWindow:{usedPercentage:Math.min(100,Math.max(0,s))}})}handleCommandsAvailable(e){const t=e,s=Array.isArray(t?.commands)?t.commands:[];this._availableCommands=s.map(i=>({name:String(i.name??""),description:i.description?String(i.description):void 0,args:i.args?String(i.args):void 0})),this._supportsCommandsExecute=!0,this.emit("commandsAvailable",this._availableCommands)}async executeCommand(e,t){if(!this.alive)throw new Error("session not active");if(!this.acpSessionId)throw new Error("no agent session id");const s=new AbortController,i=setTimeout(()=>s.abort(),2e4);try{const o=await this.transport.call("_kiro.dev/commands/execute",{sessionId:this.acpSessionId,command:e,...t?{args:t}:{}},s.signal);return clearTimeout(i),{status:o?.status??"ok",message:o?.message,options:o?.options,data:o?.data}}catch(o){clearTimeout(i);const n=o instanceof Error?o.message:String(o);if(o?.code===-32601)throw this._supportsCommandsExecute=!1,o;return{status:"failed",message:n}}}handlePermissionRequest(e,t){const s=t,i=s?.toolCall??{},o=String(e),n=Array.isArray(s?.options)?s.options:[];this.pendingPermissions.set(o,{rpcId:e,options:n});const r=i.title||i.kind||"permission",d=i.toolCallId||o,f=i.title||"",S={type:c.PermissionRequest,requestId:o,toolName:r,toolInput:f||d,sessionId:this.acpSessionId,permissionRequest:{requestId:o,toolCallId:d,toolName:r,toolTitle:f,options:n,rawParams:t}};this.emit("event",S)}matchAvailableMode(e){const t=e.toLowerCase();for(const s of this.availableModes)if(s.id.toLowerCase()===t||s.name.toLowerCase()===t)return s.id;return""}pickPermissionOptionId(e,t){if(t.length===0)return"";if(e==="deny"){for(const i of t)if(i.kind==="reject_once"||i.kind==="reject_always")return i.optionId;for(const i of t)if(i.kind.toLowerCase().includes("reject")||i.kind.toLowerCase().includes("deny"))return i.optionId;for(const i of t)if(i.name.toLowerCase().includes("reject")||i.name.toLowerCase().includes("deny"))return i.optionId;return t[t.length-1].optionId}const s=e==="allow-always"?"allow_always":e==="allow-once"?"allow_once":null;if(s){for(const i of t)if(i.kind===s)return i.optionId}for(const i of t)if(i.kind.toLowerCase().includes("allow"))return i.optionId;for(const i of t)if(i.name.toLowerCase().includes("allow"))return i.optionId;return t[0].optionId}buildPermissionResult(e,t){return e==="deny"?t?{outcome:{outcome:"selected",optionId:t}}:{outcome:{outcome:"cancelled"}}:t?{outcome:{outcome:"selected",optionId:t}}:{outcome:{outcome:"cancelled"}}}}export{h as AcpAuthRequiredError,u as AcpClient,p as isAuthRequiredError};
@@ -30,9 +30,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
30
  mod
31
31
  ));
32
32
 
33
- // node_modules/ms/index.js
33
+ // node_modules/.pnpm/ms@2.1.3/node_modules/ms/index.js
34
34
  var require_ms = __commonJS({
35
- "node_modules/ms/index.js"(exports, module) {
35
+ "node_modules/.pnpm/ms@2.1.3/node_modules/ms/index.js"(exports, module) {
36
36
  var s = 1e3;
37
37
  var m = s * 60;
38
38
  var h = m * 60;
@@ -146,9 +146,9 @@ var require_ms = __commonJS({
146
146
  }
147
147
  });
148
148
 
149
- // node_modules/debug/src/common.js
149
+ // node_modules/.pnpm/debug@4.4.3/node_modules/debug/src/common.js
150
150
  var require_common = __commonJS({
151
- "node_modules/debug/src/common.js"(exports, module) {
151
+ "node_modules/.pnpm/debug@4.4.3/node_modules/debug/src/common.js"(exports, module) {
152
152
  function setup(env) {
153
153
  createDebug.debug = createDebug;
154
154
  createDebug.default = createDebug;
@@ -323,9 +323,9 @@ var require_common = __commonJS({
323
323
  }
324
324
  });
325
325
 
326
- // node_modules/debug/src/browser.js
326
+ // node_modules/.pnpm/debug@4.4.3/node_modules/debug/src/browser.js
327
327
  var require_browser = __commonJS({
328
- "node_modules/debug/src/browser.js"(exports, module) {
328
+ "node_modules/.pnpm/debug@4.4.3/node_modules/debug/src/browser.js"(exports, module) {
329
329
  exports.formatArgs = formatArgs;
330
330
  exports.save = save;
331
331
  exports.load = load2;
@@ -493,9 +493,9 @@ var require_browser = __commonJS({
493
493
  }
494
494
  });
495
495
 
496
- // node_modules/debug/src/node.js
496
+ // node_modules/.pnpm/debug@4.4.3/node_modules/debug/src/node.js
497
497
  var require_node = __commonJS({
498
- "node_modules/debug/src/node.js"(exports, module) {
498
+ "node_modules/.pnpm/debug@4.4.3/node_modules/debug/src/node.js"(exports, module) {
499
499
  var tty = __require("tty");
500
500
  var util = __require("util");
501
501
  exports.init = init;
@@ -667,9 +667,9 @@ var require_node = __commonJS({
667
667
  }
668
668
  });
669
669
 
670
- // node_modules/debug/src/index.js
670
+ // node_modules/.pnpm/debug@4.4.3/node_modules/debug/src/index.js
671
671
  var require_src = __commonJS({
672
- "node_modules/debug/src/index.js"(exports, module) {
672
+ "node_modules/.pnpm/debug@4.4.3/node_modules/debug/src/index.js"(exports, module) {
673
673
  if (typeof process === "undefined" || process.type === "renderer" || process.browser === true || process.__nwjs) {
674
674
  module.exports = require_browser();
675
675
  } else {
@@ -678,9 +678,9 @@ var require_src = __commonJS({
678
678
  }
679
679
  });
680
680
 
681
- // node_modules/wrappy/wrappy.js
681
+ // node_modules/.pnpm/wrappy@1.0.2/node_modules/wrappy/wrappy.js
682
682
  var require_wrappy = __commonJS({
683
- "node_modules/wrappy/wrappy.js"(exports, module) {
683
+ "node_modules/.pnpm/wrappy@1.0.2/node_modules/wrappy/wrappy.js"(exports, module) {
684
684
  module.exports = wrappy;
685
685
  function wrappy(fn, cb) {
686
686
  if (fn && cb) return wrappy(fn)(cb);
@@ -708,9 +708,9 @@ var require_wrappy = __commonJS({
708
708
  }
709
709
  });
710
710
 
711
- // node_modules/once/once.js
711
+ // node_modules/.pnpm/once@1.4.0/node_modules/once/once.js
712
712
  var require_once = __commonJS({
713
- "node_modules/once/once.js"(exports, module) {
713
+ "node_modules/.pnpm/once@1.4.0/node_modules/once/once.js"(exports, module) {
714
714
  var wrappy = require_wrappy();
715
715
  module.exports = wrappy(once);
716
716
  module.exports.strict = wrappy(onceStrict);
@@ -752,9 +752,9 @@ var require_once = __commonJS({
752
752
  }
753
753
  });
754
754
 
755
- // node_modules/end-of-stream/index.js
755
+ // node_modules/.pnpm/end-of-stream@1.4.5/node_modules/end-of-stream/index.js
756
756
  var require_end_of_stream = __commonJS({
757
- "node_modules/end-of-stream/index.js"(exports, module) {
757
+ "node_modules/.pnpm/end-of-stream@1.4.5/node_modules/end-of-stream/index.js"(exports, module) {
758
758
  var once = require_once();
759
759
  var noop = function() {
760
760
  };
@@ -835,9 +835,9 @@ var require_end_of_stream = __commonJS({
835
835
  }
836
836
  });
837
837
 
838
- // node_modules/pump/index.js
838
+ // node_modules/.pnpm/pump@3.0.4/node_modules/pump/index.js
839
839
  var require_pump = __commonJS({
840
- "node_modules/pump/index.js"(exports, module) {
840
+ "node_modules/.pnpm/pump@3.0.4/node_modules/pump/index.js"(exports, module) {
841
841
  var once = require_once();
842
842
  var eos = require_end_of_stream();
843
843
  var fs;
@@ -910,9 +910,9 @@ var require_pump = __commonJS({
910
910
  }
911
911
  });
912
912
 
913
- // node_modules/get-stream/buffer-stream.js
913
+ // node_modules/.pnpm/get-stream@5.2.0/node_modules/get-stream/buffer-stream.js
914
914
  var require_buffer_stream = __commonJS({
915
- "node_modules/get-stream/buffer-stream.js"(exports, module) {
915
+ "node_modules/.pnpm/get-stream@5.2.0/node_modules/get-stream/buffer-stream.js"(exports, module) {
916
916
  "use strict";
917
917
  var { PassThrough: PassThroughStream } = __require("stream");
918
918
  module.exports = (options) => {
@@ -955,9 +955,9 @@ var require_buffer_stream = __commonJS({
955
955
  }
956
956
  });
957
957
 
958
- // node_modules/get-stream/index.js
958
+ // node_modules/.pnpm/get-stream@5.2.0/node_modules/get-stream/index.js
959
959
  var require_get_stream = __commonJS({
960
- "node_modules/get-stream/index.js"(exports, module) {
960
+ "node_modules/.pnpm/get-stream@5.2.0/node_modules/get-stream/index.js"(exports, module) {
961
961
  "use strict";
962
962
  var { constants: BufferConstants } = __require("buffer");
963
963
  var pump = require_pump();
@@ -1008,9 +1008,9 @@ var require_get_stream = __commonJS({
1008
1008
  }
1009
1009
  });
1010
1010
 
1011
- // node_modules/pend/index.js
1011
+ // node_modules/.pnpm/pend@1.2.0/node_modules/pend/index.js
1012
1012
  var require_pend = __commonJS({
1013
- "node_modules/pend/index.js"(exports, module) {
1013
+ "node_modules/.pnpm/pend@1.2.0/node_modules/pend/index.js"(exports, module) {
1014
1014
  module.exports = Pend;
1015
1015
  function Pend() {
1016
1016
  this.pending = 0;
@@ -1063,9 +1063,9 @@ var require_pend = __commonJS({
1063
1063
  }
1064
1064
  });
1065
1065
 
1066
- // node_modules/fd-slicer/index.js
1066
+ // node_modules/.pnpm/fd-slicer@1.1.0/node_modules/fd-slicer/index.js
1067
1067
  var require_fd_slicer = __commonJS({
1068
- "node_modules/fd-slicer/index.js"(exports) {
1068
+ "node_modules/.pnpm/fd-slicer@1.1.0/node_modules/fd-slicer/index.js"(exports) {
1069
1069
  var fs = __require("fs");
1070
1070
  var util = __require("util");
1071
1071
  var stream = __require("stream");
@@ -1322,9 +1322,9 @@ var require_fd_slicer = __commonJS({
1322
1322
  }
1323
1323
  });
1324
1324
 
1325
- // node_modules/buffer-crc32/index.js
1325
+ // node_modules/.pnpm/buffer-crc32@0.2.13/node_modules/buffer-crc32/index.js
1326
1326
  var require_buffer_crc32 = __commonJS({
1327
- "node_modules/buffer-crc32/index.js"(exports, module) {
1327
+ "node_modules/.pnpm/buffer-crc32@0.2.13/node_modules/buffer-crc32/index.js"(exports, module) {
1328
1328
  var Buffer2 = __require("buffer").Buffer;
1329
1329
  var CRC_TABLE = [
1330
1330
  0,
@@ -1629,9 +1629,9 @@ var require_buffer_crc32 = __commonJS({
1629
1629
  }
1630
1630
  });
1631
1631
 
1632
- // node_modules/yauzl/index.js
1632
+ // node_modules/.pnpm/yauzl@2.10.0/node_modules/yauzl/index.js
1633
1633
  var require_yauzl = __commonJS({
1634
- "node_modules/yauzl/index.js"(exports) {
1634
+ "node_modules/.pnpm/yauzl@2.10.0/node_modules/yauzl/index.js"(exports) {
1635
1635
  var fs = __require("fs");
1636
1636
  var zlib = __require("zlib");
1637
1637
  var fd_slicer = require_fd_slicer();
@@ -2258,9 +2258,9 @@ var require_yauzl = __commonJS({
2258
2258
  }
2259
2259
  });
2260
2260
 
2261
- // node_modules/extract-zip/index.js
2261
+ // node_modules/.pnpm/extract-zip@2.0.1/node_modules/extract-zip/index.js
2262
2262
  var require_extract_zip = __commonJS({
2263
- "node_modules/extract-zip/index.js"(exports, module) {
2263
+ "node_modules/.pnpm/extract-zip@2.0.1/node_modules/extract-zip/index.js"(exports, module) {
2264
2264
  var debug = require_src()("extract-zip");
2265
2265
  var { createWriteStream: createWriteStream2, promises: fs } = __require("fs");
2266
2266
  var getStream = require_get_stream();
@@ -6699,6 +6699,15 @@ function resolveGrixInboundSemantics(event) {
6699
6699
  };
6700
6700
  }
6701
6701
 
6702
+ // src/core/protocol/interaction-parser.ts
6703
+ var WHOLE_OPEN_SESSION_URI_PATTERN = /^grix:\/\/open\/\S+$/i;
6704
+ function isOpenSessionDirectiveMessage(content) {
6705
+ return WHOLE_OPEN_SESSION_URI_PATTERN.test(decodeCardContent(content).trim());
6706
+ }
6707
+ function decodeCardContent(content) {
6708
+ return content.replace(/&amp;/gi, "&");
6709
+ }
6710
+
6702
6711
  // src/openclaw/inbound-history.ts
6703
6712
  function normalizeId(value) {
6704
6713
  if (typeof value === "string") {
@@ -6733,7 +6742,7 @@ function buildGrixInboundHistory(params) {
6733
6742
  return void 0;
6734
6743
  }
6735
6744
  const currentMessageId = normalizeId(params.currentMessageId);
6736
- const history = params.contextMessages.filter((message) => normalizeId(message?.msg_id) !== currentMessageId).map((message) => {
6745
+ const history = params.contextMessages.filter((message) => normalizeId(message?.msg_id) !== currentMessageId).filter((message) => !isOpenSessionDirectiveMessage(String(message?.content ?? ""))).map((message) => {
6737
6746
  const body = normalizeBody(message?.content);
6738
6747
  if (!body) {
6739
6748
  return null;
@@ -6763,7 +6772,7 @@ function asRecord3(value) {
6763
6772
  }
6764
6773
  return value;
6765
6774
  }
6766
- function decodeCardContent(content) {
6775
+ function decodeCardContent2(content) {
6767
6776
  return String(content ?? "").replace(/&amp;/gi, "&");
6768
6777
  }
6769
6778
  function normalizeCardUriCandidate(value) {
@@ -6778,7 +6787,7 @@ function prunePartialCandidates(candidates) {
6778
6787
  );
6779
6788
  }
6780
6789
  function collectCardUriCandidates(content) {
6781
- const normalized = decodeCardContent(content);
6790
+ const normalized = decodeCardContent2(content);
6782
6791
  const candidates = [];
6783
6792
  for (const match of normalized.matchAll(MARKDOWN_CARD_URI_PATTERN)) {
6784
6793
  const candidate = normalizeCardUriCandidate(match[1] ?? "");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grix-connector",
3
- "version": "3.8.2",
3
+ "version": "3.9.0",
4
4
  "description": "Connect local AI coding agents (Claude, Codex, Gemini, Qwen, DeepSeek, Cursor, OpenCode, Pi, OpenHuman, Reasonix) to the Grix scheduling platform. Also serves as an OpenClaw plugin for Grix channel transport.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",