@qoder-ai/qoder-agent-sdk 1.0.13 → 1.0.15

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.
@@ -5,5 +5,5 @@ import{McpServer as G}from"@modelcontextprotocol/sdk/server/mcp.js";function Z(r
5
5
  `)}catch(l){this.diagnostics?.record("[QueryRunner] Failed to send control_cancel_request on timeout:",l)}u(new Error(`Control request "${v(o.request)??"unknown"}" timed out after ${n}ms`))}},n));try{this.diagnostics?.record(`[QueryRunner] control_request sending request_id=${s} subtype=${i} timeout_ms=${n}`),this.transport.write(JSON.stringify(o)+`
6
6
  `),this.diagnostics?.record(`[QueryRunner] control_request sent request_id=${s} subtype=${i}`)}catch(l){d(),this.pendingRequests.delete(s),this.diagnostics?.record(`[QueryRunner] control_request send failed request_id=${s} subtype=${i}`,l),u(l)}})}handleControlResponse(e){let t=e.response,s=t.request_id,o=this.pendingRequests.get(s);if(!o){this.diagnostics?.record(`[QueryRunner] unmatched control_response received request_id=${s} status=${t.subtype}`);return}if(this.pendingRequests.delete(s),t.subtype==="success")o.resolve(t.response);else{let n=new Error(t.error);t.code&&(n.code=t.code),o.reject(n),this.processPendingPermissionRequests(t.pending_permission_requests)}}processPendingPermissionRequests(e){if(e)for(let t of e)v(t.request)==="can_use_tool"&&this.handleControlRequest(t).catch(s=>{this.diagnostics?.record("[QueryRunner] Error handling pending permission request:",s)})}async handleControlRequest(e){let t=e.request_id,s=v(e.request)??"unknown",o=Date.now(),n=new AbortController;this.pendingInboundRequests.set(t,{abortController:n}),this.diagnostics?.record(`[QueryRunner] inbound control_request received request_id=${t} subtype=${s}`);try{let i=await this.awaitAbortable(this.processControlRequest(e,n.signal),n.signal);if(!n.signal.aborted){let a=U(t,i);this.transport.write(JSON.stringify(a)+`
7
7
  `),this.diagnostics?.record(`[QueryRunner] inbound control_response sent request_id=${t} subtype=${s} status=success duration_ms=${Date.now()-o}`)}}catch(i){if(!n.signal.aborted){let{error:a,code:c}=oe(i),u=$(t,a,c);this.transport.write(JSON.stringify(u)+`
8
- `),this.diagnostics?.record(`[QueryRunner] inbound control_response sent request_id=${t} subtype=${s} status=error duration_ms=${Date.now()-o}`,i)}}finally{this.pendingInboundRequests.delete(t)}}handleControlCancelRequest(e){let t=this.pendingInboundRequests.get(e.request_id);t&&(t.abortController.abort(),this.pendingInboundRequests.delete(e.request_id))}throwIfAborted(e){if(e.aborted)throw new R}validateProtocolHandshake(e){if(this.protocolHandshakeValidated)return;this.protocolHandshakeValidated=!0;let t=e.protocol_version,s=x;if(!t){this.diagnostics?.record(`[QueryRunner] CLI did not announce protocol_version. This SDK was built for ${s}. Consider upgrading qodercli for the version handshake.`);return}let o=W(t),n=W(s);if(!o||!n){this.diagnostics?.record(`[QueryRunner] Could not parse protocol_version "${t}" or built-in "${s}"; skipping handshake.`);return}if(o.major!==n.major)throw new C(t,s);o.minor<n.minor&&this.diagnostics?.record(`[QueryRunner] CLI protocol_version ${t} is older than this SDK's ${s}. New optional fields may be absent.`)}async awaitAbortable(e,t){if(t.aborted)throw new R;return new Promise((s,o)=>{let n=()=>{o(new R)};t.addEventListener("abort",n,{once:!0}),e.then(i=>{t.removeEventListener("abort",n),s(i)},i=>{t.removeEventListener("abort",n),o(i)})})}async processControlRequest(e,t){this.throwIfAborted(t);let s=e.request,o=v(s),n=s;switch(o){case"fetch_job_token":{if(!this.fetchJobToken)throw new Error("job_token_unavailable: No fetchJobToken callback configured");let i=n.reason??"initial",a=n.session_id,c=e.request_id,u=await this.awaitAbortable(this.fetchJobToken({requestId:c,reason:i,sessionId:a},{signal:t}),t);if(!u?.token)throw new Error("job_token_unavailable: Host did not provide a Job Token");return this.diagnostics?.record(`[QueryRunner] fetch_job_token fulfilled: reason=${i}`),{token:u.token}}case"can_use_tool":{let i=n.tool_name,a=n.input??{};if(!this.canUseTool)throw new Error("canUseTool callback is not provided.");let c=n.tool_use_id,u=n.permission_suggestions??n.suggestions,p=n.blocked_path,d=n.decision_reason,l=n.title,g=n.display_name,h=n.description,f=n.agent_id,m=await this.awaitAbortable(this.canUseTool(i,a,{signal:t,suggestions:u,blockedPath:p,decisionReason:d,title:l,displayName:g,description:h,toolUseID:c,agentID:f}),t);if(m.behavior==="deny"&&!m.message)throw new Error("Permission deny result must include a message.");return m.behavior==="allow"?{...m,updatedInput:m.updatedInput??a,toolUseID:c}:{...m,toolUseID:c}}case"hook_callback":{let i=n.callback_id;if(!i)throw new Error("Hook callback missing callback_id");return this.invokeRegisteredHookCallback(i,n.input,n.tool_use_id,t)}case"mcp_message":{let i=n.server_name,a=n.message,c=this.sdkMcpTransports.get(i);if(!c)throw new Error(`Unknown in-process MCP server: ${i}`);return{mcp_response:await this.awaitAbortable(E(i,a,c,this.pendingMcpResponses),t)}}case"elicitation":case"elicitation_response":return this.onElicitation?await this.awaitAbortable(this.onElicitation({serverName:n.mcp_server_name??"",message:n.message??n.prompt??"",mode:n.mode,url:n.url,elicitationId:n.elicitation_id,requestedSchema:n.requested_schema,title:n.title,displayName:n.display_name,description:n.description},{signal:t}),t):{action:"cancel"};case"get_model_policy":{if(!this.resolveModel)return{type:"get_model_policy"};let i={purpose:n.purpose,sessionId:n.sessionId,turnIndex:n.turnIndex,availableModels:n.models??[]},a=this.resolveModelTimeoutMs,c=Promise.resolve(this.resolveModel(i)),u,p=new Promise((g,h)=>{u=setTimeout(()=>{h(new M(a))},a)}),d;try{d=await this.awaitAbortable(Promise.race([c,p]),t)}finally{clearTimeout(u)}let l={type:"get_model_policy",model:typeof d.model=="string"?d.model:d.model.model,parameters:d.parameters};if(typeof d.model!="string"){let{model:g,...h}=d.model;l.custom_model={...h,style:h.style??"openai"}}return l}default:throw new Error(`Unhandled control request subtype: ${o??"unknown"}`)}}async initialize(){return this.initializationPromise||(this.initializationPromise=this.performInitialize()),this.initializationPromise}async performInitialize(){let e={type:"initialize",modelPolicyProvider:this.resolveModel!==void 0,supportsCatalogReadyInitialize:!0,initializeTimeoutMs:r.INITIALIZE_TIMEOUT_MS},t={};for(let[o,n]of Object.entries(this.hooks)){if(!n||n.length===0)continue;let i=[];for(let a of n){let c=a.hooks.map(u=>{let p=`hook_${this.nextHookCallbackId++}`;return this.hookCallbacks.set(p,u),p});c.length!==0&&i.push({matcher:a.matcher,hookCallbackIds:c,timeout:a.timeout})}i.length>0&&(t[o]=i)}Object.keys(t).length>0&&(e.hooks=t),this.initConfig.systemPrompt!==void 0&&(e.systemPrompt=this.initConfig.systemPrompt),this.initConfig.appendSystemPrompt!==void 0&&(e.appendSystemPrompt=this.initConfig.appendSystemPrompt),this.initConfig.planModeInstructions!==void 0&&(e.planModeInstructions=this.initConfig.planModeInstructions),this.initConfig.agents&&(e.agents=this.initConfig.agents),this.initConfig.promptSuggestions!==void 0&&(e.promptSuggestions=this.initConfig.promptSuggestions),this.initConfig.enableFileCheckpointing!==void 0&&(e.enableFileCheckpointing=this.initConfig.enableFileCheckpointing),this.jsonSchema&&(e.jsonSchema=this.jsonSchema),this.sdkMcpServers.size>0&&(e.sdkMcpServers=Array.from(this.sdkMcpServers.keys()));let s=await this.request(e,{timeoutMs:r.INITIALIZE_TIMEOUT_MS});if(s&&typeof s=="object"){let o=s;this.initResponse=o}if(!this.initResponse)throw new Error("Failed to receive initialization response");return this.initResponse}async invokeRegisteredHookCallback(e,t,s,o){let n=this.hookCallbacks.get(e);if(!n)throw new Error(`Unknown hook callback: ${e}`);return await this.awaitAbortable(n(t,s,{signal:o}),o)??{continue:!0}}async initializationResult(){return this.initialize()}async streamInput(e){(async()=>{try{await this.initialize();let t=0;for await(let s of e){if(this.closed)break;t+=1,this.transport.write(JSON.stringify(s)+`
8
+ `),this.diagnostics?.record(`[QueryRunner] inbound control_response sent request_id=${t} subtype=${s} status=error duration_ms=${Date.now()-o}`,i)}}finally{this.pendingInboundRequests.delete(t)}}handleControlCancelRequest(e){let t=this.pendingInboundRequests.get(e.request_id);t&&(t.abortController.abort(),this.pendingInboundRequests.delete(e.request_id))}throwIfAborted(e){if(e.aborted)throw new R}validateProtocolHandshake(e){if(this.protocolHandshakeValidated)return;this.protocolHandshakeValidated=!0;let t=e.protocol_version,s=x;if(!t){this.diagnostics?.record(`[QueryRunner] CLI did not announce protocol_version. This SDK was built for ${s}. Consider upgrading qodercli for the version handshake.`);return}let o=W(t),n=W(s);if(!o||!n){this.diagnostics?.record(`[QueryRunner] Could not parse protocol_version "${t}" or built-in "${s}"; skipping handshake.`);return}if(o.major!==n.major)throw new C(t,s);o.minor<n.minor&&this.diagnostics?.record(`[QueryRunner] CLI protocol_version ${t} is older than this SDK's ${s}. New optional fields may be absent.`)}async awaitAbortable(e,t){if(t.aborted)throw new R;return new Promise((s,o)=>{let n=()=>{o(new R)};t.addEventListener("abort",n,{once:!0}),e.then(i=>{t.removeEventListener("abort",n),s(i)},i=>{t.removeEventListener("abort",n),o(i)})})}async processControlRequest(e,t){this.throwIfAborted(t);let s=e.request,o=v(s),n=s;switch(o){case"fetch_job_token":{if(!this.fetchJobToken)throw new Error("job_token_unavailable: No fetchJobToken callback configured");let i=n.reason??"initial",a=n.session_id,c=e.request_id,u=await this.awaitAbortable(this.fetchJobToken({requestId:c,reason:i,sessionId:a},{signal:t}),t);if(!u?.token)throw new Error("job_token_unavailable: Host did not provide a Job Token");return this.diagnostics?.record(`[QueryRunner] fetch_job_token fulfilled: reason=${i}`),{token:u.token}}case"can_use_tool":{let i=n.tool_name,a=n.input??{};if(!this.canUseTool)throw new Error("canUseTool callback is not provided.");let c=n.tool_use_id,u=n.permission_suggestions??n.suggestions,p=n.blocked_path,d=n.decision_reason,l=n.title,g=n.display_name,h=n.description,f=n.agent_id,m=await this.awaitAbortable(this.canUseTool(i,a,{signal:t,suggestions:u,blockedPath:p,decisionReason:d,title:l,displayName:g,description:h,toolUseID:c,agentID:f}),t);if(m.behavior==="deny"&&!m.message)throw new Error("Permission deny result must include a message.");return m.behavior==="allow"?{...m,updatedInput:m.updatedInput??a,toolUseID:c}:{...m,toolUseID:c}}case"hook_callback":{let i=n.callback_id;if(!i)throw new Error("Hook callback missing callback_id");return this.invokeRegisteredHookCallback(i,n.input,n.tool_use_id,t)}case"mcp_message":{let i=n.server_name,a=n.message,c=this.sdkMcpTransports.get(i);if(!c)throw new Error(`Unknown in-process MCP server: ${i}`);return{mcp_response:await this.awaitAbortable(E(i,a,c,this.pendingMcpResponses),t)}}case"elicitation":case"elicitation_response":return this.onElicitation?await this.awaitAbortable(this.onElicitation({serverName:n.mcp_server_name??"",message:n.message??n.prompt??"",mode:n.mode,url:n.url,elicitationId:n.elicitation_id,requestedSchema:n.requested_schema,title:n.title,displayName:n.display_name,description:n.description},{signal:t}),t):{action:"cancel"};case"get_model_policy":{if(!this.resolveModel)return{type:"get_model_policy"};let i={purpose:n.purpose,sessionId:n.sessionId,turnIndex:n.turnIndex,availableModels:n.models??[]},a=this.resolveModelTimeoutMs,c=Promise.resolve(this.resolveModel(i)),u,p=new Promise((g,h)=>{u=setTimeout(()=>{h(new M(a))},a)}),d;try{d=await this.awaitAbortable(Promise.race([c,p]),t)}finally{clearTimeout(u)}let l={type:"get_model_policy",model:typeof d.model=="string"?d.model:d.model.model,parameters:d.parameters};if(typeof d.model!="string"){let{model:g,...h}=d.model;l.custom_model={...h,style:h.style??"openai"}}return l}default:throw new Error(`Unhandled control request subtype: ${o??"unknown"}`)}}async initialize(){return this.initializationPromise||(this.initializationPromise=this.performInitialize()),this.initializationPromise}async performInitialize(){let e={type:"initialize",modelPolicyProvider:this.resolveModel!==void 0,supportsCatalogReadyInitialize:!0,initializeTimeoutMs:r.INITIALIZE_TIMEOUT_MS},t={};for(let[o,n]of Object.entries(this.hooks)){if(!n||n.length===0)continue;let i=[];for(let a of n){let c=a.hooks.map(u=>{let p=`hook_${this.nextHookCallbackId++}`;return this.hookCallbacks.set(p,u),p});c.length!==0&&i.push({matcher:a.matcher,hookCallbackIds:c,timeout:a.timeout})}i.length>0&&(t[o]=i)}Object.keys(t).length>0&&(e.hooks=t),this.initConfig.systemPrompt!==void 0&&(e.systemPrompt=this.initConfig.systemPrompt),this.initConfig.appendSystemPrompt!==void 0&&(e.appendSystemPrompt=this.initConfig.appendSystemPrompt),this.initConfig.planModeInstructions!==void 0&&(e.planModeInstructions=this.initConfig.planModeInstructions),this.initConfig.agents&&(e.agents=this.initConfig.agents),this.initConfig.skills!==void 0&&(e.skills=this.initConfig.skills),this.initConfig.promptSuggestions!==void 0&&(e.promptSuggestions=this.initConfig.promptSuggestions),this.initConfig.enableFileCheckpointing!==void 0&&(e.enableFileCheckpointing=this.initConfig.enableFileCheckpointing),this.jsonSchema&&(e.jsonSchema=this.jsonSchema),this.sdkMcpServers.size>0&&(e.sdkMcpServers=Array.from(this.sdkMcpServers.keys()));let s=await this.request(e,{timeoutMs:r.INITIALIZE_TIMEOUT_MS});if(s&&typeof s=="object"){let o=s;this.initResponse=o}if(!this.initResponse)throw new Error("Failed to receive initialization response");return this.initResponse}async invokeRegisteredHookCallback(e,t,s,o){let n=this.hookCallbacks.get(e);if(!n)throw new Error(`Unknown hook callback: ${e}`);return await this.awaitAbortable(n(t,s,{signal:o}),o)??{continue:!0}}async initializationResult(){return this.initialize()}async streamInput(e){(async()=>{try{await this.initialize();let t=0;for await(let s of e){if(this.closed)break;t+=1,this.transport.write(JSON.stringify(s)+`
9
9
  `),this.recordOutboundSessionMessage(s)}t>0&&this.hasBidirectionalNeeds()&&await this.waitForFirstResult(),this.transport.endInput()}catch(t){this.diagnostics?.record("[QueryRunner] streamInput error:",t),this.inputStream.error(t instanceof Error?t:new Error(String(t))),this.transport.endInput()}})().catch(()=>{})}async interrupt(){await this.request({type:"interrupt"})}async setPermissionMode(e){await this.request({type:"set_permission_mode",mode:e==="yolo"?"bypassPermissions":e})}hasBidirectionalNeeds(){return this.sdkMcpTransports.size>0||Object.keys(this.hooks).length>0||this.canUseTool!==void 0||this.onElicitation!==void 0||this.fetchJobToken!==void 0||this.resolveModel!==void 0}waitForFirstResult(){return this.firstResultReceived||this.closed?Promise.resolve():new Promise(e=>{if(this.abortController?.signal.aborted){e();return}this.firstResultReceivedResolve=e,this.abortController?.signal.addEventListener("abort",()=>e(),{once:!0})})}async setModel(e){await this.request({type:"set_model",model:e??""})}async setProxy(e){await this.request({type:"set_proxy",proxy:e||null})}async generateSessionTitle(e,t){return(await this.request({type:"generate_session_title",description:e,...t?.persist!==void 0?{persist:t.persist}:{}}))?.title??null}async addDirectories(e){if(!Array.isArray(e))throw new Error("directories must be an array");return await this.request({type:"add_directories",directories:e})}async applyFlagSettings(e){await this.request({type:"apply_flag_settings",settings:e})}async supportedCommands(){return(await this.initializationResult()).commands??[]}async getAvailableModels(e){let t={subtype:"get_models",...e?.fetchStrategy?{fetchStrategy:e.fetchStrategy}:{},...e?.uid?{uid:e.uid}:{}};return(await this.request(t))?.models??[]}async listByokProviders(){try{return(await this.request({type:"get_byok_config"}))?.providers??null}catch{return null}}async validateByokModel(e){try{let t=await this.request({type:"validate_byok_model",provider:e.provider,model:e.model,api_key:e.api_key,...e.url!==void 0?{url:e.url}:{},...e.style!==void 0?{style:e.style}:{}});return typeof t?.success=="boolean"?t.success:null}catch{return null}}async supportedAgents(){return(await this.initializationResult()).agents??[]}async accountInfo(){try{let t=await this.request({type:"account_info"});if(t?.account)return t.account}catch{}return(await this.initializationResult()).account??{}}async mcpServerStatus(){return(await this.request({type:"mcp_status"}))?.servers??[]}async getContextUsage(){return await this.request({type:"get_context_usage"})}async getUsageInfo(){try{let e=await this.request({type:"get_usage_info"});return ne(e?.usage)}catch{return null}}async reloadPlugins(){return await this.request({type:"reload_plugins"})}async listPlugins(){return(await this.request({type:"list_plugins"})).plugins}async rewindFiles(e,t){let s={type:"rewind_files",user_message_id:e};t?.dryRun&&(s.dry_run=!0);let n=await this.request(s);if(!t?.dryRun&&n?.canRewind===!1)throw new Error(typeof n.error=="string"&&n.error.length>0?n.error:"Unable to rewind files.");return n}async seedReadState(e,t){await this.request({type:"seed_read_state",path:e,mtime:t})}async reconnectMcpServer(e){await this.request({type:"mcp_reconnect",serverName:e})}async toggleMcpServer(e,t){await this.request({type:"mcp_toggle",serverName:e,enabled:t})}async setMcpServers(e){return await this.request({type:"mcp_set_servers",servers:e})??{added:[],removed:[],errors:{}}}async injectMcpToken(e,t){await this.request({type:"mcp_inject_token",serverName:e,token:t})}async mcpAuthenticate(e,t){let s=await this.request({type:"mcp_authenticate",serverName:e,...t!==void 0?{redirectUri:t}:{}}),o=s?.requiresUserAction===!0,n=typeof s?.authUrl=="string"?s.authUrl:void 0;if(o&&n===void 0)throw new Error("mcp_authenticate response set requiresUserAction=true but did not include an authUrl");return o?{authUrl:n,requiresUserAction:!0}:{requiresUserAction:!1}}async mcpSubmitOAuthCallbackUrl(e,t){await this.request({type:"mcp_oauth_callback_url",serverName:e,callbackUrl:t})}async mcpClearAuth(e){await this.request({type:"mcp_clear_auth",serverName:e})}async close(){if(this.closed)return;this.closed=!0;for(let[,t]of this.pendingInboundRequests)t.abortController.abort();this.pendingInboundRequests.clear(),this.hookCallbacks.clear();let e=new Error("SDK closing");for(let[t,s]of this.sdkMcpTransports){try{await s.close()}catch(o){this.diagnostics?.record(`[QueryRunner] error closing SDK MCP transport "${t}":`,o)}A(t,e,this.pendingMcpResponses)}this.transport.close();try{await this.readLoopPromise}catch{}}async[Symbol.asyncDispose](){await this.close()}};function _(r){return typeof r=="object"&&r!==null}function te(r){return typeof r=="number"&&Number.isFinite(r)}function D(r){return Object.keys(r).length>0}function y(r,e,t){let s=e[t];te(s)&&(r[t]=s)}function k(r,e,t){let s=e[t];typeof s=="string"&&(r[t]=s)}function P(r,e,t){let s=e[t];typeof s=="boolean"&&(r[t]=s)}function V(r){if(!_(r)||Array.isArray(r))return;let e={};return y(e,r,"total"),y(e,r,"used"),y(e,r,"remaining"),y(e,r,"percentage"),k(e,r,"unit"),D(e)?e:void 0}function se(r){if(!_(r)||Array.isArray(r))return;let e=V(r)??{};return k(e,r,"detailUrl"),D(e)?e:void 0}function re(r){if(!_(r)||Array.isArray(r))return;let e={};return y(e,r,"used"),y(e,r,"cap"),y(e,r,"remaining"),y(e,r,"percentage"),P(e,r,"available"),k(e,r,"unit"),D(e)?e:void 0}function ne(r){if(!_(r)||Array.isArray(r))return null;let e={};k(e,r,"userId"),k(e,r,"userType"),y(e,r,"totalUsagePercentage"),P(e,r,"isHighestTier"),y(e,r,"expiresAt"),k(e,r,"upgradeUrl"),P(e,r,"isQuotaExceeded"),P(e,r,"isPlanQuotaProrated");let t=V(r.userQuota);t&&(e.userQuota=t);let s=se(r.addOnQuota);s&&(e.addOnQuota=s);let o=re(r.orgResourcePackage);return o&&(e.orgResourcePackage=o),e}function oe(r){let e=r instanceof Error?r.message:String(r),t=typeof r=="object"&&r!==null?r.code:void 0,s=typeof t=="string"&&t.length>0?t:void 0,o=/^([a-z][a-z0-9_]*):\s*(.*)$/.exec(e);if(o){let n=s??o[1];return(!s||s===o[1])&&(e=o[2]||e),{error:e,code:n}}return s?{error:e,code:s}:{error:e}}function W(r){let e=/^(\d+)\.(\d+)(?:\.\d+)?(?:[-+].*)?$/.exec(r);return e?{major:Number(e[1]),minor:Number(e[2])}:null}var q=class{sendMcpMessage;isClosed=!1;onclose;onerror;onmessage;constructor(e){this.sendMcpMessage=e}async start(){}async send(e){if(this.isClosed)throw new Error("Transport is closed");this.sendMcpMessage(e)}async close(){this.isClosed||(this.isClosed=!0,this.onclose?.())}get closed(){return this.isClosed}};function ie(r){let{prompt:e,websocket:t,abortController:s,canUseTool:o,hooks:n,mcpServers:i,jsonSchema:a}=r,c=new Map,u=new Map,p=new Map;if(i)for(let[g,h]of Object.entries(i))if(h.type==="sdk"&&"instance"in h){let f=h.instance;c.set(g,f);let m=new q(T=>{K(g,T,p)});u.set(g,m),f.connect(m).catch(()=>{})}else throw new Error(`Browser SDK only supports SDK MCP servers. Server "${g}" has type "${h.type}".`);let d=new w({url:t.url,headers:t.headers,authMessage:t.authMessage,abortController:s}),l=new I(d,!0,o,n,s,c,a,{},void 0,void 0,void 0,void 0,u,p);return l.streamInput(e),l}export{Z as createSdkMcpServer,ie as query,Y as tool};
@@ -24,7 +24,7 @@ export declare const KILL_GRACE_MS = 5000;
24
24
  /**
25
25
  * Current SDK version, sent to CLI as QODER_AGENT_SDK_VERSION environment variable.
26
26
  */
27
- export declare const SDK_VERSION = "1.0.13";
27
+ export declare const SDK_VERSION = "1.0.15";
28
28
  /**
29
29
  * Value for the `--permission-prompt-tool` CLI flag.
30
30
  *
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- var ms=Object.defineProperty;var hs=(s,e)=>{for(var t in e)ms(s,t,{get:e[t],enumerable:!0})};import{spawn as Us}from"child_process";import{createInterface as js}from"readline";var ys=["PreToolUse","PostToolUse","PostToolUseFailure","UserPromptSubmit","SessionStart","SessionEnd","Stop","SubagentStart","SubagentStop","PreCompact","PostCompact","CwdChanged","InstructionsLoaded","FileChanged","PermissionRequest"],Ss=["clear","resume","logout","prompt_input_exit","other","bypass_permissions_disabled"];var We="1.0.13";var Be=["Agent","AskUserQuestion","Bash","Edit","Glob","Grep","ImageGen","ImageSearch","NotebookEdit","Read","Skill","TodoWrite","WebFetch","WebSearch","Write"];import{chmod as Je,mkdtemp as vs,rm as Ge,writeFile as ks}from"fs/promises";import{existsSync as Pe,mkdtempSync as ws,readFileSync as bs,rmSync as Ps,writeFileSync as Rs}from"fs";import{tmpdir as Ve}from"os";import{dirname as rt,join as E}from"path";import{fileURLToPath as Ts}from"url";var Ye="QODER_AGENT_SDK_ENTRYPOINT",Xe="QODER_AGENT_SDK_VERSION",Ze="QODER_SDK_AUTH_PAYLOAD_FILE",Es="sdk-ts",Ms=["HTTPS_PROXY","https_proxy","HTTP_PROXY","http_proxy"],Cs=Ts(import.meta.url),et=rt(Cs),be=class extends Error{code="auth_access_token_env_var_not_configured";constructor(e){super(`The auth access token environment variable "${e}" is not set; set it or pass auth.accessToken directly.`),this.name="AuthAccessTokenEnvVarError"}};function nt(s){return/\.(js|mjs|tsx?|jsx)$/.test(s)}function ot(){if(process.env.QODERCLI_PATH)return process.env.QODERCLI_PATH;let s=_s();if(s)return s;let e=xs();return Pe(e)?e:"qodercli"}function _s(){let s=process.platform==="win32"?"qodercli.exe":"qodercli";for(let e of it()){let t=E(e,"dist","_bundled",s);if(Pe(t))return t}return null}function xs(){let s=process.platform==="win32"?"qodercli.exe":"qodercli";for(let e of it()){let t=[E(e,"node_modules",".bin",s),E(e,"..","..",".bin",s)];for(let r of t)if(Pe(r))return r}return"qodercli"}function it(){let s=[E(et,".."),E(et,"..","..")];return[...new Set(s)]}function Is(){return{allow:[],ask:[],deny:[]}}function tt(s){return s.replace(/[^a-zA-Z0-9_-]/g,"_").replace(/_+/g,"_").replace(/^_|_$/g,"")}function As(s,e){if(e.startsWith("mcp__"))return e;let t=tt(s),r=e==="*"?"*":tt(e);if(!t||!r)throw new Error(`Invalid MCP tool policy name for server "${s}" and tool "${e}"`);return`mcp__${t}__${r}`}function st(s,e){if(e.length===0)return;let t=new Set(s);for(let r of e)t.has(r)||(s.push(r),t.add(r))}function Os(s){let e=s??{},t=e.general&&typeof e.general=="object"&&!Array.isArray(e.general)?e.general:{},r=t.fileCheckpointing&&typeof t.fileCheckpointing=="object"&&!Array.isArray(t.fileCheckpointing)?t.fileCheckpointing:{};return{...e,general:{...t,fileCheckpointing:{...r,enabled:!0}}}}var K=class{options;diagnostics;logPrefix;authPayloadPath=null;generatedSettingsDir;constructor(e,t,r="[RuntimeLaunch]"){this.options=e,this.diagnostics=t,this.logPrefix=r}async prepare(){return this.options.auth&&(this.authPayloadPath=await this.createAuthPayloadFile(this.options.auth)),{args:this.buildArgs(),env:this.buildEnv(),authPayloadPath:this.authPayloadPath??void 0}}cleanupGeneratedSettings(){if(this.generatedSettingsDir)try{Ps(this.generatedSettingsDir,{recursive:!0,force:!0})}catch{}finally{this.generatedSettingsDir=void 0}}async cleanupAuthPayload(){if(!this.authPayloadPath)return;let e=rt(this.authPayloadPath);try{await Ge(e,{recursive:!0,force:!0}),this.diagnostics?.record(`${this.logPrefix} Auth payload cleaned up`)}catch{}this.authPayloadPath=null}buildEnv(){let e=this.options.env??{...process.env},t={};for(let[r,o]of Object.entries(e))o!==void 0&&(t[r]=o);if(delete t[Ye],delete t[Xe],delete t[Ze],t[Ye]=Es,t[Xe]=We,this.authPayloadPath&&(t[Ze]=this.authPayloadPath),delete t.NODE_OPTIONS,this.options.proxy!==void 0)for(let r of Ms)t[r]=this.options.proxy;return t}buildArgs(){let e=[],t=this.options;if(e.push("--print"),e.push("--output-format","stream-json"),e.push("--input-format","stream-json"),t.model&&e.push("--model",t.model),t.agent&&e.push("--agent",t.agent),t.debug&&e.push("--debug"),t.resume?e.push("--resume",t.resume):t.continue&&e.push("--continue"),t.sessionId&&e.push("--session-id",t.sessionId),t.permissionMode&&(t.permissionMode==="yolo"?e.push("--yolo"):e.push("--permission-mode",t.permissionMode)),t.allowDangerouslySkipPermissions&&t.permissionMode!=="yolo"&&e.push("--dangerously-skip-permissions"),t.includePartialMessages&&e.push("--include-partial-messages"),t.allowedTools&&t.allowedTools.length>0)for(let n of t.allowedTools)e.push("--allowed-tools",n);if(t.disallowedTools&&t.disallowedTools.length>0)for(let n of t.disallowedTools)e.push("--disallowed-tools",n);let r=t.tools??[...Be];if(Array.isArray(r)?e.push("--tools",r.join(",")):e.push("--tools","default"),t.canUseTool){if(t.permissionPromptToolName)throw new Error("canUseTool callback cannot be used with permissionPromptToolName. Please use one or the other.");e.push("--permission-prompt-tool","stdio")}else t.permissionPromptToolName&&e.push("--permission-prompt-tool",t.permissionPromptToolName);if(t.extensions&&t.extensions.length>0)for(let n of t.extensions)e.push("--extensions",n);if(t.mcpServers&&Object.keys(t.mcpServers).length>0&&e.push("--mcp-config",JSON.stringify({mcpServers:this.buildCliMcpServers()})),t.allowedMcpServerNames&&t.allowedMcpServerNames.length>0)for(let n of t.allowedMcpServerNames)e.push("--allowed-mcp-server-names",n);t.strictMcpConfig&&e.push("--strict-mcp-config");let o=this.buildSettingsArg();if(o!==void 0&&e.push("--settings",o),t.settingSources!==void 0&&e.push("--setting-sources",t.settingSources.join(",")),e.push("--disable-builtin-skills"),t.additionalDirectories&&t.additionalDirectories.length>0)for(let n of t.additionalDirectories)e.push("--add-dir",n);if(t.maxTurns!==void 0&&e.push("--max-turns",String(t.maxTurns)),t.forkSession&&e.push("--fork-session"),t.plugins&&t.plugins.length>0)for(let n of t.plugins)n.type==="local"&&e.push("--plugin-dir",n.path);if(t.extraArgs)for(let[n,i]of Object.entries(t.extraArgs))e.push(`--${n}`),i!==null&&e.push(i);return e}buildSettingsArg(){let e=this.options.settings,t=this.collectMcpPolicyPermissionRules();if(typeof e=="string"){if(e.length===0)return;if(!this.hasMcpPolicyRules(t)&&!this.options.enableFileCheckpointing&&(!this.options.additionalDirectories||this.options.additionalDirectories.length===0))return e;let n=this.readSettingsFile(e);this.applySettingsCompatibility(n),this.applyAdditionalDirectories(n),this.applyMcpPolicyRules(n,t);let i=this.applyFileCheckpointingSetting(n);return Object.keys(i).length>0?this.writeGeneratedSettingsFile(i):void 0}let r={...e??{}};this.applySettingsCompatibility(r),this.applyAdditionalDirectories(r),this.applyMcpPolicyRules(r,t);let o=this.applyFileCheckpointingSetting(r);return Object.keys(o).length>0?JSON.stringify(o):void 0}applyFileCheckpointingSetting(e){return this.options.enableFileCheckpointing?Os(e):e}applySettingsCompatibility(e){let t=e.permissions;if(t?.defaultMode!==void 0){let r=e.general!==null&&typeof e.general=="object"?e.general:{},o=this.toQoderDefaultPermissionMode(t.defaultMode);o!==void 0&&r.defaultPermissionMode===void 0&&(r.defaultPermissionMode=o),e.general=r}t?.disableBypassPermissionsMode==="disable"&&(e.security={...e.security??{},disableYoloMode:!0})}toQoderDefaultPermissionMode(e){switch(e){case"acceptEdits":return"accept_edits";case"bypassPermissions":case"yolo":return"bypass_permissions";case"dontAsk":return"dont_ask";case"default":case"accept_edits":case"bypass_permissions":case"dont_ask":case"plan":case"auto":return e;default:return}}applyAdditionalDirectories(e){let t=this.options.additionalDirectories;if(!t||t.length===0)return;let r=e.permissions!==null&&typeof e.permissions=="object"?e.permissions:{},o=Array.isArray(r.additionalDirectories)?[...r.additionalDirectories]:[];st(o,t),r.additionalDirectories=o,e.permissions=r}buildCliMcpServers(){let e=this.options.mcpServers;if(!e||Object.keys(e).length===0)return e;let t={};for(let[r,o]of Object.entries(e)){let{tools:n,...i}=o;t[r]=i}return t}collectMcpPolicyPermissionRules(){let e=Is(),t=new Map;for(let[r,o]of Object.entries(this.options.mcpToolPolicies??{}))o.length>0&&t.set(r,o);for(let[r,o]of Object.entries(this.options.mcpServers??{})){let n=o.tools;Array.isArray(n)&&n.length>0&&t.set(r,[...t.get(r)??[],...n])}for(let[r,o]of t)for(let n of o){let i=As(r,n.name);switch(n.permission_policy){case"always_allow":e.allow.push(i);break;case"always_ask":e.ask.push(i);break;case"always_deny":e.deny.push(i);break}}return e}hasMcpPolicyRules(e){return e.allow.length>0||e.ask.length>0||e.deny.length>0}applyMcpPolicyRules(e,t){if(!this.hasMcpPolicyRules(t))return;let r=e.permissions!==null&&typeof e.permissions=="object"?e.permissions:{};e.permissions=r;for(let o of["allow","ask","deny"]){let n=Array.isArray(r[o])?[...r[o]]:[];st(n,t[o]),r[o]=n}}readSettingsFile(e){let t=bs(e,"utf8").trim();if(!t)return{};let r=JSON.parse(t);if(r===null||typeof r!="object"||Array.isArray(r))throw new Error("Settings file must contain a JSON object.");return r}writeGeneratedSettingsFile(e){this.generatedSettingsDir=ws(E(Ve(),"qoder-agent-sdk-settings-"));let t=E(this.generatedSettingsDir,"settings.json");return Rs(t,JSON.stringify(e),"utf8"),t}async createAuthPayloadFile(e){let t=this.buildAuthPayload(e),r=await vs(E(Ve(),"qoder-sdk-auth-"));try{await Je(r,448);let o=E(r,"payload.json");return await ks(o,JSON.stringify(t),{mode:384}),await Je(o,384),this.diagnostics?.record(`${this.logPrefix} Auth payload created: type=${t.type}, path=${o}`),o}catch(o){throw await Ge(r,{recursive:!0,force:!0}).catch(()=>{}),o}}buildAuthPayload(e){switch(e.type){case"accessToken":return{type:"accessToken",accessToken:this.resolveAccessToken(e)};case"qodercli":return{type:"qodercli"};case"jobToken":return{type:"jobToken",hostTokenCallback:!0}}}resolveAccessToken(e){if(typeof e.accessToken=="string")return e.accessToken;let t=e.accessToken.envVar,r=this.options.env&&Object.hasOwn(this.options.env,t)?this.options.env[t]:process.env[t];if(!r)throw new be(t);return r}};function ae(s,e){let t={...s};for(let[r,o]of Object.entries(e))o!==void 0&&(t[r]=o);return t}var qs=41,at=8192,F=class extends Error{code="QODER_CLI_PROCESS_ERROR";exitCode;signal;stderr;constructor(e,t){super(e,t?.cause?{cause:t.cause}:void 0),this.name="QoderCliProcessError",this.exitCode=t?.exitCode,this.signal=t?.signal,this.stderr=t?.stderr}},B=class s{static default=new s;process=null;customHandle=null;options;ready=!1;closed=!1;initializePromise=null;authExpiredFired=!1;pendingInput=[];diagnostics;processExitError;stderrTail="";launchOptionsBuilder;constructor(e={}){this.options={...e},this.diagnostics=e.diagnostics,this.launchOptionsBuilder=new K(this.options,this.diagnostics,"[ProcessTransport]")}create(e){return new s(ae(this.options,e))}async initialize(){if(!this.ready)return this.initializePromise||(this.initializePromise=this._doInitialize()),this.initializePromise}async _doInitialize(){try{let e=await this.launchOptionsBuilder.prepare(),t=e.args;if(this.closed){await this.cleanupAuthPayload();return}let r=e.env,{command:o,commandArgs:n}=this.resolveExecutable(t);if(this.diagnostics?.record(`[ProcessTransport] Spawning: ${o} ${n.join(" ")}`),this.diagnostics?.record(`[ProcessTransport] CWD: ${this.options.cwd??""}`),this.options.spawnQoderCLIProcess){let i=this.options.spawnQoderCLIProcess({command:o,args:n,cwd:this.options.cwd,env:r,signal:this.options.abortController?.signal??new AbortController().signal});this.customHandle=i,i.once("error",a=>{this.ready=!1,this.processExitError=this.createSpawnError(a),this.diagnostics?.record("[ProcessTransport] Process error:",a),this.cleanupAuthPayload().catch(()=>{})}),i.once("exit",(a,c)=>{this.ready=!1;let u=this.createProcessExitError(a,c);u&&(this.processExitError=u),this.cleanupAuthPayload().catch(()=>{})})}else this.process=Us(o,n,{cwd:this.options.cwd,env:r,stdio:["pipe","pipe",this.options.stderr??"pipe"]}),this.process.on("error",i=>{this.ready=!1,this.processExitError=this.createSpawnError(i),this.diagnostics?.record("[ProcessTransport] Process error:",i),this.cleanupAuthPayload().catch(()=>{})}),this.process.on("exit",(i,a)=>{this.ready=!1,this.diagnostics?.record(`[ProcessTransport] Process exited: code=${i}, signal=${a}`),i===qs&&this.fireAuthExpired();let c=this.createProcessExitError(i,a);c&&(this.processExitError=c),this.cleanupAuthPayload().catch(()=>{})}),this.process.stderr?.on("data",i=>{let a=i.toString();this.appendStderr(a),this.options.stderrHandler?.(a);let c=a.trim();c&&this.diagnostics?.record(`[ProcessTransport] STDERR: ${c}`)});this.ready=!0,this.flushPendingInput()}catch(e){throw await this.cleanupAuthPayload(),e}}write(e){if(this.processExitError)throw this.processExitError;if(this.closed)throw new Error("Transport is not ready or has been closed");let t=e.endsWith(`
1
+ var ms=Object.defineProperty;var hs=(s,e)=>{for(var t in e)ms(s,t,{get:e[t],enumerable:!0})};import{spawn as Us}from"child_process";import{createInterface as js}from"readline";var ys=["PreToolUse","PostToolUse","PostToolUseFailure","UserPromptSubmit","SessionStart","SessionEnd","Stop","SubagentStart","SubagentStop","PreCompact","PostCompact","CwdChanged","InstructionsLoaded","FileChanged","PermissionRequest"],Ss=["clear","resume","logout","prompt_input_exit","other","bypass_permissions_disabled"];var We="1.0.15";var Be=["Agent","AskUserQuestion","Bash","Edit","Glob","Grep","ImageGen","ImageSearch","NotebookEdit","Read","Skill","TodoWrite","WebFetch","WebSearch","Write"];import{chmod as Je,mkdtemp as vs,rm as Ge,writeFile as ks}from"fs/promises";import{existsSync as Pe,mkdtempSync as ws,readFileSync as bs,rmSync as Ps,writeFileSync as Rs}from"fs";import{tmpdir as Ve}from"os";import{dirname as rt,join as E}from"path";import{fileURLToPath as Ts}from"url";var Ye="QODER_AGENT_SDK_ENTRYPOINT",Xe="QODER_AGENT_SDK_VERSION",Ze="QODER_SDK_AUTH_PAYLOAD_FILE",Es="sdk-ts",Ms=["HTTPS_PROXY","https_proxy","HTTP_PROXY","http_proxy"],Cs=Ts(import.meta.url),et=rt(Cs),be=class extends Error{code="auth_access_token_env_var_not_configured";constructor(e){super(`The auth access token environment variable "${e}" is not set; set it or pass auth.accessToken directly.`),this.name="AuthAccessTokenEnvVarError"}};function nt(s){return/\.(js|mjs|tsx?|jsx)$/.test(s)}function ot(){if(process.env.QODERCLI_PATH)return process.env.QODERCLI_PATH;let s=_s();if(s)return s;let e=xs();return Pe(e)?e:"qodercli"}function _s(){let s=process.platform==="win32"?"qodercli.exe":"qodercli";for(let e of it()){let t=E(e,"dist","_bundled",s);if(Pe(t))return t}return null}function xs(){let s=process.platform==="win32"?"qodercli.exe":"qodercli";for(let e of it()){let t=[E(e,"node_modules",".bin",s),E(e,"..","..",".bin",s)];for(let r of t)if(Pe(r))return r}return"qodercli"}function it(){let s=[E(et,".."),E(et,"..","..")];return[...new Set(s)]}function Is(){return{allow:[],ask:[],deny:[]}}function tt(s){return s.replace(/[^a-zA-Z0-9_-]/g,"_").replace(/_+/g,"_").replace(/^_|_$/g,"")}function As(s,e){if(e.startsWith("mcp__"))return e;let t=tt(s),r=e==="*"?"*":tt(e);if(!t||!r)throw new Error(`Invalid MCP tool policy name for server "${s}" and tool "${e}"`);return`mcp__${t}__${r}`}function st(s,e){if(e.length===0)return;let t=new Set(s);for(let r of e)t.has(r)||(s.push(r),t.add(r))}function Os(s){let e=s??{},t=e.general&&typeof e.general=="object"&&!Array.isArray(e.general)?e.general:{},r=t.fileCheckpointing&&typeof t.fileCheckpointing=="object"&&!Array.isArray(t.fileCheckpointing)?t.fileCheckpointing:{};return{...e,general:{...t,fileCheckpointing:{...r,enabled:!0}}}}var K=class{options;diagnostics;logPrefix;authPayloadPath=null;generatedSettingsDir;constructor(e,t,r="[RuntimeLaunch]"){this.options=e,this.diagnostics=t,this.logPrefix=r}async prepare(){return this.options.auth&&(this.authPayloadPath=await this.createAuthPayloadFile(this.options.auth)),{args:this.buildArgs(),env:this.buildEnv(),authPayloadPath:this.authPayloadPath??void 0}}cleanupGeneratedSettings(){if(this.generatedSettingsDir)try{Ps(this.generatedSettingsDir,{recursive:!0,force:!0})}catch{}finally{this.generatedSettingsDir=void 0}}async cleanupAuthPayload(){if(!this.authPayloadPath)return;let e=rt(this.authPayloadPath);try{await Ge(e,{recursive:!0,force:!0}),this.diagnostics?.record(`${this.logPrefix} Auth payload cleaned up`)}catch{}this.authPayloadPath=null}buildEnv(){let e=this.options.env??{...process.env},t={};for(let[r,o]of Object.entries(e))o!==void 0&&(t[r]=o);if(delete t[Ye],delete t[Xe],delete t[Ze],t[Ye]=Es,t[Xe]=We,this.authPayloadPath&&(t[Ze]=this.authPayloadPath),delete t.NODE_OPTIONS,this.options.proxy!==void 0)for(let r of Ms)t[r]=this.options.proxy;return t}buildArgs(){let e=[],t=this.options;if(e.push("--print"),e.push("--output-format","stream-json"),e.push("--input-format","stream-json"),t.model&&e.push("--model",t.model),t.agent&&e.push("--agent",t.agent),t.debug&&e.push("--debug"),t.resume?e.push("--resume",t.resume):t.continue&&e.push("--continue"),t.sessionId&&e.push("--session-id",t.sessionId),t.permissionMode&&(t.permissionMode==="yolo"?e.push("--yolo"):e.push("--permission-mode",t.permissionMode)),t.allowDangerouslySkipPermissions&&t.permissionMode!=="yolo"&&e.push("--dangerously-skip-permissions"),t.includePartialMessages&&e.push("--include-partial-messages"),t.allowedTools&&t.allowedTools.length>0)for(let n of t.allowedTools)e.push("--allowed-tools",n);if(t.disallowedTools&&t.disallowedTools.length>0)for(let n of t.disallowedTools)e.push("--disallowed-tools",n);let r=t.tools??[...Be];if(Array.isArray(r)?e.push("--tools",r.join(",")):e.push("--tools","default"),t.canUseTool){if(t.permissionPromptToolName)throw new Error("canUseTool callback cannot be used with permissionPromptToolName. Please use one or the other.");e.push("--permission-prompt-tool","stdio")}else t.permissionPromptToolName&&e.push("--permission-prompt-tool",t.permissionPromptToolName);if(t.extensions&&t.extensions.length>0)for(let n of t.extensions)e.push("--extensions",n);if(t.mcpServers&&Object.keys(t.mcpServers).length>0&&e.push("--mcp-config",JSON.stringify({mcpServers:this.buildCliMcpServers()})),t.allowedMcpServerNames&&t.allowedMcpServerNames.length>0)for(let n of t.allowedMcpServerNames)e.push("--allowed-mcp-server-names",n);t.strictMcpConfig&&e.push("--strict-mcp-config");let o=this.buildSettingsArg();if(o!==void 0&&e.push("--settings",o),t.settingSources!==void 0&&e.push("--setting-sources",t.settingSources.join(",")),e.push("--disable-builtin-skills"),t.additionalDirectories&&t.additionalDirectories.length>0)for(let n of t.additionalDirectories)e.push("--add-dir",n);if(t.maxTurns!==void 0&&e.push("--max-turns",String(t.maxTurns)),t.forkSession&&e.push("--fork-session"),t.plugins&&t.plugins.length>0)for(let n of t.plugins)n.type==="local"&&e.push("--plugin-dir",n.path);if(t.extraArgs)for(let[n,i]of Object.entries(t.extraArgs))e.push(`--${n}`),i!==null&&e.push(i);return e}buildSettingsArg(){let e=this.options.settings,t=this.collectMcpPolicyPermissionRules();if(typeof e=="string"){if(e.length===0)return;if(!this.hasMcpPolicyRules(t)&&!this.options.enableFileCheckpointing&&(!this.options.additionalDirectories||this.options.additionalDirectories.length===0))return e;let n=this.readSettingsFile(e);this.applySettingsCompatibility(n),this.applyAdditionalDirectories(n),this.applyMcpPolicyRules(n,t);let i=this.applyFileCheckpointingSetting(n);return Object.keys(i).length>0?this.writeGeneratedSettingsFile(i):void 0}let r={...e??{}};this.applySettingsCompatibility(r),this.applyAdditionalDirectories(r),this.applyMcpPolicyRules(r,t);let o=this.applyFileCheckpointingSetting(r);return Object.keys(o).length>0?JSON.stringify(o):void 0}applyFileCheckpointingSetting(e){return this.options.enableFileCheckpointing?Os(e):e}applySettingsCompatibility(e){let t=e.permissions;if(t?.defaultMode!==void 0){let r=e.general!==null&&typeof e.general=="object"?e.general:{},o=this.toQoderDefaultPermissionMode(t.defaultMode);o!==void 0&&r.defaultPermissionMode===void 0&&(r.defaultPermissionMode=o),e.general=r}t?.disableBypassPermissionsMode==="disable"&&(e.security={...e.security??{},disableYoloMode:!0})}toQoderDefaultPermissionMode(e){switch(e){case"acceptEdits":return"accept_edits";case"bypassPermissions":case"yolo":return"bypass_permissions";case"dontAsk":return"dont_ask";case"default":case"accept_edits":case"bypass_permissions":case"dont_ask":case"plan":case"auto":return e;default:return}}applyAdditionalDirectories(e){let t=this.options.additionalDirectories;if(!t||t.length===0)return;let r=e.permissions!==null&&typeof e.permissions=="object"?e.permissions:{},o=Array.isArray(r.additionalDirectories)?[...r.additionalDirectories]:[];st(o,t),r.additionalDirectories=o,e.permissions=r}buildCliMcpServers(){let e=this.options.mcpServers;if(!e||Object.keys(e).length===0)return e;let t={};for(let[r,o]of Object.entries(e)){let{tools:n,...i}=o;t[r]=i}return t}collectMcpPolicyPermissionRules(){let e=Is(),t=new Map;for(let[r,o]of Object.entries(this.options.mcpToolPolicies??{}))o.length>0&&t.set(r,o);for(let[r,o]of Object.entries(this.options.mcpServers??{})){let n=o.tools;Array.isArray(n)&&n.length>0&&t.set(r,[...t.get(r)??[],...n])}for(let[r,o]of t)for(let n of o){let i=As(r,n.name);switch(n.permission_policy){case"always_allow":e.allow.push(i);break;case"always_ask":e.ask.push(i);break;case"always_deny":e.deny.push(i);break}}return e}hasMcpPolicyRules(e){return e.allow.length>0||e.ask.length>0||e.deny.length>0}applyMcpPolicyRules(e,t){if(!this.hasMcpPolicyRules(t))return;let r=e.permissions!==null&&typeof e.permissions=="object"?e.permissions:{};e.permissions=r;for(let o of["allow","ask","deny"]){let n=Array.isArray(r[o])?[...r[o]]:[];st(n,t[o]),r[o]=n}}readSettingsFile(e){let t=bs(e,"utf8").trim();if(!t)return{};let r=JSON.parse(t);if(r===null||typeof r!="object"||Array.isArray(r))throw new Error("Settings file must contain a JSON object.");return r}writeGeneratedSettingsFile(e){this.generatedSettingsDir=ws(E(Ve(),"qoder-agent-sdk-settings-"));let t=E(this.generatedSettingsDir,"settings.json");return Rs(t,JSON.stringify(e),"utf8"),t}async createAuthPayloadFile(e){let t=this.buildAuthPayload(e),r=await vs(E(Ve(),"qoder-sdk-auth-"));try{await Je(r,448);let o=E(r,"payload.json");return await ks(o,JSON.stringify(t),{mode:384}),await Je(o,384),this.diagnostics?.record(`${this.logPrefix} Auth payload created: type=${t.type}, path=${o}`),o}catch(o){throw await Ge(r,{recursive:!0,force:!0}).catch(()=>{}),o}}buildAuthPayload(e){switch(e.type){case"accessToken":return{type:"accessToken",accessToken:this.resolveAccessToken(e)};case"qodercli":return{type:"qodercli"};case"jobToken":return{type:"jobToken",hostTokenCallback:!0}}}resolveAccessToken(e){if(typeof e.accessToken=="string")return e.accessToken;let t=e.accessToken.envVar,r=this.options.env&&Object.hasOwn(this.options.env,t)?this.options.env[t]:process.env[t];if(!r)throw new be(t);return r}};function ae(s,e){let t={...s};for(let[r,o]of Object.entries(e))o!==void 0&&(t[r]=o);return t}var qs=41,at=8192,F=class extends Error{code="QODER_CLI_PROCESS_ERROR";exitCode;signal;stderr;constructor(e,t){super(e,t?.cause?{cause:t.cause}:void 0),this.name="QoderCliProcessError",this.exitCode=t?.exitCode,this.signal=t?.signal,this.stderr=t?.stderr}},B=class s{static default=new s;process=null;customHandle=null;options;ready=!1;closed=!1;initializePromise=null;authExpiredFired=!1;pendingInput=[];diagnostics;processExitError;stderrTail="";launchOptionsBuilder;constructor(e={}){this.options={...e},this.diagnostics=e.diagnostics,this.launchOptionsBuilder=new K(this.options,this.diagnostics,"[ProcessTransport]")}create(e){return new s(ae(this.options,e))}async initialize(){if(!this.ready)return this.initializePromise||(this.initializePromise=this._doInitialize()),this.initializePromise}async _doInitialize(){try{let e=await this.launchOptionsBuilder.prepare(),t=e.args;if(this.closed){await this.cleanupAuthPayload();return}let r=e.env,{command:o,commandArgs:n}=this.resolveExecutable(t);if(this.diagnostics?.record(`[ProcessTransport] Spawning: ${o} ${n.join(" ")}`),this.diagnostics?.record(`[ProcessTransport] CWD: ${this.options.cwd??""}`),this.options.spawnQoderCLIProcess){let i=this.options.spawnQoderCLIProcess({command:o,args:n,cwd:this.options.cwd,env:r,signal:this.options.abortController?.signal??new AbortController().signal});this.customHandle=i,i.once("error",a=>{this.ready=!1,this.processExitError=this.createSpawnError(a),this.diagnostics?.record("[ProcessTransport] Process error:",a),this.cleanupAuthPayload().catch(()=>{})}),i.once("exit",(a,c)=>{this.ready=!1;let u=this.createProcessExitError(a,c);u&&(this.processExitError=u),this.cleanupAuthPayload().catch(()=>{})})}else this.process=Us(o,n,{cwd:this.options.cwd,env:r,stdio:["pipe","pipe",this.options.stderr??"pipe"]}),this.process.on("error",i=>{this.ready=!1,this.processExitError=this.createSpawnError(i),this.diagnostics?.record("[ProcessTransport] Process error:",i),this.cleanupAuthPayload().catch(()=>{})}),this.process.on("exit",(i,a)=>{this.ready=!1,this.diagnostics?.record(`[ProcessTransport] Process exited: code=${i}, signal=${a}`),i===qs&&this.fireAuthExpired();let c=this.createProcessExitError(i,a);c&&(this.processExitError=c),this.cleanupAuthPayload().catch(()=>{})}),this.process.stderr?.on("data",i=>{let a=i.toString();this.appendStderr(a),this.options.stderrHandler?.(a);let c=a.trim();c&&this.diagnostics?.record(`[ProcessTransport] STDERR: ${c}`)});this.ready=!0,this.flushPendingInput()}catch(e){throw await this.cleanupAuthPayload(),e}}write(e){if(this.processExitError)throw this.processExitError;if(this.closed)throw new Error("Transport is not ready or has been closed");let t=e.endsWith(`
2
2
  `)?e:e+`
3
3
  `;if(!this.ready){if(this.initializePromise){this.pendingInput.push({type:"write",line:t});return}throw new Error("Transport is not ready or has been closed")}this.writeReadyLine(t)}writeReadyLine(e){if(this.customHandle){let t=this.customHandle.stdin;if(t.destroyed||t.writableEnded)return;typeof t.write=="function"&&t.write(e)}else this.process?.stdin&&!this.process.stdin.destroyed&&!this.process.stdin.writableEnded&&this.process.stdin.write(e)}flushPendingInput(){if(this.pendingInput.length===0)return;let e=this.pendingInput;this.pendingInput=[];for(let t of e)t.type==="write"?this.writeReadyLine(t.line):this.endReadyInput()}isReady(){return this.ready&&!this.closed}endInput(){if(!this.ready&&!this.process&&!this.customHandle){this.initializePromise&&this.pendingInput.push({type:"end"});return}this.endReadyInput()}endReadyInput(){if(this.customHandle){let e=this.customHandle.stdin;if(e.destroyed||e.writableEnded)return;typeof e.end=="function"&&e.end()}else this.process?.stdin&&!this.process.stdin.destroyed&&!this.process.stdin.writableEnded&&this.process.stdin.end()}async*readMessages(){this.initializePromise&&await this.initializePromise;let e=this.getStdout();if(!e)return;let t=js({input:e,crlfDelay:1/0});try{for await(let r of t){if(this.closed)break;let o=r.trim();if(o)try{yield JSON.parse(o)}catch{}}this.closed||await this.waitForProcessExit()}finally{t.close()}}close(){if(this.closed)return;this.closed=!0,this.ready=!1,this.pendingInput=[],this.cleanupGeneratedSettings();let e=this.process,t=this.customHandle;if(this.cleanupAuthPayload().catch(()=>{}),!e&&!t)return;this.endInput();let r=e?a=>{try{e.kill(a)}catch{}}:t?a=>{try{t.kill(a)}catch{}}:void 0;if(!r)return;let o=()=>e?!e.killed&&e.exitCode===null:!0,n=this.options.closeGraceMs??2e3,i=setTimeout(()=>{if(o()){r("SIGTERM");let a=setTimeout(()=>{o()&&r("SIGKILL")},5e3);typeof a=="object"&&"unref"in a&&a.unref()}},n);typeof i=="object"&&"unref"in i&&i.unref(),e?e.once("exit",()=>{clearTimeout(i)}):t?.once&&t.once("exit",()=>{clearTimeout(i)})}cleanupGeneratedSettings(){this.launchOptionsBuilder.cleanupGeneratedSettings()}get pid(){return this.process?.pid??void 0}getStdout(){return this.process?.stdout?this.process.stdout:this.customHandle?.stdout?this.customHandle.stdout:null}appendStderr(e){this.stderrTail+=e,this.stderrTail.length>at&&(this.stderrTail=this.stderrTail.slice(-at))}createSpawnError(e){let t=this.options.pathToQoderCLIExecutable??"qodercli",o=e.code==="ENOENT"?`Qoder CLI executable not found: ${t}`:`Failed to spawn Qoder CLI process: ${e.message}`;return new F(o,{stderr:this.getStderrTail(),cause:e})}createProcessExitError(e,t){if(e!==0&&e!==null)return new F(`Qoder CLI process exited with code ${e}`,{exitCode:e,signal:t,stderr:this.getStderrTail()});if(t)return new F(`Qoder CLI process terminated by signal ${t}`,{exitCode:e,signal:t,stderr:this.getStderrTail()})}getStderrTail(){return this.stderrTail.trim()||void 0}async waitForProcessExit(){if(this.processExitError)throw this.processExitError;let e=this.process??this.customHandle;if(e){if(e.exitCode!==null||e.killed){let t=this.createProcessExitError(e.exitCode,null);if(t)throw this.processExitError=t,t;return}await new Promise((t,r)=>{let o=(i,a)=>{e.off("error",n);let c=this.createProcessExitError(i,a);c?(this.processExitError=c,r(c)):t()},n=i=>{e.off("exit",o);let a=this.createSpawnError(i);this.processExitError=a,r(a)};e.once("exit",o),e.once("error",n)})}}resolveExecutable(e){let t=this.options.pathToQoderCLIExecutable??ot();if(nt(t)){let r=this.options.executable??"node",o=this.options.executableArgs??[];return{command:r,commandArgs:[...o,t,...e]}}return{command:t,commandArgs:e}}async cleanupAuthPayload(){await this.launchOptionsBuilder.cleanupAuthPayload()}fireAuthExpired(){if(!this.authExpiredFired){this.authExpiredFired=!0;try{this.options.onAuthExpired?.()}catch{}}}};function Ns(){switch("process"){case"worker":return"worker";case"process":return"process"}return"process"}var Te=Ns();function ct(s){return typeof s=="object"&&s!==null&&typeof s.create=="function"}function ut(s,e){return s.create(e)}import{existsSync as xe}from"fs";import{createInterface as or}from"readline";import{dirname as ir,join as O}from"path";import{fileURLToPath as ar}from"url";import{Worker as cr}from"worker_threads";import{createHash as Ks}from"node:crypto";import{existsSync as Fs}from"node:fs";import{chmod as Ls,lstat as Hs,mkdir as J,readFile as dt,readdir as $s,readlink as Qs,rename as zs,rm as ce,stat as Ws,symlink as Bs,writeFile as lt}from"node:fs/promises";import{tmpdir as Js,userInfo as Gs}from"node:os";import{basename as pt,dirname as L,join as R,relative as Vs}from"node:path";var Ys="QODER_WORKER_RUNTIME_ASSET_ROOT",gt=/(^|[\\/])app\.asar([\\/]|$)/,Me=".qoder-worker-runtime-ready";function ft(s){return gt.test(s)}function Xs(s){return ft(s)?s.replace(gt,(e,t,r)=>`${t}app.asar.unpacked${r}`):null}async function mt(s,e={}){let t=Xs(s);if(!e.forceMaterialize&&t){let c=L(t);if(Fs(t))return e.diagnostics?.record(`[WorkerTransport] Using asar-unpacked worker runtime: ${t}`),Ee(t,c,!1,L(s))}if(!(e.forceMaterialize||ft(s))){let c=L(s);return Ee(s,c,!1)}let o=L(s),n=await Zs(o,s,{cacheDir:e.cacheDir,diagnostics:e.diagnostics}),i=Vs(o,s)||pt(s),a=R(n,i);return Ee(a,n,!0,o)}function Ee(s,e,t,r){return{runtimePath:s,runtimeRoot:e,materialized:t,sourceRuntimeRoot:r,env:{[Ys]:e}}}async function Zs(s,e,t){let r=await er(s,e),o=t.cacheDir??rr(),n=R(o,r),i=R(n,Me);if(await yt(i)===r)return n;let a=R(o,`.setup-${r}-${process.pid}-${Date.now()}`);await J(o,{recursive:!0,mode:448}),await ce(a,{recursive:!0,force:!0}),await ce(n,{recursive:!0,force:!0}),t.diagnostics?.record(`[WorkerTransport] Materializing worker runtime: ${s} -> ${n}`);try{return await J(a,{recursive:!0,mode:448}),await ht(s,a),await lt(R(a,Me),r,{mode:384}),await sr(a,n,r),n}catch(c){throw await ce(a,{recursive:!0,force:!0}).catch(()=>{}),c}}async function er(s,e){let t=Ks("sha256");t.update("qoder-worker-runtime-v1\0");let r=await St(R(s,"runtime-info.json"));if(r)t.update(r);else{t.update(e);let o=await Ws(e).catch(()=>null);o&&t.update(`${o.size}\0${o.mtimeMs}`)}return`runtime-${t.digest("hex").slice(0,24)}`}async function ht(s,e){let t=await $s(s,{withFileTypes:!0});await J(e,{recursive:!0,mode:448});for(let r of t){let o=R(s,r.name),n=R(e,r.name);if(r.isDirectory()){await ht(o,n);continue}if(r.isSymbolicLink()){await J(L(n),{recursive:!0,mode:448}),await Bs(await Qs(o),n);continue}if(!r.isFile())continue;let i=await tr(o);await J(L(n),{recursive:!0,mode:448}),await lt(n,await dt(o),{mode:i}),process.platform!=="win32"&&await Ls(n,i)}}async function tr(s){let e=((await Hs(s)).mode||420)&511;if(process.platform==="win32")return e||420;let t=pt(s);return t==="rg"||t==="spawn-helper"||/\.(?:node|dylib|exe)$/.test(t)||/\.so(?:\.\d+)*$/.test(t)?493:e||420}async function sr(s,e,t){try{await zs(s,e)}catch(r){if(await yt(R(e,Me))===t){await ce(s,{recursive:!0,force:!0});return}throw r}}async function yt(s){let e=await St(s);return e?e.toString("utf8"):null}async function St(s){try{return await dt(s)}catch{return null}}function rr(){let s=nr(Gs().username||process.env.USER||process.env.USERNAME||"user");return R(Js(),`qoder-sdk-worker-runtime-${s}`)}function nr(s){return s.replace(/[^a-zA-Z0-9._-]/g,"_")||"unknown"}var ur=41,vt=8192,kt="QODER_WORKER_RUNTIME_PATH",dr="QODER_WORKER_CWD",lr=new Set(["--mcp-config","--settings"]),pr=ar(import.meta.url),Ce=ir(pr),D=class extends Error{code="QODER_WORKER_RUNTIME_ERROR";exitCode;stderr;constructor(e,t){super(e,t?.cause?{cause:t.cause}:void 0),this.name="QoderWorkerRuntimeError",this.exitCode=t?.exitCode,this.stderr=t?.stderr}},G=class s{static default=new s;options;constructor(e={}){this.options={...e}}create(e){return new _e(ae(this.options,e))}},_e=class{worker=null;options;ready=!1;closed=!1;initializePromise=null;authExpiredFired=!1;pendingInput=[];diagnostics;workerExitError;stderrTail="";observedExitCode=null;launchOptionsBuilder;closeTimer=null;abortSignal;abortListener;constructor(e={}){this.options={...e},this.diagnostics=e.diagnostics,this.launchOptionsBuilder=new K(this.options,this.diagnostics,"[WorkerTransport]")}async initialize(){if(!this.ready)return this.initializePromise||(this.initializePromise=this._doInitialize()),this.initializePromise}async _doInitialize(){try{let e=await this.launchOptionsBuilder.prepare();if(this.closed){await this.cleanupAuthPayload();return}let t=Ie(this.options.pathToQoderWorkerRuntime),r;try{r=await mt(t,{diagnostics:this.diagnostics})}catch(a){throw new D(`Failed to prepare Qoder worker runtime: ${t}`,{cause:a})}let o=r.runtimePath;if(!xe(o))throw new D(`Qoder worker runtime not found: ${o}`);let n=this.options.cwd??process.cwd(),i={...e.env,[dr]:n,...r.env};if(this.diagnostics?.record(`[WorkerTransport] Starting: ${o}`),this.diagnostics?.record(`[WorkerTransport] CWD: ${n}`),this.diagnostics?.record(`[WorkerTransport] Args: ${gr(e.args)}`),this.worker=new cr(o,{argv:e.args,env:i,execArgv:this.options.execArgv??[],stdin:!0,stdout:!0,stderr:!0,workerData:{...this.options.workerData??{},qoderWorkerRuntime:{cwd:n,runtimeRoot:r.runtimeRoot,materialized:r.materialized}}}),this.worker.once("error",a=>{this.ready=!1,this.cleanupAbortListener(),this.closed||(this.workerExitError=this.createWorkerError(a)),this.diagnostics?.record("[WorkerTransport] Worker error:",a),this.destroyWorkerStreams(this.worker),this.cleanupAuthPayload().catch(()=>{})}),this.worker.once("exit",a=>{if(this.ready=!1,this.observedExitCode=a,this.cleanupAbortListener(),this.clearCloseTimer(),this.recordWorkerExit(a),this.destroyWorkerStreams(this.worker),this.closed){a!==0&&this.recordSuppressedWorkerExit(a),this.cleanupAuthPayload().catch(()=>{});return}a===ur&&this.fireAuthExpired();let c=this.createWorkerExitError(a);c&&(this.workerExitError=c),this.cleanupAuthPayload().catch(()=>{})}),this.worker.stderr?.on("data",a=>{let c=a.toString();this.appendStderr(c),this.options.stderr!=="ignore"&&this.options.stderrHandler?.(c),this.options.stderr==="inherit"&&process.stderr.write(c);let u=c.trim();u&&this.diagnostics?.record(`[WorkerTransport] STDERR: ${u}`)}),this.options.abortController){let a=this.options.abortController.signal;a.aborted?this.close():(this.abortSignal=a,this.abortListener=()=>this.close(),a.addEventListener("abort",this.abortListener,{once:!0}))}this.ready=!0,this.flushPendingInput()}catch(e){throw await this.cleanupAuthPayload(),e}}write(e){if(this.workerExitError)throw this.workerExitError;if(this.closed)throw new Error("Transport is not ready or has been closed");let t=e.endsWith(`
4
4
  `)?e:e+`
@@ -8,11 +8,11 @@ ${e.stack??e.message}`;try{return` ${JSON.stringify(e)}`}catch{return` ${String(
8
8
  `)}catch(d){this.diagnostics?.record("[QueryRunner] Failed to send control_cancel_request on timeout:",d)}u(new Error(`Control request "${H(o.request)??"unknown"}" timed out after ${n}ms`))}},n));try{this.diagnostics?.record(`[QueryRunner] control_request sending request_id=${r} subtype=${i} timeout_ms=${n}`),this.transport.write(JSON.stringify(o)+`
9
9
  `),this.diagnostics?.record(`[QueryRunner] control_request sent request_id=${r} subtype=${i}`)}catch(d){g(),this.pendingRequests.delete(r),this.diagnostics?.record(`[QueryRunner] control_request send failed request_id=${r} subtype=${i}`,d),u(d)}})}handleControlResponse(e){let t=e.response,r=t.request_id,o=this.pendingRequests.get(r);if(!o){this.diagnostics?.record(`[QueryRunner] unmatched control_response received request_id=${r} status=${t.subtype}`);return}if(this.pendingRequests.delete(r),t.subtype==="success")o.resolve(t.response);else{let n=new Error(t.error);t.code&&(n.code=t.code),o.reject(n),this.processPendingPermissionRequests(t.pending_permission_requests)}}processPendingPermissionRequests(e){if(e)for(let t of e)H(t.request)==="can_use_tool"&&this.handleControlRequest(t).catch(r=>{this.diagnostics?.record("[QueryRunner] Error handling pending permission request:",r)})}async handleControlRequest(e){let t=e.request_id,r=H(e.request)??"unknown",o=Date.now(),n=new AbortController;this.pendingInboundRequests.set(t,{abortController:n}),this.diagnostics?.record(`[QueryRunner] inbound control_request received request_id=${t} subtype=${r}`);try{let i=await this.awaitAbortable(this.processControlRequest(e,n.signal),n.signal);if(!n.signal.aborted){let a=Et(t,i);this.transport.write(JSON.stringify(a)+`
10
10
  `),this.diagnostics?.record(`[QueryRunner] inbound control_response sent request_id=${t} subtype=${r} status=success duration_ms=${Date.now()-o}`)}}catch(i){if(!n.signal.aborted){let{error:a,code:c}=Mr(i),u=Mt(t,a,c);this.transport.write(JSON.stringify(u)+`
11
- `),this.diagnostics?.record(`[QueryRunner] inbound control_response sent request_id=${t} subtype=${r} status=error duration_ms=${Date.now()-o}`,i)}}finally{this.pendingInboundRequests.delete(t)}}handleControlCancelRequest(e){let t=this.pendingInboundRequests.get(e.request_id);t&&(t.abortController.abort(),this.pendingInboundRequests.delete(e.request_id))}throwIfAborted(e){if(e.aborted)throw new U}validateProtocolHandshake(e){if(this.protocolHandshakeValidated)return;this.protocolHandshakeValidated=!0;let t=e.protocol_version,r=Ae;if(!t){this.diagnostics?.record(`[QueryRunner] CLI did not announce protocol_version. This SDK was built for ${r}. Consider upgrading qodercli for the version handshake.`);return}let o=jt(t),n=jt(r);if(!o||!n){this.diagnostics?.record(`[QueryRunner] Could not parse protocol_version "${t}" or built-in "${r}"; skipping handshake.`);return}if(o.major!==n.major)throw new Y(t,r);o.minor<n.minor&&this.diagnostics?.record(`[QueryRunner] CLI protocol_version ${t} is older than this SDK's ${r}. New optional fields may be absent.`)}async awaitAbortable(e,t){if(t.aborted)throw new U;return new Promise((r,o)=>{let n=()=>{o(new U)};t.addEventListener("abort",n,{once:!0}),e.then(i=>{t.removeEventListener("abort",n),r(i)},i=>{t.removeEventListener("abort",n),o(i)})})}async processControlRequest(e,t){this.throwIfAborted(t);let r=e.request,o=H(r),n=r;switch(o){case"fetch_job_token":{if(!this.fetchJobToken)throw new Error("job_token_unavailable: No fetchJobToken callback configured");let i=n.reason??"initial",a=n.session_id,c=e.request_id,u=await this.awaitAbortable(this.fetchJobToken({requestId:c,reason:i,sessionId:a},{signal:t}),t);if(!u?.token)throw new Error("job_token_unavailable: Host did not provide a Job Token");return this.diagnostics?.record(`[QueryRunner] fetch_job_token fulfilled: reason=${i}`),{token:u.token}}case"can_use_tool":{let i=n.tool_name,a=n.input??{};if(!this.canUseTool)throw new Error("canUseTool callback is not provided.");let c=n.tool_use_id,u=n.permission_suggestions??n.suggestions,p=n.blocked_path,g=n.decision_reason,d=n.title,l=n.display_name,f=n.description,S=n.agent_id,h=await this.awaitAbortable(this.canUseTool(i,a,{signal:t,suggestions:u,blockedPath:p,decisionReason:g,title:d,displayName:l,description:f,toolUseID:c,agentID:S}),t);if(h.behavior==="deny"&&!h.message)throw new Error("Permission deny result must include a message.");return h.behavior==="allow"?{...h,updatedInput:h.updatedInput??a,toolUseID:c}:{...h,toolUseID:c}}case"hook_callback":{let i=n.callback_id;if(!i)throw new Error("Hook callback missing callback_id");return this.invokeRegisteredHookCallback(i,n.input,n.tool_use_id,t)}case"mcp_message":{let i=n.server_name,a=n.message,c=this.sdkMcpTransports.get(i);if(!c)throw new Error(`Unknown in-process MCP server: ${i}`);return{mcp_response:await this.awaitAbortable(wt(i,a,c,this.pendingMcpResponses),t)}}case"elicitation":case"elicitation_response":return this.onElicitation?await this.awaitAbortable(this.onElicitation({serverName:n.mcp_server_name??"",message:n.message??n.prompt??"",mode:n.mode,url:n.url,elicitationId:n.elicitation_id,requestedSchema:n.requested_schema,title:n.title,displayName:n.display_name,description:n.description},{signal:t}),t):{action:"cancel"};case"get_model_policy":{if(!this.resolveModel)return{type:"get_model_policy"};let i={purpose:n.purpose,sessionId:n.sessionId,turnIndex:n.turnIndex,availableModels:n.models??[]},a=this.resolveModelTimeoutMs,c=Promise.resolve(this.resolveModel(i)),u,p=new Promise((l,f)=>{u=setTimeout(()=>{f(new V(a))},a)}),g;try{g=await this.awaitAbortable(Promise.race([c,p]),t)}finally{clearTimeout(u)}let d={type:"get_model_policy",model:typeof g.model=="string"?g.model:g.model.model,parameters:g.parameters};if(typeof g.model!="string"){let{model:l,...f}=g.model;d.custom_model={...f,style:f.style??"openai"}}return d}default:throw new Error(`Unhandled control request subtype: ${o??"unknown"}`)}}async initialize(){return this.initializationPromise||(this.initializationPromise=this.performInitialize()),this.initializationPromise}async performInitialize(){let e={type:"initialize",modelPolicyProvider:this.resolveModel!==void 0,supportsCatalogReadyInitialize:!0,initializeTimeoutMs:s.INITIALIZE_TIMEOUT_MS},t={};for(let[o,n]of Object.entries(this.hooks)){if(!n||n.length===0)continue;let i=[];for(let a of n){let c=a.hooks.map(u=>{let p=`hook_${this.nextHookCallbackId++}`;return this.hookCallbacks.set(p,u),p});c.length!==0&&i.push({matcher:a.matcher,hookCallbackIds:c,timeout:a.timeout})}i.length>0&&(t[o]=i)}Object.keys(t).length>0&&(e.hooks=t),this.initConfig.systemPrompt!==void 0&&(e.systemPrompt=this.initConfig.systemPrompt),this.initConfig.appendSystemPrompt!==void 0&&(e.appendSystemPrompt=this.initConfig.appendSystemPrompt),this.initConfig.planModeInstructions!==void 0&&(e.planModeInstructions=this.initConfig.planModeInstructions),this.initConfig.agents&&(e.agents=this.initConfig.agents),this.initConfig.promptSuggestions!==void 0&&(e.promptSuggestions=this.initConfig.promptSuggestions),this.initConfig.enableFileCheckpointing!==void 0&&(e.enableFileCheckpointing=this.initConfig.enableFileCheckpointing),this.jsonSchema&&(e.jsonSchema=this.jsonSchema),this.sdkMcpServers.size>0&&(e.sdkMcpServers=Array.from(this.sdkMcpServers.keys()));let r=await this.request(e,{timeoutMs:s.INITIALIZE_TIMEOUT_MS});if(r&&typeof r=="object"){let o=r;this.initResponse=o}if(!this.initResponse)throw new Error("Failed to receive initialization response");return this.initResponse}async invokeRegisteredHookCallback(e,t,r,o){let n=this.hookCallbacks.get(e);if(!n)throw new Error(`Unknown hook callback: ${e}`);return await this.awaitAbortable(n(t,r,{signal:o}),o)??{continue:!0}}async initializationResult(){return this.initialize()}async streamInput(e){(async()=>{try{await this.initialize();let t=0;for await(let r of e){if(this.closed)break;t+=1,this.transport.write(JSON.stringify(r)+`
11
+ `),this.diagnostics?.record(`[QueryRunner] inbound control_response sent request_id=${t} subtype=${r} status=error duration_ms=${Date.now()-o}`,i)}}finally{this.pendingInboundRequests.delete(t)}}handleControlCancelRequest(e){let t=this.pendingInboundRequests.get(e.request_id);t&&(t.abortController.abort(),this.pendingInboundRequests.delete(e.request_id))}throwIfAborted(e){if(e.aborted)throw new U}validateProtocolHandshake(e){if(this.protocolHandshakeValidated)return;this.protocolHandshakeValidated=!0;let t=e.protocol_version,r=Ae;if(!t){this.diagnostics?.record(`[QueryRunner] CLI did not announce protocol_version. This SDK was built for ${r}. Consider upgrading qodercli for the version handshake.`);return}let o=jt(t),n=jt(r);if(!o||!n){this.diagnostics?.record(`[QueryRunner] Could not parse protocol_version "${t}" or built-in "${r}"; skipping handshake.`);return}if(o.major!==n.major)throw new Y(t,r);o.minor<n.minor&&this.diagnostics?.record(`[QueryRunner] CLI protocol_version ${t} is older than this SDK's ${r}. New optional fields may be absent.`)}async awaitAbortable(e,t){if(t.aborted)throw new U;return new Promise((r,o)=>{let n=()=>{o(new U)};t.addEventListener("abort",n,{once:!0}),e.then(i=>{t.removeEventListener("abort",n),r(i)},i=>{t.removeEventListener("abort",n),o(i)})})}async processControlRequest(e,t){this.throwIfAborted(t);let r=e.request,o=H(r),n=r;switch(o){case"fetch_job_token":{if(!this.fetchJobToken)throw new Error("job_token_unavailable: No fetchJobToken callback configured");let i=n.reason??"initial",a=n.session_id,c=e.request_id,u=await this.awaitAbortable(this.fetchJobToken({requestId:c,reason:i,sessionId:a},{signal:t}),t);if(!u?.token)throw new Error("job_token_unavailable: Host did not provide a Job Token");return this.diagnostics?.record(`[QueryRunner] fetch_job_token fulfilled: reason=${i}`),{token:u.token}}case"can_use_tool":{let i=n.tool_name,a=n.input??{};if(!this.canUseTool)throw new Error("canUseTool callback is not provided.");let c=n.tool_use_id,u=n.permission_suggestions??n.suggestions,p=n.blocked_path,g=n.decision_reason,d=n.title,l=n.display_name,f=n.description,S=n.agent_id,h=await this.awaitAbortable(this.canUseTool(i,a,{signal:t,suggestions:u,blockedPath:p,decisionReason:g,title:d,displayName:l,description:f,toolUseID:c,agentID:S}),t);if(h.behavior==="deny"&&!h.message)throw new Error("Permission deny result must include a message.");return h.behavior==="allow"?{...h,updatedInput:h.updatedInput??a,toolUseID:c}:{...h,toolUseID:c}}case"hook_callback":{let i=n.callback_id;if(!i)throw new Error("Hook callback missing callback_id");return this.invokeRegisteredHookCallback(i,n.input,n.tool_use_id,t)}case"mcp_message":{let i=n.server_name,a=n.message,c=this.sdkMcpTransports.get(i);if(!c)throw new Error(`Unknown in-process MCP server: ${i}`);return{mcp_response:await this.awaitAbortable(wt(i,a,c,this.pendingMcpResponses),t)}}case"elicitation":case"elicitation_response":return this.onElicitation?await this.awaitAbortable(this.onElicitation({serverName:n.mcp_server_name??"",message:n.message??n.prompt??"",mode:n.mode,url:n.url,elicitationId:n.elicitation_id,requestedSchema:n.requested_schema,title:n.title,displayName:n.display_name,description:n.description},{signal:t}),t):{action:"cancel"};case"get_model_policy":{if(!this.resolveModel)return{type:"get_model_policy"};let i={purpose:n.purpose,sessionId:n.sessionId,turnIndex:n.turnIndex,availableModels:n.models??[]},a=this.resolveModelTimeoutMs,c=Promise.resolve(this.resolveModel(i)),u,p=new Promise((l,f)=>{u=setTimeout(()=>{f(new V(a))},a)}),g;try{g=await this.awaitAbortable(Promise.race([c,p]),t)}finally{clearTimeout(u)}let d={type:"get_model_policy",model:typeof g.model=="string"?g.model:g.model.model,parameters:g.parameters};if(typeof g.model!="string"){let{model:l,...f}=g.model;d.custom_model={...f,style:f.style??"openai"}}return d}default:throw new Error(`Unhandled control request subtype: ${o??"unknown"}`)}}async initialize(){return this.initializationPromise||(this.initializationPromise=this.performInitialize()),this.initializationPromise}async performInitialize(){let e={type:"initialize",modelPolicyProvider:this.resolveModel!==void 0,supportsCatalogReadyInitialize:!0,initializeTimeoutMs:s.INITIALIZE_TIMEOUT_MS},t={};for(let[o,n]of Object.entries(this.hooks)){if(!n||n.length===0)continue;let i=[];for(let a of n){let c=a.hooks.map(u=>{let p=`hook_${this.nextHookCallbackId++}`;return this.hookCallbacks.set(p,u),p});c.length!==0&&i.push({matcher:a.matcher,hookCallbackIds:c,timeout:a.timeout})}i.length>0&&(t[o]=i)}Object.keys(t).length>0&&(e.hooks=t),this.initConfig.systemPrompt!==void 0&&(e.systemPrompt=this.initConfig.systemPrompt),this.initConfig.appendSystemPrompt!==void 0&&(e.appendSystemPrompt=this.initConfig.appendSystemPrompt),this.initConfig.planModeInstructions!==void 0&&(e.planModeInstructions=this.initConfig.planModeInstructions),this.initConfig.agents&&(e.agents=this.initConfig.agents),this.initConfig.skills!==void 0&&(e.skills=this.initConfig.skills),this.initConfig.promptSuggestions!==void 0&&(e.promptSuggestions=this.initConfig.promptSuggestions),this.initConfig.enableFileCheckpointing!==void 0&&(e.enableFileCheckpointing=this.initConfig.enableFileCheckpointing),this.jsonSchema&&(e.jsonSchema=this.jsonSchema),this.sdkMcpServers.size>0&&(e.sdkMcpServers=Array.from(this.sdkMcpServers.keys()));let r=await this.request(e,{timeoutMs:s.INITIALIZE_TIMEOUT_MS});if(r&&typeof r=="object"){let o=r;this.initResponse=o}if(!this.initResponse)throw new Error("Failed to receive initialization response");return this.initResponse}async invokeRegisteredHookCallback(e,t,r,o){let n=this.hookCallbacks.get(e);if(!n)throw new Error(`Unknown hook callback: ${e}`);return await this.awaitAbortable(n(t,r,{signal:o}),o)??{continue:!0}}async initializationResult(){return this.initialize()}async streamInput(e){(async()=>{try{await this.initialize();let t=0;for await(let r of e){if(this.closed)break;t+=1,this.transport.write(JSON.stringify(r)+`
12
12
  `),this.recordOutboundSessionMessage(r)}t>0&&this.hasBidirectionalNeeds()&&await this.waitForFirstResult(),this.transport.endInput()}catch(t){this.diagnostics?.record("[QueryRunner] streamInput error:",t),this.inputStream.error(t instanceof Error?t:new Error(String(t))),this.transport.endInput()}})().catch(()=>{})}async interrupt(){await this.request({type:"interrupt"})}async setPermissionMode(e){await this.request({type:"set_permission_mode",mode:e==="yolo"?"bypassPermissions":e})}hasBidirectionalNeeds(){return this.sdkMcpTransports.size>0||Object.keys(this.hooks).length>0||this.canUseTool!==void 0||this.onElicitation!==void 0||this.fetchJobToken!==void 0||this.resolveModel!==void 0}waitForFirstResult(){return this.firstResultReceived||this.closed?Promise.resolve():new Promise(e=>{if(this.abortController?.signal.aborted){e();return}this.firstResultReceivedResolve=e,this.abortController?.signal.addEventListener("abort",()=>e(),{once:!0})})}async setModel(e){await this.request({type:"set_model",model:e??""})}async setProxy(e){await this.request({type:"set_proxy",proxy:e||null})}async generateSessionTitle(e,t){return(await this.request({type:"generate_session_title",description:e,...t?.persist!==void 0?{persist:t.persist}:{}}))?.title??null}async addDirectories(e){if(!Array.isArray(e))throw new Error("directories must be an array");return await this.request({type:"add_directories",directories:e})}async applyFlagSettings(e){await this.request({type:"apply_flag_settings",settings:e})}async supportedCommands(){return(await this.initializationResult()).commands??[]}async getAvailableModels(e){let t={subtype:"get_models",...e?.fetchStrategy?{fetchStrategy:e.fetchStrategy}:{},...e?.uid?{uid:e.uid}:{}};return(await this.request(t))?.models??[]}async listByokProviders(){try{return(await this.request({type:"get_byok_config"}))?.providers??null}catch{return null}}async validateByokModel(e){try{let t=await this.request({type:"validate_byok_model",provider:e.provider,model:e.model,api_key:e.api_key,...e.url!==void 0?{url:e.url}:{},...e.style!==void 0?{style:e.style}:{}});return typeof t?.success=="boolean"?t.success:null}catch{return null}}async supportedAgents(){return(await this.initializationResult()).agents??[]}async accountInfo(){try{let t=await this.request({type:"account_info"});if(t?.account)return t.account}catch{}return(await this.initializationResult()).account??{}}async mcpServerStatus(){return(await this.request({type:"mcp_status"}))?.servers??[]}async getContextUsage(){return await this.request({type:"get_context_usage"})}async getUsageInfo(){try{let e=await this.request({type:"get_usage_info"});return Er(e?.usage)}catch{return null}}async reloadPlugins(){return await this.request({type:"reload_plugins"})}async listPlugins(){return(await this.request({type:"list_plugins"})).plugins}async rewindFiles(e,t){let r={type:"rewind_files",user_message_id:e};t?.dryRun&&(r.dry_run=!0);let n=await this.request(r);if(!t?.dryRun&&n?.canRewind===!1)throw new Error(typeof n.error=="string"&&n.error.length>0?n.error:"Unable to rewind files.");return n}async seedReadState(e,t){await this.request({type:"seed_read_state",path:e,mtime:t})}async reconnectMcpServer(e){await this.request({type:"mcp_reconnect",serverName:e})}async toggleMcpServer(e,t){await this.request({type:"mcp_toggle",serverName:e,enabled:t})}async setMcpServers(e){return await this.request({type:"mcp_set_servers",servers:e})??{added:[],removed:[],errors:{}}}async injectMcpToken(e,t){await this.request({type:"mcp_inject_token",serverName:e,token:t})}async mcpAuthenticate(e,t){let r=await this.request({type:"mcp_authenticate",serverName:e,...t!==void 0?{redirectUri:t}:{}}),o=r?.requiresUserAction===!0,n=typeof r?.authUrl=="string"?r.authUrl:void 0;if(o&&n===void 0)throw new Error("mcp_authenticate response set requiresUserAction=true but did not include an authUrl");return o?{authUrl:n,requiresUserAction:!0}:{requiresUserAction:!1}}async mcpSubmitOAuthCallbackUrl(e,t){await this.request({type:"mcp_oauth_callback_url",serverName:e,callbackUrl:t})}async mcpClearAuth(e){await this.request({type:"mcp_clear_auth",serverName:e})}async close(){if(this.closed)return;this.closed=!0;for(let[,t]of this.pendingInboundRequests)t.abortController.abort();this.pendingInboundRequests.clear(),this.hookCallbacks.clear();let e=new Error("SDK closing");for(let[t,r]of this.sdkMcpTransports){try{await r.close()}catch(o){this.diagnostics?.record(`[QueryRunner] error closing SDK MCP transport "${t}":`,o)}Pt(t,e,this.pendingMcpResponses)}this.transport.close();try{await this.readLoopPromise}catch{}}async[Symbol.asyncDispose](){await this.close()}};function pe(s){return typeof s=="object"&&s!==null}function Pr(s){return typeof s=="number"&&Number.isFinite(s)}function Oe(s){return Object.keys(s).length>0}function T(s,e,t){let r=e[t];Pr(r)&&(s[t]=r)}function $(s,e,t){let r=e[t];typeof r=="string"&&(s[t]=r)}function de(s,e,t){let r=e[t];typeof r=="boolean"&&(s[t]=r)}function qt(s){if(!pe(s)||Array.isArray(s))return;let e={};return T(e,s,"total"),T(e,s,"used"),T(e,s,"remaining"),T(e,s,"percentage"),$(e,s,"unit"),Oe(e)?e:void 0}function Rr(s){if(!pe(s)||Array.isArray(s))return;let e=qt(s)??{};return $(e,s,"detailUrl"),Oe(e)?e:void 0}function Tr(s){if(!pe(s)||Array.isArray(s))return;let e={};return T(e,s,"used"),T(e,s,"cap"),T(e,s,"remaining"),T(e,s,"percentage"),de(e,s,"available"),$(e,s,"unit"),Oe(e)?e:void 0}function Er(s){if(!pe(s)||Array.isArray(s))return null;let e={};$(e,s,"userId"),$(e,s,"userType"),T(e,s,"totalUsagePercentage"),de(e,s,"isHighestTier"),T(e,s,"expiresAt"),$(e,s,"upgradeUrl"),de(e,s,"isQuotaExceeded"),de(e,s,"isPlanQuotaProrated");let t=qt(s.userQuota);t&&(e.userQuota=t);let r=Rr(s.addOnQuota);r&&(e.addOnQuota=r);let o=Tr(s.orgResourcePackage);return o&&(e.orgResourcePackage=o),e}function Mr(s){let e=s instanceof Error?s.message:String(s),t=typeof s=="object"&&s!==null?s.code:void 0,r=typeof t=="string"&&t.length>0?t:void 0,o=/^([a-z][a-z0-9_]*):\s*(.*)$/.exec(e);if(o){let n=r??o[1];return(!r||r===o[1])&&(e=o[2]||e),{error:e,code:n}}return r?{error:e,code:r}:{error:e}}function jt(s){let e=/^(\d+)\.(\d+)(?:\.\d+)?(?:[-+].*)?$/.exec(s);return e?{major:Number(e[1]),minor:Number(e[2])}:null}var ge=class{sendMcpMessage;isClosed=!1;onclose;onerror;onmessage;constructor(e){this.sendMcpMessage=e}async start(){}async send(e){if(this.isClosed)throw new Error("Transport is closed");this.sendMcpMessage(e)}async close(){this.isClosed||(this.isClosed=!0,this.onclose?.())}get closed(){return this.isClosed}};import{randomUUID as Nt}from"crypto";var Cr="QODER_CLOUD_AGENT_API_BASE",_r="https://api.qoder.com/api/v1/cloud",I={agentMessage:"agent.message",modelRequestEnd:"span.model_request_end",idle:"session.status_idle",error:"session.error",terminated:"terminated",userMessage:"user.message",userInterrupt:"user.interrupt"},xr=1024,Kt=1*1024*1024,Ft=4*1024*1024,Ir=8*1024,Ue=class extends Error{code="auth_access_token_env_var_not_configured";constructor(e){super(`The auth access token environment variable "${e}" is not set; set it or pass auth.accessToken directly.`),this.name="CloudAuthAccessTokenEnvVarError"}},fe=class extends Error{code="cloud_agent_auth_requires_access_token";constructor(){super("options.experimentalCloudAgent requires PAT authentication via accessToken() or accessTokenFromEnv()."),this.name="CloudAgentUnsupportedAuthError"}},je=class extends Error{code="cloud_agent_api_error";status;constructor(e,t){super(`Cloud Agent API request failed with status ${e}: ${t}`),this.name="CloudAgentApiError",this.status=e}},Ar=new Set(["abortController","auth","experimentalCloudAgent","debug","debugFile","stderr","env","includePartialMessages","onAuthExpired"]);function Qt(s){if(!s.experimentalCloudAgent)return;let e=Object.keys(s).filter(n=>s[n]!==void 0&&!Ar.has(n));if(e.length>0)throw new Error(`options.experimentalCloudAgent cannot be combined with CLI runtime options: ${e.join(", ")}`);if(s.auth?.type!=="accessToken")throw new fe;let{agent:t,session:r}=s.experimentalCloudAgent;if(t&&Q(t)&&De(t))throw new Error("options.experimentalCloudAgent.agent must specify either id or create, not both.");if(r&&Q(r)&&De(r))throw new Error("options.experimentalCloudAgent.session must specify either id or create, not both.");if(r&&Q(r)&&t!==void 0)throw new Error("options.experimentalCloudAgent.agent cannot be combined with experimentalCloudAgent.session.id because an existing session already selects its agent.");let o=!!r&&Q(r);if(!o&&t===void 0)throw new Error("options.experimentalCloudAgent.agent is required when experimentalCloudAgent.session.id is not provided.");if(!o){if(!r||!De(r))throw new Error("options.experimentalCloudAgent.session.create is required when creating a Cloud Agent session.");if(typeof r.create.environment_id!="string"||r.create.environment_id.length===0)throw new Error("options.experimentalCloudAgent.session.create.environment_id is required when creating a Cloud Agent session.")}}function Q(s){return"id"in s&&s.id!==void 0}function De(s){return"create"in s&&s.create!==void 0}function zt(s){return new qe(s)}var qe=class{experimentalCloudAgent;inputStream;abortController=new AbortController;accessToken;apiBase;diagnostics;onAuthExpired;sessionReadyPromise;readLoopPromise;sseConnected=Br();startedAt=Date.now();closed=!1;authExpiredFired=!1;sessionId;assistantTextParts=[];currentTurnId;lastSseEventId;hasCurrentTurn=!1;pendingTurnEvents=[];latestUsage=$t();latestModelUsage={};totalCostUsd=0;postedMessages=0;activeInputStreams=0;idleSeen=!1;resultEmitted=!1;constructor(e){if(!e.options.experimentalCloudAgent)throw new Error("options.experimentalCloudAgent is required for CloudAgentQuery.");this.experimentalCloudAgent=e.options.experimentalCloudAgent,this.diagnostics=e.diagnostics,this.onAuthExpired=e.options.onAuthExpired,this.accessToken=Or(e.options.auth,e.options.env),this.apiBase=Dr(),this.inputStream=new _(()=>{this.close().catch(()=>{})});let t=e.options.abortController?.signal;t?.aborted?this.abortController.abort():t?.addEventListener("abort",()=>{this.close().catch(()=>{})},{once:!0}),this.sessionReadyPromise=this.initializeCloudSession(),this.readLoopPromise=this.readCloudEvents().catch(r=>{this.sseConnected.reject(r),this.closed||this.inputStream.error(r)}),this.streamInput(zr(e.prompt)).catch(r=>{this.closed||this.inputStream.error(r)})}[Symbol.asyncIterator](){return this}async next(){return this.inputStream.next()}async return(){return await this.close(),{done:!0,value:void 0}}async throw(e){return await this.inputStream.throw(e),{done:!0,value:void 0}}async initializationResult(){return(await this.sessionReadyPromise).init}async streamInput(e){this.activeInputStreams+=1,(async()=>{try{await this.sessionReadyPromise,await this.sseConnected.promise;for await(let t of e){if(this.closed)break;let r=Qr(t);this.beginPendingTurn();let o=await this.postSessionEvents([{type:I.userMessage,content:r}]);this.postedMessages+=1,this.activateTurn(o.find(n=>n.type===I.userMessage)?.turnId)}}finally{this.activeInputStreams=Math.max(0,this.activeInputStreams-1),this.finishIfIdle()}})().catch(t=>{this.closed||this.inputStream.error(t)})}async interrupt(){await this.sessionReadyPromise,await this.postSessionEvents([{type:I.userInterrupt}])}async setPermissionMode(e){this.unsupported("setPermissionMode")}async setModel(e){this.unsupported("setModel")}async setProxy(e){this.unsupported("setProxy")}async generateSessionTitle(e,t){this.unsupported("generateSessionTitle")}async addDirectories(e){this.unsupported("addDirectories")}async applyFlagSettings(e){this.unsupported("applyFlagSettings")}async supportedCommands(){return[]}async getAvailableModels(){return[]}async listByokProviders(){return null}async validateByokModel(e){return null}async supportedAgents(){return[]}async mcpServerStatus(){return[]}async getContextUsage(){this.unsupported("getContextUsage")}async getUsageInfo(){return null}async reloadPlugins(){this.unsupported("reloadPlugins")}async listPlugins(){this.unsupported("listPlugins")}async accountInfo(){return{}}async rewindFiles(e,t){this.unsupported("rewindFiles")}async seedReadState(e,t){this.unsupported("seedReadState")}async mcpAuthenticate(e,t){this.unsupported("mcpAuthenticate")}async mcpSubmitOAuthCallbackUrl(e,t){this.unsupported("mcpSubmitOAuthCallbackUrl")}async close(){this.finish();try{await this.readLoopPromise}catch{}}async[Symbol.asyncDispose](){await this.close()}async initializeCloudSession(){if(this.closed)throw new Error("Cloud Agent query is closed.");let{session:e}=this.experimentalCloudAgent,t;if(e&&Q(e))t=e.id;else{let r=await this.resolveAgentId(),o=e.create,n=await this.requestJson("/sessions",{method:"POST",body:{agent:r,...jr(o)}});t=Lt(n,"Cloud session")}return this.sessionId=t,this.diagnostics?.record(`[cloud-agent] session ready: ${t}`),{sessionId:t,init:{commands:[],agents:[],output_style:"cloud-agent",available_output_styles:["cloud-agent"],models:[],account:{}}}}async resolveAgentId(){let{agent:e}=this.experimentalCloudAgent;if(!e)throw new Error("options.experimentalCloudAgent.agent is required when experimentalCloudAgent.session.id is not provided.");if(Q(e))return e.id;let t=await this.requestJson("/agents",{method:"POST",body:Ur(e.create)});return Lt(t,"Cloud agent")}async readCloudEvents(){let{sessionId:e}=await this.sessionReadyPromise,t=0;for(;!this.closed;){let r=this.lastSseEventId;if(await this.readCloudEventStream(e),this.closed||this.resultEmitted)return;if(!this.shouldReconnectSse()||t>=3){this.finishAfterSseClosed();return}this.lastSseEventId!==r&&(t=0),t+=1,await Wr(250*t,this.abortController.signal)}}async readCloudEventStream(e){let t=new URL(`${this.apiBase}/sessions/${encodeURIComponent(e)}/events/stream`),r=this.lastSseEventId??this.experimentalCloudAgent.stream?.afterId;r&&t.searchParams.set("after_id",r),this.experimentalCloudAgent.stream?.deltaFlushIntervalMs!==void 0&&t.searchParams.set("delta_flush_interval_ms",String(this.experimentalCloudAgent.stream.deltaFlushIntervalMs));let o=await fetch(t.toString(),{headers:this.authHeaders({accept:"text/event-stream"}),signal:this.abortController.signal});if(!o.ok)throw this.handleAuthFailure(o.status),await Ht(o);if(!o.body)throw new Error("Cloud Agent SSE response did not include a body.");this.sseConnected.resolve(),await this.readSseBody(o.body)}async readSseBody(e){let t=e.getReader(),r=new TextDecoder,o="",n={data:[],dataBytes:0};try{for(;!this.closed;){let{done:i,value:a}=await t.read();if(i){o+=r.decode(),o.length>0&&this.consumeSseLine(o,n);break}o+=r.decode(a,{stream:!0});let c;for(;(c=o.indexOf(`
13
13
  `))!==-1;){let u=o.slice(0,c);o=o.slice(c+1);let p=u.endsWith("\r")?u.slice(0,-1):u;if(this.consumeSseLine(p,n),this.closed)break}o.length>Kt&&(this.diagnostics?.record(`[cloud-agent] SSE line exceeded ${Kt} bytes; resetting buffer.`),o="",n.id=void 0,n.event=void 0,n.data.length=0,n.dataBytes=0)}}finally{try{await t.cancel()}catch{}t.releaseLock()}}consumeSseLine(e,t){if(e===""){(t.event||t.data.length>0)&&this.handleSseEvent({id:t.id,event:t.event??"message",data:Kr(t.data.join(`
14
14
  `))}),t.id=void 0,t.event=void 0,t.data.length=0,t.dataBytes=0;return}if(e.startsWith(":"))return;let r=e.indexOf(":"),o=r===-1?e:e.slice(0,r),n=r===-1?"":e.slice(r+1);switch(n.startsWith(" ")&&(n=n.slice(1)),o){case"id":t.id=n;break;case"event":t.event=n;break;case"data":if(t.dataBytes+n.length>Ft){this.diagnostics?.record(`[cloud-agent] SSE event data exceeded ${Ft} bytes; dropping event.`),t.id=void 0,t.event=void 0,t.data.length=0,t.dataBytes=0;return}t.data.push(n),t.dataBytes+=n.length;break}}handleSseEvent(e){if(this.closed)return;let t=P(e.data,"type")??e.event,r=P(e.data,"turn_id"),o={type:"cloud_agent_event",event:t,id:e.id,data:e.data,uuid:e.id??Nt(),session_id:this.sessionId??P(e.data,"session_id")??""};if(e.id&&(this.lastSseEventId=e.id),this.inputStream.enqueue(o),!this.isCurrentTurnEvent(r)){this.bufferPendingTurnEvent(e,t,r);return}this.handleCurrentTurnEvent(e,t)}handleCurrentTurnEvent(e,t){switch(t){case I.agentMessage:{let r=Lr(X(e.data,"content"));r&&this.assistantTextParts.push(r);return}case I.modelRequestEnd:this.captureUsage(e.data);return;case I.idle:this.idleSeen=!0,this.finishIfIdle();return;case I.error:this.emitErrorResult(e),this.finish();return;case I.terminated:this.resultEmitted||this.emitSuccessResult(),this.finish();return}}beginPendingTurn(){this.currentTurnId=void 0,this.hasCurrentTurn=!1,this.pendingTurnEvents=[],this.assistantTextParts=[],this.latestUsage=$t(),this.latestModelUsage={},this.totalCostUsd=0,this.idleSeen=!1}activateTurn(e){this.currentTurnId=e,this.hasCurrentTurn=!0;let t=this.pendingTurnEvents;this.pendingTurnEvents=[];for(let r of t)if(this.isCurrentTurnEvent(r.turnId)&&this.handleCurrentTurnEvent(r.event,r.type),this.closed)break}isCurrentTurnEvent(e){return this.hasCurrentTurn?this.currentTurnId?e===this.currentTurnId:e===void 0:!1}bufferPendingTurnEvent(e,t,r){this.hasCurrentTurn||this.activeInputStreams===0||(this.pendingTurnEvents.length>=xr&&this.pendingTurnEvents.shift(),this.pendingTurnEvents.push({event:e,type:t,turnId:r}))}finishIfIdle(){this.closed||!this.idleSeen||this.activeInputStreams>0||this.postedMessages===0||(this.emitSuccessResult(),this.finish())}finishAfterSseClosed(){this.finishIfIdle(),!this.closed&&(!this.resultEmitted&&(this.hasCurrentTurn||this.postedMessages>0||this.activeInputStreams>0)&&this.emitErrorResultMessage("Cloud Agent SSE stream closed before the current turn reached a terminal state."),this.finish())}shouldReconnectSse(){return!this.resultEmitted&&(this.hasCurrentTurn||this.postedMessages>0||this.activeInputStreams>0)}emitSuccessResult(){this.resultEmitted||this.closed||(this.resultEmitted=!0,this.inputStream.enqueue({...this.buildResultBase(),subtype:"success",is_error:!1,result:this.assistantTextParts.join("")}))}emitErrorResult(e){this.emitErrorResultMessage(P(e.data,"error")??P(me(e.data,"error"),"message")??"Cloud Agent session failed.")}emitErrorResultMessage(e){this.resultEmitted||this.closed||(this.resultEmitted=!0,this.inputStream.enqueue({...this.buildResultBase(),subtype:"error_during_execution",is_error:!0,errors:[e]}))}buildResultBase(){let e=Date.now()-this.startedAt;return{type:"result",duration_ms:e,duration_api_ms:e,num_turns:Math.max(1,this.postedMessages),stop_reason:null,total_cost_usd:this.totalCostUsd,usage:this.latestUsage,modelUsage:this.latestModelUsage,permission_denials:[],uuid:Nt(),session_id:this.sessionId??""}}async postSessionEvents(e){let t=this.sessionId??(await this.sessionReadyPromise).sessionId,r=await this.requestJson(`/sessions/${encodeURIComponent(t)}/events`,{method:"POST",body:{events:e}});return qr(r)}captureUsage(e){let t=me(e,"usage");if(!t)return;this.latestUsage=Hr(this.latestUsage,t);let r=k(e,"total_cost_usd")??k(e,"cost_usd")??k(t,"total_cost_usd")??k(t,"cost_usd");r!==void 0&&(this.totalCostUsd+=r);let o=P(e,"model")??P(t,"model");if(o){let n=this.latestModelUsage[o]?.costUSD??0;this.latestModelUsage[o]=$r(this.latestUsage,n+(r??0))}}async requestJson(e,t){let r=await fetch(`${this.apiBase}${e}`,{method:t.method,headers:this.authHeaders({accept:"application/json",contentType:t.body?"application/json":void 0}),body:t.body?JSON.stringify(t.body):void 0,signal:this.abortController.signal});if(!r.ok)throw this.handleAuthFailure(r.status),await Ht(r);if(r.status===204)return{};try{return await r.json()}catch{return{}}}authHeaders(e){let t={Authorization:`Bearer ${this.accessToken}`,Accept:e.accept};return e.contentType&&(t["Content-Type"]=e.contentType),t}handleAuthFailure(e){if((e===401||e===403)&&!this.authExpiredFired){this.authExpiredFired=!0;try{this.onAuthExpired?.()}catch(t){this.diagnostics?.record("[cloud-agent] onAuthExpired callback threw:",t)}}}finish(){this.closed||(this.closed=!0,this.abortController.abort(),this.sseConnected.resolve(),this.inputStream.done())}unsupported(e){throw new Error(`Query.${e}() is not supported when options.experimentalCloudAgent is enabled.`)}};function Or(s,e){if(s?.type!=="accessToken")throw new fe;if(typeof s.accessToken=="string")return s.accessToken;let t=s.accessToken.envVar,r=e&&Object.hasOwn(e,t)?e[t]:process.env[t];if(!r)throw new Ue(t);return r}function Dr(){return process.env[Cr]?.replace(/\/+$/,"")??_r}function Ur(s){return Ne({name:s.name,model:s.model,system:s.system,description:s.description,tools:s.tools,mcp_servers:s.mcp_servers,skills:s.skills,metadata:s.metadata})}function jr(s){return Ne({title:s.title,environment_id:s.environment_id,resources:s.resources?.map(e=>Ne({...e})),vault_ids:s.vault_ids,memory_store_ids:s.memory_store_ids})}function Ne(s){return Object.fromEntries(Object.entries(s).filter(([,e])=>e!==void 0))}function Lt(s,e){let t=P(s,"id");if(!t)throw new Error(`${e} response did not include an id.`);return t}function qr(s){let e=Fr(s,"data");return e?e.flatMap(t=>t===null||typeof t!="object"||Array.isArray(t)?[]:[{id:P(t,"id"),turnId:P(t,"turn_id"),type:P(t,"type")}]):[]}async function Ht(s){let e=await Nr(s,Ir);return new je(s.status,e||s.statusText||"unknown error")}async function Nr(s,e){if(!s.body)try{return(await s.text()).slice(0,e)}catch{return""}let t=s.body.getReader(),r=new TextDecoder,o=[],n=0;try{for(;n<e;){let{done:i,value:a}=await t.read();if(i)break;n+=a.byteLength,o.push(r.decode(a,{stream:!0}))}o.push(r.decode())}catch{}finally{try{await t.cancel()}catch{}t.releaseLock()}return o.join("").slice(0,e)}function Kr(s){if(s.length===0)return{};try{return JSON.parse(s)}catch{return s}}function me(s,e){let t=X(s,e);return t!==null&&typeof t=="object"&&!Array.isArray(t)?t:void 0}function Fr(s,e){let t=X(s,e);return Array.isArray(t)?t:void 0}function P(s,e){let t=X(s,e);return typeof t=="string"?t:void 0}function k(s,e){let t=X(s,e);return typeof t=="number"&&Number.isFinite(t)?t:void 0}function X(s,e){if(!(s===null||typeof s!="object"||Array.isArray(s)))return s[e]}function Lr(s){return typeof s=="string"?s:Array.isArray(s)&&s.map(t=>Wt(t)?t.text:"").filter(Boolean).join("")||void 0}function Hr(s,e){let t=me(e,"cache_creation"),r=me(e,"server_tool_use");return{...s,cache_creation:{ephemeral_1h_input_tokens:k(t,"ephemeral_1h_input_tokens")??s.cache_creation.ephemeral_1h_input_tokens,ephemeral_5m_input_tokens:k(t,"ephemeral_5m_input_tokens")??s.cache_creation.ephemeral_5m_input_tokens},cache_creation_input_tokens:k(e,"cache_creation_input_tokens")??s.cache_creation_input_tokens,cache_read_input_tokens:k(e,"cache_read_input_tokens")??s.cache_read_input_tokens,input_tokens:k(e,"input_tokens")??s.input_tokens,output_tokens:k(e,"output_tokens")??s.output_tokens,server_tool_use:{web_fetch_requests:k(r,"web_fetch_requests")??s.server_tool_use.web_fetch_requests,web_search_requests:k(r,"web_search_requests")??s.server_tool_use.web_search_requests}}}function $r(s,e){return{inputTokens:s.input_tokens,outputTokens:s.output_tokens,cacheReadInputTokens:s.cache_read_input_tokens,cacheCreationInputTokens:s.cache_creation_input_tokens,webSearchRequests:s.server_tool_use.web_search_requests,costUSD:e,contextWindow:0,maxOutputTokens:0}}function Qr(s){let e=s.message.content;return typeof e=="string"?e:Array.isArray(e)?e.map(t=>Wt(t)?t.text:JSON.stringify(t)).join(`
15
- `):JSON.stringify(e)}function Wt(s){return s!==null&&typeof s=="object"&&"type"in s&&s.type==="text"&&"text"in s&&typeof s.text=="string"}function zr(s){return typeof s!="string"?s:async function*(){yield{type:"user",message:{role:"user",content:[{type:"text",text:s}]},parent_tool_use_id:null}}()}function $t(){return{cache_creation:{ephemeral_1h_input_tokens:0,ephemeral_5m_input_tokens:0},cache_creation_input_tokens:0,cache_read_input_tokens:0,inference_geo:"",input_tokens:0,iterations:[],output_tokens:0,server_tool_use:{web_fetch_requests:0,web_search_requests:0},service_tier:"standard",speed:"standard"}}async function Wr(s,e){e.aborted||await new Promise(t=>{let r=setTimeout(t,s);e.addEventListener("abort",()=>{clearTimeout(r),t()},{once:!0})})}function Br(){let s,e;return{promise:new Promise((r,o)=>{s=r,e=o}),resolve:s,reject:e}}var Ke=class extends Error{code="auth_not_configured";constructor(){super("The auth option is required when calling query(); configure options.auth so the SDK can create an auth payload file before spawning qodercli."),this.name="AuthNotConfiguredError"}};function Jr(s){if(s.transport!==void 0){if(ct(s.transport))return s.transport;throw new Error("options.transport must implement QueryTransportProvider. Use ProcessTransport.default, WorkerTransport.default, or a custom provider with create().")}return Te==="worker"?G.default:B.default}function Gr(s){let{prompt:e,options:t={}}=s,r=Jr(t),o=new ue({debug:t.debug,debugFile:t.debugFile,stderr:t.stderr});if(t.canUseTool&&t.permissionPromptToolName)throw new Error("canUseTool callback cannot be used with permissionPromptToolName. Please use one or the other.");let n=t.auth;if(n==null)throw new Ke;if(t.cloudAgent!==void 0)throw new Error("options.cloudAgent is not supported. Use options.experimentalCloudAgent for the experimental Cloud Agent runtime.");if(t.experimentalCloudAgent!==void 0)return Qt(t),zt({prompt:e,options:t,diagnostics:o});let i=!!t.resolveModel,a=t.onAuthExpired,c=!1,u=a?()=>{c||(c=!0,Promise.resolve(a()).catch(y=>{o.record("[query] onAuthExpired callback threw:",y)}))}:void 0,p=new Map,g=new Map,d=new Map,l={},f={};if(t.mcpServers)for(let[y,C]of Object.entries(t.mcpServers)){let W=C.tools;if(Array.isArray(W)&&W.length>0&&(f[y]=W),C.type==="sdk"&&"instance"in C&&C.instance){let N=C.instance;p.set(y,N);let ze=new ge(fs=>{bt(y,fs,d)});g.set(y,ze),N.connect(ze).catch(()=>{})}else l[y]=C}let S=Object.keys(l).length>0,h=Object.keys(f).length>0,v=t.pathToQoderCLIExecutable,b=t.env,ne=n?.type==="jobToken"?n.fetchJobToken:void 0,ke={pathToQoderCLIExecutable:v,executable:t.executable,executableArgs:t.executableArgs,env:b,proxy:t.proxy,cwd:t.cwd,closeGraceMs:t.closeGraceMs,auth:n,model:i?void 0:t.model,agent:t.agent,debug:t.debug,diagnostics:o,maxTurns:t.maxTurns,includePartialMessages:t.includePartialMessages,includeHookEvents:t.includeHookEvents,permissionMode:t.permissionMode,allowDangerouslySkipPermissions:t.allowDangerouslySkipPermissions,permissionPromptToolName:t.permissionPromptToolName,canUseTool:t.canUseTool!==void 0,continue:t.continue,resume:t.resume,forkSession:t.forkSession,sessionId:t.sessionId,allowedTools:(()=>{let y=t.allowedTools??[];if(t.skills===void 0)return y.length>0?y:void 0;let C=t.skills==="all"?["Skill"]:t.skills.map(N=>`Skill(${N})`),W=new Set(y);return[...y,...C.filter(N=>!W.has(N))]})(),disallowedTools:t.disallowedTools,tools:t.tools,toolConfig:t.toolConfig,extensions:t.extensions,extraArgs:t.extraArgs,mcpServers:S?l:void 0,mcpToolPolicies:h?f:void 0,allowedMcpServerNames:t.allowedMcpServerNames,strictMcpConfig:t.strictMcpConfig,settings:t.settings,settingSources:t.settingSources,additionalDirectories:t.additionalDirectories,plugins:t.plugins,enableFileCheckpointing:t.enableFileCheckpointing,stderr:"pipe",stderrHandler:t.stderr,spawnQoderCLIProcess:t.spawnQoderCLIProcess,onAuthExpired:u},oe=ut(r,ke);oe.initialize().catch(()=>{});let ie=typeof e=="string",m=t.systemPrompt,M,z;if(typeof m=="string")M=m;else if(typeof m=="object"&&m!==null&&m.type==="preset"){let y=m;if(y.preset!=="qodercli")throw new Error(`Unsupported systemPrompt preset: ${String(y.preset)}`);z=y.append}let gs={systemPrompt:M,appendSystemPrompt:z,planModeInstructions:t.planModeInstructions,agents:t.agents,promptSuggestions:t.promptSuggestions,enableFileCheckpointing:t.enableFileCheckpointing},we=new le(oe,ie,t.canUseTool,t.hooks,t.abortController,p,void 0,gs,t.onElicitation,o,u,t.controlRequestTimeoutMs,g,d,ne,t.resolveModel,t.resolveModelTimeoutMs);if(typeof e=="string"){let y={type:"user",message:{role:"user",content:[{type:"text",text:e}]},parent_tool_use_id:null};we.streamInput(async function*(){yield y}())}else we.streamInput(e);return we}var Bt="QODER_PERSONAL_ACCESS_TOKEN";function Vr(s){return{type:"accessToken",accessToken:s}}function Yr(s=Bt){return{type:"accessToken",accessToken:{envVar:s}}}function Xr(){return{type:"qodercli"}}function Zr(s){return{type:"jobToken",fetchJobToken:s}}import{McpServer as en}from"@modelcontextprotocol/sdk/server/mcp.js";function tn(s){if(!s.name||typeof s.name!="string"||s.name.trim()==="")throw new Error("[createSdkMcpServer] Server name must be a non-empty string.");let e=new en({name:s.name,version:s.version??"1.0.0"},{capabilities:{tools:s.tools&&s.tools.length>0?{}:void 0}});if(s.tools&&s.tools.length>0)for(let t of s.tools){if(!t.name||typeof t.name!="string"||t.name.trim()==="")throw new Error(`[createSdkMcpServer] Tool name must be a non-empty string in server "${s.name}".`);if(!t.description||typeof t.description!="string")throw new Error(`[createSdkMcpServer] Tool "${t.name}" must have a non-empty description string.`);try{e.registerTool(t.name,{description:t.description,inputSchema:t.inputSchema,...t.annotations?{annotations:t.annotations}:{}},t.handler)}catch(r){throw r instanceof Error&&r.message.includes("already registered")?new Error(`[createSdkMcpServer] Duplicate tool name "${t.name}" in server "${s.name}". Each tool name must be unique within a server.`):r}}return{type:"sdk",name:s.name,instance:e}}function sn(s,e,t,r,o){return{name:s,description:e,inputSchema:t,handler:r,annotations:o?.annotations}}import{readdir as Le,readFile as ye,stat as te,appendFile as Xt,realpath as ln}from"fs/promises";import{basename as pn,join as w,resolve as Vt}from"path";import{execFile as gn}from"child_process";import{promisify as fn}from"util";import{homedir as rn}from"os";import{join as Gt}from"path";var nn=".qoder",on="QODER_CLI_HOME",an="QODER_CONFIG_DIR",Jt=200;function cn(){return process.env[on]||rn()}function un(){let s=process.env[an];return s||Gt(cn(),nn)}function he(){return Gt(un(),"projects")}function dn(s){let e=5381;for(let t=0;t<s.length;t++)e=e*33^s.charCodeAt(t);return e}function Z(s){let e=s.replace(/[^a-zA-Z0-9]/g,"-");if(e.length<=Jt)return e;let t=Math.abs(dn(s)).toString(36);return`${e.slice(0,Jt)}-${t}`}var mn=fn(gn),hn=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,yn=new Set(["user","assistant","system","progress","attachment"]);function j(s){return s!==null&&typeof s=="object"}function Sn(s){return hn.test(s)}function vn(s){let e=[];for(let t of s.split(`
15
+ `):JSON.stringify(e)}function Wt(s){return s!==null&&typeof s=="object"&&"type"in s&&s.type==="text"&&"text"in s&&typeof s.text=="string"}function zr(s){return typeof s!="string"?s:async function*(){yield{type:"user",message:{role:"user",content:[{type:"text",text:s}]},parent_tool_use_id:null}}()}function $t(){return{cache_creation:{ephemeral_1h_input_tokens:0,ephemeral_5m_input_tokens:0},cache_creation_input_tokens:0,cache_read_input_tokens:0,inference_geo:"",input_tokens:0,iterations:[],output_tokens:0,server_tool_use:{web_fetch_requests:0,web_search_requests:0},service_tier:"standard",speed:"standard"}}async function Wr(s,e){e.aborted||await new Promise(t=>{let r=setTimeout(t,s);e.addEventListener("abort",()=>{clearTimeout(r),t()},{once:!0})})}function Br(){let s,e;return{promise:new Promise((r,o)=>{s=r,e=o}),resolve:s,reject:e}}var Ke=class extends Error{code="auth_not_configured";constructor(){super("The auth option is required when calling query(); configure options.auth so the SDK can create an auth payload file before spawning qodercli."),this.name="AuthNotConfiguredError"}};function Jr(s){if(s.transport!==void 0){if(ct(s.transport))return s.transport;throw new Error("options.transport must implement QueryTransportProvider. Use ProcessTransport.default, WorkerTransport.default, or a custom provider with create().")}return Te==="worker"?G.default:B.default}function Gr(s){let{prompt:e,options:t={}}=s,r=Jr(t),o=new ue({debug:t.debug,debugFile:t.debugFile,stderr:t.stderr});if(t.canUseTool&&t.permissionPromptToolName)throw new Error("canUseTool callback cannot be used with permissionPromptToolName. Please use one or the other.");let n=t.auth;if(n==null)throw new Ke;if(t.cloudAgent!==void 0)throw new Error("options.cloudAgent is not supported. Use options.experimentalCloudAgent for the experimental Cloud Agent runtime.");if(t.experimentalCloudAgent!==void 0)return Qt(t),zt({prompt:e,options:t,diagnostics:o});let i=!!t.resolveModel,a=t.onAuthExpired,c=!1,u=a?()=>{c||(c=!0,Promise.resolve(a()).catch(y=>{o.record("[query] onAuthExpired callback threw:",y)}))}:void 0,p=new Map,g=new Map,d=new Map,l={},f={};if(t.mcpServers)for(let[y,C]of Object.entries(t.mcpServers)){let W=C.tools;if(Array.isArray(W)&&W.length>0&&(f[y]=W),C.type==="sdk"&&"instance"in C&&C.instance){let N=C.instance;p.set(y,N);let ze=new ge(fs=>{bt(y,fs,d)});g.set(y,ze),N.connect(ze).catch(()=>{})}else l[y]=C}let S=Object.keys(l).length>0,h=Object.keys(f).length>0,v=t.pathToQoderCLIExecutable,b=t.env,ne=n?.type==="jobToken"?n.fetchJobToken:void 0,ke={pathToQoderCLIExecutable:v,executable:t.executable,executableArgs:t.executableArgs,env:b,proxy:t.proxy,cwd:t.cwd,closeGraceMs:t.closeGraceMs,auth:n,model:i?void 0:t.model,agent:t.agent,debug:t.debug,diagnostics:o,maxTurns:t.maxTurns,includePartialMessages:t.includePartialMessages,includeHookEvents:t.includeHookEvents,permissionMode:t.permissionMode,allowDangerouslySkipPermissions:t.allowDangerouslySkipPermissions,permissionPromptToolName:t.permissionPromptToolName,canUseTool:t.canUseTool!==void 0,continue:t.continue,resume:t.resume,forkSession:t.forkSession,sessionId:t.sessionId,allowedTools:(()=>{let y=t.allowedTools??[];if(t.skills===void 0)return y.length>0?y:void 0;let C=t.skills==="all"?["Skill"]:t.skills.map(N=>`Skill(${N})`),W=new Set(y);return[...y,...C.filter(N=>!W.has(N))]})(),disallowedTools:t.disallowedTools,tools:t.tools,toolConfig:t.toolConfig,extensions:t.extensions,extraArgs:t.extraArgs,mcpServers:S?l:void 0,mcpToolPolicies:h?f:void 0,allowedMcpServerNames:t.allowedMcpServerNames,strictMcpConfig:t.strictMcpConfig,settings:t.settings,settingSources:t.settingSources,additionalDirectories:t.additionalDirectories,plugins:t.plugins,enableFileCheckpointing:t.enableFileCheckpointing,stderr:"pipe",stderrHandler:t.stderr,spawnQoderCLIProcess:t.spawnQoderCLIProcess,onAuthExpired:u},oe=ut(r,ke);oe.initialize().catch(()=>{});let ie=typeof e=="string",m=t.systemPrompt,M,z;if(typeof m=="string")M=m;else if(typeof m=="object"&&m!==null&&m.type==="preset"){let y=m;if(y.preset!=="qodercli")throw new Error(`Unsupported systemPrompt preset: ${String(y.preset)}`);z=y.append}let gs={systemPrompt:M,appendSystemPrompt:z,planModeInstructions:t.planModeInstructions,agents:t.agents,skills:Array.isArray(t.skills)?t.skills:void 0,promptSuggestions:t.promptSuggestions,enableFileCheckpointing:t.enableFileCheckpointing},we=new le(oe,ie,t.canUseTool,t.hooks,t.abortController,p,void 0,gs,t.onElicitation,o,u,t.controlRequestTimeoutMs,g,d,ne,t.resolveModel,t.resolveModelTimeoutMs);if(typeof e=="string"){let y={type:"user",message:{role:"user",content:[{type:"text",text:e}]},parent_tool_use_id:null};we.streamInput(async function*(){yield y}())}else we.streamInput(e);return we}var Bt="QODER_PERSONAL_ACCESS_TOKEN";function Vr(s){return{type:"accessToken",accessToken:s}}function Yr(s=Bt){return{type:"accessToken",accessToken:{envVar:s}}}function Xr(){return{type:"qodercli"}}function Zr(s){return{type:"jobToken",fetchJobToken:s}}import{McpServer as en}from"@modelcontextprotocol/sdk/server/mcp.js";function tn(s){if(!s.name||typeof s.name!="string"||s.name.trim()==="")throw new Error("[createSdkMcpServer] Server name must be a non-empty string.");let e=new en({name:s.name,version:s.version??"1.0.0"},{capabilities:{tools:s.tools&&s.tools.length>0?{}:void 0}});if(s.tools&&s.tools.length>0)for(let t of s.tools){if(!t.name||typeof t.name!="string"||t.name.trim()==="")throw new Error(`[createSdkMcpServer] Tool name must be a non-empty string in server "${s.name}".`);if(!t.description||typeof t.description!="string")throw new Error(`[createSdkMcpServer] Tool "${t.name}" must have a non-empty description string.`);try{e.registerTool(t.name,{description:t.description,inputSchema:t.inputSchema,...t.annotations?{annotations:t.annotations}:{}},t.handler)}catch(r){throw r instanceof Error&&r.message.includes("already registered")?new Error(`[createSdkMcpServer] Duplicate tool name "${t.name}" in server "${s.name}". Each tool name must be unique within a server.`):r}}return{type:"sdk",name:s.name,instance:e}}function sn(s,e,t,r,o){return{name:s,description:e,inputSchema:t,handler:r,annotations:o?.annotations}}import{readdir as Le,readFile as ye,stat as te,appendFile as Xt,realpath as ln}from"fs/promises";import{basename as pn,join as w,resolve as Vt}from"path";import{execFile as gn}from"child_process";import{promisify as fn}from"util";import{homedir as rn}from"os";import{join as Gt}from"path";var nn=".qoder",on="QODER_CLI_HOME",an="QODER_CONFIG_DIR",Jt=200;function cn(){return process.env[on]||rn()}function un(){let s=process.env[an];return s||Gt(cn(),nn)}function he(){return Gt(un(),"projects")}function dn(s){let e=5381;for(let t=0;t<s.length;t++)e=e*33^s.charCodeAt(t);return e}function Z(s){let e=s.replace(/[^a-zA-Z0-9]/g,"-");if(e.length<=Jt)return e;let t=Math.abs(dn(s)).toString(36);return`${e.slice(0,Jt)}-${t}`}var mn=fn(gn),hn=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,yn=new Set(["user","assistant","system","progress","attachment"]);function j(s){return s!==null&&typeof s=="object"}function Sn(s){return hn.test(s)}function vn(s){let e=[];for(let t of s.split(`
16
16
  `)){let r=t.trim();if(r)try{let o=JSON.parse(r);j(o)&&typeof o.uuid=="string"&&typeof o.type=="string"&&yn.has(o.type)&&e.push(o)}catch{}}return e}function Fe(s){if(!j(s.message))return[];let e=s.message.content;return Array.isArray(e)?e:[]}function ee(s){if(s.type!=="assistant"||!j(s.message))return;let e=s.message.id;return typeof e=="string"&&e?e:void 0}function Zt(s){return s.type!=="user"||!s.parentUuid?!1:Fe(s).some(e=>j(e)&&e.type==="tool_result")}function kn(s){if(!j(s.message))return null;let e=s.message.id;return typeof e=="string"&&e.length>0?e:null}function wn(s,e){let t=new Map;for(let[r,o]of s){let n=kn(o);if(n){let i=t.get(n);i?i.push(r):t.set(n,[r])}}for(let[r,o]of s){let n=bn(o,o.parentUuid,s,t,e);n!==o.parentUuid&&s.set(r,{...o,parentUuid:n})}}function bn(s,e,t,r,o){if(!e||t.has(e))return e;let n=r.get(e);return!n||n.length===0?e:n.length===1?n[0]:Pn(s,n,t)??Rn(s,n,t,o)??e}function Pn(s,e,t){if(!Zt(s))return;let r=Fe(s).filter(n=>j(n)&&n.type==="tool_result").map(n=>n.tool_use_id).filter(n=>typeof n=="string");if(r.length===0)return;let o=e.filter(n=>{let i=t.get(n);return i?Fe(i).some(a=>j(a)&&a.type==="tool_use"&&r.includes(typeof a.id=="string"?a.id:"")):!1});return o.length===1?o[0]:void 0}function Rn(s,e,t,r){return e.map(n=>t.get(n)).filter(n=>n!==void 0).filter(n=>(r.get(n.uuid)??-1)<(r.get(s.uuid)??-1)).at(-1)?.uuid}function Tn(s){for(let e of s.values()){if(e.type!=="system"||e.subtype!=="compact_boundary")continue;let t=e.compactMetadata?.preservedSegment,r=t?.headUuid,o=t?.anchorUuid,n=t?.tailUuid;if(!r||!o||!n)continue;let i=s.get(r);i&&s.set(r,{...i,parentUuid:o});for(let[a,c]of s)a!==r&&c.parentUuid===o&&s.set(a,{...c,parentUuid:n})}}function Yt(s,e,t){let r=(s.timestamp??"").localeCompare(e.timestamp??"");return r!==0?r:(t.get(s.uuid)??Number.MAX_SAFE_INTEGER)-(t.get(e.uuid)??Number.MAX_SAFE_INTEGER)}function En(s,e,t){let r=e.filter(d=>d.type==="assistant");if(r.length===0)return e;let o=new Map,n=0;for(let d of s.keys())o.set(d,n++);let i=new Map;for(let d of r){let l=ee(d);l&&i.set(l,d)}let a=new Map,c=new Map;for(let d of s.values()){let l=ee(d);if(l){let f=a.get(l)??[];f.push(d),a.set(l,f);continue}if(Zt(d)&&d.parentUuid){let f=c.get(d.parentUuid)??[];f.push(d),c.set(d.parentUuid,f)}}let u=new Set,p=new Map;for(let d of r){let l=ee(d);if(!l||u.has(l))continue;u.add(l);let f=a.get(l)??[d],S=f.filter(m=>!t.has(m.uuid)),h=[];for(let m of f){let M=c.get(m.uuid)??[];for(let z of M)t.has(z.uuid)||h.push(z)}if(S.length===0&&h.length===0)continue;let v=i.get(l);if(!v)continue;let b=[...f].sort((m,M)=>Yt(m,M,o));h.sort((m,M)=>Yt(m,M,o));let ne=b.findIndex(m=>m.uuid===v.uuid),ke=b.slice(0,Math.max(ne,0)).filter(m=>!t.has(m.uuid)),oe=b.slice(ne+1).filter(m=>!t.has(m.uuid)),ie=[...ke,...oe,...h];for(let m of ie)t.add(m.uuid);p.set(v.uuid,ie)}if(p.size===0)return e;let g=[];for(let d of e){let l=p.get(d.uuid);if(l){let f=o.get(d.uuid)??Number.MAX_SAFE_INTEGER,S=[],h=[];for(let v of l)(d.type==="assistant"&&v.type==="assistant"&&ee(v)===ee(d)&&(o.get(v.uuid)??Number.MAX_SAFE_INTEGER)<f?S:h).push(v);g.push(...S,d,...h)}else g.push(d)}return g}function Mn(s){if(s.length===0)return[];let e=new Map,t=new Map;for(let[d,l]of s.entries())e.set(l.uuid,l),t.set(l.uuid,d);Tn(e),wn(e,t);let r=new Set;for(let d of e.values())d.parentUuid&&r.add(d.parentUuid);let o=Array.from(e.values()).filter(d=>!r.has(d.uuid)),n=[];for(let d of o){let l=d,f=new Set;for(;l&&!f.has(l.uuid);){if(f.add(l.uuid),l.type==="user"||l.type==="assistant"){n.push(l);break}l=l.parentUuid?e.get(l.parentUuid):void 0}}if(n.length===0)return[];let i=n.filter(d=>!d.isSidechain&&!d.teamName&&!d.isMeta),c=(i.length>0?i:n).reduce((d,l)=>(t.get(l.uuid)??-1)>(t.get(d.uuid)??-1)?l:d),u=[],p=new Set,g=c;for(;g&&!p.has(g.uuid);)p.add(g.uuid),u.push(g),g=g.parentUuid?e.get(g.parentUuid):void 0;return u.reverse(),En(e,u,p)}function Cn(s,e){let t=s.type==="user"||s.type==="assistant",r=e&&s.type==="system";return!(!t&&!r||s.isMeta||s.isSidechain||s.teamName)}function _n(s){if(!s)return;let e=s.preservedSegment,t={trigger:s.trigger,pre_tokens:s.preTokens??s.pre_tokens,post_tokens:s.postTokens??s.post_tokens,messages_summarized:s.messagesSummarized??s.messages_summarized,duration_ms:s.durationMs??s.duration_ms};return!e?.headUuid||!e.anchorUuid||!e.tailUuid?t:{...t,preserved_segment:{head_uuid:e.headUuid,anchor_uuid:e.anchorUuid,tail_uuid:e.tailUuid}}}function xn(s){let e=s.type==="system"?_n(s.compactMetadata):void 0;return{type:s.type,uuid:s.uuid,session_id:s.sessionId??s.session_id??"",message:s.message,parent_tool_use_id:null,...typeof s.timestamp=="string"&&s.timestamp.length>0?{timestamp:s.timestamp}:{},...s.type==="system"&&s.subtype?{subtype:s.subtype}:{},...e?{compact_metadata:e}:{}}}function In(s,e){let t=Math.max(0,e?.offset??0),r=e?.limit;return r!==void 0&&r>0?s.slice(t,t+r):t>0?s.slice(t):s}async function es(s){try{return await ln(Vt(s))}catch{return Vt(s)}}async function An(s){return Z(await es(s))}async function q(s){let e=he();if(s?.dir){let t=await es(s.dir),r=[w(e,Z(t))];if(s.includeWorktrees!==!1)try{let{stdout:o}=await mn("git",["worktree","list","--porcelain"],{cwd:s.dir}),n=o.split(`
17
17
  `).filter(i=>i.startsWith("worktree ")).map(i=>i.substring(9).trim()).filter(i=>i!==t);for(let i of n)r.push(w(e,await An(i)))}catch{}return r}try{return(await Le(e,{withFileTypes:!0})).filter(r=>r.isDirectory()).map(r=>w(e,r.name))}catch{return[]}}async function ts(s){try{let[e,t]=await Promise.all([ye(s,"utf-8"),te(s)]),r=e.trim().split(`
18
18
  `).filter(Boolean);if(r.length===0)return null;let o=pn(s,".jsonl"),n,i,a,c,u,p,g;for(let d of r)try{let l=JSON.parse(d);if(!g&&l.timestamp&&(g=new Date(l.timestamp).getTime()),!n&&l.type==="user"&&l.message?.content){let f=l.message.content;if(typeof f=="string")n=f.substring(0,200);else if(Array.isArray(f)){let S=f.find(h=>h.type==="text");S?.text&&(n=S.text.substring(0,200))}}l.type==="custom-title"&&l.customTitle&&(i=l.customTitle),l.type==="ai-title"&&l.aiTitle&&(a=l.aiTitle),l.type==="tag"&&(p=l.tag||void 0),l.gitBranch&&(c=l.gitBranch),l.cwd&&(u=l.cwd)}catch{}return{sessionId:o,summary:i||a||n||"Untitled session",lastModified:t.mtimeMs,fileSize:t.size,customTitle:i||a,firstPrompt:n,gitBranch:c,cwd:u,tag:p,createdAt:g}}catch{return null}}function ss(s,e){return w(s,e,"subagents")}function On(s){if(typeof s!="object"||s===null)return!1;let e=s;return(e.type==="user"||e.type==="assistant")&&typeof e.uuid=="string"}async function rs(s){let e=[];async function t(r){let o;try{o=await Le(r,{withFileTypes:!0})}catch{return}for(let n of o){let i=w(r,n.name);if(n.isDirectory()){await t(i);continue}if(n.isFile()&&n.name.startsWith("agent-")&&n.name.endsWith(".jsonl")){let a=n.name.slice(6,-6);a&&e.push({agentId:a,filePath:i})}}}return await t(s),e}async function Dn(s){try{let e=await ye(s.replace(/\.jsonl$/,".meta.json"),"utf-8"),r=JSON.parse(e).toolUseId;return typeof r=="string"&&r.length>0?r:null}catch{return null}}function Un(s){if(s.length===0)return[];let e=new Map(s.map(i=>[i.uuid,i])),t=s[s.length-1],r=[],o=new Set,n=t;for(;n&&!o.has(n.uuid);)o.add(n.uuid),r.push(n),n=n.parentUuid!==void 0&&n.parentUuid!==null?e.get(n.parentUuid):void 0;return r.reverse()}async function jn(s,e,t){let[r,o]=await Promise.all([ye(s,"utf-8"),Dn(s)]),n=[];for(let p of r.trim().split(`
@@ -80,6 +80,7 @@ export type SDKControlInitializeRequest = {
80
80
  disallowedTools?: string[];
81
81
  mcpServers?: Record<string, ControlMcpServerConfig>;
82
82
  agents?: Record<string, AgentDefinition>;
83
+ skills?: string[];
83
84
  plugins?: SdkPluginConfig[];
84
85
  systemPrompt?: string;
85
86
  appendSystemPrompt?: string;
@@ -456,6 +457,11 @@ export type SDKControlRequestInner = SDKControlInterruptRequest | SDKControlPerm
456
457
  export type SDKControlInitializeResponse = {
457
458
  commands: SlashCommand[];
458
459
  agents: AgentInfo[];
460
+ skills?: Array<{
461
+ name: string;
462
+ description?: string;
463
+ source?: string;
464
+ }>;
459
465
  output_style: string;
460
466
  available_output_styles: string[];
461
467
  models: ModelInfo[];
@@ -44,6 +44,7 @@ type InitConfig = {
44
44
  appendSystemPrompt?: string;
45
45
  planModeInstructions?: string;
46
46
  agents?: Record<string, AgentDefinition>;
47
+ skills?: string[];
47
48
  promptSuggestions?: boolean;
48
49
  enableFileCheckpointing?: boolean;
49
50
  };
@@ -49,6 +49,10 @@ export type PromptResponse = {
49
49
  export type SettingSource = 'user' | 'project' | 'local';
50
50
  export type QueryTransportOptions = QueryTransportProviderOption;
51
51
  export type Options = {
52
+ /**
53
+ * Optional controller for defining when the host ends the session. Calling
54
+ * `abort()` closes the session and ends message iteration.
55
+ */
52
56
  abortController?: AbortController;
53
57
  /**
54
58
  * Authentication configuration for the qodercli child process.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qoder-ai/qoder-agent-sdk",
3
- "version": "1.0.13",
3
+ "version": "1.0.15",
4
4
  "description": "TypeScript SDK for building Qoder-powered coding agents.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -87,6 +87,7 @@
87
87
  "test:query-runtime-control:unit": "npm run build && node --test tests/query-runtime-control/unit/*.test.mjs",
88
88
  "test:query-runtime-control:functional": "npm run build && node --test tests/query-runtime-control/functional/*.test.mjs",
89
89
  "test:worker-runtime:functional": "npm run build && node --test tests/worker-runtime/functional/*.test.mjs",
90
+ "test:skills-loading-control:unit": "npm run build && node --test tests/skills-loading-control/unit/*.test.mjs",
90
91
  "test:skills-loading-control:functional": "npm run build && node --test tests/skills-loading-control/functional/*.test.mjs",
91
92
  "test:plugins-loading-control:unit": "npm run build && node --test tests/plugins-loading-control/unit/*.test.mjs",
92
93
  "test:plugins-loading-control:functional": "npm run build && node --test tests/plugins-loading-control/functional/*.test.mjs",
@@ -112,6 +113,6 @@
112
113
  "typescript": "^5.7.0",
113
114
  "zod": "^4.0.0"
114
115
  },
115
- "qoderCliVersion": "1.0.41",
116
+ "qoderCliVersion": "1.0.47",
116
117
  "license": "SEE LICENSE IN LICENSE"
117
118
  }