@codeneter/cli 0.10.3 → 0.10.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/codeneter.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -32,14 +32,14 @@ To run one prompt without opening the interactive UI:
|
|
|
32
32
|
codeneter run --prompt "Review this project and summarize the main risks"
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
## Common
|
|
35
|
+
## Common Commands
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
38
|
codeneter # Start the interactive terminal UI
|
|
39
39
|
codeneter run -p "..." # Run a single prompt
|
|
40
40
|
codeneter update # Check for CLI updates
|
|
41
41
|
codeneter --version # Print the installed CLI version
|
|
42
|
-
codeneter --help # Show all
|
|
42
|
+
codeneter --help # Show all commands and options
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
## Interactive Slash Commands
|
package/dist/codeneter.js
CHANGED
|
@@ -530,7 +530,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
530
530
|
`;break;case"id":d=B.includes("\0")?void 0:B;break;case"retry":/^\d+$/.test(B)?r(parseInt(B,10)):n(new eM(`Invalid \`retry\` value: "${B}"`,{type:"invalid-retry",value:B,line:K}));break;default:n(new eM(`Unknown field "${x.length>20?`${x.slice(0,20)}\u2026`:x}"`,{type:"unknown-field",field:x,value:B,line:K}));break}}function N(){m.length>0&&t({id:d,event:A||void 0,data:m.endsWith(`
|
|
531
531
|
`)?m.slice(0,-1):m}),d=void 0,m="",A=""}function D(x={}){a&&x.consume&&v(a),l=!0,d=void 0,m="",A="",a=""}return{feed:E,reset:D}}function zFe(e){let t=[],n="",r=0;for(;r<e.length;){let i=e.indexOf("\r",r),a=e.indexOf(`
|
|
532
532
|
`,r),l=-1;if(i!==-1&&a!==-1?l=Math.min(i,a):i!==-1?i===e.length-1?l=-1:l=i:a!==-1&&(l=a),l===-1){n=e.slice(r);break}else{let d=e.slice(r,l);t.push(d),r=l+1,e[r-1]==="\r"&&e[r]===`
|
|
533
|
-
`&&r++}}return[t,n]}var tM=class extends TransformStream{constructor({onError:t,onRetry:n,onComment:r}={}){let i;super({start(a){i=joe({onEvent:l=>{a.enqueue(l)},onError(l){t==="terminate"?a.error(l):typeof t=="function"&&t(l)},onRetry:n,onComment:r})},transform(a){i.feed(a)}})}};var $Fe={initialReconnectionDelay:1e3,maxReconnectionDelay:3e4,reconnectionDelayGrowFactor:1.5,maxRetries:2},Xh=class extends Error{constructor(t,n){super(`Streamable HTTP error: ${n}`),this.code=t}},nM=class{constructor(t,n){this._hasCompletedAuthFlow=!1,this._url=t,this._resourceMetadataUrl=void 0,this._scope=void 0,this._requestInit=n?.requestInit,this._authProvider=n?.authProvider,this._fetch=n?.fetch,this._fetchWithInit=Moe(n?.fetch,n?.requestInit),this._sessionId=n?.sessionId,this._reconnectionOptions=n?.reconnectionOptions??$Fe}async _authThenStart(){if(!this._authProvider)throw new MA("No auth provider");let t;try{t=await nN(this._authProvider,{serverUrl:this._url,resourceMetadataUrl:this._resourceMetadataUrl,scope:this._scope,fetchFn:this._fetchWithInit})}catch(n){throw this.onerror?.(n),n}if(t!=="AUTHORIZED")throw new MA;return await this._startOrAuthSse({resumptionToken:void 0})}async _commonHeaders(){let t={};if(this._authProvider){let r=await this._authProvider.tokens();r&&(t.Authorization=`Bearer ${r.access_token}`)}this._sessionId&&(t["mcp-session-id"]=this._sessionId),this._protocolVersion&&(t["mcp-protocol-version"]=this._protocolVersion);let n=XB(this._requestInit?.headers);return new Headers({...t,...n})}async _startOrAuthSse(t){let{resumptionToken:n}=t;try{let r=await this._commonHeaders();r.set("Accept","text/event-stream"),n&&r.set("last-event-id",n);let i=await(this._fetch??fetch)(this._url,{method:"GET",headers:r,signal:this._abortController?.signal});if(!i.ok){if(await i.body?.cancel(),i.status===401&&this._authProvider)return await this._authThenStart();if(i.status===405)return;throw new Xh(i.status,`Failed to open SSE stream: ${i.statusText}`)}this._handleSseStream(i.body,t,!0)}catch(r){throw this.onerror?.(r),r}}_getNextReconnectionDelay(t){if(this._serverRetryMs!==void 0)return this._serverRetryMs;let n=this._reconnectionOptions.initialReconnectionDelay,r=this._reconnectionOptions.reconnectionDelayGrowFactor,i=this._reconnectionOptions.maxReconnectionDelay;return Math.min(n*Math.pow(r,t),i)}_scheduleReconnection(t,n=0){let r=this._reconnectionOptions.maxRetries;if(n>=r){this.onerror?.(new Error(`Maximum reconnection attempts (${r}) exceeded.`));return}let i=this._getNextReconnectionDelay(n);this._reconnectionTimeout=setTimeout(()=>{this._startOrAuthSse(t).catch(a=>{this.onerror?.(new Error(`Failed to reconnect SSE stream: ${a instanceof Error?a.message:String(a)}`)),this._scheduleReconnection(t,n+1)})},i)}_handleSseStream(t,n,r){if(!t)return;let{onresumptiontoken:i,replayMessageId:a}=n,l,d=!1,m=!1;(async()=>{try{let E=t.pipeThrough(new TextDecoderStream).pipeThrough(new tM({onRetry:N=>{this._serverRetryMs=N}})).getReader();for(;;){let{value:N,done:D}=await E.read();if(D)break;if(N.id&&(l=N.id,d=!0,i?.(N.id)),!!N.data&&(!N.event||N.event==="message"))try{let x=uT.parse(JSON.parse(N.data));oy(x)&&(m=!0,a!==void 0&&(x.id=a)),this.onmessage?.(x)}catch(x){this.onerror?.(x)}}(r||d)&&!m&&this._abortController&&!this._abortController.signal.aborted&&this._scheduleReconnection({resumptionToken:l,onresumptiontoken:i,replayMessageId:a},0)}catch(E){if(this.onerror?.(new Error(`SSE stream disconnected: ${E}`)),(r||d)&&!m&&this._abortController&&!this._abortController.signal.aborted)try{this._scheduleReconnection({resumptionToken:l,onresumptiontoken:i,replayMessageId:a},0)}catch(N){this.onerror?.(new Error(`Failed to reconnect: ${N instanceof Error?N.message:String(N)}`))}}})()}async start(){if(this._abortController)throw new Error("StreamableHTTPClientTransport already started! If using Client class, note that connect() calls start() automatically.");this._abortController=new AbortController}async finishAuth(t){if(!this._authProvider)throw new MA("No auth provider");if(await nN(this._authProvider,{serverUrl:this._url,authorizationCode:t,resourceMetadataUrl:this._resourceMetadataUrl,scope:this._scope,fetchFn:this._fetchWithInit})!=="AUTHORIZED")throw new MA("Failed to authorize")}async close(){this._reconnectionTimeout&&(clearTimeout(this._reconnectionTimeout),this._reconnectionTimeout=void 0),this._abortController?.abort(),this.onclose?.()}async send(t,n){try{let{resumptionToken:r,onresumptiontoken:i}=n||{};if(r){this._startOrAuthSse({resumptionToken:r,replayMessageId:sR(t)?t.id:void 0}).catch(S=>this.onerror?.(S));return}let a=await this._commonHeaders();a.set("content-type","application/json"),a.set("accept","application/json, text/event-stream");let l={...this._requestInit,method:"POST",headers:a,body:JSON.stringify(t),signal:this._abortController?.signal},d=await(this._fetch??fetch)(this._url,l),m=d.headers.get("mcp-session-id");if(m&&(this._sessionId=m),!d.ok){let S=await d.text().catch(()=>null);if(d.status===401&&this._authProvider){if(this._hasCompletedAuthFlow)throw new Xh(401,"Server returned 401 after successful authentication");let{resourceMetadataUrl:N,scope:D}=E3(d);if(this._resourceMetadataUrl=N,this._scope=D,await nN(this._authProvider,{serverUrl:this._url,resourceMetadataUrl:this._resourceMetadataUrl,scope:this._scope,fetchFn:this._fetchWithInit})!=="AUTHORIZED")throw new MA;return this._hasCompletedAuthFlow=!0,this.send(t)}if(d.status===403&&this._authProvider){let{resourceMetadataUrl:N,scope:D,error:x}=E3(d);if(x==="insufficient_scope"){let B=d.headers.get("WWW-Authenticate");if(this._lastUpscopingHeader===B)throw new Xh(403,"Server returned 403 after trying upscoping");if(D&&(this._scope=D),N&&(this._resourceMetadataUrl=N),this._lastUpscopingHeader=B??void 0,await nN(this._authProvider,{serverUrl:this._url,resourceMetadataUrl:this._resourceMetadataUrl,scope:this._scope,fetchFn:this._fetch})!=="AUTHORIZED")throw new MA;return this.send(t)}}throw new Xh(d.status,`Error POSTing to endpoint: ${S}`)}if(this._hasCompletedAuthFlow=!1,this._lastUpscopingHeader=void 0,d.status===202){await d.body?.cancel(),$te(t)&&this._startOrAuthSse({resumptionToken:void 0}).catch(S=>this.onerror?.(S));return}let E=(Array.isArray(t)?t:[t]).filter(S=>"method"in S&&"id"in S&&S.id!==void 0).length>0,v=d.headers.get("content-type");if(E)if(v?.includes("text/event-stream"))this._handleSseStream(d.body,{onresumptiontoken:i},!1);else if(v?.includes("application/json")){let S=await d.json(),N=Array.isArray(S)?S.map(D=>uT.parse(D)):[uT.parse(S)];for(let D of N)this.onmessage?.(D)}else throw await d.body?.cancel(),new Xh(-1,`Unexpected content type: ${v}`);else await d.body?.cancel()}catch(r){throw this.onerror?.(r),r}}get sessionId(){return this._sessionId}async terminateSession(){if(this._sessionId)try{let t=await this._commonHeaders(),n={...this._requestInit,method:"DELETE",headers:t,signal:this._abortController?.signal},r=await(this._fetch??fetch)(this._url,n);if(await r.body?.cancel(),!r.ok&&r.status!==405)throw new Xh(r.status,`Failed to terminate session: ${r.statusText}`);this._sessionId=void 0}catch(t){throw this.onerror?.(t),t}}setProtocolVersion(t){this._protocolVersion=t}get protocolVersion(){return this._protocolVersion}async resumeStream(t,n){await this._startOrAuthSse({resumptionToken:t,onresumptiontoken:n?.onresumptiontoken})}};import YFe from"crypto";import{promises as rM}from"fs";import iM from"path";var Woe=180,qFe=12;async function wT(e){let t=await jFe(e),r=await WFe(t)||t;return{workspaceRoot:t,projectKey:r,projectId:KFe(r),projectSlug:VFe(r)}}function VFe(e){let r=e.trim().replace(/^[a-z]+:\/\//i,"").replace(/[/\\:@]/g,"-").replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")||"workspace";if(r.length<=Woe)return r;let i=Zoe(e).slice(0,qFe);return`${r.slice(0,Woe)}-${i}`}function KFe(e){let t=Zoe(e).slice(0,32);return`${t.slice(0,8)}-${t.slice(8,12)}-${t.slice(12,16)}-${t.slice(16,20)}-${t.slice(20)}`}async function jFe(e){let t=iM.resolve(e||process.cwd());try{return(await rM.realpath(t)).normalize("NFC")}catch{return t.normalize("NFC")}}async function WFe(e){let t=await ZFe(e);if(!t)return null;try{let n=await rM.readFile(iM.join(t,"config"),"utf8"),r=!1;for(let i of n.split(/\r?\n/)){let a=i.trim();if(a.startsWith("[remote ")){r=a.includes('"origin"');continue}if(!r)continue;let l=a.match(/^url\s*=\s*(.+)$/i);if(l)return l[1]?.trim()||null}}catch{return null}return null}async function ZFe(e){let t=iM.join(e,".git");try{let n=await rM.stat(t);if(n.isDirectory())return t;if(!n.isFile())return null;let i=(await rM.readFile(t,"utf8")).match(/^gitdir:\s*(.+)$/im);return i?.[1]?iM.resolve(e,i[1].trim()):null}catch{return null}}function Zoe(e){return YFe.createHash("sha256").update(e).digest("hex")}var Zg="0.10.3";var BT=class{configPathOverride;workspaceTrusted=!1;serverEnabled={};servers=new Map;constructor(t){this.configPathOverride=t?.configPathOverride,this.workspaceTrusted=!!t?.workspaceTrusted,this.serverEnabled={...t?.serverEnabled||{}}}setWorkspaceTrusted(t){this.workspaceTrusted=t}setServerEnabled(t){this.serverEnabled={...t}}async dispose(){let t=Array.from(this.servers.values());this.servers.clear(),await Promise.allSettled(t.map(async n=>{await this.disposeEntry(n)}))}async prepareForChat(t){await this.loadConfig(t);let n=this.getEnabledEntries();if(n.length===0)return null;await Promise.allSettled(n.map(i=>this.ensureServerConnected(t,i.name)));let r=await this.getDescriptorRoot(t);return{descriptorRoot:r,servers:n.map(i=>({name:i.name,folderPath:LA.join(r,i.folderName)}))}}async getStatus(t){await this.loadConfig(t);let n=Array.from(this.servers.values()).sort((r,i)=>r.name.localeCompare(i.name));return await Promise.allSettled(n.filter(r=>this.isEnabled(r.name)).map(r=>this.ensureServerConnected(t,r.name))),n.map(r=>({name:r.name,status:this.isEnabled(r.name)?r.status:"disabled",enabled:this.isEnabled(r.name),source:r.source,summary:r.config.url?r.config.url:[r.config.command,...r.config.args||[]].filter(Boolean).join(" "),lastError:r.lastError,toolCount:Array.isArray(r.tools)?r.tools.length:0,resourceCount:Array.isArray(r.resources)?r.resources.length:0}))}async refreshServer(t,n){await this.loadConfig(t);let r=this.servers.get(n);if(!r)throw new Error(`Unknown MCP server: ${n}`);await this.disposeEntry(r),r.client=void 0,r.transport=void 0,r.tools=void 0,r.resources=void 0,r.lastError=void 0,r.status="idle",await this.ensureServerConnected(t,n)}async callTool(t,n,r,i){return await(await this.getEnabledConnectedEntry(t,n)).client.callTool({name:r,arguments:i})}async listResources(t,n){await this.loadConfig(t);let r=n?[n]:this.getEnabledEntries().map(a=>a.name),i=[];for(let a of r){let l=await this.getEnabledConnectedEntry(t,a);try{let d=await l.client.listResources(),m=Array.isArray(d?.resources)?d.resources:[];for(let A of m)i.push({server:a,uri:String(A.uri),name:typeof A.name=="string"?A.name:void 0,description:typeof A.description=="string"?A.description:void 0,mimeType:typeof A.mimeType=="string"?A.mimeType:void 0})}catch(d){if(!eae(d))throw d}}return i}async readResource(t,n,r){return await(await this.getEnabledConnectedEntry(t,n)).client.readResource({uri:r})}async getEnabledConnectedEntry(t,n){await this.loadConfig(t);let r=this.servers.get(n);if(!r)throw new Error(`MCP server "${n}" is not configured.`);if(!this.isEnabled(n))throw new Error(`MCP server "${n}" is disabled.`);return await this.ensureServerConnected(t,n),r}async ensureServerConnected(t,n){let r=this.servers.get(n);if(!r)throw new Error(`Unknown MCP server: ${n}`);if(r.status!=="connected"){if(r.connecting){await r.connecting;return}r.connecting=this.connectServer(t,r).catch(i=>{throw r.status="error",r.lastError=i?.message||"Failed to connect to MCP server",i}).finally(()=>{r.connecting=void 0}),await r.connecting}}async connectServer(t,n){let r=await this.createTransport(n.config),i=new KB({name:"codeneter-cli",version:Zg},{capabilities:{}});await i.connect(r),n.client=i,n.transport=r,n.status="connected",n.lastError=void 0,await this.refreshServerDescriptors(t,n)}async refreshServerDescriptors(t,n){if(!n.client)return;let r=await this.getDescriptorRoot(t),i=LA.join(r,n.folderName),a=LA.join(i,"tools"),l=LA.join(i,"resources");await rN.mkdir(a,{recursive:!0}),await rN.mkdir(l,{recursive:!0});let d=await n.client.listTools(),m=Array.isArray(d?.tools)?d.tools:Array.isArray(d)?d:[];n.tools=m,await this.writeDescriptorFiles(a,m,E=>E?.name);let A=[];try{let E=await n.client.listResources();A=Array.isArray(E?.resources)?E.resources:Array.isArray(E)?E:[]}catch(E){if(!eae(E))throw E}n.resources=A,await this.writeDescriptorFiles(l,A,E=>E?.name||E?.uri)}async writeDescriptorFiles(t,n,r){await this.pruneJsonFiles(t);for(let i of n){let a=r(i);if(!a)continue;let l=LA.join(t,`${rQe(a)}.json`);await tx(l,JSON.stringify(i,null,2))}}async pruneJsonFiles(t){try{let n=await rN.readdir(t,{withFileTypes:!0});await Promise.all(n.filter(r=>r.isFile()&&r.name.endsWith(".json")).map(r=>rN.unlink(LA.join(t,r.name))))}catch(n){n?.code!=="ENOENT"&&console.warn("[CLI] Failed to prune MCP descriptor directory:",n)}}async loadConfig(t){let n=new Map,r=await this.readConfigSources(t);for(let a of r)for(let[l,d]of Object.entries(a.config)){let m=JFe(d);m&&n.set(l,{config:m,source:a.source})}let i=new Set(n.keys());for(let a of Array.from(this.servers.keys()))if(!i.has(a)){let l=this.servers.get(a);l&&this.disposeEntry(l).catch(()=>{}),this.servers.delete(a)}for(let[a,l]of n.entries()){let d=this.servers.get(a);d&&tQe(d.config,l.config)&&d.source===l.source||(d&&this.disposeEntry(d).catch(()=>{}),this.servers.set(a,{name:a,folderName:nQe(a),config:l.config,source:l.source,status:"idle"}))}}async readConfigSources(t){let n=[{source:"user",filePath:LA.join(Joe.homedir(),".codeneter","mcp.json")},{source:"project",filePath:this.workspaceTrusted?LA.join(t,".codeneter","mcp.json"):void 0},{source:"override",filePath:this.configPathOverride}],r=[];for(let i of n)if(i.filePath)try{let a=await rN.readFile(i.filePath,"utf8"),l=JSON.parse(a),d=l?.mcpServers&&typeof l.mcpServers=="object"?l.mcpServers:l?.servers&&typeof l.servers=="object"?l.servers:{};r.push({source:i.source,config:d})}catch(a){a?.code!=="ENOENT"&&console.warn("[CLI] Failed to read MCP config:",a)}return r}async getDescriptorRoot(t){let n=await wT(t);return LA.join(Joe.homedir(),".codeneter","projects",n.projectSlug,"mcps")}async createTransport(t){if(t.url)return await oQe(t.url,t.headers);let n=typeof t.command=="string"?t.command:"";if(!n)throw new Error("MCP server config is missing command or url");return new ZB({command:n,args:t.args??[],env:iQe(process.env,t.env)})}isEnabled(t){return this.serverEnabled[t]!==!1}getEnabledEntries(){return Array.from(this.servers.values()).filter(t=>this.isEnabled(t.name))}async disposeEntry(t){t.connecting=void 0,typeof t.client?.close=="function"&&await Promise.resolve(t.client.close()),typeof t.transport?.close=="function"&&await Promise.resolve(t.transport.close())}};function JFe(e){if(!e||typeof e!="object")return null;let t=typeof e.url=="string"?e.url.trim():"";if(t){let a=e.headers&&typeof e.headers=="object"?XFe(e.headers):void 0;return{url:t,headers:a}}let n=typeof e.command=="string"?e.command.trim():"";if(!n)return null;let r=Array.isArray(e.args)?e.args.map(a=>String(a)):[],i=e.env&&typeof e.env=="object"?eQe(e.env):void 0;return{command:n,args:r,env:i}}function XFe(e){let t={};for(let[n,r]of Object.entries(e))n&&(t[String(n)]=String(r));return t}function eQe(e){let t={};for(let[n,r]of Object.entries(e))n&&(t[String(n)]=String(r));return t}function tQe(e,t){let n=!!e.url,r=!!t.url;if(n!==r)return!1;if(n&&r)return e.url===t.url&&Xoe(e.headers,t.headers);if(e.command!==t.command||(e.args?.length||0)!==(t.args?.length||0))return!1;for(let i=0;i<(e.args?.length||0);i+=1)if(e.args?.[i]!==t.args?.[i])return!1;return Xoe(e.env,t.env)}function Xoe(e,t){let n=Object.keys(e||{}),r=Object.keys(t||{});if(n.length!==r.length)return!1;for(let i of n)if(e?.[i]!==t?.[i])return!1;return!0}function nQe(e){return e.trim().replace(/[^a-zA-Z0-9._-]+/g,"_").replace(/_+/g,"_").replace(/^_+|_+$/g,"")||"mcp-server"}function rQe(e){return e.trim().replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")||"descriptor"}function iQe(e,t){let n={};for(let[r,i]of Object.entries(e))typeof i=="string"&&(n[r]=i);if(t)for(let[r,i]of Object.entries(t))n[r]=String(i);return n}function eae(e){let t=typeof e?.code=="number"?e.code:void 0,n=typeof e?.message=="string"?e.message.toLowerCase():"";return t===-32601||n.includes("method not found")}async function oQe(e,t){return new nM(new URL(e),{requestInit:t?{headers:t}:void 0})}var Yt=Dt(mi(),1);h2();import{randomUUID as tae}from"crypto";var oM=class e{constructor(t){this.input=t;this.authToken=t.authToken}static STREAM_FLUSH_INTERVAL_MS=48;static PRESENCE_INTERVAL_MS=15e3;presenceTimer=null;authToken;attachUrl="";disposed=!1;callbacks=null;emitQueue=Promise.resolve();eventQueue=Promise.resolve();nextEventSeq=1;flushTimer=null;bufferedEvents=[];socket=null;connectPromise=null;reconnectTimer=null;lastPresence=null;setAuthToken(t){this.authToken=t}async register(t){let n=await this.request("/api/remote/sessions/register",{remoteId:this.input.remoteId,workspaceRoot:t.workspaceRoot,model:t.model,mode:t.mode,status:t.status,availableModels:Array.isArray(t.availableModels)?t.availableModels.map(r=>({label:r.label,value:r.value,...typeof r.supportsImages=="boolean"?{supportsImages:r.supportsImages}:{},...Number.isFinite(r.maxImages)?{maxImages:r.maxImages}:{},...Number.isFinite(r.maxContextTokens)?{maxContextTokens:r.maxContextTokens}:{},...Number.isFinite(r.defaultContextTokens)?{defaultContextTokens:r.defaultContextTokens}:{},...Array.isArray(r.contextWindowOptions)?{contextWindowOptions:r.contextWindowOptions}:{},...typeof r.reasoning=="boolean"?{reasoning:r.reasoning}:{}})):[],label:t.label});if(this.attachUrl=String(n?.session?.attachUrl||"").trim(),!this.attachUrl)throw new Error("Remote registration did not return an attach URL.");this.lastPresence={workspaceRoot:t.workspaceRoot,model:t.model,mode:t.mode,status:t.status,...t.label?{label:t.label}:{}}}startHeartbeatLoop(t){this.callbacks=t,!this.presenceTimer&&(this.sendPresence().catch(n=>{this.disposed||console.warn("[Remote] Failed to send initial presence:",n)}),this.presenceTimer=setInterval(()=>{this.sendPresence().catch(n=>{this.disposed||console.warn("[Remote] Failed to send presence:",n)})},e.PRESENCE_INTERVAL_MS),this.presenceTimer.unref?.())}async emitEvent(t,n){let r=this.emitQueue.then(()=>this.emitEventNow(t,n));this.emitQueue=r.catch(()=>{}),await r}async emitEventNow(t,n){if(this.disposed)return;let r={event:t,data:{...n&&typeof n=="object"?n:{value:n},_clientSeq:this.nextEventSeq++}};if(t==="token"||t==="reasoning"&&!r.data?.done){this.bufferedEvents.push(r),this.scheduleBufferedFlush();return}await this.flushBufferedEvents(),await this.enqueueSocketMessage({type:"event",event:t,data:r.data})}async unregister(){try{await this.request(`/api/remote/sessions/${encodeURIComponent(this.input.remoteId)}/unregister`,{})}catch(t){console.warn("[Remote] Failed to unregister remote session:",t)}}async dispose(){this.disposed||(this.presenceTimer&&(clearInterval(this.presenceTimer),this.presenceTimer=null),this.flushTimer&&(clearTimeout(this.flushTimer),this.flushTimer=null),this.clearReconnectTimer(),await this.emitQueue.catch(()=>{}),await this.flushBufferedEvents(),await this.eventQueue.catch(()=>{}),this.disposed=!0,this.closeSocket(),await this.unregister())}getShareableUrl(){return this.attachUrl}async resolveAuthToken(){try{let n=await this.input.getAuthToken?.();typeof n=="string"&&n.trim()&&(this.authToken=n.trim())}catch(n){this.disposed||console.warn("[Remote] Failed to refresh auth token:",n)}let t=this.authToken?.trim();if(!t)throw new Error("Remote control requires an authenticated CLI session.");return t}async request(t,n){let r=await this.resolveAuthToken(),i=await fetch(`${this.input.backendUrl.replace(/\/$/,"")}${t}`,{method:"POST",headers:{Authorization:`Bearer ${r}`,"Content-Type":"application/json","X-Remote-Request-Id":tae()},body:JSON.stringify(n)});if(!i.ok){let a=await i.text().catch(()=>"");throw new Error(`Remote request failed (${i.status}): ${a}`)}return await i.json()}async ensureSocket(){if(this.disposed||this.socket&&this.socket.readyState===gv.OPEN)return;if(this.connectPromise){await this.connectPromise;return}let t=await this.resolveAuthToken(),n=sQe(this.input.backendUrl,this.input.remoteId),r=new gv(n,{headers:{Authorization:`Bearer ${t}`,"X-Remote-Request-Id":tae()}});this.socket=r,this.connectPromise=new Promise((i,a)=>{let l=!1,d=!1;r.on("open",()=>{l=!0,d=!0,this.clearReconnectTimer(),i()}),r.on("message",m=>{this.handleSocketMessage(m)}),r.on("error",m=>{if(!d){d=!0,a(m instanceof Error?m:new Error(String(m)));return}this.disposed||console.warn("[Remote] Socket error:",m)}),r.on("close",()=>{let m=!l&&!d;if(this.socket===r&&(this.socket=null),m){d=!0,a(new Error("Remote socket closed before connecting."));return}this.disposed||this.scheduleReconnect()})});try{await this.connectPromise}finally{this.connectPromise=null}}handleSocketMessage(t){let n=aQe(t);if(!(!n||!this.callbacks)){if(n.type==="message"){this.callbacks.onMessage(n.payload);return}if(n.type==="prompt_response"){this.callbacks.onPromptResponse(n.payload);return}if(n.type==="config_change"){(n.payload?.model||n.payload?.mode)&&this.callbacks.onConfigChange(n.payload);return}if(n.type==="cancel"){this.callbacks.onCancel();return}n.type==="viewer_state"&&this.callbacks.onViewerState?.(Math.max(0,Number(n.payload?.viewerCount||0)))}}scheduleReconnect(){this.reconnectTimer||this.disposed||(this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.reconnect().catch(t=>{this.disposed||(console.warn("[Remote] Failed to reconnect socket:",t),this.scheduleReconnect())})},1500),this.reconnectTimer.unref?.())}async reconnect(){this.disposed||(await this.ensureSocket(),await this.sendPresence())}clearReconnectTimer(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null)}closeSocket(){let t=this.socket;if(this.socket=null,!!t)try{t.close()}catch{}}buildPresence(){return this.callbacks&&(this.lastPresence=this.callbacks.getPresence()),this.lastPresence}async sendPresence(){let t=this.buildPresence();!t||this.disposed||await this.enqueueSocketMessage({type:"presence",payload:t})}async enqueueSocketMessage(t){let n=this.eventQueue.then(async()=>{if(this.disposed)return;await this.ensureSocket();let r=this.socket;if(!r||r.readyState!==gv.OPEN)throw new Error("Remote socket is not connected.");await new Promise((i,a)=>{r.send(JSON.stringify(t),l=>{if(l){a(l);return}i()})})});this.eventQueue=n.catch(()=>{}),await n}scheduleBufferedFlush(){this.flushTimer||this.disposed||(this.flushTimer=setTimeout(()=>{this.flushTimer=null,this.flushBufferedEvents().catch(t=>{this.disposed||console.warn("[Remote] Failed to flush buffered events:",t)})},e.STREAM_FLUSH_INTERVAL_MS),this.flushTimer.unref?.())}async flushBufferedEvents(){if(this.disposed||this.bufferedEvents.length===0)return;this.flushTimer&&(clearTimeout(this.flushTimer),this.flushTimer=null);let t=lQe(this.bufferedEvents.splice(0,this.bufferedEvents.length));if(t.length!==0)for(let n of t)await this.enqueueSocketMessage({type:"event",event:n.event,data:n.data})}};function aQe(e){try{let t=Buffer.isBuffer(e)?e.toString("utf8"):Array.isArray(e)?Buffer.concat(e).toString("utf8"):typeof e=="string"?e:(e instanceof ArrayBuffer,Buffer.from(e).toString("utf8"));if(!t)return null;let n=JSON.parse(t);return n&&typeof n=="object"?n:null}catch{return null}}function sQe(e,t){let n=new URL(e);return n.protocol=n.protocol==="https:"?"wss:":"ws:",n.pathname=`/api/remote/sessions/${encodeURIComponent(t)}/ws`,n.search="",n.hash="",n.toString()}function lQe(e){if(e.length<=1)return e;let t=[];for(let n of e){let r=t[t.length-1];if(r?.event==="token"&&n.event==="token"){r.data={...r.data,delta:`${String(r.data?.delta||"")}${String(n.data?.delta||"")}`,_clientSeq:n.data?._clientSeq??r.data?._clientSeq};continue}if(r?.event==="reasoning"&&n.event==="reasoning"){r.data={...r.data,delta:`${String(r.data?.delta||"")}${String(n.data?.delta||"")}`,_clientSeq:n.data?._clientSeq??r.data?._clientSeq};continue}t.push(n)}return t}import{access as uQe}from"fs/promises";import rae from"os";import dQe from"path";function aM(e){return e.map(cQe)}function cQe(e){if(!y3(e))return structuredClone(e);let t=structuredClone(e);return delete t.reasoningItems,t}function y3(e){return Array.isArray(e.reasoningItems)&&e.reasoningItems.length>0}function nae(e,t=Date.now()){let n=Date.parse(e);return Number.isFinite(n)?t-n>72e5:!1}var fQe=6,C3=5,mQe=20,pQe=20,v3="This session is being continued from a previous conversation that ran out of context. The summary below covers the earlier portion of the conversation.",gQe=[/^Unknown or unsupported tool:/i,/^Tool use is not allowed during compaction\b/i,/^User canceled\b/i,/^User denied\b/i];async function iN(e){return{osVersion:`${rae.platform()} ${rae.release()}`,shell:process.env.SHELL||process.env.ComSpec||void 0,workspacePath:e,isGitRepo:await _Qe(e)}}function oN(e){return{workspaceRoot:e.workspaceRoot,mode:e.mode,clientSessionId:e.sessionId,projectId:e.projectId,requestedModel:e.model,source:"cli",clientSupportedTools:[...OJ],userInfo:e.userInfo,mcp:e.mcp,rules:e.rules,skills:e.skills,summaryInstructions:e.summaryInstructions}}function iae(e,t){let n={role:"system",text:TQe(t.trim(),AQe(e)),meta:{kind:"conversation_summary"}},r=e.filter(i=>!sM(i)).filter(i=>i.role==="user"||i.role==="assistant").filter(i=>i.text.trim()||Array.isArray(i.images)&&i.images.length>0).slice(-fQe);return[n,...aM(r)]}function sM(e){return e.role==="system"&&e.meta?.kind==="conversation_summary"}function oae(e){if(!sM(e))return typeof e.text=="string"?e.text:"";let t=typeof e.text=="string"?e.text.trim():"";return RQe(t,"conversation_summary")||""}async function _Qe(e){try{return await uQe(dQe.join(e,".git")),!0}catch{return!1}}function AQe(e){let t=EQe(e),n=SQe(e);if(!(t.length===0&&!n))return{importantFiles:t.length>0?t:void 0,unresolvedToolOutcome:n}}function EQe(e){let t=new Map,n=0;for(let r=e.length-1;r>=0&&t.size<C3&&n<mQe;r-=1){let i=e[r];n+=1;let a=Array.isArray(i.toolCalls)?i.toolCalls:[];for(let l of a){let d=typeof l?.function?.name=="string"?l.function.name.trim():"";if(!d)continue;let m=CQe(l?.function?.arguments),A=hQe(d,m);if(!(!A||t.has(A.path))&&(t.set(A.path,A),t.size>=C3))break}}return[...t.values()].slice(0,C3)}function hQe(e,t){if(e==="read_file"){let n=e1(typeof t.target_file=="string"?t.target_file:"");return n?{path:n,reason:"read",toolName:e}:null}if(e==="write_file"||e==="search_replace"||e==="default_api_search_replace"){let n=e1(typeof t.file_path=="string"?t.file_path:typeof t.path=="string"?t.path:"");return n?{path:n,reason:"edited",toolName:e}:null}if(e==="codebase_search"){let n=Array.isArray(t.target_directories)?t.target_directories:[],r=e1(typeof n[0]=="string"?n[0]:"");return r?{path:r,reason:"searched",toolName:e}:null}return null}function SQe(e){let t=0;for(let n=e.length-1;n>=0&&t<pQe;n-=1){let r=e[n];if(!r||r.role!=="tool")continue;t+=1;let i=typeof r.toolName=="string"?r.toolName.trim():"",a=vQe(r.text);if(i&&a&&!yQe(a))return{toolName:i,message:a}}}function yQe(e){return gQe.some(t=>t.test(e.trim()))}function CQe(e){if(typeof e!="string"||!e.trim())return{};try{let t=JSON.parse(e);return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}catch{return{}}}function vQe(e){if(typeof e!="string"||!e.trim())return null;try{let t=JSON.parse(e);if(t&&typeof t=="object"&&typeof t.error=="string"&&t.error.trim())return t.error.trim()}catch{return null}return null}function e1(e){return typeof e=="string"?e.trim():""}function TQe(e,t){let r=["<conversation_summary>",bQe(e),"</conversation_summary>"],i=IQe(t);return i&&r.push("","<preserved_working_state>",i,"</preserved_working_state>"),r.join(`
|
|
533
|
+
`&&r++}}return[t,n]}var tM=class extends TransformStream{constructor({onError:t,onRetry:n,onComment:r}={}){let i;super({start(a){i=joe({onEvent:l=>{a.enqueue(l)},onError(l){t==="terminate"?a.error(l):typeof t=="function"&&t(l)},onRetry:n,onComment:r})},transform(a){i.feed(a)}})}};var $Fe={initialReconnectionDelay:1e3,maxReconnectionDelay:3e4,reconnectionDelayGrowFactor:1.5,maxRetries:2},Xh=class extends Error{constructor(t,n){super(`Streamable HTTP error: ${n}`),this.code=t}},nM=class{constructor(t,n){this._hasCompletedAuthFlow=!1,this._url=t,this._resourceMetadataUrl=void 0,this._scope=void 0,this._requestInit=n?.requestInit,this._authProvider=n?.authProvider,this._fetch=n?.fetch,this._fetchWithInit=Moe(n?.fetch,n?.requestInit),this._sessionId=n?.sessionId,this._reconnectionOptions=n?.reconnectionOptions??$Fe}async _authThenStart(){if(!this._authProvider)throw new MA("No auth provider");let t;try{t=await nN(this._authProvider,{serverUrl:this._url,resourceMetadataUrl:this._resourceMetadataUrl,scope:this._scope,fetchFn:this._fetchWithInit})}catch(n){throw this.onerror?.(n),n}if(t!=="AUTHORIZED")throw new MA;return await this._startOrAuthSse({resumptionToken:void 0})}async _commonHeaders(){let t={};if(this._authProvider){let r=await this._authProvider.tokens();r&&(t.Authorization=`Bearer ${r.access_token}`)}this._sessionId&&(t["mcp-session-id"]=this._sessionId),this._protocolVersion&&(t["mcp-protocol-version"]=this._protocolVersion);let n=XB(this._requestInit?.headers);return new Headers({...t,...n})}async _startOrAuthSse(t){let{resumptionToken:n}=t;try{let r=await this._commonHeaders();r.set("Accept","text/event-stream"),n&&r.set("last-event-id",n);let i=await(this._fetch??fetch)(this._url,{method:"GET",headers:r,signal:this._abortController?.signal});if(!i.ok){if(await i.body?.cancel(),i.status===401&&this._authProvider)return await this._authThenStart();if(i.status===405)return;throw new Xh(i.status,`Failed to open SSE stream: ${i.statusText}`)}this._handleSseStream(i.body,t,!0)}catch(r){throw this.onerror?.(r),r}}_getNextReconnectionDelay(t){if(this._serverRetryMs!==void 0)return this._serverRetryMs;let n=this._reconnectionOptions.initialReconnectionDelay,r=this._reconnectionOptions.reconnectionDelayGrowFactor,i=this._reconnectionOptions.maxReconnectionDelay;return Math.min(n*Math.pow(r,t),i)}_scheduleReconnection(t,n=0){let r=this._reconnectionOptions.maxRetries;if(n>=r){this.onerror?.(new Error(`Maximum reconnection attempts (${r}) exceeded.`));return}let i=this._getNextReconnectionDelay(n);this._reconnectionTimeout=setTimeout(()=>{this._startOrAuthSse(t).catch(a=>{this.onerror?.(new Error(`Failed to reconnect SSE stream: ${a instanceof Error?a.message:String(a)}`)),this._scheduleReconnection(t,n+1)})},i)}_handleSseStream(t,n,r){if(!t)return;let{onresumptiontoken:i,replayMessageId:a}=n,l,d=!1,m=!1;(async()=>{try{let E=t.pipeThrough(new TextDecoderStream).pipeThrough(new tM({onRetry:N=>{this._serverRetryMs=N}})).getReader();for(;;){let{value:N,done:D}=await E.read();if(D)break;if(N.id&&(l=N.id,d=!0,i?.(N.id)),!!N.data&&(!N.event||N.event==="message"))try{let x=uT.parse(JSON.parse(N.data));oy(x)&&(m=!0,a!==void 0&&(x.id=a)),this.onmessage?.(x)}catch(x){this.onerror?.(x)}}(r||d)&&!m&&this._abortController&&!this._abortController.signal.aborted&&this._scheduleReconnection({resumptionToken:l,onresumptiontoken:i,replayMessageId:a},0)}catch(E){if(this.onerror?.(new Error(`SSE stream disconnected: ${E}`)),(r||d)&&!m&&this._abortController&&!this._abortController.signal.aborted)try{this._scheduleReconnection({resumptionToken:l,onresumptiontoken:i,replayMessageId:a},0)}catch(N){this.onerror?.(new Error(`Failed to reconnect: ${N instanceof Error?N.message:String(N)}`))}}})()}async start(){if(this._abortController)throw new Error("StreamableHTTPClientTransport already started! If using Client class, note that connect() calls start() automatically.");this._abortController=new AbortController}async finishAuth(t){if(!this._authProvider)throw new MA("No auth provider");if(await nN(this._authProvider,{serverUrl:this._url,authorizationCode:t,resourceMetadataUrl:this._resourceMetadataUrl,scope:this._scope,fetchFn:this._fetchWithInit})!=="AUTHORIZED")throw new MA("Failed to authorize")}async close(){this._reconnectionTimeout&&(clearTimeout(this._reconnectionTimeout),this._reconnectionTimeout=void 0),this._abortController?.abort(),this.onclose?.()}async send(t,n){try{let{resumptionToken:r,onresumptiontoken:i}=n||{};if(r){this._startOrAuthSse({resumptionToken:r,replayMessageId:sR(t)?t.id:void 0}).catch(S=>this.onerror?.(S));return}let a=await this._commonHeaders();a.set("content-type","application/json"),a.set("accept","application/json, text/event-stream");let l={...this._requestInit,method:"POST",headers:a,body:JSON.stringify(t),signal:this._abortController?.signal},d=await(this._fetch??fetch)(this._url,l),m=d.headers.get("mcp-session-id");if(m&&(this._sessionId=m),!d.ok){let S=await d.text().catch(()=>null);if(d.status===401&&this._authProvider){if(this._hasCompletedAuthFlow)throw new Xh(401,"Server returned 401 after successful authentication");let{resourceMetadataUrl:N,scope:D}=E3(d);if(this._resourceMetadataUrl=N,this._scope=D,await nN(this._authProvider,{serverUrl:this._url,resourceMetadataUrl:this._resourceMetadataUrl,scope:this._scope,fetchFn:this._fetchWithInit})!=="AUTHORIZED")throw new MA;return this._hasCompletedAuthFlow=!0,this.send(t)}if(d.status===403&&this._authProvider){let{resourceMetadataUrl:N,scope:D,error:x}=E3(d);if(x==="insufficient_scope"){let B=d.headers.get("WWW-Authenticate");if(this._lastUpscopingHeader===B)throw new Xh(403,"Server returned 403 after trying upscoping");if(D&&(this._scope=D),N&&(this._resourceMetadataUrl=N),this._lastUpscopingHeader=B??void 0,await nN(this._authProvider,{serverUrl:this._url,resourceMetadataUrl:this._resourceMetadataUrl,scope:this._scope,fetchFn:this._fetch})!=="AUTHORIZED")throw new MA;return this.send(t)}}throw new Xh(d.status,`Error POSTing to endpoint: ${S}`)}if(this._hasCompletedAuthFlow=!1,this._lastUpscopingHeader=void 0,d.status===202){await d.body?.cancel(),$te(t)&&this._startOrAuthSse({resumptionToken:void 0}).catch(S=>this.onerror?.(S));return}let E=(Array.isArray(t)?t:[t]).filter(S=>"method"in S&&"id"in S&&S.id!==void 0).length>0,v=d.headers.get("content-type");if(E)if(v?.includes("text/event-stream"))this._handleSseStream(d.body,{onresumptiontoken:i},!1);else if(v?.includes("application/json")){let S=await d.json(),N=Array.isArray(S)?S.map(D=>uT.parse(D)):[uT.parse(S)];for(let D of N)this.onmessage?.(D)}else throw await d.body?.cancel(),new Xh(-1,`Unexpected content type: ${v}`);else await d.body?.cancel()}catch(r){throw this.onerror?.(r),r}}get sessionId(){return this._sessionId}async terminateSession(){if(this._sessionId)try{let t=await this._commonHeaders(),n={...this._requestInit,method:"DELETE",headers:t,signal:this._abortController?.signal},r=await(this._fetch??fetch)(this._url,n);if(await r.body?.cancel(),!r.ok&&r.status!==405)throw new Xh(r.status,`Failed to terminate session: ${r.statusText}`);this._sessionId=void 0}catch(t){throw this.onerror?.(t),t}}setProtocolVersion(t){this._protocolVersion=t}get protocolVersion(){return this._protocolVersion}async resumeStream(t,n){await this._startOrAuthSse({resumptionToken:t,onresumptiontoken:n?.onresumptiontoken})}};import YFe from"crypto";import{promises as rM}from"fs";import iM from"path";var Woe=180,qFe=12;async function wT(e){let t=await jFe(e),r=await WFe(t)||t;return{workspaceRoot:t,projectKey:r,projectId:KFe(r),projectSlug:VFe(r)}}function VFe(e){let r=e.trim().replace(/^[a-z]+:\/\//i,"").replace(/[/\\:@]/g,"-").replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")||"workspace";if(r.length<=Woe)return r;let i=Zoe(e).slice(0,qFe);return`${r.slice(0,Woe)}-${i}`}function KFe(e){let t=Zoe(e).slice(0,32);return`${t.slice(0,8)}-${t.slice(8,12)}-${t.slice(12,16)}-${t.slice(16,20)}-${t.slice(20)}`}async function jFe(e){let t=iM.resolve(e||process.cwd());try{return(await rM.realpath(t)).normalize("NFC")}catch{return t.normalize("NFC")}}async function WFe(e){let t=await ZFe(e);if(!t)return null;try{let n=await rM.readFile(iM.join(t,"config"),"utf8"),r=!1;for(let i of n.split(/\r?\n/)){let a=i.trim();if(a.startsWith("[remote ")){r=a.includes('"origin"');continue}if(!r)continue;let l=a.match(/^url\s*=\s*(.+)$/i);if(l)return l[1]?.trim()||null}}catch{return null}return null}async function ZFe(e){let t=iM.join(e,".git");try{let n=await rM.stat(t);if(n.isDirectory())return t;if(!n.isFile())return null;let i=(await rM.readFile(t,"utf8")).match(/^gitdir:\s*(.+)$/im);return i?.[1]?iM.resolve(e,i[1].trim()):null}catch{return null}}function Zoe(e){return YFe.createHash("sha256").update(e).digest("hex")}var Zg="0.10.4";var BT=class{configPathOverride;workspaceTrusted=!1;serverEnabled={};servers=new Map;constructor(t){this.configPathOverride=t?.configPathOverride,this.workspaceTrusted=!!t?.workspaceTrusted,this.serverEnabled={...t?.serverEnabled||{}}}setWorkspaceTrusted(t){this.workspaceTrusted=t}setServerEnabled(t){this.serverEnabled={...t}}async dispose(){let t=Array.from(this.servers.values());this.servers.clear(),await Promise.allSettled(t.map(async n=>{await this.disposeEntry(n)}))}async prepareForChat(t){await this.loadConfig(t);let n=this.getEnabledEntries();if(n.length===0)return null;await Promise.allSettled(n.map(i=>this.ensureServerConnected(t,i.name)));let r=await this.getDescriptorRoot(t);return{descriptorRoot:r,servers:n.map(i=>({name:i.name,folderPath:LA.join(r,i.folderName)}))}}async getStatus(t){await this.loadConfig(t);let n=Array.from(this.servers.values()).sort((r,i)=>r.name.localeCompare(i.name));return await Promise.allSettled(n.filter(r=>this.isEnabled(r.name)).map(r=>this.ensureServerConnected(t,r.name))),n.map(r=>({name:r.name,status:this.isEnabled(r.name)?r.status:"disabled",enabled:this.isEnabled(r.name),source:r.source,summary:r.config.url?r.config.url:[r.config.command,...r.config.args||[]].filter(Boolean).join(" "),lastError:r.lastError,toolCount:Array.isArray(r.tools)?r.tools.length:0,resourceCount:Array.isArray(r.resources)?r.resources.length:0}))}async refreshServer(t,n){await this.loadConfig(t);let r=this.servers.get(n);if(!r)throw new Error(`Unknown MCP server: ${n}`);await this.disposeEntry(r),r.client=void 0,r.transport=void 0,r.tools=void 0,r.resources=void 0,r.lastError=void 0,r.status="idle",await this.ensureServerConnected(t,n)}async callTool(t,n,r,i){return await(await this.getEnabledConnectedEntry(t,n)).client.callTool({name:r,arguments:i})}async listResources(t,n){await this.loadConfig(t);let r=n?[n]:this.getEnabledEntries().map(a=>a.name),i=[];for(let a of r){let l=await this.getEnabledConnectedEntry(t,a);try{let d=await l.client.listResources(),m=Array.isArray(d?.resources)?d.resources:[];for(let A of m)i.push({server:a,uri:String(A.uri),name:typeof A.name=="string"?A.name:void 0,description:typeof A.description=="string"?A.description:void 0,mimeType:typeof A.mimeType=="string"?A.mimeType:void 0})}catch(d){if(!eae(d))throw d}}return i}async readResource(t,n,r){return await(await this.getEnabledConnectedEntry(t,n)).client.readResource({uri:r})}async getEnabledConnectedEntry(t,n){await this.loadConfig(t);let r=this.servers.get(n);if(!r)throw new Error(`MCP server "${n}" is not configured.`);if(!this.isEnabled(n))throw new Error(`MCP server "${n}" is disabled.`);return await this.ensureServerConnected(t,n),r}async ensureServerConnected(t,n){let r=this.servers.get(n);if(!r)throw new Error(`Unknown MCP server: ${n}`);if(r.status!=="connected"){if(r.connecting){await r.connecting;return}r.connecting=this.connectServer(t,r).catch(i=>{throw r.status="error",r.lastError=i?.message||"Failed to connect to MCP server",i}).finally(()=>{r.connecting=void 0}),await r.connecting}}async connectServer(t,n){let r=await this.createTransport(n.config),i=new KB({name:"codeneter-cli",version:Zg},{capabilities:{}});await i.connect(r),n.client=i,n.transport=r,n.status="connected",n.lastError=void 0,await this.refreshServerDescriptors(t,n)}async refreshServerDescriptors(t,n){if(!n.client)return;let r=await this.getDescriptorRoot(t),i=LA.join(r,n.folderName),a=LA.join(i,"tools"),l=LA.join(i,"resources");await rN.mkdir(a,{recursive:!0}),await rN.mkdir(l,{recursive:!0});let d=await n.client.listTools(),m=Array.isArray(d?.tools)?d.tools:Array.isArray(d)?d:[];n.tools=m,await this.writeDescriptorFiles(a,m,E=>E?.name);let A=[];try{let E=await n.client.listResources();A=Array.isArray(E?.resources)?E.resources:Array.isArray(E)?E:[]}catch(E){if(!eae(E))throw E}n.resources=A,await this.writeDescriptorFiles(l,A,E=>E?.name||E?.uri)}async writeDescriptorFiles(t,n,r){await this.pruneJsonFiles(t);for(let i of n){let a=r(i);if(!a)continue;let l=LA.join(t,`${rQe(a)}.json`);await tx(l,JSON.stringify(i,null,2))}}async pruneJsonFiles(t){try{let n=await rN.readdir(t,{withFileTypes:!0});await Promise.all(n.filter(r=>r.isFile()&&r.name.endsWith(".json")).map(r=>rN.unlink(LA.join(t,r.name))))}catch(n){n?.code!=="ENOENT"&&console.warn("[CLI] Failed to prune MCP descriptor directory:",n)}}async loadConfig(t){let n=new Map,r=await this.readConfigSources(t);for(let a of r)for(let[l,d]of Object.entries(a.config)){let m=JFe(d);m&&n.set(l,{config:m,source:a.source})}let i=new Set(n.keys());for(let a of Array.from(this.servers.keys()))if(!i.has(a)){let l=this.servers.get(a);l&&this.disposeEntry(l).catch(()=>{}),this.servers.delete(a)}for(let[a,l]of n.entries()){let d=this.servers.get(a);d&&tQe(d.config,l.config)&&d.source===l.source||(d&&this.disposeEntry(d).catch(()=>{}),this.servers.set(a,{name:a,folderName:nQe(a),config:l.config,source:l.source,status:"idle"}))}}async readConfigSources(t){let n=[{source:"user",filePath:LA.join(Joe.homedir(),".codeneter","mcp.json")},{source:"project",filePath:this.workspaceTrusted?LA.join(t,".codeneter","mcp.json"):void 0},{source:"override",filePath:this.configPathOverride}],r=[];for(let i of n)if(i.filePath)try{let a=await rN.readFile(i.filePath,"utf8"),l=JSON.parse(a),d=l?.mcpServers&&typeof l.mcpServers=="object"?l.mcpServers:l?.servers&&typeof l.servers=="object"?l.servers:{};r.push({source:i.source,config:d})}catch(a){a?.code!=="ENOENT"&&console.warn("[CLI] Failed to read MCP config:",a)}return r}async getDescriptorRoot(t){let n=await wT(t);return LA.join(Joe.homedir(),".codeneter","projects",n.projectSlug,"mcps")}async createTransport(t){if(t.url)return await oQe(t.url,t.headers);let n=typeof t.command=="string"?t.command:"";if(!n)throw new Error("MCP server config is missing command or url");return new ZB({command:n,args:t.args??[],env:iQe(process.env,t.env)})}isEnabled(t){return this.serverEnabled[t]!==!1}getEnabledEntries(){return Array.from(this.servers.values()).filter(t=>this.isEnabled(t.name))}async disposeEntry(t){t.connecting=void 0,typeof t.client?.close=="function"&&await Promise.resolve(t.client.close()),typeof t.transport?.close=="function"&&await Promise.resolve(t.transport.close())}};function JFe(e){if(!e||typeof e!="object")return null;let t=typeof e.url=="string"?e.url.trim():"";if(t){let a=e.headers&&typeof e.headers=="object"?XFe(e.headers):void 0;return{url:t,headers:a}}let n=typeof e.command=="string"?e.command.trim():"";if(!n)return null;let r=Array.isArray(e.args)?e.args.map(a=>String(a)):[],i=e.env&&typeof e.env=="object"?eQe(e.env):void 0;return{command:n,args:r,env:i}}function XFe(e){let t={};for(let[n,r]of Object.entries(e))n&&(t[String(n)]=String(r));return t}function eQe(e){let t={};for(let[n,r]of Object.entries(e))n&&(t[String(n)]=String(r));return t}function tQe(e,t){let n=!!e.url,r=!!t.url;if(n!==r)return!1;if(n&&r)return e.url===t.url&&Xoe(e.headers,t.headers);if(e.command!==t.command||(e.args?.length||0)!==(t.args?.length||0))return!1;for(let i=0;i<(e.args?.length||0);i+=1)if(e.args?.[i]!==t.args?.[i])return!1;return Xoe(e.env,t.env)}function Xoe(e,t){let n=Object.keys(e||{}),r=Object.keys(t||{});if(n.length!==r.length)return!1;for(let i of n)if(e?.[i]!==t?.[i])return!1;return!0}function nQe(e){return e.trim().replace(/[^a-zA-Z0-9._-]+/g,"_").replace(/_+/g,"_").replace(/^_+|_+$/g,"")||"mcp-server"}function rQe(e){return e.trim().replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")||"descriptor"}function iQe(e,t){let n={};for(let[r,i]of Object.entries(e))typeof i=="string"&&(n[r]=i);if(t)for(let[r,i]of Object.entries(t))n[r]=String(i);return n}function eae(e){let t=typeof e?.code=="number"?e.code:void 0,n=typeof e?.message=="string"?e.message.toLowerCase():"";return t===-32601||n.includes("method not found")}async function oQe(e,t){return new nM(new URL(e),{requestInit:t?{headers:t}:void 0})}var Yt=Dt(mi(),1);h2();import{randomUUID as tae}from"crypto";var oM=class e{constructor(t){this.input=t;this.authToken=t.authToken}static STREAM_FLUSH_INTERVAL_MS=48;static PRESENCE_INTERVAL_MS=15e3;presenceTimer=null;authToken;attachUrl="";disposed=!1;callbacks=null;emitQueue=Promise.resolve();eventQueue=Promise.resolve();nextEventSeq=1;flushTimer=null;bufferedEvents=[];socket=null;connectPromise=null;reconnectTimer=null;lastPresence=null;setAuthToken(t){this.authToken=t}async register(t){let n=await this.request("/api/remote/sessions/register",{remoteId:this.input.remoteId,workspaceRoot:t.workspaceRoot,model:t.model,mode:t.mode,status:t.status,availableModels:Array.isArray(t.availableModels)?t.availableModels.map(r=>({label:r.label,value:r.value,...typeof r.supportsImages=="boolean"?{supportsImages:r.supportsImages}:{},...Number.isFinite(r.maxImages)?{maxImages:r.maxImages}:{},...Number.isFinite(r.maxContextTokens)?{maxContextTokens:r.maxContextTokens}:{},...Number.isFinite(r.defaultContextTokens)?{defaultContextTokens:r.defaultContextTokens}:{},...Array.isArray(r.contextWindowOptions)?{contextWindowOptions:r.contextWindowOptions}:{},...typeof r.reasoning=="boolean"?{reasoning:r.reasoning}:{}})):[],label:t.label});if(this.attachUrl=String(n?.session?.attachUrl||"").trim(),!this.attachUrl)throw new Error("Remote registration did not return an attach URL.");this.lastPresence={workspaceRoot:t.workspaceRoot,model:t.model,mode:t.mode,status:t.status,...t.label?{label:t.label}:{}}}startHeartbeatLoop(t){this.callbacks=t,!this.presenceTimer&&(this.sendPresence().catch(n=>{this.disposed||console.warn("[Remote] Failed to send initial presence:",n)}),this.presenceTimer=setInterval(()=>{this.sendPresence().catch(n=>{this.disposed||console.warn("[Remote] Failed to send presence:",n)})},e.PRESENCE_INTERVAL_MS),this.presenceTimer.unref?.())}async emitEvent(t,n){let r=this.emitQueue.then(()=>this.emitEventNow(t,n));this.emitQueue=r.catch(()=>{}),await r}async emitEventNow(t,n){if(this.disposed)return;let r={event:t,data:{...n&&typeof n=="object"?n:{value:n},_clientSeq:this.nextEventSeq++}};if(t==="token"||t==="reasoning"&&!r.data?.done){this.bufferedEvents.push(r),this.scheduleBufferedFlush();return}await this.flushBufferedEvents(),await this.enqueueSocketMessage({type:"event",event:t,data:r.data})}async unregister(){try{await this.request(`/api/remote/sessions/${encodeURIComponent(this.input.remoteId)}/unregister`,{})}catch(t){console.warn("[Remote] Failed to unregister remote session:",t)}}async dispose(){this.disposed||(this.presenceTimer&&(clearInterval(this.presenceTimer),this.presenceTimer=null),this.flushTimer&&(clearTimeout(this.flushTimer),this.flushTimer=null),this.clearReconnectTimer(),await this.emitQueue.catch(()=>{}),await this.flushBufferedEvents(),await this.eventQueue.catch(()=>{}),this.disposed=!0,this.closeSocket(),await this.unregister())}getShareableUrl(){return this.attachUrl}async resolveAuthToken(){try{let n=await this.input.getAuthToken?.();typeof n=="string"&&n.trim()&&(this.authToken=n.trim())}catch(n){this.disposed||console.warn("[Remote] Failed to refresh auth token:",n)}let t=this.authToken?.trim();if(!t)throw new Error("Remote control requires an authenticated CLI session.");return t}async request(t,n){let r=await this.resolveAuthToken(),i=await fetch(`${this.input.backendUrl.replace(/\/$/,"")}${t}`,{method:"POST",headers:{Authorization:`Bearer ${r}`,"Content-Type":"application/json","X-Remote-Request-Id":tae()},body:JSON.stringify(n)});if(!i.ok){let a=await i.text().catch(()=>"");throw new Error(`Remote request failed (${i.status}): ${a}`)}return await i.json()}async ensureSocket(){if(this.disposed||this.socket&&this.socket.readyState===gv.OPEN)return;if(this.connectPromise){await this.connectPromise;return}let t=await this.resolveAuthToken(),n=sQe(this.input.backendUrl,this.input.remoteId),r=new gv(n,{headers:{Authorization:`Bearer ${t}`,"X-Remote-Request-Id":tae()}});this.socket=r,this.connectPromise=new Promise((i,a)=>{let l=!1,d=!1;r.on("open",()=>{l=!0,d=!0,this.clearReconnectTimer(),i()}),r.on("message",m=>{this.handleSocketMessage(m)}),r.on("error",m=>{if(!d){d=!0,a(m instanceof Error?m:new Error(String(m)));return}this.disposed||console.warn("[Remote] Socket error:",m)}),r.on("close",()=>{let m=!l&&!d;if(this.socket===r&&(this.socket=null),m){d=!0,a(new Error("Remote socket closed before connecting."));return}this.disposed||this.scheduleReconnect()})});try{await this.connectPromise}finally{this.connectPromise=null}}handleSocketMessage(t){let n=aQe(t);if(!(!n||!this.callbacks)){if(n.type==="message"){this.callbacks.onMessage(n.payload);return}if(n.type==="prompt_response"){this.callbacks.onPromptResponse(n.payload);return}if(n.type==="config_change"){(n.payload?.model||n.payload?.mode)&&this.callbacks.onConfigChange(n.payload);return}if(n.type==="cancel"){this.callbacks.onCancel();return}n.type==="viewer_state"&&this.callbacks.onViewerState?.(Math.max(0,Number(n.payload?.viewerCount||0)))}}scheduleReconnect(){this.reconnectTimer||this.disposed||(this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.reconnect().catch(t=>{this.disposed||(console.warn("[Remote] Failed to reconnect socket:",t),this.scheduleReconnect())})},1500),this.reconnectTimer.unref?.())}async reconnect(){this.disposed||(await this.ensureSocket(),await this.sendPresence())}clearReconnectTimer(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null)}closeSocket(){let t=this.socket;if(this.socket=null,!!t)try{t.close()}catch{}}buildPresence(){return this.callbacks&&(this.lastPresence=this.callbacks.getPresence()),this.lastPresence}async sendPresence(){let t=this.buildPresence();!t||this.disposed||await this.enqueueSocketMessage({type:"presence",payload:t})}async enqueueSocketMessage(t){let n=this.eventQueue.then(async()=>{if(this.disposed)return;await this.ensureSocket();let r=this.socket;if(!r||r.readyState!==gv.OPEN)throw new Error("Remote socket is not connected.");await new Promise((i,a)=>{r.send(JSON.stringify(t),l=>{if(l){a(l);return}i()})})});this.eventQueue=n.catch(()=>{}),await n}scheduleBufferedFlush(){this.flushTimer||this.disposed||(this.flushTimer=setTimeout(()=>{this.flushTimer=null,this.flushBufferedEvents().catch(t=>{this.disposed||console.warn("[Remote] Failed to flush buffered events:",t)})},e.STREAM_FLUSH_INTERVAL_MS),this.flushTimer.unref?.())}async flushBufferedEvents(){if(this.disposed||this.bufferedEvents.length===0)return;this.flushTimer&&(clearTimeout(this.flushTimer),this.flushTimer=null);let t=lQe(this.bufferedEvents.splice(0,this.bufferedEvents.length));if(t.length!==0)for(let n of t)await this.enqueueSocketMessage({type:"event",event:n.event,data:n.data})}};function aQe(e){try{let t=Buffer.isBuffer(e)?e.toString("utf8"):Array.isArray(e)?Buffer.concat(e).toString("utf8"):typeof e=="string"?e:(e instanceof ArrayBuffer,Buffer.from(e).toString("utf8"));if(!t)return null;let n=JSON.parse(t);return n&&typeof n=="object"?n:null}catch{return null}}function sQe(e,t){let n=new URL(e);return n.protocol=n.protocol==="https:"?"wss:":"ws:",n.pathname=`/api/remote/sessions/${encodeURIComponent(t)}/ws`,n.search="",n.hash="",n.toString()}function lQe(e){if(e.length<=1)return e;let t=[];for(let n of e){let r=t[t.length-1];if(r?.event==="token"&&n.event==="token"){r.data={...r.data,delta:`${String(r.data?.delta||"")}${String(n.data?.delta||"")}`,_clientSeq:n.data?._clientSeq??r.data?._clientSeq};continue}if(r?.event==="reasoning"&&n.event==="reasoning"){r.data={...r.data,delta:`${String(r.data?.delta||"")}${String(n.data?.delta||"")}`,_clientSeq:n.data?._clientSeq??r.data?._clientSeq};continue}t.push(n)}return t}import{access as uQe}from"fs/promises";import rae from"os";import dQe from"path";function aM(e){return e.map(cQe)}function cQe(e){if(!y3(e))return structuredClone(e);let t=structuredClone(e);return delete t.reasoningItems,t}function y3(e){return Array.isArray(e.reasoningItems)&&e.reasoningItems.length>0}function nae(e,t=Date.now()){let n=Date.parse(e);return Number.isFinite(n)?t-n>72e5:!1}var fQe=6,C3=5,mQe=20,pQe=20,v3="This session is being continued from a previous conversation that ran out of context. The summary below covers the earlier portion of the conversation.",gQe=[/^Unknown or unsupported tool:/i,/^Tool use is not allowed during compaction\b/i,/^User canceled\b/i,/^User denied\b/i];async function iN(e){return{osVersion:`${rae.platform()} ${rae.release()}`,shell:process.env.SHELL||process.env.ComSpec||void 0,workspacePath:e,isGitRepo:await _Qe(e)}}function oN(e){return{workspaceRoot:e.workspaceRoot,mode:e.mode,clientSessionId:e.sessionId,projectId:e.projectId,requestedModel:e.model,source:"cli",clientSupportedTools:[...OJ],userInfo:e.userInfo,mcp:e.mcp,rules:e.rules,skills:e.skills,summaryInstructions:e.summaryInstructions}}function iae(e,t){let n={role:"system",text:TQe(t.trim(),AQe(e)),meta:{kind:"conversation_summary"}},r=e.filter(i=>!sM(i)).filter(i=>i.role==="user"||i.role==="assistant").filter(i=>i.text.trim()||Array.isArray(i.images)&&i.images.length>0).slice(-fQe);return[n,...aM(r)]}function sM(e){return e.role==="system"&&e.meta?.kind==="conversation_summary"}function oae(e){if(!sM(e))return typeof e.text=="string"?e.text:"";let t=typeof e.text=="string"?e.text.trim():"";return RQe(t,"conversation_summary")||""}async function _Qe(e){try{return await uQe(dQe.join(e,".git")),!0}catch{return!1}}function AQe(e){let t=EQe(e),n=SQe(e);if(!(t.length===0&&!n))return{importantFiles:t.length>0?t:void 0,unresolvedToolOutcome:n}}function EQe(e){let t=new Map,n=0;for(let r=e.length-1;r>=0&&t.size<C3&&n<mQe;r-=1){let i=e[r];n+=1;let a=Array.isArray(i.toolCalls)?i.toolCalls:[];for(let l of a){let d=typeof l?.function?.name=="string"?l.function.name.trim():"";if(!d)continue;let m=CQe(l?.function?.arguments),A=hQe(d,m);if(!(!A||t.has(A.path))&&(t.set(A.path,A),t.size>=C3))break}}return[...t.values()].slice(0,C3)}function hQe(e,t){if(e==="read_file"){let n=e1(typeof t.target_file=="string"?t.target_file:"");return n?{path:n,reason:"read",toolName:e}:null}if(e==="write_file"||e==="search_replace"||e==="default_api_search_replace"){let n=e1(typeof t.file_path=="string"?t.file_path:typeof t.path=="string"?t.path:"");return n?{path:n,reason:"edited",toolName:e}:null}if(e==="codebase_search"){let n=Array.isArray(t.target_directories)?t.target_directories:[],r=e1(typeof n[0]=="string"?n[0]:"");return r?{path:r,reason:"searched",toolName:e}:null}return null}function SQe(e){let t=0;for(let n=e.length-1;n>=0&&t<pQe;n-=1){let r=e[n];if(!r||r.role!=="tool")continue;t+=1;let i=typeof r.toolName=="string"?r.toolName.trim():"",a=vQe(r.text);if(i&&a&&!yQe(a))return{toolName:i,message:a}}}function yQe(e){return gQe.some(t=>t.test(e.trim()))}function CQe(e){if(typeof e!="string"||!e.trim())return{};try{let t=JSON.parse(e);return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}catch{return{}}}function vQe(e){if(typeof e!="string"||!e.trim())return null;try{let t=JSON.parse(e);if(t&&typeof t=="object"&&typeof t.error=="string"&&t.error.trim())return t.error.trim()}catch{return null}return null}function e1(e){return typeof e=="string"?e.trim():""}function TQe(e,t){let r=["<conversation_summary>",bQe(e),"</conversation_summary>"],i=IQe(t);return i&&r.push("","<preserved_working_state>",i,"</preserved_working_state>"),r.join(`
|
|
534
534
|
`)}function bQe(e){let t=e.trim();return t?t.startsWith(v3)?t:`${v3}
|
|
535
535
|
|
|
536
536
|
Summary:
|