@qoder-ai/qoder-agent-sdk 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/index.js +8 -8
- package/dist/cloud-agent/cloud-agent-query.d.ts +2 -2
- package/dist/core/process-transport.d.ts +31 -3
- package/dist/core/sdk-diagnostics.d.ts +23 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.js +21 -24
- package/dist/protocol/common.d.ts +93 -0
- package/dist/protocol/control.d.ts +54 -1
- package/dist/protocol/index.d.ts +2 -2
- package/dist/protocol/index.js +1 -1
- package/dist/protocol/messages.d.ts +2 -0
- package/dist/query/query-runner.d.ts +21 -5
- package/dist/session/session-manager.d.ts +11 -7
- package/dist/types/byok.d.ts +1 -1
- package/dist/types/common.d.ts +1 -1
- package/dist/types/control.d.ts +1 -1
- package/dist/types/options.d.ts +53 -6
- package/dist/types/session.d.ts +2 -2
- package/package.json +3 -2
- package/scripts/postinstall.cjs +48 -10
- package/dist/core/sdk-debug.d.ts +0 -21
package/dist/browser/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import{McpServer as
|
|
1
|
+
import{McpServer as W}from"@modelcontextprotocol/sdk/server/mcp.js";function Q(r){if(!r.name||typeof r.name!="string"||r.name.trim()==="")throw new Error("[createSdkMcpServer] Server name must be a non-empty string.");let e=new W({name:r.name,version:r.version??"1.0.0"},{capabilities:{tools:r.tools&&r.tools.length>0?{}:void 0}});if(r.tools&&r.tools.length>0)for(let t of r.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 "${r.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(s){throw s instanceof Error&&s.message.includes("already registered")?new Error(`[createSdkMcpServer] Duplicate tool name "${t.name}" in server "${r.name}". Each tool name must be unique within a server.`):s}}return{type:"sdk",name:r.name,instance:e}}function B(r,e,t,s,n){return{name:r,description:e,inputSchema:t,handler:s,annotations:n?.annotations}}var v=class{queue=[];readResolve;readReject;isDone=!1;errorValue;started=!1;returnCallback;constructor(e){this.returnCallback=e}[Symbol.asyncIterator](){if(this.started)throw new Error("Stream can only be iterated once");return this.started=!0,this}async next(){if(this.queue.length>0)return{done:!1,value:this.queue.shift()};if(this.isDone)return{done:!0,value:void 0};if(this.errorValue!==void 0)throw this.errorValue;return new Promise((e,t)=>{this.readResolve=e,this.readReject=t})}enqueue(e){if(!this.isDone)if(this.readResolve){let t=this.readResolve;this.readResolve=void 0,this.readReject=void 0,t({done:!1,value:e})}else this.queue.push(e)}done(){if(this.isDone=!0,this.readResolve){let e=this.readResolve;this.readResolve=void 0,this.readReject=void 0,e({done:!0,value:void 0})}}error(e){if(this.errorValue=e,this.readReject){let t=this.readReject;this.readResolve=void 0,this.readReject=void 0,t(e)}}async return(){return this.isDone=!0,this.returnCallback?.(),{done:!0,value:void 0}}async throw(e){return this.error(e),{done:!0,value:void 0}}};var G=3e4,Z=3e4,M=class{options;ws=null;ready=!1;readyResolve;readyReject;readyPromise;messages=new v;keepAliveTimer;exitError;constructor(e){this.options=e,this.readyPromise=new Promise((t,s)=>{this.readyResolve=t,this.readyReject=s}),this.initialize()}initialize(){let e=new globalThis.WebSocket(this.options.url);this.ws=e;let t=setTimeout(()=>{if(!this.ready){let s=new Error("WebSocket connection timeout");this.readyReject?.(s),e.close()}},Z);e.onopen=()=>{clearTimeout(t),this.ready=!0,this.readyResolve?.(),this.options.authMessage&&e.send(JSON.stringify(this.options.authMessage)+`
|
|
2
2
|
`),this.keepAliveTimer=setInterval(()=>{e.readyState===WebSocket.OPEN&&e.send(JSON.stringify({type:"keep_alive"})+`
|
|
3
|
-
`)},G)},e.onmessage=
|
|
4
|
-
`);for(let
|
|
5
|
-
`)}catch(
|
|
6
|
-
`)}catch(
|
|
7
|
-
`)}}catch(n){if(!
|
|
8
|
-
`)}}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,
|
|
9
|
-
`)}t>0&&this.hasBidirectionalNeeds()&&await this.waitForFirstResult(),this.transport.endInput()}catch(t){this.
|
|
3
|
+
`)},G)},e.onmessage=s=>{let n=String(s.data).split(`
|
|
4
|
+
`);for(let o of n)if(o.trim())try{let i=JSON.parse(o);this.messages.enqueue(i)}catch{}},e.onerror=()=>{let s=new Error("WebSocket connection error");this.exitError=s,this.readyReject?.(s),this.messages.done()},e.onclose=s=>{this.ready=!1,this.keepAliveTimer&&(clearInterval(this.keepAliveTimer),this.keepAliveTimer=void 0),s.code!==1e3&&s.code!==1001&&(this.exitError=new Error(`WebSocket closed abnormally: ${s.code} ${s.reason}`)),this.messages.done()},this.options.abortController?.signal.addEventListener("abort",()=>{this.close()})}async write(e){this.ready||await this.readyPromise,this.ws?.send(e)}close(){this.keepAliveTimer&&(clearInterval(this.keepAliveTimer),this.keepAliveTimer=void 0),this.ws&&(this.ws.close(1e3),this.ws=null),this.messages.done()}isReady(){return this.ready}async*readMessages(){if(yield*this.messages,this.exitError)throw this.exitError}endInput(){}};var R=class extends Error{constructor(e="Operation was aborted"){super(e),this.name="AbortError"}};var b=class extends Error{timeoutMs;constructor(e){super(`resolveModel did not return within ${e}ms. Increase resolveModelTimeoutMs or ensure the callback resolves faster.`),this.name="ModelPolicyTimeoutError",this.timeoutMs=e}},C=class extends Error{cliProtocolVersion;sdkProtocolVersion;constructor(e,t){super(`Wire protocol major mismatch: CLI announced "${e}" but this SDK was built for "${t}". Upgrade either qodercli or @qoder-ai/qoder-agent-sdk so the major versions align.`),this.name="ProtocolVersionMismatchError",this.cliProtocolVersion=e,this.sdkProtocolVersion=t}};var T="1.0.0";var I="ExitPlanMode";import*as V from"fs";function q(r,e,t,s){return new Promise((n,o)=>{if(!("id"in e&&e.id!==null)){try{t.onmessage?.(e)}catch(l){o(l);return}n({jsonrpc:"2.0"});return}let a=`${r}:${e.id}`;s.set(a,{resolve:n,reject:o}),t.onmessage?t.onmessage(e):(s.delete(a),o(new Error(`No message handler registered for MCP server "${r}"`)))})}function E(r,e,t){if("id"in e&&e.id!==null){let s=`${r}:${e.id}`,n=t.get(s);if(n)return n.resolve(e),t.delete(s),!0}return!1}function D(r,e,t){let s=0,n=`${r}:`,o=Array.from(t.entries());for(let i of o){let[a,l]=i;a.startsWith(n)&&(l.reject(e),t.delete(a),s++)}return s}function x(){return Math.random().toString(36).substring(2,15)}function K(r,e){let t="type"in e&&!("subtype"in e)?{...e,subtype:e.type}:e;return{type:"control_request",request_id:r,request:t}}function A(r,e){return{type:"control_response",response:{subtype:"success",request_id:r,response:e}}}function j(r,e,t){return{type:"control_response",response:{subtype:"error",request_id:r,error:e,...t?{code:t}:{}}}}function O(r){return typeof r=="object"&&r!==null&&r.type==="control_response"}function N(r){return typeof r=="object"&&r!==null&&r.type==="control_request"}function U(r){return typeof r=="object"&&r!==null&&(r.type==="control_cancel_request"||r.type==="control_cancel")}function w(r){if(typeof r!="object"||r===null)return;let e=r,t=e.subtype;if(typeof t=="string")return t;let s=e.type;return typeof s=="string"?s:void 0}function J(r){if(typeof r!="object"||r===null)return!1;let e=r.type;return e==="keepalive"||e==="keep_alive"}function z(r){return typeof r=="object"&&r!==null&&r.type==="streamlined_text"}function H(r){return typeof r=="object"&&r!==null&&r.type==="streamlined_tool_use_summary"}function $(r){return typeof r=="object"&&r!==null&&r.type==="post_turn_summary"}function L(r){return typeof r=="object"&&r!==null&&r.type==="result"}var P=class r{static INITIALIZE_TIMEOUT_MS=12e4;transport;inputStream;pendingRequests=new Map;pendingInboundRequests=new Map;hooks;hookCallbacks=new Map;nextHookCallbackId=0;sdkMcpServers;sdkMcpTransports;pendingMcpResponses;isSingleTurn;canUseTool;abortController;jsonSchema;initConfig;onElicitation;onAuthExpired;fetchJobToken;diagnostics;controlRequestTimeoutMs;resolveModel;resolveModelTimeoutMs;initResponse;initializationPromise;resultMessage;readLoopPromise;closed=!1;authExpiredFired=!1;protocolHandshakeValidated=!1;firstResultReceived=!1;firstResultReceivedResolve;constructor(e,t,s,n,o,i,a,l,c,p,d,h,m,u,y,f,k){if(this.transport=e,this.isSingleTurn=t,this.canUseTool=s,this.hooks=n??{},this.abortController=o,this.sdkMcpServers=i??new Map,this.sdkMcpTransports=m??new Map,this.pendingMcpResponses=u??new Map,this.jsonSchema=a,this.initConfig=l??{},this.onElicitation=c,this.onAuthExpired=d,this.fetchJobToken=y,this.diagnostics=p,this.controlRequestTimeoutMs=h??6e4,this.resolveModel=f,this.resolveModelTimeoutMs=k??500,this.inputStream=new v(()=>{this.close().catch(()=>{})}),this.readLoopPromise=this.readMessages().catch(g=>{this.inputStream.error(g)}),this.initializationPromise=this.performInitialize(),this.initializationPromise.catch(()=>{}),this.abortController){let g=this.abortController.signal;g.aborted?this.close().catch(()=>{}):g.addEventListener("abort",()=>{this.close().catch(()=>{})},{once:!0})}}[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 readMessages(){let e;try{for await(let t of this.transport.readMessages()){if(this.closed)break;if(O(t)){this.handleControlResponse(t);continue}if(N(t)){this.handleControlRequest(t).catch(n=>{this.diagnostics?.record("[QueryRunner] Error handling control request:",n)});continue}if(U(t)){this.handleControlCancelRequest(t);continue}if(J(t)||z(t)||H(t)||$(t))continue;if(L(t)){let n=t;this.resultMessage=n,this.firstResultReceived=!0,this.firstResultReceivedResolve?.(),this.firstResultReceivedResolve=void 0,this.inputStream.enqueue(n),this.isSingleTurn&&this.transport.endInput();continue}let s=t;if(s.type==="system"&&s.subtype==="init")try{this.validateProtocolHandshake(s)}catch(n){throw this.inputStream.error(n),n}if(this.onAuthExpired&&!this.authExpiredFired){let n=!1;(s.type==="auth_status"&&s.error||s.type==="assistant"&&s.error==="authentication_failed")&&(n=!0),n&&(this.authExpiredFired=!0,Promise.resolve(this.onAuthExpired()).catch(i=>{this.diagnostics?.record("[QueryRunner] onAuthExpired callback threw:",i)}))}this.inputStream.enqueue(s)}}catch(t){e=t}finally{let t=e instanceof Error?e:new Error("Transport closed");this.firstResultReceivedResolve?.(),this.firstResultReceivedResolve=void 0;for(let[,s]of this.pendingRequests)s.reject(t);this.pendingRequests.clear(),e!==void 0?this.inputStream.error(e):this.inputStream.done()}}async request(e,t){let s=x(),n=K(s,e),o=t?.timeoutMs??this.controlRequestTimeoutMs;return new Promise((i,a)=>{let l=null,c=()=>{l&&(clearTimeout(l),l=null)};this.pendingRequests.set(s,{resolve:p=>{c(),i(p)},reject:p=>{c(),a(p)}}),o>0&&Number.isFinite(o)&&(l=setTimeout(()=>{if(this.pendingRequests.has(s)){this.pendingRequests.delete(s);try{this.transport.write(JSON.stringify({type:"control_cancel_request",request_id:s})+`
|
|
5
|
+
`)}catch(p){this.diagnostics?.record("[QueryRunner] Failed to send control_cancel_request on timeout:",p)}a(new Error(`Control request "${w(n.request)??"unknown"}" timed out after ${o}ms`))}},o));try{this.transport.write(JSON.stringify(n)+`
|
|
6
|
+
`)}catch(p){c(),this.pendingRequests.delete(s),a(p)}})}handleControlResponse(e){let t=e.response,s=t.request_id,n=this.pendingRequests.get(s);if(n)if(this.pendingRequests.delete(s),t.subtype==="success")n.resolve(t.response);else{let o=new Error(t.error);t.code&&(o.code=t.code),n.reject(o),this.processPendingPermissionRequests(t.pending_permission_requests)}}processPendingPermissionRequests(e){if(e)for(let t of e)w(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=new AbortController;this.pendingInboundRequests.set(t,{abortController:s});try{let n=await this.awaitAbortable(this.processControlRequest(e,s.signal),s.signal);if(!s.signal.aborted){let o=A(t,n);this.transport.write(JSON.stringify(o)+`
|
|
7
|
+
`)}}catch(n){if(!s.signal.aborted){let{error:o,code:i}=X(n),a=j(t,o,i);this.transport.write(JSON.stringify(a)+`
|
|
8
|
+
`)}}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=T;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 n=F(t),o=F(s);if(!n||!o){this.diagnostics?.record(`[QueryRunner] Could not parse protocol_version "${t}" or built-in "${s}"; skipping handshake.`);return}if(n.major!==o.major)throw new C(t,s);n.minor<o.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,n)=>{let o=()=>{n(new R)};t.addEventListener("abort",o,{once:!0}),e.then(i=>{t.removeEventListener("abort",o),s(i)},i=>{t.removeEventListener("abort",o),n(i)})})}async processControlRequest(e,t){this.throwIfAborted(t);let s=e.request,n=w(s),o=s;switch(n){case"fetch_job_token":{if(!this.fetchJobToken)throw new Error("job_token_unavailable: No fetchJobToken callback configured");let i=o.reason??"initial",a=o.session_id,l=e.request_id,c=await this.awaitAbortable(this.fetchJobToken({requestId:l,reason:i,sessionId:a},{signal:t}),t);if(!c?.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:c.token}}case"can_use_tool":case"permission_response":{let i=o.tool_name,a=o.input??o.tool_input??{};if(!this.canUseTool)throw new Error("canUseTool callback is not provided.");let l=o.tool_use_id,c=o.permission_suggestions??o.suggestions,p=o.blocked_path,d=o.decision_reason,h=o.decision_reason_type,m=o.classifier_approvable,u=o.title,y=o.display_name,f=o.description,k=o.agent_id,g=Y(i,o.details,o.plan_path,o.plan_content),S=await this.awaitAbortable(this.canUseTool(i,a,{signal:t,suggestions:c,blockedPath:p,decisionReason:d,decisionReasonType:h,classifierApprovable:m,title:u,displayName:y,description:f,toolUseID:l,agentID:k,exitPlanMode:g}),t);if(S.behavior==="deny"&&!S.message)throw new Error("Permission deny result must include a message.");return S.behavior==="allow"?{...S,updatedInput:S.updatedInput??a,toolUseID:l}:{...S,toolUseID:l}}case"hook_callback":{let i=o.callback_id;if(!i)throw new Error("Hook callback missing callback_id");return this.invokeRegisteredHookCallback(i,o.input,o.tool_use_id,t)}case"mcp_message":{let i=o.server_name,a=o.message,l=this.sdkMcpTransports.get(i);if(!l)throw new Error(`Unknown in-process MCP server: ${i}`);return{mcp_response:await this.awaitAbortable(q(i,a,l,this.pendingMcpResponses),t)}}case"elicitation":case"elicitation_response":return this.onElicitation?await this.awaitAbortable(this.onElicitation({serverName:o.mcp_server_name??"",message:o.message??o.prompt??"",mode:o.mode,url:o.url,elicitationId:o.elicitation_id,requestedSchema:o.requested_schema,title:o.title,displayName:o.display_name,description:o.description},{signal:t}),t):{action:"cancel"};case"get_model_policy":{if(!this.resolveModel)return{type:"get_model_policy"};let i={purpose:o.purpose,sessionId:o.sessionId,turnIndex:o.turnIndex,availableModels:o.models??[]},a=this.resolveModelTimeoutMs,l=Promise.resolve(this.resolveModel(i)),c,p=new Promise((m,u)=>{c=setTimeout(()=>{u(new b(a))},a)}),d;try{d=await this.awaitAbortable(Promise.race([l,p]),t)}finally{clearTimeout(c)}let h={type:"get_model_policy",model:typeof d.model=="string"?d.model:d.model.model,parameters:d.parameters};if(typeof d.model!="string"){let{model:m,...u}=d.model;h.custom_model={...u,style:u.style??"openai"}}return h}default:throw new Error(`Unhandled control request subtype: ${n??"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[n,o]of Object.entries(this.hooks)){if(!o||o.length===0)continue;let i=[];for(let a of o){let l=a.hooks.map(c=>{let p=`hook_${this.nextHookCallbackId++}`;return this.hookCallbacks.set(p,c),p});l.length!==0&&i.push({matcher:a.matcher,hookCallbackIds:l,timeout:a.timeout})}i.length>0&&(t[n]=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 n=s;this.initResponse=n}if(!this.initResponse)throw new Error("Failed to receive initialization response");return this.initResponse}async invokeRegisteredHookCallback(e,t,s,n){let o=this.hookCallbacks.get(e);if(!o)throw new Error(`Unknown hook callback: ${e}`);return await this.awaitAbortable(o(t,s,{signal:n}),n)??{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
|
+
`)}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(){let e={subtype:"get_models"};return(await this.request(e))?.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 reloadPlugins(){return await this.request({type:"reload_plugins"})}async rewindFiles(e,t){let s={type:"rewind_files",user_message_id:e};t?.dryRun&&(s.dry_run=!0);let o=await this.request(s);if(!t?.dryRun&&o?.canRewind===!1)throw new Error(typeof o.error=="string"&&o.error.length>0?o.error:"Unable to rewind files.");return o}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}:{}}),n=s?.requiresUserAction===!0,o=typeof s?.authUrl=="string"?s.authUrl:void 0;if(n&&o===void 0)throw new Error("mcp_authenticate response set requiresUserAction=true but did not include an authUrl");return n?{authUrl:o,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(n){this.diagnostics?.record(`[QueryRunner] error closing SDK MCP transport "${t}":`,n)}D(t,e,this.pendingMcpResponses)}this.transport.close();try{await this.readLoopPromise}catch{}}async[Symbol.asyncDispose](){await this.close()}};function X(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,n=/^([a-z][a-z0-9_]*):\s*(.*)$/.exec(e);if(n){let o=s??n[1];return(!s||s===n[1])&&(e=n[2]||e),{error:e,code:o}}return s?{error:e,code:s}:{error:e}}function Y(r,e,t,s){if(r!==I)return;let n=e!==null&&typeof e=="object"?e:void 0,o=n?.type===I||n?.type==="ExitPlanMode",i=o&&typeof n?.planPath=="string"&&n.planPath.length>0?n.planPath:typeof t=="string"&&t.length>0?t:void 0,a=o&&typeof n?.planContent=="string"&&n.planContent.length>0?n.planContent:typeof s=="string"&&s.length>0?s:void 0;if(!a&&i&&(a=V.readFileSync(i,"utf8").trim()||void 0),!(!i&&!a))return{planPath:i,planContent:a}}function F(r){let e=/^(\d+)\.(\d+)(?:\.\d+)?(?:[-+].*)?$/.exec(r);return e?{major:Number(e[1]),minor:Number(e[2])}:null}var _=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 ee(r){let{prompt:e,websocket:t,abortController:s,canUseTool:n,hooks:o,mcpServers:i,jsonSchema:a}=r,l=new Map,c=new Map,p=new Map;if(i)for(let[m,u]of Object.entries(i))if(u.type==="sdk"&&"instance"in u){let y=u.instance;l.set(m,y);let f=new _(k=>{E(m,k,p)});c.set(m,f),y.connect(f).catch(()=>{})}else throw new Error(`Browser SDK only supports SDK MCP servers. Server "${m}" has type "${u.type}".`);let d=new M({url:t.url,headers:t.headers,authMessage:t.authMessage,abortController:s}),h=new P(d,!0,n,o,s,l,a,{},void 0,void 0,void 0,void 0,c,p);return h.streamInput(e),h}export{Q as createSdkMcpServer,ee as query,B as tool};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { DiagnosticsSink } from '../core/sdk-diagnostics.js';
|
|
2
2
|
import type { InternalAuthOptions } from '../types/auth.js';
|
|
3
3
|
import type { CloudAgentOptions } from '../types/cloud-agent.js';
|
|
4
4
|
import type { Query } from '../types/options.js';
|
|
@@ -12,7 +12,7 @@ type CreateCloudAgentQueryParams = {
|
|
|
12
12
|
abortController?: AbortController;
|
|
13
13
|
onAuthExpired?: () => void;
|
|
14
14
|
};
|
|
15
|
-
|
|
15
|
+
diagnostics?: DiagnosticsSink;
|
|
16
16
|
};
|
|
17
17
|
export declare function validateCloudAgentQueryOptions(options: CreateCloudAgentQueryParams['options'] & Record<string, unknown>): void;
|
|
18
18
|
export declare function createCloudAgentQuery(params: CreateCloudAgentQueryParams): Query;
|
|
@@ -16,6 +16,19 @@ import type { PermissionMode } from '../types/permissions.js';
|
|
|
16
16
|
import type { McpServerConfigForProcessTransport, McpServerToolPolicy } from '../types/mcp.js';
|
|
17
17
|
import type { InternalAuthOptions } from '../types/auth.js';
|
|
18
18
|
import type { SpawnedProcess, SpawnOptions, SettingSource } from '../types/options.js';
|
|
19
|
+
import type { DiagnosticsSink } from './sdk-diagnostics.js';
|
|
20
|
+
export declare class QoderCliProcessError extends Error {
|
|
21
|
+
readonly code: "QODER_CLI_PROCESS_ERROR";
|
|
22
|
+
readonly exitCode?: number | null;
|
|
23
|
+
readonly signal?: NodeJS.Signals | null;
|
|
24
|
+
readonly stderr?: string;
|
|
25
|
+
constructor(message: string, options?: {
|
|
26
|
+
exitCode?: number | null;
|
|
27
|
+
signal?: NodeJS.Signals | null;
|
|
28
|
+
stderr?: string;
|
|
29
|
+
cause?: unknown;
|
|
30
|
+
});
|
|
31
|
+
}
|
|
19
32
|
/**
|
|
20
33
|
* Options for configuring the ProcessTransport.
|
|
21
34
|
*
|
|
@@ -33,6 +46,7 @@ export interface ProcessTransportOptions {
|
|
|
33
46
|
cwd?: string;
|
|
34
47
|
/** Custom environment variables (defaults to process.env) */
|
|
35
48
|
env?: Record<string, string | undefined>;
|
|
49
|
+
proxy?: string;
|
|
36
50
|
/** stderr handling mode */
|
|
37
51
|
stderr?: 'inherit' | 'pipe' | 'ignore';
|
|
38
52
|
/** Optional callback for child-process stderr output */
|
|
@@ -44,6 +58,8 @@ export interface ProcessTransportOptions {
|
|
|
44
58
|
model?: string;
|
|
45
59
|
/** Forward --debug to the CLI process. */
|
|
46
60
|
debug?: boolean;
|
|
61
|
+
/** SDK-internal diagnostics sink. This is not forwarded to qodercli. */
|
|
62
|
+
diagnostics?: DiagnosticsSink;
|
|
47
63
|
agent?: string;
|
|
48
64
|
sessionId?: string;
|
|
49
65
|
continue?: boolean;
|
|
@@ -59,7 +75,7 @@ export interface ProcessTransportOptions {
|
|
|
59
75
|
includeHookEvents?: boolean;
|
|
60
76
|
allowedTools?: string[];
|
|
61
77
|
disallowedTools?: string[];
|
|
62
|
-
tools?:
|
|
78
|
+
tools?: ToolsOption;
|
|
63
79
|
toolConfig?: ToolConfig;
|
|
64
80
|
extensions?: string[];
|
|
65
81
|
mcpServers?: Record<string, McpServerConfigForProcessTransport>;
|
|
@@ -86,6 +102,10 @@ export interface ProcessTransportOptions {
|
|
|
86
102
|
*/
|
|
87
103
|
onAuthExpired?: () => void;
|
|
88
104
|
}
|
|
105
|
+
type ToolsOption = string[] | {
|
|
106
|
+
type: 'preset';
|
|
107
|
+
preset: 'qodercli';
|
|
108
|
+
};
|
|
89
109
|
export declare class ProcessTransport implements Transport {
|
|
90
110
|
private process;
|
|
91
111
|
private customHandle;
|
|
@@ -97,7 +117,9 @@ export declare class ProcessTransport implements Transport {
|
|
|
97
117
|
private authPayloadPath;
|
|
98
118
|
private pendingInput;
|
|
99
119
|
private generatedSettingsDir;
|
|
100
|
-
private
|
|
120
|
+
private diagnostics?;
|
|
121
|
+
private processExitError;
|
|
122
|
+
private stderrTail;
|
|
101
123
|
constructor(options?: ProcessTransportOptions);
|
|
102
124
|
/**
|
|
103
125
|
* Build CLI arguments, resolve the executable, spawn the process,
|
|
@@ -144,6 +166,11 @@ export declare class ProcessTransport implements Transport {
|
|
|
144
166
|
* Get the stdout stream from the process or custom handle.
|
|
145
167
|
*/
|
|
146
168
|
private getStdout;
|
|
169
|
+
private appendStderr;
|
|
170
|
+
private createSpawnError;
|
|
171
|
+
private createProcessExitError;
|
|
172
|
+
private getStderrTail;
|
|
173
|
+
private waitForProcessExit;
|
|
147
174
|
/**
|
|
148
175
|
* Resolve the executable command and arguments.
|
|
149
176
|
*
|
|
@@ -183,4 +210,5 @@ export declare class ProcessTransport implements Transport {
|
|
|
183
210
|
private cleanupAuthPayload;
|
|
184
211
|
/** Fire `onAuthExpired` at most once per session. */
|
|
185
212
|
private fireAuthExpired;
|
|
186
|
-
}
|
|
213
|
+
}
|
|
214
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Minimal internal diagnostics sink used by query runtimes. */
|
|
2
|
+
export interface DiagnosticsSink {
|
|
3
|
+
record(message: string, error?: unknown): void;
|
|
4
|
+
}
|
|
5
|
+
export type SdkDiagnosticsOptions = {
|
|
6
|
+
debug?: boolean;
|
|
7
|
+
debugFile?: string;
|
|
8
|
+
stderr?: (data: string) => void;
|
|
9
|
+
};
|
|
10
|
+
export declare function isSdkDiagnosticsEnabled(options: SdkDiagnosticsOptions): boolean;
|
|
11
|
+
export declare function resolveSdkDiagnosticsFilePath(options: SdkDiagnosticsOptions): string | undefined;
|
|
12
|
+
export declare class SdkDiagnostics implements DiagnosticsSink {
|
|
13
|
+
private readonly enabled;
|
|
14
|
+
private readonly debugFile?;
|
|
15
|
+
private readonly stderr?;
|
|
16
|
+
constructor(options?: SdkDiagnosticsOptions);
|
|
17
|
+
record(message: string, error?: unknown): void;
|
|
18
|
+
get filePath(): string | undefined;
|
|
19
|
+
private writeToFile;
|
|
20
|
+
private writeToStderr;
|
|
21
|
+
private formatLine;
|
|
22
|
+
private formatError;
|
|
23
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
* ```
|
|
53
53
|
*/
|
|
54
54
|
export { query } from './query/query.js';
|
|
55
|
+
export { QoderCliProcessError } from './core/process-transport.js';
|
|
55
56
|
export { DEFAULT_ACCESS_TOKEN_ENV_VAR, accessToken, accessTokenFromEnv, jobToken, qodercliAuth, } from './auth.js';
|
|
56
57
|
export { createSdkMcpServer, tool } from './mcp/sdk-mcp-server.js';
|
|
57
58
|
export type { AnyZodRawShape, InferShape, SdkMcpToolDefinition, ToolExtras, CreateSdkMcpServerOptions, } from './mcp/sdk-mcp-server.js';
|
|
@@ -73,7 +74,7 @@ export type { AccessTokenInput, AuthOptions } from './types/auth.js';
|
|
|
73
74
|
* @internal Internal auth types for first-party host integration, not general public use.
|
|
74
75
|
*/
|
|
75
76
|
export type { FetchJobToken, JobTokenAuthOptions, JobTokenRequest, JobTokenResult, } from './types/auth.js';
|
|
76
|
-
export type { AccountInfo, ApiKeySource, ExitReason, FastModeState, ConfigScope, SettingSource, SDKAssistantMessageError, SDKStatus, EffortLevel, ThinkingAdaptive, ThinkingEnabled, ThinkingDisabled, ThinkingConfig, OutputFormatType, JsonSchemaOutputFormat, OutputFormat, BaseOutputFormat, ModelInfo, ModelUsage, NonNullableUsage, SlashCommand, ToolConfig, SdkPluginConfig, } from './types/common.js';
|
|
77
|
+
export type { AccountInfo, ApiKeySource, ExitReason, FastModeState, ConfigScope, SettingSource, SDKAssistantMessageError, SDKStatus, EffortLevel, ThinkingAdaptive, ThinkingEnabled, ThinkingDisabled, ThinkingConfig, OutputFormatType, JsonSchemaOutputFormat, OutputFormat, BaseOutputFormat, ModelInfo, ModelSource, ModelStrategy, ModelContextConfig, ModelContextWindowEntry, ModelEffortEntry, ModelThinkingConfig, ModelThinkingDisabled, ModelThinkingEnabled, ModelUsage, NonNullableUsage, SlashCommand, ToolConfig, SdkPluginConfig, } from './types/common.js';
|
|
77
78
|
export type { SDKMessage, SDKAssistantMessage, SDKUserMessage, SDKUserMessageReplay, SDKResultMessage, SDKResultSuccess, SDKResultError, SDKSystemMessage, SDKSystemInitMessage, SDKSystemMessageSubtype, SDKSystemMessageBySubtype, SDKPartialAssistantMessage, SDKCompactBoundaryMessage, SDKStatusMessage, SDKAPIRetryMessage, SDKLocalCommandOutputMessage, SDKHookStartedMessage, SDKHookProgressMessage, SDKHookResponseMessage, SDKPermissionDeniedMessage, SDKTaskNotificationMessage, SDKTaskStartedMessage, SDKTaskProgressMessage, SDKSessionStateChangedMessage, SDKSessionTitleChangedMessage, SDKBridgeStateMessage, SDKFilesPersistedEvent, SDKElicitationCompleteMessage, SDKPromptSuggestionMessage, SDKCloudAgentEventMessage, SDKPermissionDenial, } from './types/messages.js';
|
|
78
79
|
export type { Options, Query, SpawnOptions, SpawnedProcess, ElicitationRequest, ElicitationResult, OnElicitation, PromptRequest, PromptRequestOption, PromptResponse, CanUseTool, Transport, } from './types/options.js';
|
|
79
80
|
export type { AgentCreateParams, BetaManagedAgentsAgentToolName, BetaManagedAgentsAgentToolset20260401Params, BetaManagedAgentsCustomSkillParams, BetaManagedAgentsFileResourceParams, BetaManagedAgentsModel, BetaManagedAgentsSkillParams, BetaManagedAgentsURLMCPServerParams, CloudAgentOptions, CloudAgentReference, CloudAgentStreamOptions, CloudSessionResource, CloudSessionCreateParams, CloudSessionCreateReference, CloudSessionExistingReference, CloudSessionReference, SessionCreateParams, } from './types/cloud-agent.js';
|
|
@@ -86,9 +87,9 @@ export type { SDKSessionInfo, SessionMessage, ListSessionsOptions, GetSessionInf
|
|
|
86
87
|
export type { Settings, SandboxSettings, SandboxNetworkConfig, SandboxFilesystemConfig, SandboxIgnoreViolations, ResolvedSettings, ResolvedSettingsSource, } from './types/settings.js';
|
|
87
88
|
export { filterEscalatingDefaultMode } from './types/settings.js';
|
|
88
89
|
export type { QoderModelPurpose } from './types/control.js';
|
|
89
|
-
export type { SDKControlRequest, SDKControlResponse, SDKControlInitializeResponse, SDKControlGetContextUsageResponse, SDKControlReloadPluginsResponse, } from './types/control.js';
|
|
90
|
+
export type { SDKControlRequest, SDKControlResponse, SDKControlInitializeResponse, SDKControlGetContextUsageResponse, SDKControlAddDirectoriesResponse, SDKControlReloadPluginsResponse, } from './types/control.js';
|
|
90
91
|
export type { SDKControlGetModelPolicyRequest, SDKControlGetModelPolicyResponse, SDKCapabilities, ModelPolicyContext, ModelPolicyResult, ModelPolicyProvider, } from './types/model-policy-provider.js';
|
|
91
|
-
export type { SDKControlGetByokConfigRequest, SDKControlGetByokConfigResponse, BYOKProviderInfo, BYOKModelTypeInfo, BYOKModelInfo, CustomModel, } from './types/byok.js';
|
|
92
|
+
export type { SDKControlGetByokConfigRequest, SDKControlGetByokConfigResponse, SDKControlValidateByokModelRequest, SDKControlValidateByokModelResponse, BYOKModelValidationInput, BYOKProviderInfo, BYOKModelTypeInfo, BYOKModelInfo, CustomModel, } from './types/byok.js';
|
|
92
93
|
export type { SessionState, BridgeSessionHandle, AttachBridgeSessionOptions, RemoteCredentials, } from './types/bridge.js';
|
|
93
94
|
export type { OAuthCredential, AuthMessage, WebSocketOptions, BrowserQueryOptions, } from './types/browser.js';
|
|
94
95
|
export type { AgentInput, AgentOutput, BashInput, FileReadInput, FileReadOutput, FileEditInput, FileWriteInput, GlobInput, GrepInput, WebFetchInput, WebSearchInput, AskUserQuestionInput, NotebookEditInput, ExitPlanModeInput, TodoWriteInput, ToolInputSchemas, ToolOutputSchemas, } from './types/tools.js';
|