grix-connector 3.33.2 → 3.34.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.
Files changed (92) hide show
  1. package/dist/adapter/acp/acp-adapter.js +6 -6
  2. package/dist/adapter/agy/agy-adapter.js +9 -9
  3. package/dist/adapter/agy/model-list.js +2 -2
  4. package/dist/adapter/agy/quota.js +5 -5
  5. package/dist/adapter/claude/claude-adapter.js +21 -21
  6. package/dist/adapter/claude/claude-bridge-server.js +1 -0
  7. package/dist/adapter/claude/claude-tools.js +1 -0
  8. package/dist/adapter/claude/claude-worker-client.js +1 -0
  9. package/dist/adapter/claude/mcp-http-launcher.js +2 -0
  10. package/dist/adapter/claude/model-list.js +1 -1
  11. package/dist/adapter/claude/result-timeout.js +1 -0
  12. package/dist/adapter/codewhale/codewhale-adapter.js +2 -2
  13. package/dist/adapter/codewhale/model-list.js +2 -2
  14. package/dist/adapter/codex/codex-bridge.js +9 -9
  15. package/dist/adapter/cursor/cursor-adapter.js +7 -7
  16. package/dist/adapter/cursor/fetch-models.js +2 -2
  17. package/dist/adapter/cursor/resolve-command.js +1 -1
  18. package/dist/adapter/deepseek/deepseek-adapter.js +6 -0
  19. package/dist/adapter/deepseek/index.js +1 -0
  20. package/dist/adapter/deepseek-harness/jsonrpc-adapter.js +2 -2
  21. package/dist/adapter/opencode/opencode-adapter.js +3 -3
  22. package/dist/adapter/openhuman/openhuman-adapter.js +3 -3
  23. package/dist/adapter/qwen/index.js +1 -0
  24. package/dist/adapter/qwen/qwen-adapter.js +4 -0
  25. package/dist/aibot/client.js +1 -0
  26. package/dist/aibot/index.js +1 -0
  27. package/dist/aibot/types.js +0 -0
  28. package/dist/assets/dsh-bridge/{grix-dsh-bridge-3.33.2.tgz → grix-dsh-bridge-3.34.0.tgz} +0 -0
  29. package/dist/assets/dsh-bridge/manifest.json +5 -5
  30. package/dist/audit/adapters/agy/agy-audit-adapter.js +1 -0
  31. package/dist/audit/adapters/openclaw/openclaw-audit-adapter.js +1 -1
  32. package/dist/audit/adapters/pi/pi-transcript-source.js +1 -1
  33. package/dist/audit/core/audit-state.js +1 -1
  34. package/dist/audit/core/transcript-fingerprint.js +1 -0
  35. package/dist/audit/producer/ipc-audit-producer.js +1 -1
  36. package/dist/audit/worker/audit-recorder-worker-entry.js +1 -1
  37. package/dist/bridge/adapter-pool.js +1 -1
  38. package/dist/bridge/bridge.js +9 -9
  39. package/dist/bridge/cli-install-offer.js +1 -0
  40. package/dist/bridge/deferred-events.js +1 -1
  41. package/dist/bridge/lifecycle-barrier.js +1 -0
  42. package/dist/bridge/pending-event-coordinator.js +1 -0
  43. package/dist/bridge/respawn-manager.js +1 -1
  44. package/dist/core/access/allowlist-gate.js +1 -0
  45. package/dist/core/access/allowlist-store.js +1 -0
  46. package/dist/core/access/index.js +1 -0
  47. package/dist/core/aibot/client.js +2 -2
  48. package/dist/core/file-ops/handler.js +1 -0
  49. package/dist/core/file-ops/list-files.js +1 -0
  50. package/dist/core/file-ops/types.js +0 -0
  51. package/dist/core/files/file-serve.js +1 -1
  52. package/dist/core/installer/installer.js +6 -6
  53. package/dist/core/installer/npm-registry.js +3 -3
  54. package/dist/core/installer/prereq-installer.js +1 -1
  55. package/dist/core/observability/sentry.js +1 -1
  56. package/dist/core/persistence/pending-event-store.js +1 -0
  57. package/dist/core/protocol/interaction-parser.js +1 -1
  58. package/dist/core/proxy/hermes-profile-relay.js +1 -1
  59. package/dist/core/proxy/hermes-profile-relay.py +34 -15
  60. package/dist/core/proxy/relay-state-sync.js +1 -1
  61. package/dist/core/runtime/spawn.js +2 -3
  62. package/dist/core/upgrade/npm-upgrader.js +2 -2
  63. package/dist/core/upgrade/upgrade-checker.js +1 -1
  64. package/dist/core/util/cli-probe.js +2 -2
  65. package/dist/core/util/git-project-root.js +1 -1
  66. package/dist/default-skills/grix-agent-dispatch/SKILL.md +19 -9
  67. package/dist/default-skills/grix-egg/SKILL.md +2 -2
  68. package/dist/default-skills/message-send/SKILL.md +1 -1
  69. package/dist/default-skills/message-unsend/SKILL.md +1 -1
  70. package/dist/grix.js +0 -0
  71. package/dist/log.js +3 -0
  72. package/dist/main.js +31 -0
  73. package/dist/manager-share-config.js +1 -1
  74. package/dist/manager.js +2 -2
  75. package/dist/mcp/stream-http/config.js +1 -0
  76. package/dist/mcp/stream-http/connection-binding.js +1 -0
  77. package/dist/mcp/stream-http/event-tool-executor.js +1 -0
  78. package/dist/mcp/stream-http/gateway.js +1 -0
  79. package/dist/mcp/stream-http/index.js +1 -0
  80. package/dist/mcp/stream-http/security.js +1 -0
  81. package/dist/mcp/stream-http/session-manager.js +1 -0
  82. package/dist/mcp/stream-http/tool-executor.js +1 -0
  83. package/dist/mcp/stream-http/tool-registry.js +1 -0
  84. package/dist/mcp/stream-http/tool-schemas.js +1 -0
  85. package/dist/service/process-control.js +1 -1
  86. package/dist/session/index.js +1 -0
  87. package/dist/session/manager.js +1 -0
  88. package/dist/transport/index.js +1 -0
  89. package/dist/transport/json-rpc.js +3 -0
  90. package/openclaw-plugin/audit-recorder-worker.js +531 -76
  91. package/openclaw-plugin/index.js +89 -14
  92. package/package.json +1 -1
@@ -1,12 +1,12 @@
1
- import{execFileSync as ee}from"node:child_process";import{createInterface as $}from"node:readline";import{EventEmitter as q}from"node:events";import{randomUUID as te}from"node:crypto";import{mkdirSync as E,readFileSync as L,writeFileSync as P,readdirSync as se,statSync as D}from"node:fs";import{join as A,resolve as ne}from"node:path";import{fileURLToPath as ie}from"node:url";import{homedir as N}from"node:os";import{GRIX_PATHS as re,log as h}from"../../core/log/index.js";import{IdentityInjector as oe}from"../shared/identity-injector.js";import{buildSimpleProbeReport as ae}from"../shared/probe-util.js";import{InternalApiServer as de}from"../../core/mcp/internal-api-server.js";import{resolveMcpServerName as le,pruneLegacyMcpServerEntries as ce}from"../../core/mcp/server-name.js";import{InboundMessageIdInjector as ue}from"../shared/inbound-message-id-injector.js";import{syncDefaultSkillsToDir as he}from"../../default-skills/index.js";import{resolveCommandPath as R,spawnCommand as M,killProcessGroup as I}from"../../core/runtime/spawn.js";import{SessionBindingStore as me}from"../../core/persistence/session-binding-store.js";import{fetchCursorParameterizedModels as fe}from"./fetch-models.js";import{resolveCursorCommand as F,withCursorShimEnv as j}from"./resolve-command.js";import{fetchCursorAccountUsage as pe}from"./fetch-usage.js";import{buildCursorContextWindow as ge,buildCursorContextWindowFromUsage as Se,resolveCursorContextWindowSize as ye}from"./context-window.js";const ve=12e4,T=300*1e3,Q=90*1e3,O=1800*1e3,_e=8192,W="Summarize this conversation for handoff to a fresh chat. Include: goals, key decisions, important file paths, current status, and next steps. Be concise but complete. Output ONLY the summary text.",U=12e4,H=new Set(["completed","failed","error","errored","canceled","cancelled","rejected"]);function Ae(d){const e=d.replace(/ToolCall$/i,"").trim();return e?e.charAt(0).toUpperCase()+e.slice(1):d||"tool"}function z(d){const e=String(d.call_id??d.callId??"").trim(),t=d.tool_call??d.toolCall;if(t&&typeof t=="object"&&!Array.isArray(t)){const n=Object.keys(t);if(n.length>0){const s=n[0],i=t[s],r=i&&typeof i=="object"&&!Array.isArray(i)?i:null;return{toolName:Ae(s),toolInput:r?.args??r?.arguments??{},callId:e}}}return{toolName:String(d.name??d.tool_name??d.toolName??"tool").trim()||"tool",toolInput:d.args??d.tool_input??d.toolInput??{},callId:e}}function J(d){return String(d??"").trim().toLowerCase().replace(/[^a-z0-9]/g,"")}function G(d){const e=J(d);return e==="askquestion"||e==="askuserquestion"}function X(d){const e=J(d);return e==="createplan"||e==="exitplanmode"}function be(d){if(!Array.isArray(d))return;const e=d.map(t=>{if(typeof t=="string")return t.trim();if(!t||typeof t!="object")return"";const n=t,s=String(n.label??"").trim();if(s)return s;const i=String(n.value??"").trim();if(i)return i;const r=String(n.text??"").trim();return r||""}).filter(t=>t.length>0);return e.length>0?e:void 0}function ke(d){if(!d||typeof d!="object"||Array.isArray(d))return null;const e=d,t=String(e.title??"").trim(),n=e.questions;if(!Array.isArray(n)||n.length===0)return null;const s=[];for(let i=0;i<n.length;i++){const r=n[i];if(!r||typeof r!="object")continue;const o=r,a=t||`Question ${i+1}`,l=String(o.header??o.id??o.question??a).trim()||a,c=String(o.prompt??o.question??"").trim();if(!c)continue;const u=be(o.options),p=o.multiSelect===!0||o.multi_select===!0;s.push({header:l,prompt:c,...u?{options:u}:{},...p?{multi_select:!0}:{}})}return s.length>0?s:null}function we(d){if(!d||typeof d!="object"||Array.isArray(d))return null;const e=d,t=String(e.name??e.title??"").trim(),n=String(e.overview??"").trim(),s=String(e.plan??"").trim();if(!s&&!n&&!t)return null;const i=[];return t&&i.push(`# ${t}`),n&&i.push(n),s&&i.push(s),i.join(`
1
+ import{execFileSync as Y}from"node:child_process";import{createInterface as $}from"node:readline";import{EventEmitter as q}from"node:events";import{randomUUID as Z}from"node:crypto";import{mkdirSync as E,readFileSync as L,writeFileSync as P,readdirSync as ee,statSync as D}from"node:fs";import{join as A,resolve as te}from"node:path";import{fileURLToPath as se}from"node:url";import{homedir as N}from"node:os";import{GRIX_PATHS as ne,log as h}from"../../core/log/index.js";import{IdentityInjector as ie}from"../shared/identity-injector.js";import{buildSimpleProbeReport as re}from"../shared/probe-util.js";import{InternalApiServer as oe}from"../../core/mcp/internal-api-server.js";import{resolveMcpServerName as ae,pruneLegacyMcpServerEntries as de}from"../../core/mcp/server-name.js";import{InboundMessageIdInjector as le}from"../shared/inbound-message-id-injector.js";import{syncDefaultSkillsToDir as ce}from"../../default-skills/index.js";import{spawnCommand as R,killProcessGroup as I}from"../../core/runtime/spawn.js";import{SessionBindingStore as ue}from"../../core/persistence/session-binding-store.js";import{fetchCursorParameterizedModels as he}from"./fetch-models.js";import{resolveCursorSpawn as M}from"./resolve-command.js";import{fetchCursorAccountUsage as me}from"./fetch-usage.js";import{buildCursorContextWindow as fe,buildCursorContextWindowFromUsage as pe,resolveCursorContextWindowSize as ge}from"./context-window.js";const Se=12e4,x=300*1e3,F=90*1e3,j=1800*1e3,ye=8192,Q="Summarize this conversation for handoff to a fresh chat. Include: goals, key decisions, important file paths, current status, and next steps. Be concise but complete. Output ONLY the summary text.",O=12e4,W=new Set(["completed","failed","error","errored","canceled","cancelled","rejected"]);function ve(d){const e=d.replace(/ToolCall$/i,"").trim();return e?e.charAt(0).toUpperCase()+e.slice(1):d||"tool"}function U(d){const e=String(d.call_id??d.callId??"").trim(),t=d.tool_call??d.toolCall;if(t&&typeof t=="object"&&!Array.isArray(t)){const n=Object.keys(t);if(n.length>0){const s=n[0],i=t[s],r=i&&typeof i=="object"&&!Array.isArray(i)?i:null;return{toolName:ve(s),toolInput:r?.args??r?.arguments??{},callId:e}}}return{toolName:String(d.name??d.tool_name??d.toolName??"tool").trim()||"tool",toolInput:d.args??d.tool_input??d.toolInput??{},callId:e}}function H(d){return String(d??"").trim().toLowerCase().replace(/[^a-z0-9]/g,"")}function z(d){const e=H(d);return e==="askquestion"||e==="askuserquestion"}function J(d){const e=H(d);return e==="createplan"||e==="exitplanmode"}function _e(d){if(!Array.isArray(d))return;const e=d.map(t=>{if(typeof t=="string")return t.trim();if(!t||typeof t!="object")return"";const n=t,s=String(n.label??"").trim();if(s)return s;const i=String(n.value??"").trim();if(i)return i;const r=String(n.text??"").trim();return r||""}).filter(t=>t.length>0);return e.length>0?e:void 0}function Ae(d){if(!d||typeof d!="object"||Array.isArray(d))return null;const e=d,t=String(e.title??"").trim(),n=e.questions;if(!Array.isArray(n)||n.length===0)return null;const s=[];for(let i=0;i<n.length;i++){const r=n[i];if(!r||typeof r!="object")continue;const o=r,a=t||`Question ${i+1}`,l=String(o.header??o.id??o.question??a).trim()||a,c=String(o.prompt??o.question??"").trim();if(!c)continue;const u=_e(o.options),p=o.multiSelect===!0||o.multi_select===!0;s.push({header:l,prompt:c,...u?{options:u}:{},...p?{multi_select:!0}:{}})}return s.length>0?s:null}function be(d){if(!d||typeof d!="object"||Array.isArray(d))return null;const e=d,t=String(e.name??e.title??"").trim(),n=String(e.overview??"").trim(),s=String(e.plan??"").trim();if(!s&&!n&&!t)return null;const i=[];return t&&i.push(`# ${t}`),n&&i.push(n),s&&i.push(s),i.join(`
2
2
 
3
- `)}function Ie(d){if(!d||typeof d!="object"||Array.isArray(d))return null;const e=d,t=String(e.type??"").trim().toLowerCase();if(!t)return null;switch(t){case"tool_call":{const n=String(e.subtype??"").trim().toLowerCase(),s=z(e);return G(s.toolName)||X(s.toolName)?null:n==="started"||n==="start"?{type:"tool_call",payload:{tool_name:s.toolName,...s.callId?{tool_call_id:s.callId}:{}}}:(H.has(n),null)}case"error":return{type:"error",payload:{message:String(e.message??e.error??e.result??"cursor error").trim()||"cursor error"}};case"result":{const n=String(e.subtype??"").trim().toLowerCase();return e.is_error===!0||n==="error"?{type:"error",payload:{message:String(e.result??e.message??"cursor run failed").trim()||"cursor run failed"}}:null}default:return null}}function Ce(d,e){if(!d||typeof d!="object"||Array.isArray(d))return"";const t=d;if(String(t.type??"")!=="assistant")return"";const n=t.model_call_id??t.modelCallId;if(n!=null&&String(n).trim()!=="")return"";const s=t.message,i=s&&typeof s=="object"&&!Array.isArray(s)?s.content:void 0;if(!Array.isArray(i))return"";const r=i.map(o=>{if(!o||typeof o!="object"||Array.isArray(o))return"";const a=o;return a.type==="text"?String(a.text??""):""}).filter(Boolean).join("");if(!r)return"";if(e){if(r===e||e.startsWith(r)&&r.length<e.length)return"";if(r.startsWith(e))return r.slice(e.length)}return r}const K=[{id:"approval",displayName:"\u4EBA\u5DE5\u786E\u8BA4"},{id:"full_auto",displayName:"\u81EA\u7531\u6A21\u5F0F"},{id:"plan",displayName:"\u8BA1\u5212\u6A21\u5F0F"}];function C(d){const e=String(d??"").trim().toLowerCase();return K.some(t=>t.id===e)?e:null}function B(d){try{return process.kill(d,0),!0}catch(e){return e.code==="EPERM"}}function V(d,e,t){if(t<0)return null;let n;try{n=se(d,{withFileTypes:!0})}catch{return null}for(const s of n){const i=A(d,s.name);if(s.isDirectory()){const r=V(i,e,t-1);if(r)return r}else if(s.isFile()&&s.name.endsWith(e))return i}return null}function Y(d,e){if(!d)return null;const t=e||A(N(),".cursor","projects");return V(t,`${d}.jsonl`,6)}function Re(d){const e=d.context_messages_json;if(e)try{const t=JSON.parse(e);return!Array.isArray(t)||t.length===0?void 0:t.map(n=>({senderId:String(n.sender_id??"unknown"),content:String(n.content??"")}))}catch{return}}function Me(d,e){const t=[String(d??"")],n=String(e.quoted_message_id??"").trim();n&&t.push(`[quoted_message_id] ${n}`);const s=String(e.attachments_json??"").trim();return s&&t.push(`[attachments_json]
3
+ `)}function ke(d){if(!d||typeof d!="object"||Array.isArray(d))return null;const e=d,t=String(e.type??"").trim().toLowerCase();if(!t)return null;switch(t){case"tool_call":{const n=String(e.subtype??"").trim().toLowerCase(),s=U(e);return z(s.toolName)||J(s.toolName)?null:n==="started"||n==="start"?{type:"tool_call",payload:{tool_name:s.toolName,...s.callId?{tool_call_id:s.callId}:{}}}:(W.has(n),null)}case"error":return{type:"error",payload:{message:String(e.message??e.error??e.result??"cursor error").trim()||"cursor error"}};case"result":{const n=String(e.subtype??"").trim().toLowerCase();return e.is_error===!0||n==="error"?{type:"error",payload:{message:String(e.result??e.message??"cursor run failed").trim()||"cursor run failed"}}:null}default:return null}}function we(d,e){if(!d||typeof d!="object"||Array.isArray(d))return"";const t=d;if(String(t.type??"")!=="assistant")return"";const n=t.model_call_id??t.modelCallId;if(n!=null&&String(n).trim()!=="")return"";const s=t.message,i=s&&typeof s=="object"&&!Array.isArray(s)?s.content:void 0;if(!Array.isArray(i))return"";const r=i.map(o=>{if(!o||typeof o!="object"||Array.isArray(o))return"";const a=o;return a.type==="text"?String(a.text??""):""}).filter(Boolean).join("");if(!r)return"";if(e){if(r===e||e.startsWith(r)&&r.length<e.length)return"";if(r.startsWith(e))return r.slice(e.length)}return r}const G=[{id:"approval",displayName:"\u4EBA\u5DE5\u786E\u8BA4"},{id:"full_auto",displayName:"\u81EA\u7531\u6A21\u5F0F"},{id:"plan",displayName:"\u8BA1\u5212\u6A21\u5F0F"}];function C(d){const e=String(d??"").trim().toLowerCase();return G.some(t=>t.id===e)?e:null}function B(d){try{return process.kill(d,0),!0}catch(e){return e.code==="EPERM"}}function X(d,e,t){if(t<0)return null;let n;try{n=ee(d,{withFileTypes:!0})}catch{return null}for(const s of n){const i=A(d,s.name);if(s.isDirectory()){const r=X(i,e,t-1);if(r)return r}else if(s.isFile()&&s.name.endsWith(e))return i}return null}function K(d,e){if(!d)return null;const t=e||A(N(),".cursor","projects");return X(t,`${d}.jsonl`,6)}function Ie(d){const e=d.context_messages_json;if(e)try{const t=JSON.parse(e);return!Array.isArray(t)||t.length===0?void 0:t.map(n=>({senderId:String(n.sender_id??"unknown"),content:String(n.content??"")}))}catch{return}}function Ce(d,e){const t=[String(d??"")],n=String(e.quoted_message_id??"").trim();n&&t.push(`[quoted_message_id] ${n}`);const s=String(e.attachments_json??"").trim();return s&&t.push(`[attachments_json]
4
4
  ${s}`),t.filter(i=>i.length>0).join(`
5
5
 
6
- `)}class Z extends q{adapterSessionId;constructor(e){super(),this.adapterSessionId=e}emitDone(e){this.emit("done",e)}emitError(e){if(this.listenerCount("error")===0){h.warn("cursor-adapter",`Prompt handle error (no listeners): ${e.message}`);return}this.emit("error",e)}async cancel(){}}class x extends q{type="cursor";static STDERR_MAX_CHARS=8192;config;callbacks;alive=!1;stopped=!1;permissionHandler=null;internalApi=null;bindingStore=null;identity;inboundMessageIds=new ue;inboundQueue=[];pendingBySession=new Map;sessions=new Set;sessionRuntime=new Map;sessionSeq=0;lastUsageBySession=new Map;auditCaptures=new Map;completedAuditBoundaries=new Map;lastContextBySession=new Map;pendingHandoffBySession=new Map;pendingQuestionByRequestId=new Map;pendingQuestionAnswerBySession=new Map;cachedAccountRateLimits=null;rateLimitsInflight=null;_availableModels=[];transcriptPathBySession=new Map;activeBySession=new Map;constructor(e,t){super(),this.config=e,this.callbacks=t;const n=e.options??{};this.bindingStore=n.bindingStore instanceof me?n.bindingStore:null,this.identity=new oe("cursor-adapter",t.getAgentProfile)}async start(){this.alive=!0,this.stopped=!1,(this.config.options??{}).mcp_tools!==!1&&(this.internalApi=new de,this.internalApi.setInvokeHandler(async(t,n,s,i)=>this.callbacks.agentInvoke(t,n,i)),await this.internalApi.start()),this.notifyBindingReady(),this.refreshModels().then(()=>this.notifyBindingReady()).catch(()=>{}),this.refreshAccountRateLimits().then(()=>this.notifyBindingReady()).catch(()=>{})}get availableModels(){return this._availableModels}get availableModes(){return K.map(e=>({...e}))}async refreshModels(){try{const e={...process.env,...this.config.env??{}},t=await fe({command:this.config.command,env:e,cwd:process.cwd()});t.length>0&&(this._availableModels=t,h.info("cursor-adapter",`Loaded ${t.length} available models`))}catch(e){h.warn("cursor-adapter",`Failed to refresh models: ${e instanceof Error?e.message:String(e)}`)}}async stop(){this.stopped=!0,this.alive=!1;for(const e of this.activeBySession.values())I(e.child,"SIGTERM");this.activeBySession.clear(),this.transcriptPathBySession.clear(),this.internalApi&&(await this.internalApi.stop(),this.internalApi=null)}isAlive(){return this.alive}async createSession(e){const t=`cursor-${Date.now()}-${++this.sessionSeq}`;return this.sessions.add(t),this.sessionRuntime.set(t,{cwd:typeof e.cwd=="string"?e.cwd:void 0,modelId:typeof e.modelId=="string"?e.modelId:void 0,modeId:typeof e.modeId=="string"?e.modeId:void 0}),t}async resumeSession(e,t){this.sessions.add(e);const n=this.sessionRuntime.get(e)??{};this.sessionRuntime.set(e,{...n,cwd:typeof t?.cwd=="string"?t.cwd:n.cwd,modelId:typeof t?.modelId=="string"?t.modelId:n.modelId,modeId:typeof t?.modeId=="string"?t.modeId:n.modeId})}onAgentProfileChanged(){this.identity.onProfileChanged()}async destroySession(e){this.sessions.delete(e),this.sessionRuntime.delete(e),this.transcriptPathBySession.delete(e),this.identity.forgetSession(e),this.inboundMessageIds.forgetSession(e),this.pendingQuestionAnswerBySession.delete(e),this.pendingHandoffBySession.delete(e);for(const[t,n]of this.pendingQuestionByRequestId)n.sessionId===e&&this.pendingQuestionByRequestId.delete(t)}sendPrompt(e){const t=new Z(e.adapterSessionId);if(!this.alive||this.stopped)return queueMicrotask(()=>t.emitError(new Error("adapter not running"))),t;const n=this.inboundQueue.shift()??{event_id:`cursor-evt-${Date.now()}`,session_id:e.adapterSessionId,content:e.text},s=e.adapterSessionId,i=this.pendingBySession.get(s)??[];return i.push({event:n,request:e,handle:t}),this.pendingBySession.set(s,i),this.tryStartNext(s),t}tryStartNext(e){if(this.activeBySession.has(e)||!this.alive||this.stopped)return;const t=this.pendingBySession.get(e);if(!t||t.length===0)return;const n=t.shift();t.length===0?this.pendingBySession.delete(e):this.pendingBySession.set(e,t),n&&this.startJob(n,!1,0)}startJob(e,t,n){const{event:s,request:i,handle:r}=e;s.audit?.enabled&&!this.auditCaptures.has(s.event_id)&&this.auditCaptures.set(s.event_id,[]);const o=i.adapterSessionId,a=this.sessionRuntime.get(i.adapterSessionId)??{},l=this.config.options??{},c=[...this.config.args??[]];c.push("-p","--output-format","stream-json"),l.trust!==!1&&c.push("--trust");const u=a.cwd||l.workspace;this.internalApi&&u&&(this.ensureWorkspaceMcpAndSkills(u),c.push("--approve-mcps")),u&&c.push("--workspace",u);const p=a.modelId||l.model;p&&c.push("--model",p);const _=C(a.modeId||l.mode)??"full_auto";_==="full_auto"?c.push("--yolo"):_==="plan"&&c.push("--plan");const v=a.cursorSessionId??this.bindingStore?.getAcpSessionId(i.adapterSessionId),b=!!(v&&l.use_continue!==!1&&!t);b&&c.push("--resume",v),c.push(this.buildPromptText(i));const m={...process.env,...this.config.env??{}},y=F(R(this.config.command,typeof m.PATH=="string"?m.PATH:void 0));h.info("cursor-adapter",`job start: event=${s.event_id} session=${s.session_id} retry=${n}`);let g;try{g=M(y.command,[...y.prefixArgs,...c],{cwd:u||process.cwd(),env:j(m,y),stdio:["ignore","pipe","pipe"]}).process}catch(S){this.finishActive(o,"failed",`spawn failed: ${S instanceof Error?S.message:String(S)}`);return}this.callbacks.sendEventAck(s.event_id,s.session_id),this.emit("eventStarted",s.event_id,s.session_id);const f={event:s,request:i,handle:r,child:g,seq:0,done:!1,stderr:"",timer:null,idleTimer:null,toolCallsInFlight:new Set,toolCallsStarted:0,assistantTextEmitted:"",streamBuffer:"",lastIoAt:Date.now(),sawResult:!1,retryCount:n,usedContinue:b,workspace:u||process.cwd(),args:c};this.activeBySession.set(o,f),this.notifyBindingReady(o),this.armActiveIdleTimer(o);const k=i.timeoutMs&&i.timeoutMs>0?i.timeoutMs:0;k>0&&(f.timer=setTimeout(()=>{f.done||(I(g,"SIGTERM"),this.finishActive(o,"failed",`cursor agent timeout after ${k}ms`))},k)),$({input:g.stdout}).on("line",S=>this.handleStdoutLineForActive(f,S)),g.stderr?.on("data",S=>{if(f.done)return;const w=f.stderr+String(S??"");f.stderr=w.length>x.STDERR_MAX_CHARS?w.slice(-x.STDERR_MAX_CHARS):w,f.lastIoAt=Date.now(),this.armActiveIdleTimer(o)}),g.once("error",S=>{this.finishActive(o,"failed",`spawn failed: ${String(S?.message??S)}`)}),g.once("close",S=>{if(!f.done)if((S??0)===0)this.finishActive(o,"responded");else{if(this.shouldRetryWithoutContinue(f)){f.timer&&clearTimeout(f.timer),f.idleTimer&&clearTimeout(f.idleTimer),this.activeBySession.delete(o),this.startJob(e,!0,f.retryCount+1);return}const w=f.stderr.trim()||`cursor agent exited with code ${S??-1}`;this.finishActive(o,"failed",w)}})}async cancel(e){const t=this.activeBySession.get(e);t&&(I(t.child,"SIGTERM"),this.finishActive(e,"canceled","canceled"))}deliverInboundEvent(e){const t=String(e.session_id??"").trim();if(!t){h.warn("cursor-adapter",`Dropping event ${e.event_id}: missing session_id`),this.callbacks.sendEventResult(e.event_id,"failed","missing session_id");return}if(!this.alive||this.stopped){h.warn("cursor-adapter",`Dropping event ${e.event_id}: adapter not running`),this.callbacks.sendEventAck(e.event_id,t),this.callbacks.sendEventResult(e.event_id,"failed","adapter not running");return}const n={adapterSessionId:t,text:this.inboundMessageIds.inject(t,Me(String(e.content??""),e),e.msg_id),contextMessages:Re(e)},s=new Z(t),i=this.pendingBySession.get(t)??[];i.push({event:e,request:n,handle:s}),this.pendingBySession.set(t,i),h.info("cursor-adapter",`inbound queued: event=${e.event_id} session=${t} depth=${i.length}`),this.tryStartNext(t)}cancelSessionWork(e,t){const n=this.pendingBySession.get(e)??[];this.pendingBySession.delete(e);const s=this.activeBySession.get(e);s&&(this.killChildWithFallback(s.child),this.finishActive(e,"canceled",t));for(const i of n)this.callbacks.sendEventAck(i.event.event_id,i.event.session_id),this.callbacks.sendEventResult(i.event.event_id,"canceled",t),i.handle.emitDone({status:"canceled",error:t})}killChildWithFallback(e){I(e,"SIGTERM"),setTimeout(()=>{if(e.exitCode===null&&e.signalCode===null)try{I(e,"SIGKILL")}catch{}},5e3).unref()}deliverStopEvent(e,t){if(t){const n=this.activeBySession.get(t);if(n?.event.event_id===e){this.killChildWithFallback(n.child),this.finishActive(t,"canceled","stopped");return}const s=this.pendingBySession.get(t)??[],i=s.findIndex(r=>r.event.event_id===e);if(i>=0){const[r]=s.splice(i,1);s.length===0?this.pendingBySession.delete(t):this.pendingBySession.set(t,s),this.callbacks.sendEventAck(r.event.event_id,r.event.session_id),this.callbacks.sendEventResult(r.event.event_id,"canceled","stopped"),r.handle.emitDone({status:"canceled",error:"stopped"})}return}for(const[n,s]of this.activeBySession.entries())if(s.event.event_id===e){this.killChildWithFallback(s.child),this.finishActive(n,"canceled","stopped");return}for(const[n,s]of this.pendingBySession.entries()){const i=s.findIndex(o=>o.event.event_id===e);if(i<0)continue;const[r]=s.splice(i,1);s.length===0?this.pendingBySession.delete(n):this.pendingBySession.set(n,s),this.callbacks.sendEventAck(r.event.event_id,r.event.session_id),this.callbacks.sendEventResult(r.event.event_id,"canceled","stopped"),r.handle.emitDone({status:"canceled",error:"stopped"});return}}async handleLocalAction(e){const t=String(e.action_type??"").trim().toLowerCase(),n=e.params??{},s=String(n.session_id??"").trim(),i=e.action_id;if(t==="claude_interaction_reply")return String(n.kind??"").trim()==="permission"?(this.callbacks.sendLocalActionResult(i,"failed",void 0,"unsupported","Cursor adapter does not support interactive permission approvals"),{handled:!0,kind:"permission_unsupported"}):this.handleQuestionReply(e);switch(t){case"set_model":{const r=String(n.model_id??"").trim();if(!r||!s)return this.callbacks.sendLocalActionResult(i,"failed",void 0,"invalid_params","model_id and session_id are required"),{handled:!0,kind:"set_model"};const o=this.sessionRuntime.get(s)??{};this.sessionRuntime.set(s,{...o,modelId:r}),this.notifyBindingReady(s);const a=this.getToolbarMeta(s);return this.callbacks.sendLocalActionResult(i,"ok",{outcome:"model_set",session_context:{model_id:r,mode_id:a.mode_id,modelId:r,modeId:a.mode_id},model_id:r,mode_id:a.mode_id,available_models:this.availableModels,available_modes:this.availableModes}),{handled:!0,kind:"set_model"}}case"set_mode":{const r=C(n.mode_id);if(!r||!s)return this.callbacks.sendLocalActionResult(i,"failed",void 0,"invalid_params","mode_id must be approval, full_auto, or plan and session_id is required"),{handled:!0,kind:"set_mode"};const o=this.sessionRuntime.get(s)??{};this.sessionRuntime.set(s,{...o,modeId:r}),this.notifyBindingReady(s);const a=this.getToolbarMeta(s);return this.callbacks.sendLocalActionResult(i,"ok",{outcome:"mode_set",session_context:{model_id:a.model_id,mode_id:r,modelId:a.model_id,modeId:r},model_id:a.model_id,mode_id:r,available_models:this.availableModels,available_modes:this.availableModes}),{handled:!0,kind:"set_mode"}}case"get_context":{const r=s?this.sessionRuntime.get(s):void 0,o=this.config.options??{},a=this.getToolbarMeta(s);return this.callbacks.sendLocalActionResult(i,"ok",{session_context:{model_id:a.model_id,mode_id:a.mode_id,cwd:r?.cwd??o.workspace??null},model_id:a.model_id,mode_id:a.mode_id,modelId:a.model_id,modeId:a.mode_id,cwd:r?.cwd??o.workspace??null,available_models:this.availableModels,available_modes:this.availableModes}),{handled:!0,kind:"get_context"}}case"get_rate_limits":{await this.refreshAccountRateLimits({force:!0});const r=this.getRateLimitsSnapshot(s||void 0);return this.callbacks.sendLocalActionResult(i,"ok",r),s&&this.notifyBindingReady(s),{handled:!0,kind:"get_rate_limits"}}case"get_session_usage":{const r=s?this.getUsageSnapshot(s):null;if(r){const o={inputTokens:r.total.input,outputTokens:r.total.output,cacheReadInputTokens:r.total.cacheRead,cacheCreationInputTokens:r.total.cacheWrite};this.callbacks.sendLocalActionResult(i,"ok",{sessionId:s,adapterType:"cursor",sampledAt:r.sampledAt,turns:r.turns,total:o,models:[{model:this.getToolbarMeta(s).model_id??"auto",turns:r.turns,total:o}]})}else this.callbacks.sendLocalActionResult(i,"failed",void 0,"usage_not_found","No usage data found for this session");return{handled:!0,kind:"get_session_usage"}}case"session_control":{const r=String(n.verb??"").trim().toLowerCase();if(r==="restart"&&s)this.cancelSessionWork(s,"restarted"),this.callbacks.sendLocalActionResult(i,"ok",{outcome:"restarted"});else if(r==="status"){const o=this.sessionRuntime.get(s),a=this.config.options??{},l=this.getToolbarMeta(s),c=this.activeBySession.has(s);this.callbacks.sendLocalActionResult(i,"ok",{verb:"status",status:c?"running":"idle",session_context:{model_id:l.model_id,mode_id:l.mode_id,cwd:o?.cwd??a.workspace??null},model_id:l.model_id,mode_id:l.mode_id,modelId:l.model_id,modeId:l.mode_id,cwd:o?.cwd??a.workspace??null,available_models:this.availableModels,available_modes:this.availableModes})}else this.callbacks.sendLocalActionResult(i,"failed",void 0,"invalid_verb",`Unsupported verb: ${r}`);return{handled:!0,kind:"session_control"}}default:return{handled:!1,kind:"unsupported"}}}getSupportedCommands(){return[{name:"compact",description:"\u538B\u7F29\u4E0A\u4E0B\u6587",args:"[instructions]"}]}async execCommand(e,t,n){return e!=="compact"?{status:"unsupported",message:`Unsupported command: ${e}`}:this.runCompactHandoff(n,t)}async runCompactHandoff(e,t=""){if(!e)return{status:"failed",message:"session_id is required"};if(this.activeBySession.has(e))return{status:"failed",message:"Cannot compact while a Cursor turn is active"};const n=this.sessionRuntime.get(e)??{},s=this.config.options??{},i=n.cursorSessionId??this.bindingStore?.getAcpSessionId(e)??null;if(!i)return{status:"failed",message:"No Cursor chat to compact (send a message first)"};const r=String(n.cwd||s.workspace||process.cwd()),o=String(n.modelId||s.model||""),a=C(n.modeId||s.mode)??"full_auto",l=t.trim(),c=l?`${W}
6
+ `)}class V extends q{adapterSessionId;constructor(e){super(),this.adapterSessionId=e}emitDone(e){this.emit("done",e)}emitError(e){if(this.listenerCount("error")===0){h.warn("cursor-adapter",`Prompt handle error (no listeners): ${e.message}`);return}this.emit("error",e)}async cancel(){}}class T extends q{type="cursor";static STDERR_MAX_CHARS=8192;config;callbacks;alive=!1;stopped=!1;permissionHandler=null;internalApi=null;bindingStore=null;identity;inboundMessageIds=new le;inboundQueue=[];pendingBySession=new Map;sessions=new Set;sessionRuntime=new Map;sessionSeq=0;lastUsageBySession=new Map;auditCaptures=new Map;completedAuditBoundaries=new Map;lastContextBySession=new Map;pendingHandoffBySession=new Map;pendingQuestionByRequestId=new Map;pendingQuestionAnswerBySession=new Map;cachedAccountRateLimits=null;rateLimitsInflight=null;_availableModels=[];transcriptPathBySession=new Map;activeBySession=new Map;constructor(e,t){super(),this.config=e,this.callbacks=t;const n=e.options??{};this.bindingStore=n.bindingStore instanceof ue?n.bindingStore:null,this.identity=new ie("cursor-adapter",t.getAgentProfile)}async start(){this.alive=!0,this.stopped=!1,(this.config.options??{}).mcp_tools!==!1&&(this.internalApi=new oe,this.internalApi.setInvokeHandler(async(t,n,s,i)=>this.callbacks.agentInvoke(t,n,i)),await this.internalApi.start()),this.notifyBindingReady(),this.refreshModels().then(()=>this.notifyBindingReady()).catch(()=>{}),this.refreshAccountRateLimits().then(()=>this.notifyBindingReady()).catch(()=>{})}get availableModels(){return this._availableModels}get availableModes(){return G.map(e=>({...e}))}async refreshModels(){try{const e={...process.env,...this.config.env??{}},t=await he({command:this.config.command,env:e,cwd:process.cwd()});t.length>0&&(this._availableModels=t,h.info("cursor-adapter",`Loaded ${t.length} available models`))}catch(e){h.warn("cursor-adapter",`Failed to refresh models: ${e instanceof Error?e.message:String(e)}`)}}async stop(){this.stopped=!0,this.alive=!1;for(const e of this.activeBySession.values())I(e.child,"SIGTERM");this.activeBySession.clear(),this.transcriptPathBySession.clear(),this.internalApi&&(await this.internalApi.stop(),this.internalApi=null)}isAlive(){return this.alive}async createSession(e){const t=`cursor-${Date.now()}-${++this.sessionSeq}`;return this.sessions.add(t),this.sessionRuntime.set(t,{cwd:typeof e.cwd=="string"?e.cwd:void 0,modelId:typeof e.modelId=="string"?e.modelId:void 0,modeId:typeof e.modeId=="string"?e.modeId:void 0}),t}async resumeSession(e,t){this.sessions.add(e);const n=this.sessionRuntime.get(e)??{};this.sessionRuntime.set(e,{...n,cwd:typeof t?.cwd=="string"?t.cwd:n.cwd,modelId:typeof t?.modelId=="string"?t.modelId:n.modelId,modeId:typeof t?.modeId=="string"?t.modeId:n.modeId})}onAgentProfileChanged(){this.identity.onProfileChanged()}async destroySession(e){this.sessions.delete(e),this.sessionRuntime.delete(e),this.transcriptPathBySession.delete(e),this.identity.forgetSession(e),this.inboundMessageIds.forgetSession(e),this.pendingQuestionAnswerBySession.delete(e),this.pendingHandoffBySession.delete(e);for(const[t,n]of this.pendingQuestionByRequestId)n.sessionId===e&&this.pendingQuestionByRequestId.delete(t)}sendPrompt(e){const t=new V(e.adapterSessionId);if(!this.alive||this.stopped)return queueMicrotask(()=>t.emitError(new Error("adapter not running"))),t;const n=this.inboundQueue.shift()??{event_id:`cursor-evt-${Date.now()}`,session_id:e.adapterSessionId,content:e.text},s=e.adapterSessionId,i=this.pendingBySession.get(s)??[];return i.push({event:n,request:e,handle:t}),this.pendingBySession.set(s,i),this.tryStartNext(s),t}tryStartNext(e){if(this.activeBySession.has(e)||!this.alive||this.stopped)return;const t=this.pendingBySession.get(e);if(!t||t.length===0)return;const n=t.shift();t.length===0?this.pendingBySession.delete(e):this.pendingBySession.set(e,t),n&&this.startJob(n,!1,0)}startJob(e,t,n){const{event:s,request:i,handle:r}=e;s.audit?.enabled&&!this.auditCaptures.has(s.event_id)&&this.auditCaptures.set(s.event_id,[]);const o=i.adapterSessionId,a=this.sessionRuntime.get(i.adapterSessionId)??{},l=this.config.options??{},c=[...this.config.args??[]];c.push("-p","--output-format","stream-json"),l.trust!==!1&&c.push("--trust");const u=a.cwd||l.workspace;this.internalApi&&u&&(this.ensureWorkspaceMcpAndSkills(u),c.push("--approve-mcps")),u&&c.push("--workspace",u);const p=a.modelId||l.model;p&&c.push("--model",p);const _=C(a.modeId||l.mode)??"full_auto";_==="full_auto"?c.push("--yolo"):_==="plan"&&c.push("--plan");const v=a.cursorSessionId??this.bindingStore?.getAcpSessionId(i.adapterSessionId),b=!!(v&&l.use_continue!==!1&&!t);b&&c.push("--resume",v),c.push(this.buildPromptText(i));const f={...process.env,...this.config.env??{}},y=M(this.config.command,f);h.info("cursor-adapter",`job start: event=${s.event_id} session=${s.session_id} retry=${n}`);let g;try{g=R(y.command,[...y.prefixArgs,...c],{cwd:u||process.cwd(),env:y.env,stdio:["ignore","pipe","pipe"]}).process}catch(S){this.finishActive(o,"failed",`spawn failed: ${S instanceof Error?S.message:String(S)}`);return}this.callbacks.sendEventAck(s.event_id,s.session_id),this.emit("eventStarted",s.event_id,s.session_id);const m={event:s,request:i,handle:r,child:g,seq:0,done:!1,stderr:"",timer:null,idleTimer:null,toolCallsInFlight:new Set,toolCallsStarted:0,assistantTextEmitted:"",streamBuffer:"",lastIoAt:Date.now(),sawResult:!1,retryCount:n,usedContinue:b,workspace:u||process.cwd(),args:c};this.activeBySession.set(o,m),this.notifyBindingReady(o),this.armActiveIdleTimer(o);const k=i.timeoutMs&&i.timeoutMs>0?i.timeoutMs:0;k>0&&(m.timer=setTimeout(()=>{m.done||(I(g,"SIGTERM"),this.finishActive(o,"failed",`cursor agent timeout after ${k}ms`))},k)),$({input:g.stdout}).on("line",S=>this.handleStdoutLineForActive(m,S)),g.stderr?.on("data",S=>{if(m.done)return;const w=m.stderr+String(S??"");m.stderr=w.length>T.STDERR_MAX_CHARS?w.slice(-T.STDERR_MAX_CHARS):w,m.lastIoAt=Date.now(),this.armActiveIdleTimer(o)}),g.once("error",S=>{this.finishActive(o,"failed",`spawn failed: ${String(S?.message??S)}`)}),g.once("close",S=>{if(!m.done)if((S??0)===0)this.finishActive(o,"responded");else{if(this.shouldRetryWithoutContinue(m)){m.timer&&clearTimeout(m.timer),m.idleTimer&&clearTimeout(m.idleTimer),this.activeBySession.delete(o),this.startJob(e,!0,m.retryCount+1);return}const w=m.stderr.trim()||`cursor agent exited with code ${S??-1}`;this.finishActive(o,"failed",w)}})}async cancel(e){const t=this.activeBySession.get(e);t&&(I(t.child,"SIGTERM"),this.finishActive(e,"canceled","canceled"))}deliverInboundEvent(e){const t=String(e.session_id??"").trim();if(!t){h.warn("cursor-adapter",`Dropping event ${e.event_id}: missing session_id`),this.callbacks.sendEventResult(e.event_id,"failed","missing session_id");return}if(!this.alive||this.stopped){h.warn("cursor-adapter",`Dropping event ${e.event_id}: adapter not running`),this.callbacks.sendEventAck(e.event_id,t),this.callbacks.sendEventResult(e.event_id,"failed","adapter not running");return}const n={adapterSessionId:t,text:this.inboundMessageIds.inject(t,Ce(String(e.content??""),e),e.msg_id),contextMessages:Ie(e)},s=new V(t),i=this.pendingBySession.get(t)??[];i.push({event:e,request:n,handle:s}),this.pendingBySession.set(t,i),h.info("cursor-adapter",`inbound queued: event=${e.event_id} session=${t} depth=${i.length}`),this.tryStartNext(t)}cancelSessionWork(e,t){const n=this.pendingBySession.get(e)??[];this.pendingBySession.delete(e);const s=this.activeBySession.get(e);s&&(this.killChildWithFallback(s.child),this.finishActive(e,"canceled",t));for(const i of n)this.callbacks.sendEventAck(i.event.event_id,i.event.session_id),this.callbacks.sendEventResult(i.event.event_id,"canceled",t),i.handle.emitDone({status:"canceled",error:t})}killChildWithFallback(e){I(e,"SIGTERM"),setTimeout(()=>{if(e.exitCode===null&&e.signalCode===null)try{I(e,"SIGKILL")}catch{}},5e3).unref()}deliverStopEvent(e,t){if(t){const n=this.activeBySession.get(t);if(n?.event.event_id===e){this.killChildWithFallback(n.child),this.finishActive(t,"canceled","stopped");return}const s=this.pendingBySession.get(t)??[],i=s.findIndex(r=>r.event.event_id===e);if(i>=0){const[r]=s.splice(i,1);s.length===0?this.pendingBySession.delete(t):this.pendingBySession.set(t,s),this.callbacks.sendEventAck(r.event.event_id,r.event.session_id),this.callbacks.sendEventResult(r.event.event_id,"canceled","stopped"),r.handle.emitDone({status:"canceled",error:"stopped"})}return}for(const[n,s]of this.activeBySession.entries())if(s.event.event_id===e){this.killChildWithFallback(s.child),this.finishActive(n,"canceled","stopped");return}for(const[n,s]of this.pendingBySession.entries()){const i=s.findIndex(o=>o.event.event_id===e);if(i<0)continue;const[r]=s.splice(i,1);s.length===0?this.pendingBySession.delete(n):this.pendingBySession.set(n,s),this.callbacks.sendEventAck(r.event.event_id,r.event.session_id),this.callbacks.sendEventResult(r.event.event_id,"canceled","stopped"),r.handle.emitDone({status:"canceled",error:"stopped"});return}}async handleLocalAction(e){const t=String(e.action_type??"").trim().toLowerCase(),n=e.params??{},s=String(n.session_id??"").trim(),i=e.action_id;if(t==="claude_interaction_reply")return String(n.kind??"").trim()==="permission"?(this.callbacks.sendLocalActionResult(i,"failed",void 0,"unsupported","Cursor adapter does not support interactive permission approvals"),{handled:!0,kind:"permission_unsupported"}):this.handleQuestionReply(e);switch(t){case"set_model":{const r=String(n.model_id??"").trim();if(!r||!s)return this.callbacks.sendLocalActionResult(i,"failed",void 0,"invalid_params","model_id and session_id are required"),{handled:!0,kind:"set_model"};const o=this.sessionRuntime.get(s)??{};this.sessionRuntime.set(s,{...o,modelId:r}),this.notifyBindingReady(s);const a=this.getToolbarMeta(s);return this.callbacks.sendLocalActionResult(i,"ok",{outcome:"model_set",session_context:{model_id:r,mode_id:a.mode_id,modelId:r,modeId:a.mode_id},model_id:r,mode_id:a.mode_id,available_models:this.availableModels,available_modes:this.availableModes}),{handled:!0,kind:"set_model"}}case"set_mode":{const r=C(n.mode_id);if(!r||!s)return this.callbacks.sendLocalActionResult(i,"failed",void 0,"invalid_params","mode_id must be approval, full_auto, or plan and session_id is required"),{handled:!0,kind:"set_mode"};const o=this.sessionRuntime.get(s)??{};this.sessionRuntime.set(s,{...o,modeId:r}),this.notifyBindingReady(s);const a=this.getToolbarMeta(s);return this.callbacks.sendLocalActionResult(i,"ok",{outcome:"mode_set",session_context:{model_id:a.model_id,mode_id:r,modelId:a.model_id,modeId:r},model_id:a.model_id,mode_id:r,available_models:this.availableModels,available_modes:this.availableModes}),{handled:!0,kind:"set_mode"}}case"get_context":{const r=s?this.sessionRuntime.get(s):void 0,o=this.config.options??{},a=this.getToolbarMeta(s);return this.callbacks.sendLocalActionResult(i,"ok",{session_context:{model_id:a.model_id,mode_id:a.mode_id,cwd:r?.cwd??o.workspace??null},model_id:a.model_id,mode_id:a.mode_id,modelId:a.model_id,modeId:a.mode_id,cwd:r?.cwd??o.workspace??null,available_models:this.availableModels,available_modes:this.availableModes}),{handled:!0,kind:"get_context"}}case"get_rate_limits":{await this.refreshAccountRateLimits({force:!0});const r=this.getRateLimitsSnapshot(s||void 0);return this.callbacks.sendLocalActionResult(i,"ok",r),s&&this.notifyBindingReady(s),{handled:!0,kind:"get_rate_limits"}}case"get_session_usage":{const r=s?this.getUsageSnapshot(s):null;if(r){const o={inputTokens:r.total.input,outputTokens:r.total.output,cacheReadInputTokens:r.total.cacheRead,cacheCreationInputTokens:r.total.cacheWrite};this.callbacks.sendLocalActionResult(i,"ok",{sessionId:s,adapterType:"cursor",sampledAt:r.sampledAt,turns:r.turns,total:o,models:[{model:this.getToolbarMeta(s).model_id??"auto",turns:r.turns,total:o}]})}else this.callbacks.sendLocalActionResult(i,"failed",void 0,"usage_not_found","No usage data found for this session");return{handled:!0,kind:"get_session_usage"}}case"session_control":{const r=String(n.verb??"").trim().toLowerCase();if(r==="restart"&&s)this.cancelSessionWork(s,"restarted"),this.callbacks.sendLocalActionResult(i,"ok",{outcome:"restarted"});else if(r==="status"){const o=this.sessionRuntime.get(s),a=this.config.options??{},l=this.getToolbarMeta(s),c=this.activeBySession.has(s);this.callbacks.sendLocalActionResult(i,"ok",{verb:"status",status:c?"running":"idle",session_context:{model_id:l.model_id,mode_id:l.mode_id,cwd:o?.cwd??a.workspace??null},model_id:l.model_id,mode_id:l.mode_id,modelId:l.model_id,modeId:l.mode_id,cwd:o?.cwd??a.workspace??null,available_models:this.availableModels,available_modes:this.availableModes})}else this.callbacks.sendLocalActionResult(i,"failed",void 0,"invalid_verb",`Unsupported verb: ${r}`);return{handled:!0,kind:"session_control"}}default:return{handled:!1,kind:"unsupported"}}}getSupportedCommands(){return[{name:"compact",description:"\u538B\u7F29\u4E0A\u4E0B\u6587",args:"[instructions]"}]}async execCommand(e,t,n){return e!=="compact"?{status:"unsupported",message:`Unsupported command: ${e}`}:this.runCompactHandoff(n,t)}async runCompactHandoff(e,t=""){if(!e)return{status:"failed",message:"session_id is required"};if(this.activeBySession.has(e))return{status:"failed",message:"Cannot compact while a Cursor turn is active"};const n=this.sessionRuntime.get(e)??{},s=this.config.options??{},i=n.cursorSessionId??this.bindingStore?.getAcpSessionId(e)??null;if(!i)return{status:"failed",message:"No Cursor chat to compact (send a message first)"};const r=String(n.cwd||s.workspace||process.cwd()),o=String(n.modelId||s.model||""),a=C(n.modeId||s.mode)??"full_auto",l=t.trim(),c=l?`${Q}
7
7
 
8
8
  Additional focus from user:
9
- ${l}`:W;this.emit("pauseIntake","compaction"),h.info("cursor-adapter",`[compact] summarize resume=${i} session=${e}`);try{const u=await this.runPrintOnce({prompt:c,resumeChatId:i,cwd:r,modelId:o||void 0,modeId:a,timeoutMs:U});if(!u.ok||!u.text.trim())return{status:"failed",message:u.error??"Summarize failed (empty result)"};const p=await this.createEmptyChat();return p?(this.sessionRuntime.set(e,{...n,cwd:r,modelId:o||n.modelId,modeId:a,cursorSessionId:p}),this.transcriptPathBySession.delete(e),this.bindingStore?.setAcpSessionId(e,p),this.identity.forgetSession(e),this.inboundMessageIds.forgetSession(e),this.pendingHandoffBySession.set(e,u.text.trim()),this.lastContextBySession.set(e,ge(0,ye(o))),this.notifyBindingReady(e),h.info("cursor-adapter",`[compact] handoff ready: old=${i} new=${p} summaryChars=${u.text.trim().length}`),{status:"ok",message:"Context compacted via summarize + new chat",data:{previousChatId:i,chatId:p}}):{status:"failed",message:"agent create-chat failed"}}finally{this.emit("resumeIntake","compaction")}}runPrintOnce(e){const t={...process.env,...this.config.env??{}},n=F(R(this.config.command,typeof t.PATH=="string"?t.PATH:void 0)),s=[...n.prefixArgs,...this.config.args??[]];s.push("-p","--output-format","stream-json"),this.config.options?.trust!==!1&&s.push("--trust"),e.cwd&&s.push("--workspace",e.cwd),e.modelId&&s.push("--model",e.modelId);const i=C(e.modeId)??"full_auto";return i==="full_auto"?s.push("--yolo"):i==="plan"&&s.push("--plan"),e.resumeChatId&&s.push("--resume",e.resumeChatId),s.push(e.prompt),new Promise(r=>{let o;try{o=M(n.command,s,{cwd:e.cwd||process.cwd(),env:j(t,n),stdio:["ignore","pipe","pipe"]}).process}catch(m){r({ok:!1,text:"",error:`spawn failed: ${m instanceof Error?m.message:String(m)}`});return}let a="",l="",c="",u=!1;const p=e.timeoutMs&&e.timeoutMs>0?e.timeoutMs:U,_=setTimeout(()=>{u||(u=!0,this.killChildWithFallback(o),r({ok:!1,text:a,sessionId:l||void 0,error:`compact timeout after ${p}ms`}))},p);_.unref?.();const v=(m,y)=>{u||(u=!0,clearTimeout(_),r({ok:m,text:a,sessionId:l||void 0,error:y}))};$({input:o.stdout}).on("line",m=>{const y=m.trim();if(!y)return;let g;try{g=JSON.parse(y)}catch{return}if(g?.type!=="result")return;const f=typeof g?.result=="string"?g.result:"";f&&(a=f);const k=String(g?.session_id??"").trim();k&&(l=k)}),o.stderr?.on("data",m=>{c+=typeof m=="string"?m:m.toString("utf8")}),o.on("error",m=>v(!1,m.message)),o.on("close",m=>{if(!u){if(a.trim()){v(!0);return}v(!1,c.trim()||`cursor agent exited with code ${m??"unknown"}`)}})})}createEmptyChat(){const e={...process.env,...this.config.env??{}},t=R(this.config.command,typeof e.PATH=="string"?e.PATH:void 0);return new Promise(n=>{let s;try{s=M(t,["create-chat"],{cwd:process.cwd(),env:e,stdio:["ignore","pipe","pipe"]}).process}catch{n(null);return}let i="",r=!1;const o=setTimeout(()=>{r||(r=!0,this.killChildWithFallback(s),n(null))},3e4);o.unref?.(),s.stdout?.on("data",a=>{i+=typeof a=="string"?a:a.toString("utf8")}),s.on("error",()=>{r||(r=!0,clearTimeout(o),n(null))}),s.on("close",a=>{if(r)return;r=!0,clearTimeout(o);const l=i.trim().split(/\s+/)[0]??"";n(a===0&&/^[0-9a-f-]{16,}$/i.test(l)?l:null)})})}setPermissionHandler(e){this.permissionHandler=e}async ping(e){if(!this.alive||this.stopped||(this.config.options??{}).mcp_tools!==!1&&this.internalApi===null)return!1;for(const n of this.activeBySession.values()){const s=n.child?.pid;if(s&&!B(s))return!1}return!0}getStatus(){let e=0;for(const t of this.pendingBySession.values())e+=t.length;return{alive:this.alive,busy:this.activeBySession.size>0,sessions:this.sessions.size,details:{queueDepth:e+this.inboundQueue.length,activeSessions:this.activeBySession.size}}}getActiveEventIds(){const e=[];for(const t of this.activeBySession.values())t.event.event_id&&e.push(t.event.event_id);return e}clearActiveEventForShutdown(){for(const[e,t]of this.activeBySession)this.snapshotAuditBoundary(t.event.event_id,e);this.activeBySession.clear()}takeAuditBoundary(e){const t=this.completedAuditBoundaries.get(e);return t&&this.completedAuditBoundaries.delete(e),t}getMcpConfig(){return null}async probe(e){const t=this.getStatus();return{...await ae(this.config.command||"cursor-agent",{alive:t.alive,busy:t.busy,started:this.alive},e),session:this.probeSessionRecord()}}probeSessionRecord(){const e=this.firstKnownCursorSessionId(),t=e?Y(e):null;if(!t)return{recordPath:null,lastActivityMs:null,freshMs:null};try{const n=D(t);return{recordPath:t,lastActivityMs:n.mtimeMs,freshMs:Date.now()-n.mtimeMs}}catch{return{recordPath:t,lastActivityMs:null,freshMs:null}}}firstKnownCursorSessionId(){for(const e of this.activeBySession.keys()){const t=this.sessionRuntime.get(e);if(t?.cursorSessionId)return t.cursorSessionId}for(const e of this.sessionRuntime.values())if(e.cursorSessionId)return e.cursorSessionId;return null}getUsageSnapshot(e){return this.lastUsageBySession.get(e)??null}getRateLimitsSnapshot(e){const t=this.cachedAccountRateLimits,n=e?this.lastContextBySession.get(e)??null:null;if(!t)return{adapterType:"cursor",available:!1,cached:!1,sampledAt:null,rateLimits:null,contextWindow:n,tokenUsage:null};const s=Date.parse(t.sampledAt);return{adapterType:"cursor",available:t.available&&!!t.rateLimits,cached:!0,sampledAt:Number.isFinite(s)?s:Date.now(),rateLimits:t.rateLimits,contextWindow:n,tokenUsage:null,...t.displayMessage?{displayMessage:t.displayMessage}:{},...t.error?{error:t.error}:{}}}async refreshAccountRateLimits(e){const t=e?.force===!0,n=this.cachedAccountRateLimits,s=n?Date.now()-Date.parse(n.sampledAt):Number.POSITIVE_INFINITY;if(!t&&n&&Number.isFinite(s)&&s<6e4||this.rateLimitsInflight&&(await this.rateLimitsInflight,!t))return;const i=(async()=>{const r=await pe();this.cachedAccountRateLimits={available:r.available,sampledAt:r.sampledAt,rateLimits:r.rateLimits,displayMessage:r.displayMessage,error:r.error},r.available&&r.rateLimits?h.info("cursor-adapter",`[rate-limits] monthly=${r.rateLimits.fiveHour.usedPercentage.toFixed(1)}% api=${r.rateLimits.sevenDay.usedPercentage.toFixed(1)}% resetsAt=${r.rateLimits.fiveHour.resetsAt}`+(r.displayMessage?` msg=${r.displayMessage}`:"")):h.warn("cursor-adapter",`[rate-limits] unavailable: ${r.error??"unknown"}`)})();this.rateLimitsInflight=i.finally(()=>{this.rateLimitsInflight=null}),await this.rateLimitsInflight}getToolbarMeta(e){const t=this.config.options??{},n=e||String(t.aibotSessionId??""),s=n?this.sessionRuntime.get(n):void 0,i=String(s?.modelId||t.model||"auto"),r=C(s?.modeId||t.mode)??"full_auto",o={model_id:i,mode_id:r,currentModelId:i,currentModeId:r,available_models:this.availableModels,available_modes:this.availableModes},a=this.cachedAccountRateLimits?.rateLimits;if(a?.fiveHour||a?.sevenDay){const c=Date.parse(this.cachedAccountRateLimits?.sampledAt??"")||Date.now();o.rate_limits={...a.fiveHour?{fiveHour:a.fiveHour}:{},...a.sevenDay?{sevenDay:a.sevenDay}:{},sampledAt:c}}const l=n?this.lastContextBySession.get(n):void 0;return l&&(o.context_window={usedPercentage:l.usedPercentage,remainingPercentage:l.remainingPercentage,usedTokens:l.usedTokens,sizeTokens:l.sizeTokens}),o}notifyBindingReady(e){if(!this.callbacks.sendUpdateBindingCard)return;const t=this.config.options??{},n=e||String(t.aibotSessionId??"");if(!n)return;const s=this.sessionRuntime.get(n),i=String(s?.cwd||t.workspace||"");i&&this.callbacks.sendUpdateBindingCard(n,this.activeBySession.has(n)?"busy":"ready",i,this.getToolbarMeta(n))}buildPromptText(e){let t;!e.contextMessages||e.contextMessages.length===0?t=e.text:t=`${e.contextMessages.map(r=>`[${r.senderId}] ${r.content}`).join(`
9
+ ${l}`:Q;this.emit("pauseIntake","compaction"),h.info("cursor-adapter",`[compact] summarize resume=${i} session=${e}`);try{const u=await this.runPrintOnce({prompt:c,resumeChatId:i,cwd:r,modelId:o||void 0,modeId:a,timeoutMs:O});if(!u.ok||!u.text.trim())return{status:"failed",message:u.error??"Summarize failed (empty result)"};const p=await this.createEmptyChat();return p?(this.sessionRuntime.set(e,{...n,cwd:r,modelId:o||n.modelId,modeId:a,cursorSessionId:p}),this.transcriptPathBySession.delete(e),this.bindingStore?.setAcpSessionId(e,p),this.identity.forgetSession(e),this.inboundMessageIds.forgetSession(e),this.pendingHandoffBySession.set(e,u.text.trim()),this.lastContextBySession.set(e,fe(0,ge(o))),this.notifyBindingReady(e),h.info("cursor-adapter",`[compact] handoff ready: old=${i} new=${p} summaryChars=${u.text.trim().length}`),{status:"ok",message:"Context compacted via summarize + new chat",data:{previousChatId:i,chatId:p}}):{status:"failed",message:"agent create-chat failed"}}finally{this.emit("resumeIntake","compaction")}}runPrintOnce(e){const t={...process.env,...this.config.env??{}},n=M(this.config.command,t),s=[...n.prefixArgs,...this.config.args??[]];s.push("-p","--output-format","stream-json"),this.config.options?.trust!==!1&&s.push("--trust"),e.cwd&&s.push("--workspace",e.cwd),e.modelId&&s.push("--model",e.modelId);const i=C(e.modeId)??"full_auto";return i==="full_auto"?s.push("--yolo"):i==="plan"&&s.push("--plan"),e.resumeChatId&&s.push("--resume",e.resumeChatId),s.push(e.prompt),new Promise(r=>{let o;try{o=R(n.command,s,{cwd:e.cwd||process.cwd(),env:n.env,stdio:["ignore","pipe","pipe"]}).process}catch(f){r({ok:!1,text:"",error:`spawn failed: ${f instanceof Error?f.message:String(f)}`});return}let a="",l="",c="",u=!1;const p=e.timeoutMs&&e.timeoutMs>0?e.timeoutMs:O,_=setTimeout(()=>{u||(u=!0,this.killChildWithFallback(o),r({ok:!1,text:a,sessionId:l||void 0,error:`compact timeout after ${p}ms`}))},p);_.unref?.();const v=(f,y)=>{u||(u=!0,clearTimeout(_),r({ok:f,text:a,sessionId:l||void 0,error:y}))};$({input:o.stdout}).on("line",f=>{const y=f.trim();if(!y)return;let g;try{g=JSON.parse(y)}catch{return}if(g?.type!=="result")return;const m=typeof g?.result=="string"?g.result:"";m&&(a=m);const k=String(g?.session_id??"").trim();k&&(l=k)}),o.stderr?.on("data",f=>{c+=typeof f=="string"?f:f.toString("utf8")}),o.on("error",f=>v(!1,f.message)),o.on("close",f=>{if(!u){if(a.trim()){v(!0);return}v(!1,c.trim()||`cursor agent exited with code ${f??"unknown"}`)}})})}createEmptyChat(){const e={...process.env,...this.config.env??{}},t=M(this.config.command,e);return new Promise(n=>{let s;try{s=R(t.command,[...t.prefixArgs,"create-chat"],{cwd:process.cwd(),env:t.env,stdio:["ignore","pipe","pipe"]}).process}catch{n(null);return}let i="",r=!1;const o=setTimeout(()=>{r||(r=!0,this.killChildWithFallback(s),n(null))},3e4);o.unref?.(),s.stdout?.on("data",a=>{i+=typeof a=="string"?a:a.toString("utf8")}),s.on("error",()=>{r||(r=!0,clearTimeout(o),n(null))}),s.on("close",a=>{if(r)return;r=!0,clearTimeout(o);const l=i.trim().split(/\s+/)[0]??"";n(a===0&&/^[0-9a-f-]{16,}$/i.test(l)?l:null)})})}setPermissionHandler(e){this.permissionHandler=e}async ping(e){if(!this.alive||this.stopped||(this.config.options??{}).mcp_tools!==!1&&this.internalApi===null)return!1;for(const n of this.activeBySession.values()){const s=n.child?.pid;if(s&&!B(s))return!1}return!0}getStatus(){let e=0;for(const t of this.pendingBySession.values())e+=t.length;return{alive:this.alive,busy:this.activeBySession.size>0,sessions:this.sessions.size,details:{queueDepth:e+this.inboundQueue.length,activeSessions:this.activeBySession.size}}}getActiveEventIds(){const e=[];for(const t of this.activeBySession.values())t.event.event_id&&e.push(t.event.event_id);return e}clearActiveEventForShutdown(){for(const[e,t]of this.activeBySession)this.snapshotAuditBoundary(t.event.event_id,e);this.activeBySession.clear()}takeAuditBoundary(e){const t=this.completedAuditBoundaries.get(e);return t&&this.completedAuditBoundaries.delete(e),t}getMcpConfig(){return null}async probe(e){const t=this.getStatus();return{...await re(this.config.command||"cursor-agent",{alive:t.alive,busy:t.busy,started:this.alive},e),session:this.probeSessionRecord()}}probeSessionRecord(){const e=this.firstKnownCursorSessionId(),t=e?K(e):null;if(!t)return{recordPath:null,lastActivityMs:null,freshMs:null};try{const n=D(t);return{recordPath:t,lastActivityMs:n.mtimeMs,freshMs:Date.now()-n.mtimeMs}}catch{return{recordPath:t,lastActivityMs:null,freshMs:null}}}firstKnownCursorSessionId(){for(const e of this.activeBySession.keys()){const t=this.sessionRuntime.get(e);if(t?.cursorSessionId)return t.cursorSessionId}for(const e of this.sessionRuntime.values())if(e.cursorSessionId)return e.cursorSessionId;return null}getUsageSnapshot(e){return this.lastUsageBySession.get(e)??null}getRateLimitsSnapshot(e){const t=this.cachedAccountRateLimits,n=e?this.lastContextBySession.get(e)??null:null;if(!t)return{adapterType:"cursor",available:!1,cached:!1,sampledAt:null,rateLimits:null,contextWindow:n,tokenUsage:null};const s=Date.parse(t.sampledAt);return{adapterType:"cursor",available:t.available&&!!t.rateLimits,cached:!0,sampledAt:Number.isFinite(s)?s:Date.now(),rateLimits:t.rateLimits,contextWindow:n,tokenUsage:null,...t.displayMessage?{displayMessage:t.displayMessage}:{},...t.error?{error:t.error}:{}}}async refreshAccountRateLimits(e){const t=e?.force===!0,n=this.cachedAccountRateLimits,s=n?Date.now()-Date.parse(n.sampledAt):Number.POSITIVE_INFINITY;if(!t&&n&&Number.isFinite(s)&&s<6e4||this.rateLimitsInflight&&(await this.rateLimitsInflight,!t))return;const i=(async()=>{const r=await me();this.cachedAccountRateLimits={available:r.available,sampledAt:r.sampledAt,rateLimits:r.rateLimits,displayMessage:r.displayMessage,error:r.error},r.available&&r.rateLimits?h.info("cursor-adapter",`[rate-limits] monthly=${r.rateLimits.fiveHour.usedPercentage.toFixed(1)}% api=${r.rateLimits.sevenDay.usedPercentage.toFixed(1)}% resetsAt=${r.rateLimits.fiveHour.resetsAt}`+(r.displayMessage?` msg=${r.displayMessage}`:"")):h.warn("cursor-adapter",`[rate-limits] unavailable: ${r.error??"unknown"}`)})();this.rateLimitsInflight=i.finally(()=>{this.rateLimitsInflight=null}),await this.rateLimitsInflight}getToolbarMeta(e){const t=this.config.options??{},n=e||String(t.aibotSessionId??""),s=n?this.sessionRuntime.get(n):void 0,i=String(s?.modelId||t.model||"auto"),r=C(s?.modeId||t.mode)??"full_auto",o={model_id:i,mode_id:r,currentModelId:i,currentModeId:r,available_models:this.availableModels,available_modes:this.availableModes},a=this.cachedAccountRateLimits?.rateLimits;if(a?.fiveHour||a?.sevenDay){const c=Date.parse(this.cachedAccountRateLimits?.sampledAt??"")||Date.now();o.rate_limits={...a.fiveHour?{fiveHour:a.fiveHour}:{},...a.sevenDay?{sevenDay:a.sevenDay}:{},sampledAt:c}}const l=n?this.lastContextBySession.get(n):void 0;return l&&(o.context_window={usedPercentage:l.usedPercentage,remainingPercentage:l.remainingPercentage,usedTokens:l.usedTokens,sizeTokens:l.sizeTokens}),o}notifyBindingReady(e){if(!this.callbacks.sendUpdateBindingCard)return;const t=this.config.options??{},n=e||String(t.aibotSessionId??"");if(!n)return;const s=this.sessionRuntime.get(n),i=String(s?.cwd||t.workspace||"");i&&this.callbacks.sendUpdateBindingCard(n,this.activeBySession.has(n)?"busy":"ready",i,this.getToolbarMeta(n))}buildPromptText(e){let t;!e.contextMessages||e.contextMessages.length===0?t=e.text:t=`${e.contextMessages.map(r=>`[${r.senderId}] ${r.content}`).join(`
10
10
  `)}
11
11
 
12
12
  [Current user message]
@@ -18,6 +18,6 @@ ${t}`);const s=this.pendingHandoffBySession.get(e.adapterSessionId);return s&&(t
18
18
  ${s}
19
19
 
20
20
  [Current user message]
21
- ${t}`),this.identity.injectOnce(e.adapterSessionId,t)}handleStdoutLineForActive(e,t){if(e.done)return;const n=t.trim();if(!n)return;e.lastIoAt=Date.now();const{event:s}=e;let i;try{i=JSON.parse(n)}catch{this.armActiveIdleTimer(e.request.adapterSessionId);return}const r=this.auditCaptures.get(s.event_id);if(r&&i&&typeof i=="object"&&r.push({sequence:r.length,observedAt:new Date().toISOString(),event:structuredClone(i)}),i?.type==="tool_call"){const l=String(i?.call_id??""),c=String(i?.subtype??"");l&&(c==="started"||c==="start"?(this.flushAssistantStreamBuffer(e),e.toolCallsInFlight.add(l),e.toolCallsStarted+=1,this.handleSpecialToolCallStarted(e,i)):H.has(c)&&e.toolCallsInFlight.delete(l))}this.armActiveIdleTimer(e.request.adapterSessionId);const o=Ie(i);o&&this.callbacks.sendRawEventEnvelope?.(s.event_id,s.session_id,o);const a=Ce(i,e.assistantTextEmitted);if(a&&this.enqueueAssistantStreamDelta(e,a),i?.type==="result"){e.sawResult=!0;const l=typeof i?.result=="string"?i.result.trim():"";l&&(e.assistantTextEmitted?l.startsWith(e.assistantTextEmitted)&&l.length>e.assistantTextEmitted.length&&this.enqueueAssistantStreamDelta(e,l.slice(e.assistantTextEmitted.length)):this.enqueueAssistantStreamDelta(e,l)),this.flushAssistantStreamBuffer(e);const c=String(i?.session_id??"").trim();if(c){const f=this.sessionRuntime.get(e.request.adapterSessionId)??{};f.cursorSessionId!==c&&this.transcriptPathBySession.delete(e.request.adapterSessionId),this.sessionRuntime.set(e.request.adapterSessionId,{...f,cursorSessionId:c}),this.bindingStore?.setAcpSessionId(e.request.adapterSessionId,c)}const u=i?.usage??{},p=this.lastUsageBySession.get(e.request.adapterSessionId);this.lastUsageBySession.set(e.request.adapterSessionId,{sampledAt:new Date().toISOString(),turns:(p?.turns??0)+1,total:{input:(p?.total.input??0)+Number(u.inputTokens??0),output:(p?.total.output??0)+Number(u.outputTokens??0),cacheRead:(p?.total.cacheRead??0)+Number(u.cacheReadTokens??0),cacheWrite:(p?.total.cacheWrite??0)+Number(u.cacheWriteTokens??0)}});const _=String((this.sessionRuntime.get(e.request.adapterSessionId)?.modelId??this.config.options?.model??"")||""),v=Math.max(1,(e.toolCallsStarted??0)+1),b=Number(u.inputTokens??0),m=Number(u.cacheReadTokens??0),y=Number(u.cacheWriteTokens??0),g=Se({inputTokens:b,cacheReadTokens:m,cacheWriteTokens:y},_,{apiRounds:v});g&&(this.lastContextBySession.set(e.request.adapterSessionId,g),h.info("cursor-adapter",`[context_window] used=${g.usedTokens} size=${g.sizeTokens} pct=${g.usedPercentage.toFixed(1)}% model=${_||"auto"} rawIn=${b} rawCache=${m} rawWrite=${y} apiRounds=${v}`))}}handleSpecialToolCallStarted(e,t){const n=z(t);if(X(n.toolName)){const s=we(n.toolInput);s?(e.seq+=1,this.callbacks.sendStreamChunk(e.event.event_id,e.event.session_id,s,e.seq,!1),h.info("cursor-adapter",`CreatePlan forwarded as stream text: event=${e.event.event_id} chars=${s.length}`)):(e.seq+=1,this.callbacks.sendStreamChunk(e.event.event_id,e.event.session_id,"[CreatePlan] \u65B9\u6848\u5185\u5BB9\u89E3\u6790\u5931\u8D25\uFF0C\u672A\u4E0B\u53D1\u6B63\u6587\u3002",e.seq,!1),h.warn("cursor-adapter",`CreatePlan missing plan body: event=${e.event.event_id}`));return}G(n.toolName)&&this.emitAskQuestionCard(e,n.toolInput)}emitAskQuestionCard(e,t){const n=e.event,s=ke(t);if(!s){e.seq+=1,this.callbacks.sendStreamChunk(n.event_id,n.session_id,"[AskQuestion] \u95EE\u9898\u5185\u5BB9\u89E3\u6790\u5931\u8D25\uFF0C\u672A\u4E0B\u53D1\u95EE\u9898\u5361\u3002",e.seq,!1),h.warn("cursor-adapter",`AskQuestion parse failed: event=${n.event_id}`);return}if(!this.callbacks.sendAgentQuestionCard){h.warn("cursor-adapter","AskQuestion skipped: sendAgentQuestionCard callback not wired");return}const i=te(),r=Date.now();this.pendingQuestionByRequestId.set(i,{eventId:n.event_id,sessionId:n.session_id,createdAt:r}),this.callbacks.sendAgentQuestionCard(n.event_id,n.session_id,{request_id:i,mode:"form",questions:s,expires_at:r+T}),h.info("cursor-adapter",`Sent agent_question card: request_id=${i} questions=${s.length} event=${n.event_id}`)}async handleQuestionReply(e){const t=e.params??{},n=String(t.request_id??"").trim();if(!n)return this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,"request_id_required","request_id is required"),{handled:!0,kind:"question_reply_no_id"};const s=this.pendingQuestionByRequestId.get(n),i=s?Date.now()-s.createdAt>T+3e4:!0;if(!s||i)return this.pendingQuestionByRequestId.delete(n),this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,"interaction_request_not_pending","The question is no longer pending; the reply was not delivered."),{handled:!0,kind:"question_reply_not_pending"};const r=t.resolution??{},o=String(r.type??"");if(o==="action"&&String(r.value??"")==="cancel")return this.pendingQuestionByRequestId.delete(n),this.callbacks.sendLocalActionResult(e.action_id,"ok",{request_id:n,resolution:"cancel"}),{handled:!0,kind:"question_reply_cancel"};let a="";return o==="text"?a=String(r.value??""):o==="map"&&(a=(Array.isArray(r.entries)?r.entries:[]).map(c=>c.value).join(", ")),a?(this.pendingQuestionByRequestId.delete(n),this.pendingQuestionAnswerBySession.set(s.sessionId,a),this.callbacks.sendLocalActionResult(e.action_id,"ok",{request_id:n,resolution:"answer"}),h.info("cursor-adapter",`Question reply cached for next prompt: request_id=${n} session=${s.sessionId}`),{handled:!0,kind:"question_reply"}):(this.pendingQuestionByRequestId.delete(n),this.callbacks.sendLocalActionResult(e.action_id,"ok",{request_id:n,resolution:"cancel"}),{handled:!0,kind:"question_reply_empty"})}enqueueAssistantStreamDelta(e,t){t&&(e.assistantTextEmitted+=t,e.streamBuffer+=t,e.streamBuffer.length>=_e&&this.flushAssistantStreamBuffer(e))}flushAssistantStreamBuffer(e){if(!e.streamBuffer)return;const t=e.streamBuffer;e.streamBuffer="",e.seq+=1,this.callbacks.sendStreamChunk(e.event.event_id,e.event.session_id,t,e.seq,!1,void 0,void 0)}shouldExtendByLiveness(e){const t=this.activeBySession.get(e);if(!t||t.done)return!1;const n=t.child?.pid;if(!n||!B(n)||t.sawResult)return!1;const s=Date.now(),i=s-t.lastIoAt,r=this.transcriptFreshMsForSession(e);if(i<Q||r!==null&&r<Q)return t.livenessExtendStartAt=s,h.info("cursor-adapter",`Liveness check: fresh progress for ${t.event.event_id} (ioAge=${i}ms, transcriptAge=${r??"n/a"}, toolsInFlight=${t.toolCallsInFlight.size}), extending`),!0;const a=t.livenessExtendStartAt??s;return t.livenessExtendStartAt===void 0&&(t.livenessExtendStartAt=a),s-a>O?(h.warn("cursor-adapter",`Liveness extension budget exhausted for ${t.event.event_id} (no progress for ${Math.round((s-a)/6e4)}min), allowing idle kill`),!1):(h.info("cursor-adapter",`Liveness check: turn in progress for ${t.event.event_id} (toolsInFlight=${t.toolCallsInFlight.size}, ioAge=${i}ms), extending`),!0)}transcriptFreshMsForSession(e){const t=this.sessionRuntime.get(e)?.cursorSessionId;if(!t)return null;let n=this.transcriptPathBySession.get(e);if(!n){const s=Y(t);if(!s)return null;this.transcriptPathBySession.set(e,s),n=s}try{return Date.now()-D(n).mtimeMs}catch{return this.transcriptPathBySession.delete(e),null}}hasPendingQuestionForSession(e){const t=Date.now();for(const[n,s]of this.pendingQuestionByRequestId)if(s.sessionId===e){if(t-s.createdAt>T){this.pendingQuestionByRequestId.delete(n);continue}return!0}return!1}armActiveIdleTimer(e){const t=this.activeBySession.get(e);!t||t.done||(t.idleTimer&&clearTimeout(t.idleTimer),t.idleTimer=setTimeout(()=>{if(t.done)return;if(this.hasPendingQuestionForSession(e)){h.info("cursor-adapter",`Idle timeout skipped: awaiting AskQuestion for ${t.event.event_id}, resetting timer`),this.armActiveIdleTimer(e);return}if(this.shouldExtendByLiveness(e)){this.armActiveIdleTimer(e);return}if(t.sawResult){h.warn("cursor-adapter",`Idle after result with no close \u2014 finishing as responded: event=${t.event.event_id} session=${e}`),this.killChildWithFallback(t.child),this.finishActive(e,"responded");return}const n=t.child?.pid,i=!!(n&&B(n))?`liveness budget exhausted after ${O/6e4}min`:"child process dead";h.error("cursor-adapter",`Idle timeout (${i}, toolsInFlight=${t.toolCallsInFlight.size}) \u2014 killing cursor child: event=${t.event.event_id} session=${e}`),this.killChildWithFallback(t.child),this.finishActive(e,"failed",`idle timeout: ${i}`)},ve),t.idleTimer.unref?.())}finishActive(e,t,n){const s=this.activeBySession.get(e);if(!s)return;s.done=!0,s.timer&&clearTimeout(s.timer),s.idleTimer&&clearTimeout(s.idleTimer),this.flushAssistantStreamBuffer(s),s.seq+=1;const i=String(s.event.quoted_message_id??"").trim()||void 0;this.callbacks.sendStreamChunk(s.event.event_id,s.event.session_id,"",s.seq,!0,void 0,i),h.info("cursor-adapter",`job finish: event=${s.event.event_id} session=${s.event.session_id} status=${t}${n?` msg=${n}`:""}`),this.snapshotAuditBoundary(s.event.event_id,e),this.emit("eventDone",s.event.event_id),this.callbacks.sendEventResult(s.event.event_id,t,n),t==="responded"?s.handle.emitDone({status:"completed"}):t==="canceled"?s.handle.emitDone({status:"canceled",error:n}):s.handle.emitDone({status:"failed",error:n}),this.activeBySession.delete(e),this.notifyBindingReady(e),this.tryStartNext(e)}snapshotAuditBoundary(e,t){const n=this.auditCaptures.get(e);if(!n)return;const s=this.sessionRuntime.get(t);this.completedAuditBoundaries.set(e,{adapterType:"cursor",providerSessionId:s?.cursorSessionId,cursorEvidence:{events:n}}),this.auditCaptures.delete(e)}shouldRetryWithoutContinue(e){if(!e.usedContinue||e.retryCount>0)return!1;const t=e.stderr.toLowerCase(),n=t.includes("resume")||t.includes("continue")||t.includes("chat")||t.includes("session"),s=t.includes("not found")||t.includes("no previous session")||t.includes("does not exist")||t.includes("invalid");return n&&s}ensureWorkspaceMcpAndSkills(e){if(!this.internalApi)return;this.ensureCursorMcpConfig(e,this.internalApi.url);const t=A(N(),".cursor","skills"),n=he(t);n.length>0&&h.info("cursor-adapter",`Synced connector skills to ${t}: [${n.join(", ")}]`)}ensureCursorMcpConfig(e,t){const n=le(this.callbacks.getAgentId?.()),s={command:process.execPath,args:[ne(ie(import.meta.url),"../../../mcp/acp-mcp-server.js"),"--api-url",t]},i=[e],r=this.resolveGitRoot(e);r&&r!==e&&i.push(r);let o=null;for(const a of i){const l=this.writeCursorMcpConfig(a,n,s,t);!o&&l&&(o=l)}o&&this.recordCursorMcpRegistry(e,o,s)}resolveGitRoot(e){try{return ee("git",["-C",e,"rev-parse","--show-toplevel"],{timeout:5e3,stdio:["ignore","pipe","ignore"]}).toString("utf8").trim()||null}catch{return null}}writeCursorMcpConfig(e,t,n,s){try{const i=A(e,".cursor"),r=A(i,"mcp.json");E(i,{recursive:!0});let o={};try{o=JSON.parse(L(r,"utf8"))}catch{o={}}(!o.mcpServers||typeof o.mcpServers!="object")&&(o.mcpServers={});const a=ce(o.mcpServers,s);return o.mcpServers[t]=n,P(r,`${JSON.stringify(o,null,2)}
22
- `,"utf8"),h.info("cursor-adapter",`MCP config synced: dir=${e} file=${r} server=${t}${a.length>0?` pruned=${a.join(",")}`:""}`),r}catch(i){return h.warn("cursor-adapter",`Failed to ensure ${A(e,".cursor","mcp.json")}: ${String(i)}`),null}}recordCursorMcpRegistry(e,t,n){try{const s=A(re.data,"cursor"),i=A(s,"mcp-registry.json");E(s,{recursive:!0});let r={};try{r=JSON.parse(L(i,"utf8"))}catch{r={}}r[e]={mcp_path:t,server:n,updated_at:new Date().toISOString()},P(i,`${JSON.stringify(r,null,2)}
23
- `,"utf8")}catch(s){h.warn("cursor-adapter",`Failed to record MCP registry: ${String(s)}`)}}}export{K as CURSOR_MODE_OPTIONS,x as CursorAdapter,Ce as extractCursorAssistantStreamDelta,Y as findCursorTranscript,we as formatCursorCreatePlanText,G as isCursorAskQuestionTool,X as isCursorCreatePlanTool,Ie as mapCursorStreamJsonToRawEnvelope,ke as parseCursorAskQuestionPayload};
21
+ ${t}`),this.identity.injectOnce(e.adapterSessionId,t)}handleStdoutLineForActive(e,t){if(e.done)return;const n=t.trim();if(!n)return;e.lastIoAt=Date.now();const{event:s}=e;let i;try{i=JSON.parse(n)}catch{this.armActiveIdleTimer(e.request.adapterSessionId);return}const r=this.auditCaptures.get(s.event_id);if(r&&i&&typeof i=="object"&&r.push({sequence:r.length,observedAt:new Date().toISOString(),event:structuredClone(i)}),i?.type==="tool_call"){const l=String(i?.call_id??""),c=String(i?.subtype??"");l&&(c==="started"||c==="start"?(this.flushAssistantStreamBuffer(e),e.toolCallsInFlight.add(l),e.toolCallsStarted+=1,this.handleSpecialToolCallStarted(e,i)):W.has(c)&&e.toolCallsInFlight.delete(l))}this.armActiveIdleTimer(e.request.adapterSessionId);const o=ke(i);o&&this.callbacks.sendRawEventEnvelope?.(s.event_id,s.session_id,o);const a=we(i,e.assistantTextEmitted);if(a&&this.enqueueAssistantStreamDelta(e,a),i?.type==="result"){e.sawResult=!0;const l=typeof i?.result=="string"?i.result.trim():"";l&&(e.assistantTextEmitted?l.startsWith(e.assistantTextEmitted)&&l.length>e.assistantTextEmitted.length&&this.enqueueAssistantStreamDelta(e,l.slice(e.assistantTextEmitted.length)):this.enqueueAssistantStreamDelta(e,l)),this.flushAssistantStreamBuffer(e);const c=String(i?.session_id??"").trim();if(c){const m=this.sessionRuntime.get(e.request.adapterSessionId)??{};m.cursorSessionId!==c&&this.transcriptPathBySession.delete(e.request.adapterSessionId),this.sessionRuntime.set(e.request.adapterSessionId,{...m,cursorSessionId:c}),this.bindingStore?.setAcpSessionId(e.request.adapterSessionId,c)}const u=i?.usage??{},p=this.lastUsageBySession.get(e.request.adapterSessionId);this.lastUsageBySession.set(e.request.adapterSessionId,{sampledAt:new Date().toISOString(),turns:(p?.turns??0)+1,total:{input:(p?.total.input??0)+Number(u.inputTokens??0),output:(p?.total.output??0)+Number(u.outputTokens??0),cacheRead:(p?.total.cacheRead??0)+Number(u.cacheReadTokens??0),cacheWrite:(p?.total.cacheWrite??0)+Number(u.cacheWriteTokens??0)}});const _=String((this.sessionRuntime.get(e.request.adapterSessionId)?.modelId??this.config.options?.model??"")||""),v=Math.max(1,(e.toolCallsStarted??0)+1),b=Number(u.inputTokens??0),f=Number(u.cacheReadTokens??0),y=Number(u.cacheWriteTokens??0),g=pe({inputTokens:b,cacheReadTokens:f,cacheWriteTokens:y},_,{apiRounds:v});g&&(this.lastContextBySession.set(e.request.adapterSessionId,g),h.info("cursor-adapter",`[context_window] used=${g.usedTokens} size=${g.sizeTokens} pct=${g.usedPercentage.toFixed(1)}% model=${_||"auto"} rawIn=${b} rawCache=${f} rawWrite=${y} apiRounds=${v}`))}}handleSpecialToolCallStarted(e,t){const n=U(t);if(J(n.toolName)){const s=be(n.toolInput);s?(e.seq+=1,this.callbacks.sendStreamChunk(e.event.event_id,e.event.session_id,s,e.seq,!1),h.info("cursor-adapter",`CreatePlan forwarded as stream text: event=${e.event.event_id} chars=${s.length}`)):(e.seq+=1,this.callbacks.sendStreamChunk(e.event.event_id,e.event.session_id,"[CreatePlan] \u65B9\u6848\u5185\u5BB9\u89E3\u6790\u5931\u8D25\uFF0C\u672A\u4E0B\u53D1\u6B63\u6587\u3002",e.seq,!1),h.warn("cursor-adapter",`CreatePlan missing plan body: event=${e.event.event_id}`));return}z(n.toolName)&&this.emitAskQuestionCard(e,n.toolInput)}emitAskQuestionCard(e,t){const n=e.event,s=Ae(t);if(!s){e.seq+=1,this.callbacks.sendStreamChunk(n.event_id,n.session_id,"[AskQuestion] \u95EE\u9898\u5185\u5BB9\u89E3\u6790\u5931\u8D25\uFF0C\u672A\u4E0B\u53D1\u95EE\u9898\u5361\u3002",e.seq,!1),h.warn("cursor-adapter",`AskQuestion parse failed: event=${n.event_id}`);return}if(!this.callbacks.sendAgentQuestionCard){h.warn("cursor-adapter","AskQuestion skipped: sendAgentQuestionCard callback not wired");return}const i=Z(),r=Date.now();this.pendingQuestionByRequestId.set(i,{eventId:n.event_id,sessionId:n.session_id,createdAt:r}),this.callbacks.sendAgentQuestionCard(n.event_id,n.session_id,{request_id:i,mode:"form",questions:s,expires_at:r+x}),h.info("cursor-adapter",`Sent agent_question card: request_id=${i} questions=${s.length} event=${n.event_id}`)}async handleQuestionReply(e){const t=e.params??{},n=String(t.request_id??"").trim();if(!n)return this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,"request_id_required","request_id is required"),{handled:!0,kind:"question_reply_no_id"};const s=this.pendingQuestionByRequestId.get(n),i=s?Date.now()-s.createdAt>x+3e4:!0;if(!s||i)return this.pendingQuestionByRequestId.delete(n),this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,"interaction_request_not_pending","The question is no longer pending; the reply was not delivered."),{handled:!0,kind:"question_reply_not_pending"};const r=t.resolution??{},o=String(r.type??"");if(o==="action"&&String(r.value??"")==="cancel")return this.pendingQuestionByRequestId.delete(n),this.callbacks.sendLocalActionResult(e.action_id,"ok",{request_id:n,resolution:"cancel"}),{handled:!0,kind:"question_reply_cancel"};let a="";return o==="text"?a=String(r.value??""):o==="map"&&(a=(Array.isArray(r.entries)?r.entries:[]).map(c=>c.value).join(", ")),a?(this.pendingQuestionByRequestId.delete(n),this.pendingQuestionAnswerBySession.set(s.sessionId,a),this.callbacks.sendLocalActionResult(e.action_id,"ok",{request_id:n,resolution:"answer"}),h.info("cursor-adapter",`Question reply cached for next prompt: request_id=${n} session=${s.sessionId}`),{handled:!0,kind:"question_reply"}):(this.pendingQuestionByRequestId.delete(n),this.callbacks.sendLocalActionResult(e.action_id,"ok",{request_id:n,resolution:"cancel"}),{handled:!0,kind:"question_reply_empty"})}enqueueAssistantStreamDelta(e,t){t&&(e.assistantTextEmitted+=t,e.streamBuffer+=t,e.streamBuffer.length>=ye&&this.flushAssistantStreamBuffer(e))}flushAssistantStreamBuffer(e){if(!e.streamBuffer)return;const t=e.streamBuffer;e.streamBuffer="",e.seq+=1,this.callbacks.sendStreamChunk(e.event.event_id,e.event.session_id,t,e.seq,!1,void 0,void 0)}shouldExtendByLiveness(e){const t=this.activeBySession.get(e);if(!t||t.done)return!1;const n=t.child?.pid;if(!n||!B(n)||t.sawResult)return!1;const s=Date.now(),i=s-t.lastIoAt,r=this.transcriptFreshMsForSession(e);if(i<F||r!==null&&r<F)return t.livenessExtendStartAt=s,h.info("cursor-adapter",`Liveness check: fresh progress for ${t.event.event_id} (ioAge=${i}ms, transcriptAge=${r??"n/a"}, toolsInFlight=${t.toolCallsInFlight.size}), extending`),!0;const a=t.livenessExtendStartAt??s;return t.livenessExtendStartAt===void 0&&(t.livenessExtendStartAt=a),s-a>j?(h.warn("cursor-adapter",`Liveness extension budget exhausted for ${t.event.event_id} (no progress for ${Math.round((s-a)/6e4)}min), allowing idle kill`),!1):(h.info("cursor-adapter",`Liveness check: turn in progress for ${t.event.event_id} (toolsInFlight=${t.toolCallsInFlight.size}, ioAge=${i}ms), extending`),!0)}transcriptFreshMsForSession(e){const t=this.sessionRuntime.get(e)?.cursorSessionId;if(!t)return null;let n=this.transcriptPathBySession.get(e);if(!n){const s=K(t);if(!s)return null;this.transcriptPathBySession.set(e,s),n=s}try{return Date.now()-D(n).mtimeMs}catch{return this.transcriptPathBySession.delete(e),null}}hasPendingQuestionForSession(e){const t=Date.now();for(const[n,s]of this.pendingQuestionByRequestId)if(s.sessionId===e){if(t-s.createdAt>x){this.pendingQuestionByRequestId.delete(n);continue}return!0}return!1}armActiveIdleTimer(e){const t=this.activeBySession.get(e);!t||t.done||(t.idleTimer&&clearTimeout(t.idleTimer),t.idleTimer=setTimeout(()=>{if(t.done)return;if(this.hasPendingQuestionForSession(e)){h.info("cursor-adapter",`Idle timeout skipped: awaiting AskQuestion for ${t.event.event_id}, resetting timer`),this.armActiveIdleTimer(e);return}if(this.shouldExtendByLiveness(e)){this.armActiveIdleTimer(e);return}if(t.sawResult){h.warn("cursor-adapter",`Idle after result with no close \u2014 finishing as responded: event=${t.event.event_id} session=${e}`),this.killChildWithFallback(t.child),this.finishActive(e,"responded");return}const n=t.child?.pid,i=!!(n&&B(n))?`liveness budget exhausted after ${j/6e4}min`:"child process dead";h.error("cursor-adapter",`Idle timeout (${i}, toolsInFlight=${t.toolCallsInFlight.size}) \u2014 killing cursor child: event=${t.event.event_id} session=${e}`),this.killChildWithFallback(t.child),this.finishActive(e,"failed",`idle timeout: ${i}`)},Se),t.idleTimer.unref?.())}finishActive(e,t,n){const s=this.activeBySession.get(e);if(!s)return;s.done=!0,s.timer&&clearTimeout(s.timer),s.idleTimer&&clearTimeout(s.idleTimer),this.flushAssistantStreamBuffer(s),s.seq+=1;const i=String(s.event.quoted_message_id??"").trim()||void 0;this.callbacks.sendStreamChunk(s.event.event_id,s.event.session_id,"",s.seq,!0,void 0,i),h.info("cursor-adapter",`job finish: event=${s.event.event_id} session=${s.event.session_id} status=${t}${n?` msg=${n}`:""}`),this.snapshotAuditBoundary(s.event.event_id,e),this.emit("eventDone",s.event.event_id),this.callbacks.sendEventResult(s.event.event_id,t,n),t==="responded"?s.handle.emitDone({status:"completed"}):t==="canceled"?s.handle.emitDone({status:"canceled",error:n}):s.handle.emitDone({status:"failed",error:n}),this.activeBySession.delete(e),this.notifyBindingReady(e),this.tryStartNext(e)}snapshotAuditBoundary(e,t){const n=this.auditCaptures.get(e);if(!n)return;const s=this.sessionRuntime.get(t);this.completedAuditBoundaries.set(e,{adapterType:"cursor",providerSessionId:s?.cursorSessionId,cursorEvidence:{events:n}}),this.auditCaptures.delete(e)}shouldRetryWithoutContinue(e){if(!e.usedContinue||e.retryCount>0)return!1;const t=e.stderr.toLowerCase(),n=t.includes("resume")||t.includes("continue")||t.includes("chat")||t.includes("session"),s=t.includes("not found")||t.includes("no previous session")||t.includes("does not exist")||t.includes("invalid");return n&&s}ensureWorkspaceMcpAndSkills(e){if(!this.internalApi)return;this.ensureCursorMcpConfig(e,this.internalApi.url);const t=A(N(),".cursor","skills"),n=ce(t);n.length>0&&h.info("cursor-adapter",`Synced connector skills to ${t}: [${n.join(", ")}]`)}ensureCursorMcpConfig(e,t){const n=ae(this.callbacks.getAgentId?.()),s={command:process.execPath,args:[te(se(import.meta.url),"../../../mcp/acp-mcp-server.js"),"--api-url",t]},i=[e],r=this.resolveGitRoot(e);r&&r!==e&&i.push(r);let o=null;for(const a of i){const l=this.writeCursorMcpConfig(a,n,s,t);!o&&l&&(o=l)}o&&this.recordCursorMcpRegistry(e,o,s)}resolveGitRoot(e){try{return Y("git",["-C",e,"rev-parse","--show-toplevel"],{timeout:5e3,stdio:["ignore","pipe","ignore"],windowsHide:!0}).toString("utf8").trim()||null}catch{return null}}writeCursorMcpConfig(e,t,n,s){try{const i=A(e,".cursor"),r=A(i,"mcp.json");E(i,{recursive:!0});let o={};try{o=JSON.parse(L(r,"utf8"))}catch{o={}}(!o.mcpServers||typeof o.mcpServers!="object")&&(o.mcpServers={});const a=de(o.mcpServers,s);return o.mcpServers[t]=n,P(r,`${JSON.stringify(o,null,2)}
22
+ `,"utf8"),h.info("cursor-adapter",`MCP config synced: dir=${e} file=${r} server=${t}${a.length>0?` pruned=${a.join(",")}`:""}`),r}catch(i){return h.warn("cursor-adapter",`Failed to ensure ${A(e,".cursor","mcp.json")}: ${String(i)}`),null}}recordCursorMcpRegistry(e,t,n){try{const s=A(ne.data,"cursor"),i=A(s,"mcp-registry.json");E(s,{recursive:!0});let r={};try{r=JSON.parse(L(i,"utf8"))}catch{r={}}r[e]={mcp_path:t,server:n,updated_at:new Date().toISOString()},P(i,`${JSON.stringify(r,null,2)}
23
+ `,"utf8")}catch(s){h.warn("cursor-adapter",`Failed to record MCP registry: ${String(s)}`)}}}export{G as CURSOR_MODE_OPTIONS,T as CursorAdapter,we as extractCursorAssistantStreamDelta,K as findCursorTranscript,be as formatCursorCreatePlanText,z as isCursorAskQuestionTool,J as isCursorCreatePlanTool,ke as mapCursorStreamJsonToRawEnvelope,Ae as parseCursorAskQuestionPayload};
@@ -1,2 +1,2 @@
1
- import{JsonRpcTransport as y}from"../../core/transport/json-rpc.js";import{log as c}from"../../core/log/index.js";import{killProcessGroup as g,resolveCommandPath as w,spawnCommand as h}from"../../core/runtime/spawn.js";const E=3e4,u="none|low|medium|high|xhigh|extra-high|max";function M(o,e){const t=o.trim(),r=e.trim();return t==="default"||t==="default[]"||/^default\[.*\]$/.test(t)?{id:"auto",displayName:!r||r==="default"||r==="Auto"?"Auto (default)":r}:{id:t,displayName:r||t}}function v(o){const e=o.trim();if(!e||e==="auto"||e==="default"||e==="default[]")return"auto";let t=e;return t=t.replace(new RegExp(`-thinking-(?:${u})(?:-fast)?$`),""),t=t.replace(new RegExp(`-(?:${u})-thinking$`),""),t=t.replace(/-thinking(?:-fast)?$/,""),t=t.replace(new RegExp(`-(?:${u})(?:-fast)?$`),""),t=t.replace(/-fast$/,""),t||e}function T(o){let e=o.trim();e=e.replace(/\s*\(default\)\s*$/i,""),e=e.replace(/\s*\(NO ZDR\)\s*$/i,"");const t=/(?:\s+(?:None|Low|Medium|High|Extra High|Max|Fast|Thinking|1M))$/i;for(let r=0;r<8&&t.test(e);r++)e=e.replace(t,"").trim();return e||o.trim()}function $(o){const e=[];for(const t of o.split(`
2
- `)){const r=t.trim();if(!r||r.toLowerCase().includes("available model")||r.toLowerCase().startsWith("tip:"))continue;const n=r.match(/^(\S+)\s+-\s+(.+)$/);n&&e.push({id:n[1],displayName:n[2].trim()})}return e}function A(o){const e=new Set,t=[];for(const r of o){const n=v(r.id);if(e.has(n))continue;e.add(n);const s=n==="auto"?"Auto (default)":T(r.displayName);t.push({id:n,displayName:s})}return t}async function I(o){return new Promise(e=>{let t="";o.stdout?.on("data",r=>{t+=String(r)}),o.once("close",()=>e(t)),o.once("error",()=>e(t))})}async function C(o){const e={...process.env,...o.env??{}},t=w(o.command,typeof e.PATH=="string"?e.PATH:void 0),{process:r}=h(t,["models"],{cwd:o.cwd??process.cwd(),env:e,stdio:["ignore","pipe","pipe"]}),n=await I(r);return $(n)}async function k(o){const e=await C(o);return A(e)}async function P(o){const e=o.timeoutMs??E,t=o.cwd??process.cwd(),r={...process.env,...o.env??{}},n=w(o.command,typeof r.PATH=="string"?r.PATH:void 0),{process:s}=h(n,["acp"],{cwd:t,env:r,stdio:["pipe","pipe","pipe"]});if(!s.stdout||!s.stdin)throw g(s,"SIGTERM"),new Error("cursor acp spawn missing stdio pipes");const a=new y(s.stdout,s.stdin);a.setHandlers(void 0,(d,m)=>{String(d).startsWith("cursor/")?a.respondSuccess(m,{}):a.respondError(m,-32601,"method not implemented")});const l=new AbortController,x=setTimeout(()=>l.abort(),e),p=d=>{l.abort(d)};s.once("error",p);try{await a.call("initialize",{protocolVersion:1,clientCapabilities:{fs:{readTextFile:!1,writeTextFile:!1}},clientInfo:{name:"grix-connector",version:"0"}},l.signal);const f=((await a.call("session/new",{cwd:t,mcpServers:[]},l.signal)).models?.availableModels??[]).filter(i=>typeof i.modelId=="string"&&i.modelId.length>0).map(i=>M(i.modelId,i.name??i.modelId));if(f.length===0)throw new Error("cursor acp session/new returned no models");return f}finally{clearTimeout(x),s.off("error",p);try{a.close()}catch{}g(s,"SIGTERM")}}async function L(o){try{const e=await C(o);if(e.length>0)return c.info("cursor-adapter",`Loaded ${e.length} models via CLI agent models`),e;c.warn("cursor-adapter","CLI agent models returned empty list, falling back to ACP")}catch(e){const t=e instanceof Error?e.message:String(e);c.warn("cursor-adapter",`CLI agent models failed, falling back to ACP: ${t}`)}try{const e=await P(o);return c.info("cursor-adapter",`Loaded ${e.length} parameterized models via acp fallback`),e}catch(e){const t=e instanceof Error?e.message:String(e);return c.warn("cursor-adapter",`ACP model fallback failed: ${t}`),[]}}export{T as collapseCursorDisplayName,v as collapseCursorModelId,A as collapseExplodedCursorModels,k as fetchCollapsedModelsFromCli,L as fetchCursorParameterizedModels,P as fetchCursorParameterizedModelsViaAcp,C as fetchExplodedModelsFromCli,M as normalizeCursorAvailableModel,$ as parseExplodedCursorModels};
1
+ import{JsonRpcTransport as v}from"../../core/transport/json-rpc.js";import{log as c}from"../../core/log/index.js";import{killProcessGroup as g,spawnCommand as w}from"../../core/runtime/spawn.js";import{resolveCursorSpawn as h}from"./resolve-command.js";const E=3e4,u="none|low|medium|high|xhigh|extra-high|max";function y(o,e){const t=o.trim(),r=e.trim();return t==="default"||t==="default[]"||/^default\[.*\]$/.test(t)?{id:"auto",displayName:!r||r==="default"||r==="Auto"?"Auto (default)":r}:{id:t,displayName:r||t}}function M(o){const e=o.trim();if(!e||e==="auto"||e==="default"||e==="default[]")return"auto";let t=e;return t=t.replace(new RegExp(`-thinking-(?:${u})(?:-fast)?$`),""),t=t.replace(new RegExp(`-(?:${u})-thinking$`),""),t=t.replace(/-thinking(?:-fast)?$/,""),t=t.replace(new RegExp(`-(?:${u})(?:-fast)?$`),""),t=t.replace(/-fast$/,""),t||e}function $(o){let e=o.trim();e=e.replace(/\s*\(default\)\s*$/i,""),e=e.replace(/\s*\(NO ZDR\)\s*$/i,"");const t=/(?:\s+(?:None|Low|Medium|High|Extra High|Max|Fast|Thinking|1M))$/i;for(let r=0;r<8&&t.test(e);r++)e=e.replace(t,"").trim();return e||o.trim()}function A(o){const e=[];for(const t of o.split(`
2
+ `)){const r=t.trim();if(!r||r.toLowerCase().includes("available model")||r.toLowerCase().startsWith("tip:"))continue;const s=r.match(/^(\S+)\s+-\s+(.+)$/);s&&e.push({id:s[1],displayName:s[2].trim()})}return e}function I(o){const e=new Set,t=[];for(const r of o){const s=M(r.id);if(e.has(s))continue;e.add(s);const n=s==="auto"?"Auto (default)":$(r.displayName);t.push({id:s,displayName:n})}return t}async function S(o){return new Promise(e=>{let t="";o.stdout?.on("data",r=>{t+=String(r)}),o.once("close",()=>e(t)),o.once("error",()=>e(t))})}async function x(o){const e={...process.env,...o.env??{}},t=h(o.command,e),{process:r}=w(t.command,[...t.prefixArgs,"models"],{cwd:o.cwd??process.cwd(),env:t.env,stdio:["ignore","pipe","pipe"]}),s=await S(r);return A(s)}async function F(o){const e=await x(o);return I(e)}async function T(o){const e=o.timeoutMs??E,t=o.cwd??process.cwd(),r={...process.env,...o.env??{}},s=h(o.command,r),{process:n}=w(s.command,[...s.prefixArgs,"acp"],{cwd:t,env:s.env,stdio:["pipe","pipe","pipe"]});if(!n.stdout||!n.stdin)throw g(n,"SIGTERM"),new Error("cursor acp spawn missing stdio pipes");const a=new v(n.stdout,n.stdin);a.setHandlers(void 0,(d,m)=>{String(d).startsWith("cursor/")?a.respondSuccess(m,{}):a.respondError(m,-32601,"method not implemented")});const l=new AbortController,C=setTimeout(()=>l.abort(),e),p=d=>{l.abort(d)};n.once("error",p);try{await a.call("initialize",{protocolVersion:1,clientCapabilities:{fs:{readTextFile:!1,writeTextFile:!1}},clientInfo:{name:"grix-connector",version:"0"}},l.signal);const f=((await a.call("session/new",{cwd:t,mcpServers:[]},l.signal)).models?.availableModels??[]).filter(i=>typeof i.modelId=="string"&&i.modelId.length>0).map(i=>y(i.modelId,i.name??i.modelId));if(f.length===0)throw new Error("cursor acp session/new returned no models");return f}finally{clearTimeout(C),n.off("error",p);try{a.close()}catch{}g(n,"SIGTERM")}}async function P(o){try{const e=await x(o);if(e.length>0)return c.info("cursor-adapter",`Loaded ${e.length} models via CLI agent models`),e;c.warn("cursor-adapter","CLI agent models returned empty list, falling back to ACP")}catch(e){const t=e instanceof Error?e.message:String(e);c.warn("cursor-adapter",`CLI agent models failed, falling back to ACP: ${t}`)}try{const e=await T(o);return c.info("cursor-adapter",`Loaded ${e.length} parameterized models via acp fallback`),e}catch(e){const t=e instanceof Error?e.message:String(e);return c.warn("cursor-adapter",`ACP model fallback failed: ${t}`),[]}}export{$ as collapseCursorDisplayName,M as collapseCursorModelId,I as collapseExplodedCursorModels,F as fetchCollapsedModelsFromCli,P as fetchCursorParameterizedModels,T as fetchCursorParameterizedModelsViaAcp,x as fetchExplodedModelsFromCli,y as normalizeCursorAvailableModel,A as parseExplodedCursorModels};
@@ -1 +1 @@
1
- import{existsSync as d,readdirSync as u}from"node:fs";import{dirname as p,join as i}from"node:path";const m=/^\d{4}\.\d{1,2}\.\d{1,2}(-\d{2}-\d{2}-\d{2})?-[a-f0-9]+$/;function f(r){const n=r.split("-")[0],[e,o,s]=n.split(".");return!e||!o||!s?0:Number(e+o.padStart(2,"0")+s.padStart(2,"0"))}function x(r){const n={command:r,prefixArgs:[],viaNode:!1};if(process.platform!=="win32"||!/\.cmd$/i.test(r))return n;try{const e=p(r),o=i(e,"versions"),s=u(o,{withFileTypes:!0}).filter(t=>t.isDirectory()&&m.test(t.name)).map(t=>t.name).sort((t,a)=>f(a)-f(t));for(const t of s){const a=i(o,t,"node.exe"),c=i(o,t,"index.js");if(d(a)&&d(c))return{command:a,prefixArgs:[c],viaNode:!0}}}catch{}return n}function A(r,n){if(!n.viaNode)return r;const e={...r};return e.CURSOR_INVOKED_AS??="cursor-agent",e.NODE_COMPILE_CACHE??=i(r.LOCALAPPDATA??i(r.USERPROFILE??"","AppData","Local"),"cursor-compile-cache"),e}export{x as resolveCursorCommand,A as withCursorShimEnv};
1
+ import{existsSync as d,readdirSync as u}from"node:fs";import{dirname as p,join as i}from"node:path";import{resolveCommandPath as m}from"../../core/runtime/spawn.js";const l=/^\d{4}\.\d{1,2}\.\d{1,2}(-\d{2}-\d{2}-\d{2})?-[a-f0-9]+$/;function f(r){const t=r.split("-")[0],[e,n,s]=t.split(".");return!e||!n||!s?0:Number(e+n.padStart(2,"0")+s.padStart(2,"0"))}function A(r){const t={command:r,prefixArgs:[],viaNode:!1};if(process.platform!=="win32"||!/\.cmd$/i.test(r))return t;try{const e=p(r),n=i(e,"versions"),s=u(n,{withFileTypes:!0}).filter(o=>o.isDirectory()&&l.test(o.name)).map(o=>o.name).sort((o,a)=>f(a)-f(o));for(const o of s){const a=i(n,o,"node.exe"),c=i(n,o,"index.js");if(d(a)&&d(c))return{command:a,prefixArgs:[c],viaNode:!0}}}catch{}return t}function x(r,t){if(!t.viaNode)return r;const e={...r};return e.CURSOR_INVOKED_AS??="cursor-agent",e.NODE_COMPILE_CACHE??=i(r.LOCALAPPDATA??i(r.USERPROFILE??"","AppData","Local"),"cursor-compile-cache"),e}function C(r,t){const e=A(m(r,typeof t.PATH=="string"?t.PATH:void 0));return{...e,env:x(t,e)}}export{A as resolveCursorCommand,C as resolveCursorSpawn,x as withCursorShimEnv};
@@ -0,0 +1,6 @@
1
+ import{resolveCommandPath as f,spawnCommand as T}from"../../core/runtime/spawn.js";import{createInterface as w}from"node:readline";import{EventEmitter as I}from"node:events";import{formatInboundMessageReferenceText as _}from"../../core/protocol/message-reference.js";import{log as o}from"../../core/log/index.js";import{SessionBindingStore as E}from"../../core/persistence/session-binding-store.js";const S=120*1e3;class y extends I{type="deepseek";config;callbacks;alive=!1;stopped=!1;deepSeekSessionId=null;activeEventId=null;activeSessionId=null;chunkSeq=0;activeClientMsgId=null;idleTimer=null;activeProcess=null;composingTimer=null;composingTTLClear=null;composingTTL=12e4;composingRefreshInterval=3e4;bindingStore=null;aibotSessionId="";cwd;lastUsage=null;currentModel=null;constructor(e,s){super(),this.config=e,this.callbacks=s;const t=e.options??{};if(this.aibotSessionId=String(t.aibotSessionId??"").trim(),this.bindingStore=t.bindingStore instanceof E?t.bindingStore:null,this.cwd=this.resolveCwd(),this.bindingStore&&this.aibotSessionId){const i=this.bindingStore.getDeepSeekThreadId(this.aibotSessionId);i&&(this.deepSeekSessionId=i)}}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,this.notifyBindingReady(),o.info("deepseek-adapter","Ready (exec mode)")}async stop(){this.stopped=!0,this.alive=!1,this.stopComposing(),this.clearIdleTimer(),this.killActiveProcess()}isAlive(){return this.alive}async createSession(e){const s=this.deepSeekSessionId??`ds-${Date.now()}`;return this.notifyBindingReady(),s}async resumeSession(e,s){}async destroySession(e){this.deepSeekSessionId=null,this.persistSessionId(void 0)}sendPrompt(e){const s=new k(e.adapterSessionId);return this.runMessage(e,s).catch(t=>{s.emitError(t instanceof Error?t:new Error(String(t)))}),s}async cancel(e){this.killActiveProcess()}setPermissionHandler(e){}async ping(e){return this.alive}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=null}getMcpConfig(){return null}getUsageSnapshot(){return this.lastUsage}getSupportedCommands(){return[{name:"status",description:"Show session and working directory status"}]}async execCommand(e,s,t){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 s=e.action_type??"",t=e.params??{};switch(s){case"get_context":return this.callbacks.sendLocalActionResult(e.action_id,"ok",{sessionId:this.deepSeekSessionId,cwd:this.cwd,model:this.currentModel}),{handled:!0,kind:"get_context"};case"set_model":{const i=String(t.model_id??"").trim();return i?(this.currentModel=i,this.callbacks.sendLocalActionResult(e.action_id,"ok",{outcome:"model_set",modelId:i}),o.info("deepseek-adapter",`Model set to: ${i}`),{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:""}}}deliverInboundEvent(e){const s=_(e.content,{messageId:e.msg_id,quotedMessageId:e.quoted_message_id});if(this.activeEventId){o.info("deepseek-adapter",`Event ${e.event_id}: rejected, busy with ${this.activeEventId}`),this.callbacks.sendEventResult(e.event_id,"failed","agent busy");return}this.startNewMessage(e,s)}deliverStopEvent(e,s){this.activeEventId===e&&(this.callbacks.sendEventResult(e,"canceled","stopped by user"),this.clearActive())}startNewMessage(e,s){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.startComposing();const t={adapterSessionId:this.deepSeekSessionId??"",text:s,contextMessages:e.context_messages_json?JSON.parse(e.context_messages_json).map(n=>({senderId:n.sender_id??"unknown",content:n.content})):void 0},i=new k(this.deepSeekSessionId??"");this.runMessage(t,i,e.event_id,e.session_id).catch(n=>{o.error("deepseek-adapter",`Message failed: ${n}`),this.callbacks.sendEventResult(e.event_id,"failed",n instanceof Error?n.message:String(n)),this.clearActive()}),this.resetIdleTimer(e.event_id)}buildExecArgs(e){const s=["exec","--output-format","stream-json"];return this.currentModel&&s.push("--model",this.currentModel),this.deepSeekSessionId&&s.push("--resume",this.deepSeekSessionId),s.push("--",e),s}async runMessage(e,s,t,i){let n=e.text;e.contextMessages&&e.contextMessages.length>0&&(n=`Conversation context:
2
+ ${e.contextMessages.map(c=>`[${c.senderId??"unknown"}]: ${c.content}`).join(`
3
+ `)}
4
+
5
+ Latest user message:
6
+ ${n}`);const h=this.config.command||"codewhale",d=this.buildExecArgs(n),u={...process.env,...this.config.env},g=f(h,typeof u.PATH=="string"?u.PATH:void 0);o.info("deepseek-adapter",`Spawning: ${g} ${d.slice(0,5).join(" ")}...`);const r=T(g,d,{cwd:this.cwd,env:u}).process;return this.activeProcess=r,r.stderr?.on("data",c=>{const l=c.toString().trim();l&&o.info("deepseek-adapter",`[deepseek stderr] ${l}`)}),new Promise((c,l)=>{let p=!1,m="";const v=()=>{this.activeProcess=null};r.on("error",a=>{p||(p=!0,v(),l(a))}),r.on("exit",a=>{if(m.trim()&&this.handleOutputLine(m.trim(),t),m="",p){v();return}if(p=!0,v(),a!==0&&t&&this.activeEventId===t){l(new Error(`deepseek exec exited with code ${a}`));return}s.emitDone({status:"completed"}),c()}),w({input:r.stdout}).on("line",a=>{a.trim()&&this.handleOutputLine(a.trim(),t)}),r.stdin?.end()})}handleOutputLine(e,s){let t;try{t=JSON.parse(e)}catch{o.error("deepseek-adapter",`Invalid JSON: ${e.slice(0,200)}`);return}switch(t.type){case"content":{const i=t.content;i&&s&&this.activeEventId===s&&this.activeSessionId&&(this.chunkSeq++,this.callbacks.sendStreamChunk(s,this.activeSessionId,i,this.chunkSeq,!1,this.activeClientMsgId??void 0),this.startComposing(),this.resetIdleTimer(s));break}case"session_capture":{const i=t.content;i&&(this.deepSeekSessionId=i,this.persistSessionId(i),o.info("deepseek-adapter",`Session captured: ${i}`));break}case"metadata":{const i=t.meta;if(i){o.info("deepseek-adapter",`Metadata: model=${i.model}, tokens_in=${i.input_tokens}, tokens_out=${i.output_tokens}`);const n=Number(i.input_tokens??0),h=Number(i.output_tokens??0);if(n>0||h>0){const d=this.lastUsage;this.lastUsage={sampledAt:new Date().toISOString(),turns:(d?.turns??0)+1,total:{input:(d?.total.input??0)+n,output:(d?.total.output??0)+h}}}}break}case"tool_use":{const i=t.name,n=typeof t.input=="string"?t.input:JSON.stringify(t.input??{});i&&s&&this.activeEventId===s&&this.activeSessionId&&(o.info("deepseek-adapter",`Tool use: ${i}`),this.callbacks.sendToolUse(s,this.activeSessionId,i,n),this.resetIdleTimer(s));break}case"tool_result":{const i=t.name,n=t.output;s&&this.activeEventId===s&&this.activeSessionId&&(this.callbacks.sendToolResult(s,this.activeSessionId,i??"unknown",n??""),this.resetIdleTimer(s));break}case"done":{this.handleMessageCompleted(s);break}default:break}}handleMessageCompleted(e){if(this.stopComposing(),e&&this.activeEventId===e){const s=this.activeSessionId??"",t=this.activeClientMsgId??void 0;s&&(this.chunkSeq++,this.callbacks.sendStreamChunk(e,s,"",this.chunkSeq,!0,t)),this.callbacks.sendEventResult(e,"responded"),this.clearActive()}}killActiveProcess(){const e=this.activeProcess;if(this.activeProcess=null,e?.pid)try{e.kill("SIGTERM")}catch{}}notifyBindingReady(){!this.aibotSessionId||!this.cwd||this.callbacks.sendUpdateBindingCard(this.aibotSessionId,"ready",this.cwd)}persistSessionId(e){!this.bindingStore||!this.aibotSessionId||this.bindingStore.setDeepSeekThreadId(this.aibotSessionId,e)}startComposing(){if(!this.activeSessionId||this.composingTimer)return;this.stopComposing();const e=this.activeSessionId,s={ttl_ms:this.composingTTL};this.callbacks.sendSessionActivitySet(e,"composing",!0,s),this.composingTimer=setInterval(()=>{this.callbacks.sendSessionActivitySet(e,"composing",!0,s)},this.composingRefreshInterval),this.composingTTLClear=setTimeout(()=>{this.stopComposing()},this.composingTTL)}stopComposing(){this.composingTimer&&(clearInterval(this.composingTimer),this.composingTimer=null),this.composingTTLClear&&(clearTimeout(this.composingTTLClear),this.composingTTLClear=null),this.activeSessionId&&this.callbacks.sendSessionActivitySet(this.activeSessionId,"composing",!1)}resetIdleTimer(e){this.clearIdleTimer(),this.idleTimer=setTimeout(()=>{this.activeEventId===e&&(o.error("deepseek-adapter",`Agent idle for ${S/1e3}s: ${e}`),this.killActiveProcess(),this.callbacks.sendEventResult(e,"failed",`agent idle for ${S/1e3}s`),this.clearActive(),this.emit("stuck"))},S)}clearIdleTimer(){this.idleTimer&&(clearTimeout(this.idleTimer),this.idleTimer=null)}clearActive(){const e=this.activeEventId;this.stopComposing(),this.activeEventId=null,this.activeSessionId=null,this.chunkSeq=0,this.activeClientMsgId=null,this.clearIdleTimer(),e&&this.emit("eventDone",e)}}class k extends I{adapterSessionId;constructor(e){super(),this.adapterSessionId=e}emitDone(e){this.emit("done",e)}emitError(e){if(this.listenerCount("error")===0){o.warn("deepseek-adapter",`Prompt handle error (no listeners): ${e.message}`);return}this.emit("error",e)}async cancel(){}}export{y as DeepSeekAdapter};
@@ -0,0 +1 @@
1
+ import{DeepSeekAdapter as e}from"./deepseek-adapter.js";export{e as DeepSeekAdapter};