@iflow-ai/iflow-cli-sdk 0.1.1 → 0.1.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/README.md +0 -1
- package/README_CN.md +0 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +0 -23
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
package/README_CN.md
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=require("fs"),t=require("path"),o=require("ws"),s=require("fs/promises"),i=require("os"),r=require("net"),n=require("child_process");function l(e){var t=Object.create(null);return e&&Object.keys(e).forEach(function(o){if("default"!==o){var s=Object.getOwnPropertyDescriptor(e,o);Object.defineProperty(t,o,s.get?s:{enumerable:!0,get:function(){return e[o]}})}}),t.default=e,Object.freeze(t)}var a,c,d,h,u,p,g,f,w,y,m,v,S,T=l(e),E=l(t),I=l(s),x=l(i),A=l(r),O=l(n);class P extends Error{constructor(e,t){super(e),this.name="IFlowError",this.details=t||{}}}class _ extends P{constructor(e,t){super(e,t),this.name="TimeoutError"}}class R extends P{constructor(e,t){super(e,{rawData:t}),this.name="JSONDecodeError",this.rawData=t}}class C extends P{constructor(e,t){super(e,t),this.name="IFlowNotInstalledError"}}class N extends P{constructor(e,t){super(e,t),this.name="IFlowProcessError"}}class L extends P{constructor(e,t){super(e,t),this.name="PortNotAvailableError"}}class M extends P{constructor(e,t){super(e,t),this.name="ConnectionError"}}class F extends P{constructor(e,t){super(e,t),this.name="TransportError"}}class $ extends P{constructor(e,t){super(e,t),this.name="PermissionError"}}class b extends P{constructor(e,t){super(e,t),this.name="ValidationError"}}class D extends P{constructor(e,t){super(e,t),this.name="ProtocolError"}}class k extends P{constructor(e,t){super(e,t),this.name="AuthenticationError"}}function U(e,t,o,s){return new(o||(o=Promise))(function(i,r){function n(e){try{a(s.next(e))}catch(e){r(e)}}function l(e){try{a(s.throw(e))}catch(e){r(e)}}function a(e){var t;e.done?i(e.value):(t=e.value,t instanceof o?t:new o(function(e){e(t)})).then(n,l)}a((s=s.apply(e,t||[])).next())})}function j(e){var t="function"==typeof Symbol&&Symbol.iterator,o=t&&e[t],s=0;if(o)return o.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&s>=e.length&&(e=void 0),{value:e&&e[s++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function H(e){return this instanceof H?(this.v=e,this):new H(e)}function q(e,t,o){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var s,i=o.apply(e,t||[]),r=[];return s=Object.create(("function"==typeof AsyncIterator?AsyncIterator:Object).prototype),n("next"),n("throw"),n("return",function(e){return function(t){return Promise.resolve(t).then(e,c)}}),s[Symbol.asyncIterator]=function(){return this},s;function n(e,t){i[e]&&(s[e]=function(t){return new Promise(function(o,s){r.push([e,t,o,s])>1||l(e,t)})},t&&(s[e]=t(s[e])))}function l(e,t){try{(o=i[e](t)).value instanceof H?Promise.resolve(o.value.v).then(a,c):d(r[0][2],o)}catch(e){d(r[0][3],e)}var o}function a(e){l("next",e)}function c(e){l("throw",e)}function d(e,t){e(t),r.shift(),r.length&&l(r[0][0],r[0][1])}}function W(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t,o=e[Symbol.asyncIterator];return o?o.call(e):(e=j(e),t={},s("next"),s("throw"),s("return"),t[Symbol.asyncIterator]=function(){return this},t);function s(o){t[o]=e[o]&&function(t){return new Promise(function(s,i){(function(e,t,o,s){Promise.resolve(s).then(function(t){e({value:t,done:o})},t)})(s,i,(t=e[o](t)).done,t.value)})}}}exports.LogLevel=void 0,(a=exports.LogLevel||(exports.LogLevel={}))[a.DEBUG=0]="DEBUG",a[a.INFO=1]="INFO",a[a.WARN=2]="WARN",a[a.ERROR=3]="ERROR",exports.PermissionMode=void 0,(c=exports.PermissionMode||(exports.PermissionMode={})).AUTO="auto",c.MANUAL="manual",c.SELECTIVE="selective",exports.ApprovalMode=void 0,(d=exports.ApprovalMode||(exports.ApprovalMode={})).DEFAULT="default",d.AUTO_EDIT="autoEdit",d.YOLO="yolo",d.PLAN="plan",exports.HookEventType=void 0,(h=exports.HookEventType||(exports.HookEventType={})).PRE_TOOL_USE="PreToolUse",h.POST_TOOL_USE="PostToolUse",h.STOP="Stop",h.SUBAGENT_STOP="SubagentStop",h.SET_UP_ENVIRONMENT="SetUpEnvironment",exports.PlanPriority=void 0,(u=exports.PlanPriority||(exports.PlanPriority={})).HIGH="high",u.MEDIUM="medium",u.LOW="low",exports.PlanStatus=void 0,(p=exports.PlanStatus||(exports.PlanStatus={})).PENDING="pending",p.IN_PROGRESS="in_progress",p.COMPLETED="completed",exports.StopReason=void 0,(g=exports.StopReason||(exports.StopReason={})).END_TURN="end_turn",g.MAX_TOKENS="max_tokens",g.REFUSAL="refusal",g.CANCELLED="cancelled",exports.ToolCallStatus=void 0,(f=exports.ToolCallStatus||(exports.ToolCallStatus={})).PENDING="pending",f.IN_PROGRESS="in_progress",f.COMPLETED="completed",f.FAILED="failed",exports.ToolCallContentType=void 0,(w=exports.ToolCallContentType||(exports.ToolCallContentType={})).DIFF="diff",w.MARKDOWN="markdown",exports.ToolCallConfirmationType=void 0,(y=exports.ToolCallConfirmationType||(exports.ToolCallConfirmationType={})).EDIT="edit",y.EXECUTE="execute",y.MCP="mcp",y.FETCH="fetch",y.OTHER="other",exports.ToolCallConfirmationOutcome=void 0,(m=exports.ToolCallConfirmationOutcome||(exports.ToolCallConfirmationOutcome={})).ALLOW="allow",m.ALWAYS_ALLOW="alwaysAllow",m.ALWAYS_ALLOW_TOOL="alwaysAllowTool",m.ALWAYS_ALLOW_MCP_SERVER="alwaysAllowMcpServer",m.REJECT="reject",exports.ToolCallIconType=void 0,(v=exports.ToolCallIconType||(exports.ToolCallIconType={})).URL="url",v.EMOJI="emoji",exports.MessageType=void 0,(S=exports.MessageType||(exports.MessageType={})).PLAN="plan",S.USER="user",S.ASSISTANT="assistant",S.TOOL_CALL="tool_call",S.ERROR="error",S.TASK_FINISH="task_finish","function"==typeof SuppressedError&&SuppressedError;const z="2.0";var G,Q,K;function J(e){return e instanceof Error?e.message:e?String(e):"unknown error"}!function(e){e.INITIALIZE="initialize",e.AUTHENTICATE="authenticate",e.SESSION_NEW="session/new",e.SESSION_LOAD="session/load",e.SESSION_PROMPT="session/prompt",e.SESSION_CANCEL="session/cancel"}(G||(G={})),function(e){e.SESSION_UPDATE="session/update",e.SESSION_REQUEST_PERMISSION="session/request_permission",e.FS_READ_TEXT_FILE="fs/read_text_file",e.FS_WRITE_TEXT_FILE="fs/write_text_file",e.PUSH_TOOL_CALL="pushToolCall",e.UPDATE_TOOL_CALL="updateToolCall",e.NOTIFY_TASK_FINISH="notifyTaskFinish"}(Q||(Q={})),function(e){e.PLAN="plan",e.TOOL_CALL="tool_call",e.TOOL_CALL_UPDATE="tool_call_update",e.USER_MESSAGE_CHUNK="user_message_chunk",e.AGENT_MESSAGE_CHUNK="agent_message_chunk",e.AGENT_THOUGHT_CHUNK="agent_thought_chunk"}(K||(K={}));class V{constructor(e={}){const t=e.level||"INFO";this.level=exports.LogLevel[t]}debug(e){this.log(exports.LogLevel.DEBUG,e)}info(e){this.log(exports.LogLevel.INFO,e)}warn(e){this.log(exports.LogLevel.WARN,e)}error(e,t){this.log(exports.LogLevel.ERROR,e,t)}log(e,t,o){if(e<this.level)return;const s=`[${(new Date).toLocaleString("sv-SE").replace("T"," ")}] ${exports.LogLevel[e]}: ${t}${o?`\n${o.stack}`:""}`;switch(e){case exports.LogLevel.DEBUG:console.debug(s);break;case exports.LogLevel.INFO:console.info(s);break;case exports.LogLevel.WARN:console.warn(s);break;case exports.LogLevel.ERROR:console.error(s)}}}const X=new V;function Y(e){return!!e&&"id"in e&&"result"in e&&null!=e.result}function B(e){return!!e&&"id"in e&&"error"in e&&null!=e.error}function Z(e){return!!e&&"method"in e&&!("result"in e)&&!("error"in e)}class ee{constructor(e){this.requestId=0,this.initialized=!1,this.authenticated=!1,this.logger=e.logger||X,this.transport=e.transport,this.fileHandler=e.fileHandler,this.permissionMode=e.permissionMode||exports.PermissionMode.AUTO,this.autoApproveTypes=e.autoApproveTypes||["read","fetch","list"]}nextRequestId(){return++this.requestId}checkAuthenticated(){if(!this.initialized)throw new D("Protocol not initialized. Call initialize() first.");if(!this.authenticated)throw new D("Not authenticated. Call authenticate() first.")}sendResult(e,t){return U(this,void 0,void 0,function*(){const o={jsonrpc:z,id:e,result:t};yield this.transport.send(o)})}sendError(e,t,o){return U(this,void 0,void 0,function*(){const s={jsonrpc:z,id:e,error:{code:t,message:o}};yield this.transport.send(s)})}waitForReadySignal(){return U(this,void 0,void 0,function*(){var e,t,o,s;try{for(var i,r=!0,n=W(this.transport.receive());!(e=(i=yield n.next()).done);r=!0){s=i.value,r=!1;const e=s.trim();if("//ready"===e){this.logger.info("Received //ready signal");break}e.startsWith("//")&&this.logger.debug(`Control message: ${e}`)}}catch(e){t={error:e}}finally{try{r||e||!(o=n.return)||(yield o.call(n))}finally{if(t)throw t.error}}})}waitForMessageResponse(e,t,o){return U(this,void 0,void 0,function*(){var s,i,r,n;const{timeout:l,timeoutMsg:a=`Timeout after ${l} seconds`}=o||{},c=Date.now();try{for(var d,h=!0,u=W(this.transport.receive());!(s=(d=yield u.next()).done);h=!0){n=d.value,h=!1;const o=n;if(o.trim().startsWith("//")){this.logger.debug(`Control message: ${o.trim()}`);continue}let s;try{s=JSON.parse(o.trim())}catch(e){this.logger.error(`Failed to parse response: ${J(e)}`);continue}if(s.id===e){const e=t(s);if(void 0!==e)return e}if(l&&l>0&&Date.now()-c>l)throw new _(a)}}catch(e){i={error:e}}finally{try{h||s||!(r=u.return)||(yield r.call(u))}finally{if(i)throw i.error}}})}initialize(){return U(this,arguments,void 0,function*(e={}){if(this.initialized)return this.logger.warn("Protocol already initialized"),{protocolVersion:1,isAuthenticated:this.authenticated};this.logger.info("Waiting for //ready signal..."),yield this.waitForReadySignal();const t=this.nextRequestId(),o={jsonrpc:z,id:t,method:G.INITIALIZE,params:Object.assign({protocolVersion:1,clientCapabilities:{fs:{readTextFile:!0,writeTextFile:!0}}},e)};yield this.transport.send(o),this.logger.info("Sent initialize request");const s=yield this.waitForMessageResponse(t,e=>{var t;if("error"in e)throw new D(`Initialize failed: ${null===(t=e.error)||void 0===t?void 0:t.message}`,e.error);const o=e.result||{};return this.initialized=!0,this.authenticated=o.isAuthenticated||!1,this.logger.info(`Initialized with protocol version: ${o.protocolVersion}, authenticated: ${this.authenticated}`),o},{timeout:1e4,timeoutMsg:"Initialize timeout after 10 seconds"});if(s)return s;throw new D("Connection closed during initialization")})}authenticate(){return U(this,arguments,void 0,function*(e={}){const t=e.methodId||"iflow";if(this.authenticated)return void this.logger.warn("Already authenticated");const o=this.nextRequestId(),s={jsonrpc:z,id:o,method:G.AUTHENTICATE,params:Object.assign(Object.assign({},e),{methodId:t})};yield this.transport.send(s),this.logger.info(`Sent authenticate request with method: ${s.params.methodId}`);if(!(yield this.waitForMessageResponse(o,e=>{var o;if("error"in e)throw new k(`Authentication failed: ${null===(o=e.error)||void 0===o?void 0:o.message}`,e.error);const s=e.result||{};return s.methodId===t?(this.authenticated=!0,this.logger.info(`Authentication successful with method: ${s.methodId}`),!0):(this.authenticated=!0,this.logger.warn(`Unexpected methodId in response: ${s.methodId} (expected ${t})`),!0)},{timeout:1e4,timeoutMsg:"Authentication timeout after 10 seconds"})))throw new k("Connection closed during authentication")})}createSession(){return U(this,arguments,void 0,function*(e={}){this.checkAuthenticated();const t=this.nextRequestId(),o={jsonrpc:z,id:t,method:G.SESSION_NEW,params:Object.assign(Object.assign({},e),{cwd:e.cwd||process.cwd(),mcpServers:e.mcpServers||[]})};yield this.transport.send(o),this.logger.info(`Sent session/new request with cwd: ${e.cwd}`);const s=yield this.waitForMessageResponse(t,e=>{var t;if("error"in e)throw new D(`session/new failed: ${null===(t=e.error)||void 0===t?void 0:t.message}`,e.error);const o=e.result||{};if(o.sessionId)return this.logger.info(`Created session: ${o.sessionId}`),o.sessionId;throw new D(`Invalid session/new response: ${JSON.stringify(o)}`)},{timeout:1e4,timeoutMsg:"Session creation timeout after 10 seconds"});if(s)return s;throw new D("Connection closed while waiting for session/new response")})}loadSession(e){return U(this,void 0,void 0,function*(){this.checkAuthenticated();const t=this.nextRequestId(),o={jsonrpc:z,id:t,method:G.SESSION_LOAD,params:Object.assign(Object.assign({},e),{cwd:e.cwd||process.cwd(),mcpServers:e.mcpServers||[]})};yield this.transport.send(o),this.logger.info(`Sent session/load request for session: ${e.sessionId}`);if(!(yield this.waitForMessageResponse(t,t=>{var o;if("error"in t){if(-32601===t.error.code)throw new D("session/load is not supported by the current iFlow version. Use session/new to create a new session instead.",t.error);throw new D(`session/load failed: ${null===(o=t.error)||void 0===o?void 0:o.message}`,t.error)}return this.logger.info(`Session loaded successfully: ${e.sessionId}`),!0},{timeout:1e4,timeoutMsg:"Session load timeout after 10 seconds"})))throw new D("Connection closed while waiting for session/load response")})}sendPrompt(e){return U(this,void 0,void 0,function*(){this.checkAuthenticated();const t=this.nextRequestId(),o={jsonrpc:z,id:t,method:G.SESSION_PROMPT,params:e};return yield this.transport.send(o),this.logger.info(`Sent prompt with ${e.prompt.length} content blocks`),t})}cancelSession(e){return U(this,void 0,void 0,function*(){this.checkAuthenticated();const t=this.nextRequestId(),o={jsonrpc:z,id:t,method:G.SESSION_CANCEL,params:e};yield this.transport.send(o),this.logger.info("Sent session/cancel request")})}handleMessages(){return q(this,arguments,function*(){var e,t,o,s;try{for(var i,r=!0,n=W(this.transport.receive());!(e=(i=yield H(n.next())).done);r=!0){s=i.value,r=!1;const e=s;if(e.trim().startsWith("//")){this.logger.debug(`Control message: ${e.trim()}`);continue}let t;try{t=JSON.parse(e.trim())}catch(t){throw this.logger.error(`Failed to parse message: ${J(t)}`),new R("Invalid JSON received",e)}Z(t)?yield yield H(yield H(this.handleClientMessage(t))):Y(t)?yield yield H({type:"response",id:t.id,result:t.result}):B(t)&&(yield yield H({type:"error",code:t.error.code,error:t.error.message}))}}catch(e){t={error:e}}finally{try{r||e||!(o=n.return)||(yield H(o.call(n)))}finally{if(t)throw t.error}}})}handleClientMessage(e){return U(this,void 0,void 0,function*(){const{method:t}=e;switch(t){case Q.FS_READ_TEXT_FILE:return yield this.handleReadTextFile(e);case Q.FS_WRITE_TEXT_FILE:return yield this.handleWriteTextFile(e);case Q.SESSION_UPDATE:return yield this.handleSessionUpdate(e);case Q.SESSION_REQUEST_PERMISSION:return yield this.handleRequestPermission(e);case Q.PUSH_TOOL_CALL:return yield this.handlePushToolCall(e);case Q.UPDATE_TOOL_CALL:return yield this.handleUpdateToolCall(e);case Q.NOTIFY_TASK_FINISH:return yield this.handleNotifyTaskFinish(e);default:return yield this.handleUnknownMessage(e)}})}handleReadTextFile(e){return U(this,void 0,void 0,function*(){const{id:t,method:o,params:s}=e,{path:i,limit:r,line:n}=s||{};let l;if(this.logger.info(`fs/read_text_file request for: ${i}`),!this.fileHandler){const e="File system access not configured";return void 0!==t&&(yield this.sendError(t,-32603,e)),{type:"error",code:-32603,error:e,method:o}}try{l=yield this.fileHandler.readFile(i,n,r)}catch(e){const s=J(e);return this.logger.error(`Error reading file ${i}: ${s}`),void 0!==t&&(yield this.sendError(t,-32603,s)),{type:"error",code:-32603,error:s,method:o}}return void 0!==t&&(yield this.sendResult(t,{content:l})),{type:"file_read",path:i,content:l}})}handleWriteTextFile(e){return U(this,void 0,void 0,function*(){const{id:t,method:o,params:s}=e,{path:i,content:r}=s||{};if(this.logger.info(`fs/write_text_file request for: ${i}`),!this.fileHandler){const e="File system access not configured";return void 0!==t&&(yield this.sendError(t,-32603,e)),{type:"error",code:-32603,error:e,method:o}}try{yield this.fileHandler.writeFile(i,r)}catch(e){const s=J(e);return this.logger.error(`Error writing file ${i}: ${s}`),void 0!==t&&(yield this.sendError(t,-32603,s)),{type:"error",code:-32603,error:s,method:o}}return void 0!==t&&(yield this.sendResult(t,{success:!0})),{type:"file_write",path:i,content:r}})}handleSessionUpdate(e){return U(this,void 0,void 0,function*(){const{params:t}=e,{sessionId:o,update:s}=t;return{type:"session_update",sessionId:o,updateData:s}})}handleRequestPermission(e){return U(this,void 0,void 0,function*(){const{id:t,params:o}=e,s=o.toolCall||{},i=o.options||[];let r,n;if(r=this.permissionMode===exports.PermissionMode.AUTO||this.permissionMode!==exports.PermissionMode.MANUAL&&this.autoApproveTypes.includes(s.type||""),r){let e;for(const t of i){const o=t.optionId||"";if("proceed_once"===o){e=o;break}"proceed_always"===o&&(e=o)}!e&&i.length>0&&(e=i[0].optionId||"proceed_once"),n={outcome:{outcome:"selected",optionId:e}}}else n={outcome:{outcome:"cancelled"}};return void 0!==t&&(yield this.sendResult(t,n)),this.logger.info(`Permission request for tool '${s.title||"unknown"}' - Response: ${n.outcome.outcome}`),{type:"tool_confirmation",params:o,response:n}})}handlePushToolCall(e){return U(this,void 0,void 0,function*(){const{id:t,params:o}=e,s=`tool_${this.nextRequestId()}`,i={id:s};return void 0!==t&&(yield this.sendResult(t,i)),{type:"tool_call",id:s,params:o}})}handleUpdateToolCall(e){return U(this,void 0,void 0,function*(){const{id:t,params:o}=e;return void 0!==t&&(yield this.sendResult(t,null)),{type:"tool_update",params:o}})}handleNotifyTaskFinish(e){return U(this,void 0,void 0,function*(){const{id:t,params:o}=e;return void 0!==t&&(yield this.sendResult(t,null)),{type:"task_finish",params:o}})}handleUnknownMessage(e){return U(this,void 0,void 0,function*(){const{id:t,method:o,params:s}=e;return this.logger.warn(`Unknown method: ${o}`),void 0!==t&&(yield this.sendError(t,-32601,"Method not found")),{type:"unknown",method:o,params:s}})}}class te{constructor(e){this.ws=null,this.connected=!1,this.url=e.url,this.logger=e.logger||X,this.timeout=e.timeout||3e5}get isConnected(){return!!this.ws&&this.connected}checkConnected(){if(!this.isConnected)throw new M("Not connected")}connect(){return U(this,void 0,void 0,function*(){if(this.connected)this.logger.warn(`Already connected to ${this.url}`);else try{this.logger.info(`Connecting to ${this.url}`),this.ws=yield new Promise((e,t)=>{const s=new o(this.url),i=setTimeout(()=>{s.close(),t(new _(`Connected to ${this.url} timeout after ${this.timeout/1e3}s`))},this.timeout);s.on("open",()=>{clearTimeout(i),this.connected=!0,this.logger.info(`Connected to ${this.url} succesfully`),e(s)}),s.on("error",e=>{clearTimeout(i),this.connected=!1,t(e)}),s.on("close",(e,o)=>{clearTimeout(i),this.connected=!1,t(new Error(`${o} (code: ${e})`))})})}catch(e){if(e instanceof _)throw e;throw new M(`Failed to connect to ${this.url}: ${J(e)}`)}})}close(){return U(this,void 0,void 0,function*(){if(this.ws&&this.connected)try{this.ws.close(),this.logger.info("Connection closed")}catch(e){this.logger.warn(`Error closing connection: ${J(e)}`)}this.ws=null,this.connected=!1})}send(e){return U(this,void 0,void 0,function*(){this.checkConnected();try{const t="string"==typeof e?e:JSON.stringify(e);yield new Promise((e,o)=>{this.ws.send(t,s=>{s?o(s):(this.logger.debug(`Sent message: ${t}`),e())})})}catch(e){throw this.connected=!1,new F(`Failed to send message: ${J(e)}`)}})}receive(){return q(this,arguments,function*(){for(this.checkConnected();this.isConnected;)try{const e=yield H(this.receiveRawData());this.logger.debug(`Received message: ${e}`),yield yield H(e)}catch(e){if(this.connected=!1,e instanceof M&&e.details.isClosed){this.logger.info("Connection closed");break}throw new F(`Failed to receive message: ${J(e)}`)}})}receiveRawData(){return new Promise((e,t)=>{if(!this.isConnected)return void t(new M("Not connected"));const o=()=>{this.ws&&(this.ws.off("close",s),this.ws.off("error",i),this.ws.off("message",r))},s=()=>{o(),this.connected=!1,t(new M("Connection closed",{isClosed:!0}))},i=e=>{o(),this.connected=!1,t(e)},r=t=>{o(),e(t.toString())};this.ws&&(this.ws.on("close",s),this.ws.on("error",i),this.ws.on("message",r))})}}class oe{constructor(e={}){this.cwd=e.cwd||process.cwd(),this.logger=e.logger||X,this.readOnly=e.readOnly||!1,this.maxFileSize=e.maxFileSize||10485760,e.allowedDirs?this.allowedDirs=new Set(e.allowedDirs.map(e=>E.resolve(this.cwd,e))):this.allowedDirs=new Set([this.cwd]),this.logger.info(`File handler initialized with ${this.allowedDirs.size} allowed directories`);for(const e of this.allowedDirs)this.logger.debug(` Allowed: ${e}`)}isPathAllowed(e){try{const t=E.resolve(this.cwd,e);for(const e of this.allowedDirs)if(t.startsWith(e))return!0;return this.logger.warn(`Path not in allowed directories: ${t}`),!1}catch(e){return e instanceof Error&&this.logger.error(`Error checking path: ${e.message}`,e),!1}}readFile(e,t,o){return U(this,void 0,void 0,function*(){if(!this.isPathAllowed(e))throw new $(`Access denied: ${e}`);const s=E.resolve(this.cwd,e);try{if(!T.existsSync(s))throw new b(`File not found: ${e}`);try{yield I.access(s,T.constants.R_OK)}catch(t){throw new $(`Permission denied: ${e}`)}const i=yield I.stat(s);if(!i.isFile())throw new b(`Not a file: ${e}`);if(i.size>this.maxFileSize)throw new b(`File too large: ${i.size} bytes (max: ${this.maxFileSize})`);const r=yield I.readFile(s,"utf-8");if(void 0!==t||void 0!==o){const s=r.split("\n"),i=t?t-1:0,n=o?i+o:s.length,l=Math.max(0,i),a=Math.min(s.length,n);return this.logger.debug(`Read ${a-l} lines from ${e}`),s.slice(l,a).join("\n")}return this.logger.debug(`Read ${r.length} bytes from ${e}`),r}catch(e){if(e instanceof b||e instanceof $)throw e;throw new b(`Failed to read file: ${J(e)}`)}})}writeFile(e,t){return U(this,void 0,void 0,function*(){if(this.readOnly)throw new $("File system is in read-only mode");if(!this.isPathAllowed(e))throw new $(`Access denied: ${e}`);const o=E.resolve(this.cwd,e);try{yield I.mkdir(E.dirname(o),{recursive:!0}),yield I.writeFile(o,t,"utf-8"),this.logger.debug(`Wrote ${t.length} bytes to ${e}`)}catch(e){throw new b(`Failed to write file: ${J(e)}`)}})}addAllowedDir(e){return U(this,void 0,void 0,function*(){const t=E.resolve(this.cwd,e);try{if(!T.existsSync(t))throw new b(`Directory does not exist: ${t}`);if(!(yield I.stat(t)).isDirectory())throw new b(`Not a directory: ${t}`);this.allowedDirs.add(t),this.logger.info(`Added allowed directory: ${t}`)}catch(e){if(e instanceof b)throw e;throw new b(`Failed to add ${t} as allowed directory: ${J(e)}`)}})}removeAllowedDir(e){const t=E.resolve(this.cwd,e);this.allowedDirs.delete(t),this.logger.info(`Removed allowed directory: ${t}`)}}class se{constructor(e={}){this.port=null,this.process=null,this.iflowPath=null,this.logger=e.logger||X,this.startPort=e.startPort||8090}get url(){if(!this.port)throw new N("iFlow process not started");return`ws://localhost:${this.port}/acp`}isRunning(){return!!this.process&&!this.process.killed&&null===this.process.exitCode}which(e){try{return O.execSync(`which ${e}`,{encoding:"utf-8"}).trim()}catch(e){return null}}fileExists(e){try{return T.existsSync(e)&&T.statSync(e).isFile()}catch(e){return!1}}findIflowPath(){const e=this.which("iflow");if(e)return this.logger.debug(`Found iflow at: ${e}`),e;const t=x.homedir(),o=[E.join(t,".npm-global","bin","iflow"),"/usr/local/bin/iflow",E.join(t,".local","bin","iflow"),E.join(t,"node_modules",".bin","iflow"),E.join(t,".yarn","bin","iflow"),E.join(t,"AppData","Roaming","npm","iflow.cmd"),E.join("C:","Program Files","nodejs","iflow.cmd")];for(const e of o)if(this.fileExists(e))return this.logger.debug(`Found iflow at: ${e}`),e;const s=null!==this.which("npm"),i=null!==this.which("node");let r;throw r="win32"===x.platform()?s||i?"iFlow CLI not found. Please use the following command to install:\n npm install -g @iflow-ai/iflow-cli@latest":"iFlow requires Node.js, but it is not installed in the system.\n\nPlease install Node.js first: https://nodejs.org/\n\nAfter installing Node.js, use the following command to install iFlow:\n npm install -g @iflow-ai/iflow-cli@latest":'iFlow CLI not found. Please use the following command to install:\n\n🍎 Mac/Linux/Ubuntu users:\n bash -c "$(curl -fsSL https://cloud.iflow.cn/iflow-cli/install.sh)"\n\n🪟 Windows users:\n npm install -g @iflow-ai/iflow-cli@latest',new C(r)}isPortAvailable(e){return new Promise(t=>{const o=A.createServer();o.listen(e,"localhost",()=>{o.once("close",()=>{t(!0)}),o.close()}),o.once("error",()=>{t(!1)})})}findAvailablePort(){return U(this,void 0,void 0,function*(){for(let e=0;e<100;e++){const t=this.startPort+e;if(yield this.isPortAvailable(t))return this.logger.debug(`Found available port: ${t}`),t}throw new L(`No available port found in range ${this.startPort}-${this.startPort+100}`)})}start(){return U(this,void 0,void 0,function*(){if(this.isRunning())return this.url;this.iflowPath=this.findIflowPath(),this.port=yield this.findAvailablePort();const e=[this.iflowPath,"--experimental-acp","--port",this.port.toString()];this.logger.info(`Starting iFlow process: ${e.join(" ")}`);try{if(this.process=O.spawn(e[0],e.slice(1),{stdio:["ignore","pipe","pipe"],detached:!1}),yield new Promise(e=>setTimeout(e,500)),!this.isRunning()){let e="iFlow process exited immediately";if(this.process.stderr){const t=this.process.stderr.read();t&&(e+=`: ${t.toString("utf-8")}`)}throw new Error(e)}return this.logger.info(`iFlow process started on port ${this.port} (PID: ${this.process.pid})`),this.url}catch(e){throw this.port=null,this.process=null,new N(`Failed to start iFlow process: ${J(e)}`)}})}stop(){return U(this,void 0,void 0,function*(){if(this.process){if(!this.isRunning())return this.port=null,void(this.process=null);this.logger.info(`Stopping iFlow process (PID: ${this.process.pid})`);try{this.process.kill("SIGTERM"),yield Promise.race([new Promise(e=>{this.process?this.process.once("exit",()=>e()):e()}),new Promise(e=>setTimeout(()=>e(),5e3))]),this.isRunning()?(this.logger.warn("iFlow process did not terminate gracefully, forcing kill"),this.process.kill("SIGKILL"),yield new Promise(e=>{this.process?this.process.once("exit",()=>e()):e()})):this.logger.info("iFlow process terminated gracefully")}catch(e){this.logger.error(`Error stopping iFlow process: ${J(e)}`)}finally{this.port=null,this.process=null}}})}}var ie;!function(e){e.ERROR="error",e.RESPONSE="response",e.FILE_READ="file_read",e.FILE_WRITE="file_write",e.SESSION_UPDATE="session_update",e.TOOL_CALL="tool_call",e.TOOL_UPDATE="tool_update",e.TOOL_CONFIRMATION="tool_confirmation",e.TASK_FINISH="task_finish",e.UNKNOWN="unknown"}(ie||(ie={}));class re{constructor(e={}){this.protocol=null,this.transport=null,this.connected=!1,this.authenticated=!1,this.messageTask=null,this.messageQueue=[],this.pendingToolCalls=new Map,this.url=null,this.sessionId=null,this.processManager=null,this.processStarted=!1,this.options=Object.assign({url:"ws://localhost:8090/acp",cwd:process.cwd(),timeout:3e4,logLevel:"INFO",fileMaxSize:10485760,permissionMode:exports.PermissionMode.AUTO,autoApproveTypes:["read","fetch","list"],authMethodId:"iflow",autoStartProcess:!0,processStartPort:8090},e),this.logger=new V({level:this.options.logLevel})}connect(){return U(this,void 0,void 0,function*(){var e,t;if(this.connected)this.logger.warn("Already connected");else try{if(this.options.autoStartProcess&&((null===(e=this.options.url)||void 0===e?void 0:e.startsWith("ws://localhost:"))||(null===(t=this.options.url)||void 0===t?void 0:t.startsWith("ws://127.0.0.1:")))){const e=new te({url:this.options.url,logger:this.logger,timeout:2e3});try{yield e.connect(),yield e.close(),this.url=this.options.url,this.logger.info(`iFlow already running at ${this.options.url}`)}catch(e){this.logger.info("iFlow not running, starting process..."),this.processManager=new se({logger:this.logger,startPort:this.options.processStartPort});try{const e=yield this.processManager.start();this.url=e,this.processStarted=!0,this.logger.info(`Started iFlow process at ${e}`),yield new Promise(e=>setTimeout(e,1e3))}catch(e){throw e instanceof C?(this.logger.error("iFlow not installed"),C):(this.logger.error(`Failed to start iFlow process: ${J(e)}`),new M(`Failed to start iFlow process: ${J(e)}`))}}}let o=null;this.options.fileAccess&&(o=new oe({cwd:this.options.cwd,logger:this.logger,readOnly:this.options.fileReadOnly,maxFileSize:this.options.fileMaxSize,allowedDirs:this.options.fileAllowedDirs}),this.logger.info(`File system access enabled with ${this.options.fileReadOnly?"read-only":"read-write"} mode`)),this.transport=new te({url:this.url,logger:this.logger,timeout:this.options.timeout}),this.protocol=new ee({logger:this.logger,transport:this.transport,fileHandler:o,permissionMode:this.options.permissionMode,autoApproveTypes:this.options.autoApproveTypes}),yield this.transport.connect();const s=yield this.protocol.initialize({mcpServers:this.options.mcpServers,hooks:this.options.hooks,commands:this.options.commands,agents:this.options.agents});this.authenticated=s.isAuthenticated||!1,this.authenticated||(yield this.protocol.authenticate({methodId:this.options.authMethodId,methodInfo:this.options.authMethodInfo}),this.authenticated=!0),this.sessionId=yield this.protocol.createSession({cwd:this.options.cwd||process.cwd(),mcpServers:this.options.mcpServers,hooks:this.options.hooks,commands:this.options.commands,agents:this.options.agents,settings:this.options.sessionSettings}),this.connected=!0,this.messageTask=this.handleMessages(),this.logger.info("Connected to iFlow")}catch(e){throw yield this.disconnect(),new M(`Failed to connect: ${J(e)}`)}})}loadSession(e){return U(this,void 0,void 0,function*(){if(!this.connected||!this.protocol)throw new M("Not connected. Call connect() first.");yield this.protocol.loadSession({sessionId:e,cwd:this.options.cwd||process.cwd(),mcpServers:this.options.mcpServers}),this.sessionId=e,this.logger.info(`Loaded session: ${e}`)})}disconnect(){return U(this,void 0,void 0,function*(){this.connected=!1,this.transport&&(yield this.transport.close()),this.processManager&&this.processStarted&&(yield this.processManager.stop()),this.url=null,this.protocol=null,this.transport=null,this.messageTask=null,this.authenticated=!1,this.processManager=null,this.processStarted=!1,this.logger.info("Disconnected from iFlow")})}sendMessage(e,t){return U(this,void 0,void 0,function*(){if(!this.connected||!this.protocol||!this.sessionId)throw new M("Not connected. Call connect() first.");const o=[{type:"text",text:e}];if(null==t?void 0:t.length)for(const e of t){const t=E.resolve(this.options.cwd||process.cwd(),e),s=E.parse(e);if(!T.existsSync(t)){this.logger.warn(`File not found, skipping: ${t}`);continue}const i=s.ext.toLowerCase();if([".png",".jpg",".jpeg",".gif",".bmp",".webp",".svg"].includes(i))try{const e=T.readFileSync(t).toString("base64"),r={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".bmp":"image/bmp",".webp":"image/webp",".svg":"image/svg+xml"};o.push({type:"image",data:e,mimeType:r[i]||"image/unknown"}),this.logger.debug(`Added image file: ${s.base}`)}catch(e){this.logger.error(`Failed to read image file ${t}: ${J(e)}`);continue}else if([".mp3",".wav",".m4a",".ogg",".flac"].includes(i))try{const e=T.readFileSync(t).toString("base64"),r={".mp3":"audio/mpeg",".wav":"audio/wav",".m4a":"audio/mp4",".ogg":"audio/ogg",".flac":"audio/flac"};o.push({type:"audio",data:e,mimeType:r[i]||"audio/unknown"}),this.logger.debug(`Added audio file: ${s.base}`)}catch(e){this.logger.error(`Failed to read audio file ${t}: ${J(e)}`);continue}else{const e=T.statSync(t);o.push({type:"resource_link",uri:`file://${t}`,name:s.base,title:s.name,size:e.size}),this.logger.debug(`Added resource link: ${s.base}`)}}yield this.protocol.sendPrompt({sessionId:this.sessionId,prompt:o})})}interrupt(){return U(this,void 0,void 0,function*(){if(!this.connected||!this.protocol||!this.sessionId)throw new M("Not connected");yield this.protocol.cancelSession({sessionId:this.sessionId}),this.logger.info("Sent interrupt signal")})}receiveMessages(){return q(this,arguments,function*(){if(!this.connected)throw new M("Not connected");for(;this.connected;)try{this.messageQueue.length>0?yield yield H(this.messageQueue.shift()):yield H(new Promise(e=>setTimeout(e,100)))}catch(e){continue}})}approveToolCall(e){return U(this,arguments,void 0,function*(e,t=exports.ToolCallConfirmationOutcome.ALLOW){if(!this.pendingToolCalls.has(e))throw new Error(`Unknown tool call: ${e}`);this.logger.info(`Approved tool call ${e} with outcome ${t}`),this.pendingToolCalls.delete(e)})}rejectToolCall(e){return U(this,void 0,void 0,function*(){if(!this.pendingToolCalls.has(e))throw new Error(`Unknown tool call: ${e}`);this.logger.info(`Rejected tool call ${e}`),this.pendingToolCalls.delete(e)})}handleMessages(){return U(this,void 0,void 0,function*(){var e,t,o,s;if(this.protocol)try{try{for(var i,r=!0,n=W(this.protocol.handleMessages());!(e=(i=yield n.next()).done);r=!0){s=i.value,r=!1;const e=s,t=this.processProtocolMessage(e);t&&this.messageQueue.push(t)}}catch(e){t={error:e}}finally{try{r||e||!(o=n.return)||(yield o.call(n))}finally{if(t)throw t.error}}}catch(e){this.logger.error(`Error in message handler: ${J(e)}`);const t={type:exports.MessageType.ERROR,code:-1,message:String(J(e))};this.messageQueue.push(t)}})}processProtocolMessage(e){var t,o,s;switch(e.type){case ie.SESSION_UPDATE:{const{updateData:i}=e;let r,n;switch("agentId"in i&&i.agentId&&(r=i.agentId,n=function(e){const t=e.split("-");return"subagent"!==t[0]||t.length<4?{agentId:e}:4===t.length?{agentId:e,taskId:["null","undefined"].includes(t[1])?void 0:t[1],agentIndex:parseInt(t[2])||void 0,timestamp:parseInt(t[3])||void 0}:{agentId:e,taskId:t.slice(1,-2).join("-"),agentIndex:parseInt(t[t.length-2])||void 0,timestamp:parseInt(t[t.length-1])||void 0}}(r)),i.sessionUpdate){case K.PLAN:{const e=null===(t=i.entries)||void 0===t?void 0:t.map(e=>({content:e.content||"",status:e.status||exports.PlanStatus.PENDING,priority:e.priority||exports.PlanPriority.MEDIUM}));return e&&(null==e?void 0:e.length)>0?{type:exports.MessageType.PLAN,entries:e}:null}case K.TOOL_CALL:{const e={type:exports.MessageType.TOOL_CALL,id:i.toolCallId||"",label:i.title||"Tool",icon:{type:exports.ToolCallIconType.EMOJI,value:"🔧"},status:i.status||exports.ToolCallStatus.IN_PROGRESS,toolName:i.toolName};return r&&(e.agentId=r,e.agentInfo=n),this.pendingToolCalls.set(e.id,e),e}case K.TOOL_CALL_UPDATE:{const e=i.toolCallId;let t;if(this.pendingToolCalls.has(e)?(t=this.pendingToolCalls.get(e),t.status=i.status||exports.ToolCallStatus.COMPLETED,i.toolName&&(t.toolName=i.toolName),!t.agentId&&r&&(t.agentId=r),!t.agentInfo&&n&&(t.agentInfo=n)):(t={type:exports.MessageType.TOOL_CALL,id:e,label:i.title||"Tool",icon:{type:exports.ToolCallIconType.EMOJI,value:"🔧"},status:i.status||exports.ToolCallStatus.COMPLETED,toolName:i.toolName},r&&(t.agentId=r,t.agentInfo=n),this.pendingToolCalls.set(e,t)),i.content&&(null===(o=i.content)||void 0===o?void 0:o.length)>0){let e;const o=[];for(const t of i.content)"args"in t&&(e=t.args),"content"===t.type&&"text"===(null===(s=t.content)||void 0===s?void 0:s.type)&&o.push(t.content.text||"");void 0!==e&&(t.args=e),o.length>0&&(t.output=o.join("\n"))}return t}case K.USER_MESSAGE_CHUNK:{const e=i.content;if("text"===(null==e?void 0:e.type)){const t=e.text||"";if(t)return{type:exports.MessageType.USER,chunks:[{text:t}]}}return null}case K.AGENT_MESSAGE_CHUNK:{const e=i.content;if("text"===(null==e?void 0:e.type)){const t=e.text||"";if(t){const e={type:exports.MessageType.ASSISTANT,chunk:{text:t}};return r&&(e.agentId=r,e.agentInfo=n),e}}return null}case K.AGENT_THOUGHT_CHUNK:{const e=i.content;if("text"===(null==e?void 0:e.type)){const t=e.text||"";if(t){const e={type:exports.MessageType.ASSISTANT,chunk:{thought:t}};return r&&(e.agentId=r,e.agentInfo=n),e}}}default:return null}}case ie.RESPONSE:return"stopReason"in(e.result||{})?{type:exports.MessageType.TASK_FINISH,stopReason:e.result.stopReason}:null;case ie.ERROR:return{type:exports.MessageType.ERROR,code:e.code||-1,message:e.error||"Unknown error"};default:return null}}}function ne(e){let t,o=!1,s="text";if(e.startsWith("//"))o=!0,s="control";else try{t=JSON.parse(e),t&&"method"in t?s=`method:${t.method}`:t&&("result"in t||"error"in t)?s="response":t&&"type"in t&&(s=t.type)}catch(e){}return{isControl:o,messageType:s,rawData:e,jsonData:t,timestamp:Date.now()}}function le(e,t,o){return U(this,void 0,void 0,function*(){var s,i,r,n;const l=[],a=new re(o);yield a.connect();try{yield a.sendMessage(e,t);try{for(var c,d=!0,h=W(a.receiveMessages());!(s=(c=yield h.next()).done);d=!0){n=c.value,d=!1;const e=n;if(e.type===exports.MessageType.ASSISTANT&&e.chunk.text)l.push(e.chunk.text);else if(e.type===exports.MessageType.TASK_FINISH)break}}catch(e){i={error:e}}finally{try{d||s||!(r=h.return)||(yield r.call(h))}finally{if(i)throw i.error}}}finally{yield a.disconnect()}return l.join("")})}exports.AuthenticationError=k,exports.ConnectionError=M,exports.IFlowClient=re,exports.IFlowError=P,exports.IFlowNotInstalledError=C,exports.IFlowProcessError=N,exports.JSONDecodeError=R,exports.PermissionError=$,exports.PortNotAvailableError=L,exports.ProtocolError=D,exports.RawDataClient=class extends re{constructor(e,t=!0){super(e),this.rawQueue=[],this.rawHistory=[],this.rawQueueResolvers=[],this.messageQueueResolvers=[],this.captureRaw=t}handleMessages(){const e=Object.create(null,{handleMessages:{get:()=>super.handleMessages}});return U(this,void 0,void 0,function*(){if(this.protocol)try{if(this.captureRaw&&this.transport){const e=this.captureRawStream(),t=this.handleParsedStream();yield Promise.all([e,t])}else yield e.handleMessages.call(this)}catch(e){this.logger.error(`Error in message handler: ${J(e)}`)}})}captureRawStream(){return U(this,void 0,void 0,function*(){var e,t,o,s;if(this.transport)try{try{for(var i,r=!0,n=W(this.transport.receive());!(e=(i=yield n.next()).done);r=!0){s=i.value,r=!1;const e=s,t=ne("string"==typeof e?e:JSON.stringify(e));this.rawQueue.push(t),this.rawHistory.push(t);const o=this.rawQueueResolvers.shift();o&&o(t)}}catch(e){t={error:e}}finally{try{r||e||!(o=n.return)||(yield o.call(n))}finally{if(t)throw t.error}}}catch(e){this.logger.error(`Error capturing raw stream: ${J(e)}`)}})}handleParsedStream(){return U(this,void 0,void 0,function*(){var e,t,o,s;if(this.protocol)try{for(var i,r=!0,n=W(this.protocol.handleMessages());!(e=(i=yield n.next()).done);r=!0){s=i.value,r=!1;const e=s,t=this.processProtocolMessage(e);if(t){const e=this.messageQueueResolvers.shift();e&&e(t)}}}catch(e){t={error:e}}finally{try{r||e||!(o=n.return)||(yield o.call(n))}finally{if(t)throw t.error}}})}receiveRawMessages(){return q(this,arguments,function*(){for(;this.connected||this.rawQueue.length>0;)try{if(this.rawQueue.length>0)yield yield H(this.rawQueue.shift());else{const e=yield H(Promise.race([new Promise(e=>{this.rawQueueResolvers.push(e)}),new Promise((e,t)=>{setTimeout(()=>t(new Error("Timeout")),100)})]));yield yield H(e)}}catch(e){if(e instanceof Error&&"Timeout"===e.message)continue;throw e}})}receiveDualStream(){return q(this,arguments,function*(){const e=[],t=[];for(;this.connected||this.rawQueue.length>0||e.length>0||t.length>0;)try{let e,t;e=this.rawQueue.length>0?this.rawQueue.shift():yield H(Promise.race([new Promise(e=>{this.rawQueueResolvers.push(e)}),new Promise((e,t)=>{setTimeout(()=>t(new Error("Timeout")),10)})]));try{t=yield H(Promise.race([new Promise(e=>{this.messageQueueResolvers.push(e)}),new Promise((e,t)=>{setTimeout(()=>t(new Error("Timeout")),10)})]))}catch(e){}e.parsedMessage=t,yield yield H([e,t])}catch(e){if(!(e instanceof Error&&"Timeout"===e.message))throw e;try{const e=yield H(Promise.race([new Promise(e=>{this.messageQueueResolvers.push(e)}),new Promise((e,t)=>{setTimeout(()=>t(new Error("Timeout")),10)})])),t=ne("<no-raw-data>");t.messageType="parsed_only",yield yield H([t,e])}catch(e){if(e instanceof Error&&"Timeout"===e.message)continue;throw e}}})}getRawHistory(){return[...this.rawHistory]}getProtocolStats(){const e={totalMessages:this.rawHistory.length,messageTypes:{},controlMessages:0,jsonMessages:0,textMessages:0,errors:0};for(const t of this.rawHistory)t.messageType&&(e.messageTypes[t.messageType]=(e.messageTypes[t.messageType]||0)+1),t.isControl?e.controlMessages++:t.jsonData?e.jsonMessages++:e.textMessages++,t.jsonData&&"error"in t.jsonData&&e.errors++;return e}sendRaw(e){return U(this,void 0,void 0,function*(){if(!this.transport)throw new Error("Not connected");yield this.transport.send(e);const t="string"==typeof e?e:JSON.stringify(e).substring(0,100);this.logger.info(`Sent raw data: ${t}`)})}},exports.TimeoutError=_,exports.TransportError=F,exports.ValidationError=b,exports.query=le,exports.queryStream=function(e,t,o){return q(this,arguments,function*(){var s,i,r,n;const l=new re(o);yield H(l.connect());try{yield H(l.sendMessage(e,t));try{for(var a,c=!0,d=W(l.receiveMessages());!(s=(a=yield H(d.next())).done);c=!0){n=a.value,c=!1;const e=n;if(e.type===exports.MessageType.ASSISTANT&&e.chunk.text)yield yield H(e.chunk.text);else if(e.type===exports.MessageType.TASK_FINISH)break}}catch(e){i={error:e}}finally{try{c||s||!(r=d.return)||(yield H(r.call(d)))}finally{if(i)throw i.error}}}finally{yield H(l.disconnect())}})},exports.querySync=function(e,t,o){let s,i;if(le(e,t,o).then(e=>{i=e}).catch(e=>{s=e}),s)throw s;return i};
|
|
1
|
+
"use strict";var e=require("fs"),t=require("path"),o=require("ws"),s=require("fs/promises"),i=require("os"),r=require("net"),n=require("child_process");function l(e){var t=Object.create(null);return e&&Object.keys(e).forEach(function(o){if("default"!==o){var s=Object.getOwnPropertyDescriptor(e,o);Object.defineProperty(t,o,s.get?s:{enumerable:!0,get:function(){return e[o]}})}}),t.default=e,Object.freeze(t)}var a,c,d,h,u,p,g,f,w,y,m,v,S,T=l(e),E=l(t),I=l(s),x=l(i),A=l(r),O=l(n);class P extends Error{constructor(e,t){super(e),this.name="IFlowError",this.details=t||{}}}class _ extends P{constructor(e,t){super(e,t),this.name="TimeoutError"}}class R extends P{constructor(e,t){super(e,{rawData:t}),this.name="JSONDecodeError",this.rawData=t}}class C extends P{constructor(e,t){super(e,t),this.name="IFlowNotInstalledError"}}class N extends P{constructor(e,t){super(e,t),this.name="IFlowProcessError"}}class L extends P{constructor(e,t){super(e,t),this.name="PortNotAvailableError"}}class M extends P{constructor(e,t){super(e,t),this.name="ConnectionError"}}class F extends P{constructor(e,t){super(e,t),this.name="TransportError"}}class $ extends P{constructor(e,t){super(e,t),this.name="PermissionError"}}class b extends P{constructor(e,t){super(e,t),this.name="ValidationError"}}class D extends P{constructor(e,t){super(e,t),this.name="ProtocolError"}}class k extends P{constructor(e,t){super(e,t),this.name="AuthenticationError"}}function U(e,t,o,s){return new(o||(o=Promise))(function(i,r){function n(e){try{a(s.next(e))}catch(e){r(e)}}function l(e){try{a(s.throw(e))}catch(e){r(e)}}function a(e){var t;e.done?i(e.value):(t=e.value,t instanceof o?t:new o(function(e){e(t)})).then(n,l)}a((s=s.apply(e,t||[])).next())})}function j(e){var t="function"==typeof Symbol&&Symbol.iterator,o=t&&e[t],s=0;if(o)return o.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&s>=e.length&&(e=void 0),{value:e&&e[s++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function H(e){return this instanceof H?(this.v=e,this):new H(e)}function W(e,t,o){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var s,i=o.apply(e,t||[]),r=[];return s=Object.create(("function"==typeof AsyncIterator?AsyncIterator:Object).prototype),n("next"),n("throw"),n("return",function(e){return function(t){return Promise.resolve(t).then(e,c)}}),s[Symbol.asyncIterator]=function(){return this},s;function n(e,t){i[e]&&(s[e]=function(t){return new Promise(function(o,s){r.push([e,t,o,s])>1||l(e,t)})},t&&(s[e]=t(s[e])))}function l(e,t){try{(o=i[e](t)).value instanceof H?Promise.resolve(o.value.v).then(a,c):d(r[0][2],o)}catch(e){d(r[0][3],e)}var o}function a(e){l("next",e)}function c(e){l("throw",e)}function d(e,t){e(t),r.shift(),r.length&&l(r[0][0],r[0][1])}}function q(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t,o=e[Symbol.asyncIterator];return o?o.call(e):(e=j(e),t={},s("next"),s("throw"),s("return"),t[Symbol.asyncIterator]=function(){return this},t);function s(o){t[o]=e[o]&&function(t){return new Promise(function(s,i){(function(e,t,o,s){Promise.resolve(s).then(function(t){e({value:t,done:o})},t)})(s,i,(t=e[o](t)).done,t.value)})}}}exports.LogLevel=void 0,(a=exports.LogLevel||(exports.LogLevel={}))[a.DEBUG=0]="DEBUG",a[a.INFO=1]="INFO",a[a.WARN=2]="WARN",a[a.ERROR=3]="ERROR",exports.PermissionMode=void 0,(c=exports.PermissionMode||(exports.PermissionMode={})).AUTO="auto",c.MANUAL="manual",c.SELECTIVE="selective",exports.ApprovalMode=void 0,(d=exports.ApprovalMode||(exports.ApprovalMode={})).DEFAULT="default",d.AUTO_EDIT="autoEdit",d.YOLO="yolo",d.PLAN="plan",exports.HookEventType=void 0,(h=exports.HookEventType||(exports.HookEventType={})).PRE_TOOL_USE="PreToolUse",h.POST_TOOL_USE="PostToolUse",h.STOP="Stop",h.SUBAGENT_STOP="SubagentStop",h.SET_UP_ENVIRONMENT="SetUpEnvironment",exports.PlanPriority=void 0,(u=exports.PlanPriority||(exports.PlanPriority={})).HIGH="high",u.MEDIUM="medium",u.LOW="low",exports.PlanStatus=void 0,(p=exports.PlanStatus||(exports.PlanStatus={})).PENDING="pending",p.IN_PROGRESS="in_progress",p.COMPLETED="completed",exports.StopReason=void 0,(g=exports.StopReason||(exports.StopReason={})).END_TURN="end_turn",g.MAX_TOKENS="max_tokens",g.REFUSAL="refusal",g.CANCELLED="cancelled",exports.ToolCallStatus=void 0,(f=exports.ToolCallStatus||(exports.ToolCallStatus={})).PENDING="pending",f.IN_PROGRESS="in_progress",f.COMPLETED="completed",f.FAILED="failed",exports.ToolCallContentType=void 0,(w=exports.ToolCallContentType||(exports.ToolCallContentType={})).DIFF="diff",w.MARKDOWN="markdown",exports.ToolCallConfirmationType=void 0,(y=exports.ToolCallConfirmationType||(exports.ToolCallConfirmationType={})).EDIT="edit",y.EXECUTE="execute",y.MCP="mcp",y.FETCH="fetch",y.OTHER="other",exports.ToolCallConfirmationOutcome=void 0,(m=exports.ToolCallConfirmationOutcome||(exports.ToolCallConfirmationOutcome={})).ALLOW="allow",m.ALWAYS_ALLOW="alwaysAllow",m.ALWAYS_ALLOW_TOOL="alwaysAllowTool",m.ALWAYS_ALLOW_MCP_SERVER="alwaysAllowMcpServer",m.REJECT="reject",exports.ToolCallIconType=void 0,(v=exports.ToolCallIconType||(exports.ToolCallIconType={})).URL="url",v.EMOJI="emoji",exports.MessageType=void 0,(S=exports.MessageType||(exports.MessageType={})).PLAN="plan",S.USER="user",S.ASSISTANT="assistant",S.TOOL_CALL="tool_call",S.ERROR="error",S.TASK_FINISH="task_finish","function"==typeof SuppressedError&&SuppressedError;const z="2.0";var G,Q,K;function J(e){return e instanceof Error?e.message:e?String(e):"unknown error"}!function(e){e.INITIALIZE="initialize",e.AUTHENTICATE="authenticate",e.SESSION_NEW="session/new",e.SESSION_LOAD="session/load",e.SESSION_PROMPT="session/prompt",e.SESSION_CANCEL="session/cancel"}(G||(G={})),function(e){e.SESSION_UPDATE="session/update",e.SESSION_REQUEST_PERMISSION="session/request_permission",e.FS_READ_TEXT_FILE="fs/read_text_file",e.FS_WRITE_TEXT_FILE="fs/write_text_file",e.PUSH_TOOL_CALL="pushToolCall",e.UPDATE_TOOL_CALL="updateToolCall",e.NOTIFY_TASK_FINISH="notifyTaskFinish"}(Q||(Q={})),function(e){e.PLAN="plan",e.TOOL_CALL="tool_call",e.TOOL_CALL_UPDATE="tool_call_update",e.USER_MESSAGE_CHUNK="user_message_chunk",e.AGENT_MESSAGE_CHUNK="agent_message_chunk",e.AGENT_THOUGHT_CHUNK="agent_thought_chunk"}(K||(K={}));class V{constructor(e={}){const t=e.level||"INFO";this.level=exports.LogLevel[t]}debug(e){this.log(exports.LogLevel.DEBUG,e)}info(e){this.log(exports.LogLevel.INFO,e)}warn(e){this.log(exports.LogLevel.WARN,e)}error(e,t){this.log(exports.LogLevel.ERROR,e,t)}log(e,t,o){if(e<this.level)return;const s=`[${(new Date).toLocaleString("sv-SE").replace("T"," ")}] ${exports.LogLevel[e]}: ${t}${o?`\n${o.stack}`:""}`;switch(e){case exports.LogLevel.DEBUG:console.debug(s);break;case exports.LogLevel.INFO:console.info(s);break;case exports.LogLevel.WARN:console.warn(s);break;case exports.LogLevel.ERROR:console.error(s)}}}const X=new V;function Y(e){return!!e&&"id"in e&&"result"in e&&null!=e.result}function B(e){return!!e&&"id"in e&&"error"in e&&null!=e.error}function Z(e){return!!e&&"method"in e&&!("result"in e)&&!("error"in e)}class ee{constructor(e){this.requestId=0,this.initialized=!1,this.authenticated=!1,this.logger=e.logger||X,this.transport=e.transport,this.fileHandler=e.fileHandler,this.permissionMode=e.permissionMode||exports.PermissionMode.AUTO,this.autoApproveTypes=e.autoApproveTypes||["read","fetch","list"]}nextRequestId(){return++this.requestId}checkAuthenticated(){if(!this.initialized)throw new D("Protocol not initialized. Call initialize() first.");if(!this.authenticated)throw new D("Not authenticated. Call authenticate() first.")}sendResult(e,t){return U(this,void 0,void 0,function*(){const o={jsonrpc:z,id:e,result:t};yield this.transport.send(o)})}sendError(e,t,o){return U(this,void 0,void 0,function*(){const s={jsonrpc:z,id:e,error:{code:t,message:o}};yield this.transport.send(s)})}waitForReadySignal(){return U(this,void 0,void 0,function*(){var e,t,o,s;try{for(var i,r=!0,n=q(this.transport.receive());!(e=(i=yield n.next()).done);r=!0){s=i.value,r=!1;const e=s.trim();if("//ready"===e){this.logger.info("Received //ready signal");break}e.startsWith("//")&&this.logger.debug(`Control message: ${e}`)}}catch(e){t={error:e}}finally{try{r||e||!(o=n.return)||(yield o.call(n))}finally{if(t)throw t.error}}})}waitForMessageResponse(e,t,o){return U(this,void 0,void 0,function*(){var s,i,r,n;const{timeout:l,timeoutMsg:a=`Timeout after ${l} seconds`}=o||{},c=Date.now();try{for(var d,h=!0,u=q(this.transport.receive());!(s=(d=yield u.next()).done);h=!0){n=d.value,h=!1;const o=n;if(o.trim().startsWith("//")){this.logger.debug(`Control message: ${o.trim()}`);continue}let s;try{s=JSON.parse(o.trim())}catch(e){this.logger.error(`Failed to parse response: ${J(e)}`);continue}if(s.id===e){const e=t(s);if(void 0!==e)return e}if(l&&l>0&&Date.now()-c>l)throw new _(a)}}catch(e){i={error:e}}finally{try{h||s||!(r=u.return)||(yield r.call(u))}finally{if(i)throw i.error}}})}initialize(){return U(this,arguments,void 0,function*(e={}){if(this.initialized)return this.logger.warn("Protocol already initialized"),{protocolVersion:1,isAuthenticated:this.authenticated};this.logger.info("Waiting for //ready signal..."),yield this.waitForReadySignal();const t=this.nextRequestId(),o={jsonrpc:z,id:t,method:G.INITIALIZE,params:Object.assign({protocolVersion:1,clientCapabilities:{fs:{readTextFile:!0,writeTextFile:!0}}},e)};yield this.transport.send(o),this.logger.info("Sent initialize request");const s=yield this.waitForMessageResponse(t,e=>{var t;if("error"in e)throw new D(`Initialize failed: ${null===(t=e.error)||void 0===t?void 0:t.message}`,e.error);const o=e.result||{};return this.initialized=!0,this.authenticated=o.isAuthenticated||!1,this.logger.info(`Initialized with protocol version: ${o.protocolVersion}, authenticated: ${this.authenticated}`),o},{timeout:1e4,timeoutMsg:"Initialize timeout after 10 seconds"});if(s)return s;throw new D("Connection closed during initialization")})}authenticate(){return U(this,arguments,void 0,function*(e={}){const t=e.methodId||"iflow";if(this.authenticated)return void this.logger.warn("Already authenticated");const o=this.nextRequestId(),s={jsonrpc:z,id:o,method:G.AUTHENTICATE,params:Object.assign(Object.assign({},e),{methodId:t})};yield this.transport.send(s),this.logger.info(`Sent authenticate request with method: ${s.params.methodId}`);if(!(yield this.waitForMessageResponse(o,e=>{var o;if("error"in e)throw new k(`Authentication failed: ${null===(o=e.error)||void 0===o?void 0:o.message}`,e.error);const s=e.result||{};return s.methodId===t?(this.authenticated=!0,this.logger.info(`Authentication successful with method: ${s.methodId}`),!0):(this.authenticated=!0,this.logger.warn(`Unexpected methodId in response: ${s.methodId} (expected ${t})`),!0)},{timeout:1e4,timeoutMsg:"Authentication timeout after 10 seconds"})))throw new k("Connection closed during authentication")})}createSession(){return U(this,arguments,void 0,function*(e={}){this.checkAuthenticated();const t=this.nextRequestId(),o={jsonrpc:z,id:t,method:G.SESSION_NEW,params:Object.assign(Object.assign({},e),{cwd:e.cwd||process.cwd(),mcpServers:e.mcpServers||[]})};yield this.transport.send(o),this.logger.info(`Sent session/new request with cwd: ${e.cwd}`);const s=yield this.waitForMessageResponse(t,e=>{var t;if("error"in e)throw new D(`session/new failed: ${null===(t=e.error)||void 0===t?void 0:t.message}`,e.error);const o=e.result||{};if(o.sessionId)return this.logger.info(`Created session: ${o.sessionId}`),o.sessionId;throw new D(`Invalid session/new response: ${JSON.stringify(o)}`)},{timeout:1e4,timeoutMsg:"Session creation timeout after 10 seconds"});if(s)return s;throw new D("Connection closed while waiting for session/new response")})}loadSession(e){return U(this,void 0,void 0,function*(){this.checkAuthenticated();const t=this.nextRequestId(),o={jsonrpc:z,id:t,method:G.SESSION_LOAD,params:Object.assign(Object.assign({},e),{cwd:e.cwd||process.cwd(),mcpServers:e.mcpServers||[]})};yield this.transport.send(o),this.logger.info(`Sent session/load request for session: ${e.sessionId}`);if(!(yield this.waitForMessageResponse(t,t=>{var o;if("error"in t){if(-32601===t.error.code)throw new D("session/load is not supported by the current iFlow version. Use session/new to create a new session instead.",t.error);throw new D(`session/load failed: ${null===(o=t.error)||void 0===o?void 0:o.message}`,t.error)}return this.logger.info(`Session loaded successfully: ${e.sessionId}`),!0},{timeout:1e4,timeoutMsg:"Session load timeout after 10 seconds"})))throw new D("Connection closed while waiting for session/load response")})}sendPrompt(e){return U(this,void 0,void 0,function*(){this.checkAuthenticated();const t=this.nextRequestId(),o={jsonrpc:z,id:t,method:G.SESSION_PROMPT,params:e};return yield this.transport.send(o),this.logger.info(`Sent prompt with ${e.prompt.length} content blocks`),t})}cancelSession(e){return U(this,void 0,void 0,function*(){this.checkAuthenticated();const t=this.nextRequestId(),o={jsonrpc:z,id:t,method:G.SESSION_CANCEL,params:e};yield this.transport.send(o),this.logger.info("Sent session/cancel request")})}handleMessages(){return W(this,arguments,function*(){var e,t,o,s;try{for(var i,r=!0,n=q(this.transport.receive());!(e=(i=yield H(n.next())).done);r=!0){s=i.value,r=!1;const e=s;if(e.trim().startsWith("//")){this.logger.debug(`Control message: ${e.trim()}`);continue}let t;try{t=JSON.parse(e.trim())}catch(t){throw this.logger.error(`Failed to parse message: ${J(t)}`),new R("Invalid JSON received",e)}Z(t)?yield yield H(yield H(this.handleClientMessage(t))):Y(t)?yield yield H({type:"response",id:t.id,result:t.result}):B(t)&&(yield yield H({type:"error",code:t.error.code,error:t.error.message}))}}catch(e){t={error:e}}finally{try{r||e||!(o=n.return)||(yield H(o.call(n)))}finally{if(t)throw t.error}}})}handleClientMessage(e){return U(this,void 0,void 0,function*(){const{method:t}=e;switch(t){case Q.FS_READ_TEXT_FILE:return yield this.handleReadTextFile(e);case Q.FS_WRITE_TEXT_FILE:return yield this.handleWriteTextFile(e);case Q.SESSION_UPDATE:return yield this.handleSessionUpdate(e);case Q.SESSION_REQUEST_PERMISSION:return yield this.handleRequestPermission(e);case Q.PUSH_TOOL_CALL:return yield this.handlePushToolCall(e);case Q.UPDATE_TOOL_CALL:return yield this.handleUpdateToolCall(e);case Q.NOTIFY_TASK_FINISH:return yield this.handleNotifyTaskFinish(e);default:return yield this.handleUnknownMessage(e)}})}handleReadTextFile(e){return U(this,void 0,void 0,function*(){const{id:t,method:o,params:s}=e,{path:i,limit:r,line:n}=s||{};let l;if(this.logger.info(`fs/read_text_file request for: ${i}`),!this.fileHandler){const e="File system access not configured";return void 0!==t&&(yield this.sendError(t,-32603,e)),{type:"error",code:-32603,error:e,method:o}}try{l=yield this.fileHandler.readFile(i,n,r)}catch(e){const s=J(e);return this.logger.error(`Error reading file ${i}: ${s}`),void 0!==t&&(yield this.sendError(t,-32603,s)),{type:"error",code:-32603,error:s,method:o}}return void 0!==t&&(yield this.sendResult(t,{content:l})),{type:"file_read",path:i,content:l}})}handleWriteTextFile(e){return U(this,void 0,void 0,function*(){const{id:t,method:o,params:s}=e,{path:i,content:r}=s||{};if(this.logger.info(`fs/write_text_file request for: ${i}`),!this.fileHandler){const e="File system access not configured";return void 0!==t&&(yield this.sendError(t,-32603,e)),{type:"error",code:-32603,error:e,method:o}}try{yield this.fileHandler.writeFile(i,r)}catch(e){const s=J(e);return this.logger.error(`Error writing file ${i}: ${s}`),void 0!==t&&(yield this.sendError(t,-32603,s)),{type:"error",code:-32603,error:s,method:o}}return void 0!==t&&(yield this.sendResult(t,{success:!0})),{type:"file_write",path:i,content:r}})}handleSessionUpdate(e){return U(this,void 0,void 0,function*(){const{params:t}=e,{sessionId:o,update:s}=t;return{type:"session_update",sessionId:o,updateData:s}})}handleRequestPermission(e){return U(this,void 0,void 0,function*(){const{id:t,params:o}=e,s=o.toolCall||{},i=o.options||[];let r,n;if(r=this.permissionMode===exports.PermissionMode.AUTO||this.permissionMode!==exports.PermissionMode.MANUAL&&this.autoApproveTypes.includes(s.type||""),r){let e;for(const t of i){const o=t.optionId||"";if("proceed_once"===o){e=o;break}"proceed_always"===o&&(e=o)}!e&&i.length>0&&(e=i[0].optionId||"proceed_once"),n={outcome:{outcome:"selected",optionId:e}}}else n={outcome:{outcome:"cancelled"}};return void 0!==t&&(yield this.sendResult(t,n)),this.logger.info(`Permission request for tool '${s.title||"unknown"}' - Response: ${n.outcome.outcome}`),{type:"tool_confirmation",params:o,response:n}})}handlePushToolCall(e){return U(this,void 0,void 0,function*(){const{id:t,params:o}=e,s=`tool_${this.nextRequestId()}`,i={id:s};return void 0!==t&&(yield this.sendResult(t,i)),{type:"tool_call",id:s,params:o}})}handleUpdateToolCall(e){return U(this,void 0,void 0,function*(){const{id:t,params:o}=e;return void 0!==t&&(yield this.sendResult(t,null)),{type:"tool_update",params:o}})}handleNotifyTaskFinish(e){return U(this,void 0,void 0,function*(){const{id:t,params:o}=e;return void 0!==t&&(yield this.sendResult(t,null)),{type:"task_finish",params:o}})}handleUnknownMessage(e){return U(this,void 0,void 0,function*(){const{id:t,method:o,params:s}=e;return this.logger.warn(`Unknown method: ${o}`),void 0!==t&&(yield this.sendError(t,-32601,"Method not found")),{type:"unknown",method:o,params:s}})}}class te{constructor(e){this.ws=null,this.connected=!1,this.url=e.url,this.logger=e.logger||X,this.timeout=e.timeout||3e5}get isConnected(){return!!this.ws&&this.connected}checkConnected(){if(!this.isConnected)throw new M("Not connected")}connect(){return U(this,void 0,void 0,function*(){if(this.connected)this.logger.warn(`Already connected to ${this.url}`);else try{this.logger.info(`Connecting to ${this.url}`),this.ws=yield new Promise((e,t)=>{const s=new o(this.url),i=setTimeout(()=>{s.close(),t(new _(`Connected to ${this.url} timeout after ${this.timeout/1e3}s`))},this.timeout);s.on("open",()=>{clearTimeout(i),this.connected=!0,this.logger.info(`Connected to ${this.url} succesfully`),e(s)}),s.on("error",e=>{clearTimeout(i),this.connected=!1,t(e)}),s.on("close",(e,o)=>{clearTimeout(i),this.connected=!1,t(new Error(`${o} (code: ${e})`))})})}catch(e){if(e instanceof _)throw e;throw new M(`Failed to connect to ${this.url}: ${J(e)}`)}})}close(){return U(this,void 0,void 0,function*(){if(this.ws&&this.connected)try{this.ws.close(),this.logger.info("Connection closed")}catch(e){this.logger.warn(`Error closing connection: ${J(e)}`)}this.ws=null,this.connected=!1})}send(e){return U(this,void 0,void 0,function*(){this.checkConnected();try{const t="string"==typeof e?e:JSON.stringify(e);yield new Promise((e,o)=>{this.ws.send(t,s=>{s?o(s):(this.logger.debug(`Sent message: ${t}`),e())})})}catch(e){throw this.connected=!1,new F(`Failed to send message: ${J(e)}`)}})}receive(){return W(this,arguments,function*(){for(this.checkConnected();this.isConnected;)try{const e=yield H(this.receiveRawData());this.logger.debug(`Received message: ${e}`),yield yield H(e)}catch(e){if(this.connected=!1,e instanceof M&&e.details.isClosed){this.logger.info("Connection closed");break}throw new F(`Failed to receive message: ${J(e)}`)}})}receiveRawData(){return new Promise((e,t)=>{if(!this.isConnected)return void t(new M("Not connected"));const o=()=>{this.ws&&(this.ws.off("close",s),this.ws.off("error",i),this.ws.off("message",r))},s=()=>{o(),this.connected=!1,t(new M("Connection closed",{isClosed:!0}))},i=e=>{o(),this.connected=!1,t(e)},r=t=>{o(),e(t.toString())};this.ws&&(this.ws.on("close",s),this.ws.on("error",i),this.ws.on("message",r))})}}class oe{constructor(e={}){this.cwd=e.cwd||process.cwd(),this.logger=e.logger||X,this.readOnly=e.readOnly||!1,this.maxFileSize=e.maxFileSize||10485760,e.allowedDirs?this.allowedDirs=new Set(e.allowedDirs.map(e=>E.resolve(this.cwd,e))):this.allowedDirs=new Set([this.cwd]),this.logger.info(`File handler initialized with ${this.allowedDirs.size} allowed directories`);for(const e of this.allowedDirs)this.logger.debug(` Allowed: ${e}`)}isPathAllowed(e){try{const t=E.resolve(this.cwd,e);for(const e of this.allowedDirs)if(t.startsWith(e))return!0;return this.logger.warn(`Path not in allowed directories: ${t}`),!1}catch(e){return e instanceof Error&&this.logger.error(`Error checking path: ${e.message}`,e),!1}}readFile(e,t,o){return U(this,void 0,void 0,function*(){if(!this.isPathAllowed(e))throw new $(`Access denied: ${e}`);const s=E.resolve(this.cwd,e);try{if(!T.existsSync(s))throw new b(`File not found: ${e}`);try{yield I.access(s,T.constants.R_OK)}catch(t){throw new $(`Permission denied: ${e}`)}const i=yield I.stat(s);if(!i.isFile())throw new b(`Not a file: ${e}`);if(i.size>this.maxFileSize)throw new b(`File too large: ${i.size} bytes (max: ${this.maxFileSize})`);const r=yield I.readFile(s,"utf-8");if(void 0!==t||void 0!==o){const s=r.split("\n"),i=t?t-1:0,n=o?i+o:s.length,l=Math.max(0,i),a=Math.min(s.length,n);return this.logger.debug(`Read ${a-l} lines from ${e}`),s.slice(l,a).join("\n")}return this.logger.debug(`Read ${r.length} bytes from ${e}`),r}catch(e){if(e instanceof b||e instanceof $)throw e;throw new b(`Failed to read file: ${J(e)}`)}})}writeFile(e,t){return U(this,void 0,void 0,function*(){if(this.readOnly)throw new $("File system is in read-only mode");if(!this.isPathAllowed(e))throw new $(`Access denied: ${e}`);const o=E.resolve(this.cwd,e);try{yield I.mkdir(E.dirname(o),{recursive:!0}),yield I.writeFile(o,t,"utf-8"),this.logger.debug(`Wrote ${t.length} bytes to ${e}`)}catch(e){throw new b(`Failed to write file: ${J(e)}`)}})}addAllowedDir(e){return U(this,void 0,void 0,function*(){const t=E.resolve(this.cwd,e);try{if(!T.existsSync(t))throw new b(`Directory does not exist: ${t}`);if(!(yield I.stat(t)).isDirectory())throw new b(`Not a directory: ${t}`);this.allowedDirs.add(t),this.logger.info(`Added allowed directory: ${t}`)}catch(e){if(e instanceof b)throw e;throw new b(`Failed to add ${t} as allowed directory: ${J(e)}`)}})}removeAllowedDir(e){const t=E.resolve(this.cwd,e);this.allowedDirs.delete(t),this.logger.info(`Removed allowed directory: ${t}`)}}class se{constructor(e={}){this.port=null,this.process=null,this.iflowPath=null,this.logger=e.logger||X,this.startPort=e.startPort||8090}get url(){if(!this.port)throw new N("iFlow process not started");return`ws://localhost:${this.port}/acp`}isRunning(){return!!this.process&&!this.process.killed&&null===this.process.exitCode}which(e){try{return O.execSync(`which ${e}`,{encoding:"utf-8"}).trim()}catch(e){return null}}fileExists(e){try{return T.existsSync(e)&&T.statSync(e).isFile()}catch(e){return!1}}findIflowPath(){const e=this.which("iflow");if(e)return this.logger.debug(`Found iflow at: ${e}`),e;const t=x.homedir(),o=[E.join(t,".npm-global","bin","iflow"),"/usr/local/bin/iflow",E.join(t,".local","bin","iflow"),E.join(t,"node_modules",".bin","iflow"),E.join(t,".yarn","bin","iflow"),E.join(t,"AppData","Roaming","npm","iflow.cmd"),E.join("C:","Program Files","nodejs","iflow.cmd")];for(const e of o)if(this.fileExists(e))return this.logger.debug(`Found iflow at: ${e}`),e;const s=null!==this.which("npm"),i=null!==this.which("node");let r;throw r="win32"===x.platform()?s||i?"iFlow CLI not found. Please use the following command to install:\n npm install -g @iflow-ai/iflow-cli@latest":"iFlow requires Node.js, but it is not installed in the system.\n\nPlease install Node.js first: https://nodejs.org/\n\nAfter installing Node.js, use the following command to install iFlow:\n npm install -g @iflow-ai/iflow-cli@latest":'iFlow CLI not found. Please use the following command to install:\n\n🍎 Mac/Linux/Ubuntu users:\n bash -c "$(curl -fsSL https://cloud.iflow.cn/iflow-cli/install.sh)"\n\n🪟 Windows users:\n npm install -g @iflow-ai/iflow-cli@latest',new C(r)}isPortAvailable(e){return new Promise(t=>{const o=A.createServer();o.listen(e,"localhost",()=>{o.once("close",()=>{t(!0)}),o.close()}),o.once("error",()=>{t(!1)})})}findAvailablePort(){return U(this,void 0,void 0,function*(){for(let e=0;e<100;e++){const t=this.startPort+e;if(yield this.isPortAvailable(t))return this.logger.debug(`Found available port: ${t}`),t}throw new L(`No available port found in range ${this.startPort}-${this.startPort+100}`)})}start(){return U(this,void 0,void 0,function*(){if(this.isRunning())return this.url;this.iflowPath=this.findIflowPath(),this.port=yield this.findAvailablePort();const e=[this.iflowPath,"--experimental-acp","--port",this.port.toString()];this.logger.info(`Starting iFlow process: ${e.join(" ")}`);try{if(this.process=O.spawn(e[0],e.slice(1),{stdio:["ignore","pipe","pipe"],detached:!1}),yield new Promise(e=>setTimeout(e,500)),!this.isRunning()){let e="iFlow process exited immediately";if(this.process.stderr){const t=this.process.stderr.read();t&&(e+=`: ${t.toString("utf-8")}`)}throw new Error(e)}return this.logger.info(`iFlow process started on port ${this.port} (PID: ${this.process.pid})`),this.url}catch(e){throw this.port=null,this.process=null,new N(`Failed to start iFlow process: ${J(e)}`)}})}stop(){return U(this,void 0,void 0,function*(){if(this.process){if(!this.isRunning())return this.port=null,void(this.process=null);this.logger.info(`Stopping iFlow process (PID: ${this.process.pid})`);try{this.process.kill("SIGTERM"),yield Promise.race([new Promise(e=>{this.process?this.process.once("exit",()=>e()):e()}),new Promise(e=>setTimeout(()=>e(),5e3))]),this.isRunning()?(this.logger.warn("iFlow process did not terminate gracefully, forcing kill"),this.process.kill("SIGKILL"),yield new Promise(e=>{this.process?this.process.once("exit",()=>e()):e()})):this.logger.info("iFlow process terminated gracefully")}catch(e){this.logger.error(`Error stopping iFlow process: ${J(e)}`)}finally{this.port=null,this.process=null}}})}}var ie;!function(e){e.ERROR="error",e.RESPONSE="response",e.FILE_READ="file_read",e.FILE_WRITE="file_write",e.SESSION_UPDATE="session_update",e.TOOL_CALL="tool_call",e.TOOL_UPDATE="tool_update",e.TOOL_CONFIRMATION="tool_confirmation",e.TASK_FINISH="task_finish",e.UNKNOWN="unknown"}(ie||(ie={}));class re{constructor(e={}){this.protocol=null,this.transport=null,this.connected=!1,this.authenticated=!1,this.messageTask=null,this.messageQueue=[],this.pendingToolCalls=new Map,this.url=null,this.sessionId=null,this.processManager=null,this.processStarted=!1,this.options=Object.assign({url:"ws://localhost:8090/acp",cwd:process.cwd(),timeout:3e4,logLevel:"INFO",fileMaxSize:10485760,permissionMode:exports.PermissionMode.AUTO,autoApproveTypes:["read","fetch","list"],authMethodId:"iflow",autoStartProcess:!0,processStartPort:8090},e),this.logger=new V({level:this.options.logLevel})}connect(){return U(this,void 0,void 0,function*(){var e,t;if(this.connected)this.logger.warn("Already connected");else try{if(this.options.autoStartProcess&&((null===(e=this.options.url)||void 0===e?void 0:e.startsWith("ws://localhost:"))||(null===(t=this.options.url)||void 0===t?void 0:t.startsWith("ws://127.0.0.1:")))){const e=new te({url:this.options.url,logger:this.logger,timeout:2e3});try{yield e.connect(),yield e.close(),this.url=this.options.url,this.logger.info(`iFlow already running at ${this.options.url}`)}catch(e){this.logger.info("iFlow not running, starting process..."),this.processManager=new se({logger:this.logger,startPort:this.options.processStartPort});try{const e=yield this.processManager.start();this.url=e,this.processStarted=!0,this.logger.info(`Started iFlow process at ${e}`),yield new Promise(e=>setTimeout(e,1e3))}catch(e){throw e instanceof C?(this.logger.error("iFlow not installed"),C):(this.logger.error(`Failed to start iFlow process: ${J(e)}`),new M(`Failed to start iFlow process: ${J(e)}`))}}}let o=null;this.options.fileAccess&&(o=new oe({cwd:this.options.cwd,logger:this.logger,readOnly:this.options.fileReadOnly,maxFileSize:this.options.fileMaxSize,allowedDirs:this.options.fileAllowedDirs}),this.logger.info(`File system access enabled with ${this.options.fileReadOnly?"read-only":"read-write"} mode`)),this.transport=new te({url:this.options.url,logger:this.logger,timeout:this.options.timeout}),this.protocol=new ee({logger:this.logger,transport:this.transport,fileHandler:o,permissionMode:this.options.permissionMode,autoApproveTypes:this.options.autoApproveTypes}),yield this.transport.connect();const s=yield this.protocol.initialize({mcpServers:this.options.mcpServers,hooks:this.options.hooks,commands:this.options.commands,agents:this.options.agents});this.authenticated=s.isAuthenticated||!1,this.authenticated||(yield this.protocol.authenticate({methodId:this.options.authMethodId,methodInfo:this.options.authMethodInfo}),this.authenticated=!0),this.sessionId=yield this.protocol.createSession({cwd:this.options.cwd||process.cwd(),mcpServers:this.options.mcpServers,hooks:this.options.hooks,commands:this.options.commands,agents:this.options.agents,settings:this.options.sessionSettings}),this.connected=!0,this.messageTask=this.handleMessages(),this.logger.info("Connected to iFlow")}catch(e){throw yield this.disconnect(),new M(`Failed to connect: ${J(e)}`)}})}loadSession(e){return U(this,void 0,void 0,function*(){if(!this.connected||!this.protocol)throw new M("Not connected. Call connect() first.");yield this.protocol.loadSession({sessionId:e,cwd:this.options.cwd||process.cwd(),mcpServers:this.options.mcpServers}),this.sessionId=e,this.logger.info(`Loaded session: ${e}`)})}disconnect(){return U(this,void 0,void 0,function*(){this.connected=!1,this.transport&&(yield this.transport.close()),this.processManager&&this.processStarted&&(yield this.processManager.stop()),this.url=null,this.protocol=null,this.transport=null,this.messageTask=null,this.authenticated=!1,this.processManager=null,this.processStarted=!1,this.logger.info("Disconnected from iFlow")})}sendMessage(e,t){return U(this,void 0,void 0,function*(){if(!this.connected||!this.protocol||!this.sessionId)throw new M("Not connected. Call connect() first.");const o=[{type:"text",text:e}];if(null==t?void 0:t.length)for(const e of t){const t=E.resolve(this.options.cwd||process.cwd(),e),s=E.parse(e);if(!T.existsSync(t)){this.logger.warn(`File not found, skipping: ${t}`);continue}const i=s.ext.toLowerCase();if([".png",".jpg",".jpeg",".gif",".bmp",".webp",".svg"].includes(i))try{const e=T.readFileSync(t).toString("base64"),r={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".bmp":"image/bmp",".webp":"image/webp",".svg":"image/svg+xml"};o.push({type:"image",data:e,mimeType:r[i]||"image/unknown"}),this.logger.debug(`Added image file: ${s.base}`)}catch(e){this.logger.error(`Failed to read image file ${t}: ${J(e)}`);continue}else if([".mp3",".wav",".m4a",".ogg",".flac"].includes(i))try{const e=T.readFileSync(t).toString("base64"),r={".mp3":"audio/mpeg",".wav":"audio/wav",".m4a":"audio/mp4",".ogg":"audio/ogg",".flac":"audio/flac"};o.push({type:"audio",data:e,mimeType:r[i]||"audio/unknown"}),this.logger.debug(`Added audio file: ${s.base}`)}catch(e){this.logger.error(`Failed to read audio file ${t}: ${J(e)}`);continue}else{const e=T.statSync(t);o.push({type:"resource_link",uri:`file://${t}`,name:s.base,title:s.name,size:e.size}),this.logger.debug(`Added resource link: ${s.base}`)}}yield this.protocol.sendPrompt({sessionId:this.sessionId,prompt:o})})}interrupt(){return U(this,void 0,void 0,function*(){if(!this.connected||!this.protocol||!this.sessionId)throw new M("Not connected");yield this.protocol.cancelSession({sessionId:this.sessionId}),this.logger.info("Sent interrupt signal")})}receiveMessages(){return W(this,arguments,function*(){if(!this.connected)throw new M("Not connected");for(;this.connected;)try{this.messageQueue.length>0?yield yield H(this.messageQueue.shift()):yield H(new Promise(e=>setTimeout(e,100)))}catch(e){continue}})}approveToolCall(e){return U(this,arguments,void 0,function*(e,t=exports.ToolCallConfirmationOutcome.ALLOW){if(!this.pendingToolCalls.has(e))throw new Error(`Unknown tool call: ${e}`);this.logger.info(`Approved tool call ${e} with outcome ${t}`),this.pendingToolCalls.delete(e)})}rejectToolCall(e){return U(this,void 0,void 0,function*(){if(!this.pendingToolCalls.has(e))throw new Error(`Unknown tool call: ${e}`);this.logger.info(`Rejected tool call ${e}`),this.pendingToolCalls.delete(e)})}handleMessages(){return U(this,void 0,void 0,function*(){var e,t,o,s;if(this.protocol)try{try{for(var i,r=!0,n=q(this.protocol.handleMessages());!(e=(i=yield n.next()).done);r=!0){s=i.value,r=!1;const e=s,t=this.processProtocolMessage(e);t&&this.messageQueue.push(t)}}catch(e){t={error:e}}finally{try{r||e||!(o=n.return)||(yield o.call(n))}finally{if(t)throw t.error}}}catch(e){this.logger.error(`Error in message handler: ${J(e)}`);const t={type:exports.MessageType.ERROR,code:-1,message:String(J(e))};this.messageQueue.push(t)}})}processProtocolMessage(e){var t,o,s;switch(e.type){case ie.SESSION_UPDATE:{const{updateData:i}=e;let r,n;switch("agentId"in i&&i.agentId&&(r=i.agentId,n=function(e){const t=e.split("-");return"subagent"!==t[0]||t.length<4?{agentId:e}:4===t.length?{agentId:e,taskId:["null","undefined"].includes(t[1])?void 0:t[1],agentIndex:parseInt(t[2])||void 0,timestamp:parseInt(t[3])||void 0}:{agentId:e,taskId:t.slice(1,-2).join("-"),agentIndex:parseInt(t[t.length-2])||void 0,timestamp:parseInt(t[t.length-1])||void 0}}(r)),i.sessionUpdate){case K.PLAN:{const e=null===(t=i.entries)||void 0===t?void 0:t.map(e=>({content:e.content||"",status:e.status||exports.PlanStatus.PENDING,priority:e.priority||exports.PlanPriority.MEDIUM}));return e&&(null==e?void 0:e.length)>0?{type:exports.MessageType.PLAN,entries:e}:null}case K.TOOL_CALL:{const e={type:exports.MessageType.TOOL_CALL,id:i.toolCallId||"",label:i.title||"Tool",icon:{type:exports.ToolCallIconType.EMOJI,value:"🔧"},status:i.status||exports.ToolCallStatus.IN_PROGRESS,toolName:i.toolName};return r&&(e.agentId=r,e.agentInfo=n),this.pendingToolCalls.set(e.id,e),e}case K.TOOL_CALL_UPDATE:{const e=i.toolCallId;let t;if(this.pendingToolCalls.has(e)?(t=this.pendingToolCalls.get(e),t.status=i.status||exports.ToolCallStatus.COMPLETED,i.toolName&&(t.toolName=i.toolName),!t.agentId&&r&&(t.agentId=r),!t.agentInfo&&n&&(t.agentInfo=n)):(t={type:exports.MessageType.TOOL_CALL,id:e,label:i.title||"Tool",icon:{type:exports.ToolCallIconType.EMOJI,value:"🔧"},status:i.status||exports.ToolCallStatus.COMPLETED,toolName:i.toolName},r&&(t.agentId=r,t.agentInfo=n),this.pendingToolCalls.set(e,t)),i.content&&(null===(o=i.content)||void 0===o?void 0:o.length)>0){let e;const o=[];for(const t of i.content)"args"in t&&(e=t.args),"content"===t.type&&"text"===(null===(s=t.content)||void 0===s?void 0:s.type)&&o.push(t.content.text||"");void 0!==e&&(t.args=e),o.length>0&&(t.output=o.join("\n"))}return t}case K.USER_MESSAGE_CHUNK:{const e=i.content;if("text"===(null==e?void 0:e.type)){const t=e.text||"";if(t)return{type:exports.MessageType.USER,chunks:[{text:t}]}}return null}case K.AGENT_MESSAGE_CHUNK:{const e=i.content;if("text"===(null==e?void 0:e.type)){const t=e.text||"";if(t){const e={type:exports.MessageType.ASSISTANT,chunk:{text:t}};return r&&(e.agentId=r,e.agentInfo=n),e}}return null}case K.AGENT_THOUGHT_CHUNK:{const e=i.content;if("text"===(null==e?void 0:e.type)){const t=e.text||"";if(t){const e={type:exports.MessageType.ASSISTANT,chunk:{thought:t}};return r&&(e.agentId=r,e.agentInfo=n),e}}}default:return null}}case ie.RESPONSE:return"stopReason"in(e.result||{})?{type:exports.MessageType.TASK_FINISH,stopReason:e.result.stopReason}:null;case ie.ERROR:return{type:exports.MessageType.ERROR,code:e.code||-1,message:e.error||"Unknown error"};default:return null}}}function ne(e){let t,o=!1,s="text";if(e.startsWith("//"))o=!0,s="control";else try{t=JSON.parse(e),t&&"method"in t?s=`method:${t.method}`:t&&("result"in t||"error"in t)?s="response":t&&"type"in t&&(s=t.type)}catch(e){}return{isControl:o,messageType:s,rawData:e,jsonData:t,timestamp:Date.now()}}exports.AuthenticationError=k,exports.ConnectionError=M,exports.IFlowClient=re,exports.IFlowError=P,exports.IFlowNotInstalledError=C,exports.IFlowProcessError=N,exports.JSONDecodeError=R,exports.PermissionError=$,exports.PortNotAvailableError=L,exports.ProtocolError=D,exports.RawDataClient=class extends re{constructor(e,t=!0){super(e),this.rawQueue=[],this.rawHistory=[],this.rawQueueResolvers=[],this.messageQueueResolvers=[],this.captureRaw=t}handleMessages(){const e=Object.create(null,{handleMessages:{get:()=>super.handleMessages}});return U(this,void 0,void 0,function*(){if(this.protocol)try{if(this.captureRaw&&this.transport){const e=this.captureRawStream(),t=this.handleParsedStream();yield Promise.all([e,t])}else yield e.handleMessages.call(this)}catch(e){this.logger.error(`Error in message handler: ${J(e)}`)}})}captureRawStream(){return U(this,void 0,void 0,function*(){var e,t,o,s;if(this.transport)try{try{for(var i,r=!0,n=q(this.transport.receive());!(e=(i=yield n.next()).done);r=!0){s=i.value,r=!1;const e=s,t=ne("string"==typeof e?e:JSON.stringify(e));this.rawQueue.push(t),this.rawHistory.push(t);const o=this.rawQueueResolvers.shift();o&&o(t)}}catch(e){t={error:e}}finally{try{r||e||!(o=n.return)||(yield o.call(n))}finally{if(t)throw t.error}}}catch(e){this.logger.error(`Error capturing raw stream: ${J(e)}`)}})}handleParsedStream(){return U(this,void 0,void 0,function*(){var e,t,o,s;if(this.protocol)try{for(var i,r=!0,n=q(this.protocol.handleMessages());!(e=(i=yield n.next()).done);r=!0){s=i.value,r=!1;const e=s,t=this.processProtocolMessage(e);if(t){const e=this.messageQueueResolvers.shift();e&&e(t)}}}catch(e){t={error:e}}finally{try{r||e||!(o=n.return)||(yield o.call(n))}finally{if(t)throw t.error}}})}receiveRawMessages(){return W(this,arguments,function*(){for(;this.connected||this.rawQueue.length>0;)try{if(this.rawQueue.length>0)yield yield H(this.rawQueue.shift());else{const e=yield H(Promise.race([new Promise(e=>{this.rawQueueResolvers.push(e)}),new Promise((e,t)=>{setTimeout(()=>t(new Error("Timeout")),100)})]));yield yield H(e)}}catch(e){if(e instanceof Error&&"Timeout"===e.message)continue;throw e}})}receiveDualStream(){return W(this,arguments,function*(){const e=[],t=[];for(;this.connected||this.rawQueue.length>0||e.length>0||t.length>0;)try{let e,t;e=this.rawQueue.length>0?this.rawQueue.shift():yield H(Promise.race([new Promise(e=>{this.rawQueueResolvers.push(e)}),new Promise((e,t)=>{setTimeout(()=>t(new Error("Timeout")),10)})]));try{t=yield H(Promise.race([new Promise(e=>{this.messageQueueResolvers.push(e)}),new Promise((e,t)=>{setTimeout(()=>t(new Error("Timeout")),10)})]))}catch(e){}e.parsedMessage=t,yield yield H([e,t])}catch(e){if(!(e instanceof Error&&"Timeout"===e.message))throw e;try{const e=yield H(Promise.race([new Promise(e=>{this.messageQueueResolvers.push(e)}),new Promise((e,t)=>{setTimeout(()=>t(new Error("Timeout")),10)})])),t=ne("<no-raw-data>");t.messageType="parsed_only",yield yield H([t,e])}catch(e){if(e instanceof Error&&"Timeout"===e.message)continue;throw e}}})}getRawHistory(){return[...this.rawHistory]}getProtocolStats(){const e={totalMessages:this.rawHistory.length,messageTypes:{},controlMessages:0,jsonMessages:0,textMessages:0,errors:0};for(const t of this.rawHistory)t.messageType&&(e.messageTypes[t.messageType]=(e.messageTypes[t.messageType]||0)+1),t.isControl?e.controlMessages++:t.jsonData?e.jsonMessages++:e.textMessages++,t.jsonData&&"error"in t.jsonData&&e.errors++;return e}sendRaw(e){return U(this,void 0,void 0,function*(){if(!this.transport)throw new Error("Not connected");yield this.transport.send(e);const t="string"==typeof e?e:JSON.stringify(e).substring(0,100);this.logger.info(`Sent raw data: ${t}`)})}},exports.TimeoutError=_,exports.TransportError=F,exports.ValidationError=b,exports.query=function(e,t,o){return U(this,void 0,void 0,function*(){var s,i,r,n;const l=[],a=new re(o);yield a.connect();try{yield a.sendMessage(e,t);try{for(var c,d=!0,h=q(a.receiveMessages());!(s=(c=yield h.next()).done);d=!0){n=c.value,d=!1;const e=n;if(e.type===exports.MessageType.ASSISTANT&&e.chunk.text)l.push(e.chunk.text);else if(e.type===exports.MessageType.TASK_FINISH)break}}catch(e){i={error:e}}finally{try{d||s||!(r=h.return)||(yield r.call(h))}finally{if(i)throw i.error}}}finally{yield a.disconnect()}return l.join("")})},exports.queryStream=function(e,t,o){return W(this,arguments,function*(){var s,i,r,n;const l=new re(o);yield H(l.connect());try{yield H(l.sendMessage(e,t));try{for(var a,c=!0,d=q(l.receiveMessages());!(s=(a=yield H(d.next())).done);c=!0){n=a.value,c=!1;const e=n;if(e.type===exports.MessageType.ASSISTANT&&e.chunk.text)yield yield H(e.chunk.text);else if(e.type===exports.MessageType.TASK_FINISH)break}}catch(e){i={error:e}}finally{try{c||s||!(r=d.return)||(yield H(r.call(d)))}finally{if(i)throw i.error}}}finally{yield H(l.disconnect())}})};
|
package/dist/index.d.ts
CHANGED
|
@@ -920,29 +920,6 @@ export declare class RawDataClient extends IFlowClient {
|
|
|
920
920
|
* ```
|
|
921
921
|
*/
|
|
922
922
|
export declare function query(prompt: string, files?: string[], options?: IFlowOptions): Promise<string>;
|
|
923
|
-
/**
|
|
924
|
-
* 同步查询函数 - 阻塞等待响应完成
|
|
925
|
-
*
|
|
926
|
-
* 注意:这是一个同步函数,会阻塞当前线程直到响应完成。
|
|
927
|
-
* 建议在大多数情况下使用异步的 query() 函数。
|
|
928
|
-
*
|
|
929
|
-
* @param prompt - 用户提示文本
|
|
930
|
-
* @param files - 可选的文件路径数组,用于上下文
|
|
931
|
-
* @param options - 可选的 iFlow 配置选项
|
|
932
|
-
* @returns string - 完整的 AI 响应文本
|
|
933
|
-
* @throws Error - 如果查询过程中发生错误
|
|
934
|
-
*
|
|
935
|
-
* @example
|
|
936
|
-
* ```typescript
|
|
937
|
-
* try {
|
|
938
|
-
* const response = querySync("Hello, world!");
|
|
939
|
-
* console.log(response);
|
|
940
|
-
* } catch (error) {
|
|
941
|
-
* console.error("Query failed:", error);
|
|
942
|
-
* }
|
|
943
|
-
* ```
|
|
944
|
-
*/
|
|
945
|
-
export declare function querySync(prompt: string, files?: string[], options?: IFlowOptions): string;
|
|
946
923
|
/**
|
|
947
924
|
* 流式查询函数 - 实时返回响应片段
|
|
948
925
|
*
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import*as e from"fs";import*as t from"path";import s from"ws";import*as o from"fs/promises";import*as i from"os";import*as n from"net";import*as r from"child_process";class l extends Error{constructor(e,t){super(e),this.name="IFlowError",this.details=t||{}}}class a extends l{constructor(e,t){super(e,t),this.name="TimeoutError"}}class c extends l{constructor(e,t){super(e,{rawData:t}),this.name="JSONDecodeError",this.rawData=t}}class d extends l{constructor(e,t){super(e,t),this.name="IFlowNotInstalledError"}}class h extends l{constructor(e,t){super(e,t),this.name="IFlowProcessError"}}class u extends l{constructor(e,t){super(e,t),this.name="PortNotAvailableError"}}class p extends l{constructor(e,t){super(e,t),this.name="ConnectionError"}}class g extends l{constructor(e,t){super(e,t),this.name="TransportError"}}class f extends l{constructor(e,t){super(e,t),this.name="PermissionError"}}class w extends l{constructor(e,t){super(e,t),this.name="ValidationError"}}class m extends l{constructor(e,t){super(e,t),this.name="ProtocolError"}}class y extends l{constructor(e,t){super(e,t),this.name="AuthenticationError"}}var v,S,E,I,T,A,_,O,R,N,P,$,F;function L(e,t,s,o){return new(s||(s=Promise))(function(i,n){function r(e){try{a(o.next(e))}catch(e){n(e)}}function l(e){try{a(o.throw(e))}catch(e){n(e)}}function a(e){var t;e.done?i(e.value):(t=e.value,t instanceof s?t:new s(function(e){e(t)})).then(r,l)}a((o=o.apply(e,t||[])).next())})}function x(e){var t="function"==typeof Symbol&&Symbol.iterator,s=t&&e[t],o=0;if(s)return s.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&o>=e.length&&(e=void 0),{value:e&&e[o++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function C(e){return this instanceof C?(this.v=e,this):new C(e)}function M(e,t,s){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var o,i=s.apply(e,t||[]),n=[];return o=Object.create(("function"==typeof AsyncIterator?AsyncIterator:Object).prototype),r("next"),r("throw"),r("return",function(e){return function(t){return Promise.resolve(t).then(e,c)}}),o[Symbol.asyncIterator]=function(){return this},o;function r(e,t){i[e]&&(o[e]=function(t){return new Promise(function(s,o){n.push([e,t,s,o])>1||l(e,t)})},t&&(o[e]=t(o[e])))}function l(e,t){try{(s=i[e](t)).value instanceof C?Promise.resolve(s.value.v).then(a,c):d(n[0][2],s)}catch(e){d(n[0][3],e)}var s}function a(e){l("next",e)}function c(e){l("throw",e)}function d(e,t){e(t),n.shift(),n.length&&l(n[0][0],n[0][1])}}function b(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t,s=e[Symbol.asyncIterator];return s?s.call(e):(e=x(e),t={},o("next"),o("throw"),o("return"),t[Symbol.asyncIterator]=function(){return this},t);function o(s){t[s]=e[s]&&function(t){return new Promise(function(o,i){(function(e,t,s,o){Promise.resolve(o).then(function(t){e({value:t,done:s})},t)})(o,i,(t=e[s](t)).done,t.value)})}}}!function(e){e[e.DEBUG=0]="DEBUG",e[e.INFO=1]="INFO",e[e.WARN=2]="WARN",e[e.ERROR=3]="ERROR"}(v||(v={})),function(e){e.AUTO="auto",e.MANUAL="manual",e.SELECTIVE="selective"}(S||(S={})),function(e){e.DEFAULT="default",e.AUTO_EDIT="autoEdit",e.YOLO="yolo",e.PLAN="plan"}(E||(E={})),function(e){e.PRE_TOOL_USE="PreToolUse",e.POST_TOOL_USE="PostToolUse",e.STOP="Stop",e.SUBAGENT_STOP="SubagentStop",e.SET_UP_ENVIRONMENT="SetUpEnvironment"}(I||(I={})),function(e){e.HIGH="high",e.MEDIUM="medium",e.LOW="low"}(T||(T={})),function(e){e.PENDING="pending",e.IN_PROGRESS="in_progress",e.COMPLETED="completed"}(A||(A={})),function(e){e.END_TURN="end_turn",e.MAX_TOKENS="max_tokens",e.REFUSAL="refusal",e.CANCELLED="cancelled"}(_||(_={})),function(e){e.PENDING="pending",e.IN_PROGRESS="in_progress",e.COMPLETED="completed",e.FAILED="failed"}(O||(O={})),function(e){e.DIFF="diff",e.MARKDOWN="markdown"}(R||(R={})),function(e){e.EDIT="edit",e.EXECUTE="execute",e.MCP="mcp",e.FETCH="fetch",e.OTHER="other"}(N||(N={})),function(e){e.ALLOW="allow",e.ALWAYS_ALLOW="alwaysAllow",e.ALWAYS_ALLOW_TOOL="alwaysAllowTool",e.ALWAYS_ALLOW_MCP_SERVER="alwaysAllowMcpServer",e.REJECT="reject"}(P||(P={})),function(e){e.URL="url",e.EMOJI="emoji"}($||($={})),function(e){e.PLAN="plan",e.USER="user",e.ASSISTANT="assistant",e.TOOL_CALL="tool_call",e.ERROR="error",e.TASK_FINISH="task_finish"}(F||(F={})),"function"==typeof SuppressedError&&SuppressedError;const D="2.0";var U,k,j;function H(e){return e instanceof Error?e.message:e?String(e):"unknown error"}!function(e){e.INITIALIZE="initialize",e.AUTHENTICATE="authenticate",e.SESSION_NEW="session/new",e.SESSION_LOAD="session/load",e.SESSION_PROMPT="session/prompt",e.SESSION_CANCEL="session/cancel"}(U||(U={})),function(e){e.SESSION_UPDATE="session/update",e.SESSION_REQUEST_PERMISSION="session/request_permission",e.FS_READ_TEXT_FILE="fs/read_text_file",e.FS_WRITE_TEXT_FILE="fs/write_text_file",e.PUSH_TOOL_CALL="pushToolCall",e.UPDATE_TOOL_CALL="updateToolCall",e.NOTIFY_TASK_FINISH="notifyTaskFinish"}(k||(k={})),function(e){e.PLAN="plan",e.TOOL_CALL="tool_call",e.TOOL_CALL_UPDATE="tool_call_update",e.USER_MESSAGE_CHUNK="user_message_chunk",e.AGENT_MESSAGE_CHUNK="agent_message_chunk",e.AGENT_THOUGHT_CHUNK="agent_thought_chunk"}(j||(j={}));class W{constructor(e={}){const t=e.level||"INFO";this.level=v[t]}debug(e){this.log(v.DEBUG,e)}info(e){this.log(v.INFO,e)}warn(e){this.log(v.WARN,e)}error(e,t){this.log(v.ERROR,e,t)}log(e,t,s){if(e<this.level)return;const o=`[${(new Date).toLocaleString("sv-SE").replace("T"," ")}] ${v[e]}: ${t}${s?`\n${s.stack}`:""}`;switch(e){case v.DEBUG:console.debug(o);break;case v.INFO:console.info(o);break;case v.WARN:console.warn(o);break;case v.ERROR:console.error(o)}}}const z=new W;function G(e){return!!e&&"id"in e&&"result"in e&&null!=e.result}function Q(e){return!!e&&"id"in e&&"error"in e&&null!=e.error}function q(e){return!!e&&"method"in e&&!("result"in e)&&!("error"in e)}class K{constructor(e){this.requestId=0,this.initialized=!1,this.authenticated=!1,this.logger=e.logger||z,this.transport=e.transport,this.fileHandler=e.fileHandler,this.permissionMode=e.permissionMode||S.AUTO,this.autoApproveTypes=e.autoApproveTypes||["read","fetch","list"]}nextRequestId(){return++this.requestId}checkAuthenticated(){if(!this.initialized)throw new m("Protocol not initialized. Call initialize() first.");if(!this.authenticated)throw new m("Not authenticated. Call authenticate() first.")}sendResult(e,t){return L(this,void 0,void 0,function*(){const s={jsonrpc:D,id:e,result:t};yield this.transport.send(s)})}sendError(e,t,s){return L(this,void 0,void 0,function*(){const o={jsonrpc:D,id:e,error:{code:t,message:s}};yield this.transport.send(o)})}waitForReadySignal(){return L(this,void 0,void 0,function*(){var e,t,s,o;try{for(var i,n=!0,r=b(this.transport.receive());!(e=(i=yield r.next()).done);n=!0){o=i.value,n=!1;const e=o.trim();if("//ready"===e){this.logger.info("Received //ready signal");break}e.startsWith("//")&&this.logger.debug(`Control message: ${e}`)}}catch(e){t={error:e}}finally{try{n||e||!(s=r.return)||(yield s.call(r))}finally{if(t)throw t.error}}})}waitForMessageResponse(e,t,s){return L(this,void 0,void 0,function*(){var o,i,n,r;const{timeout:l,timeoutMsg:c=`Timeout after ${l} seconds`}=s||{},d=Date.now();try{for(var h,u=!0,p=b(this.transport.receive());!(o=(h=yield p.next()).done);u=!0){r=h.value,u=!1;const s=r;if(s.trim().startsWith("//")){this.logger.debug(`Control message: ${s.trim()}`);continue}let o;try{o=JSON.parse(s.trim())}catch(e){this.logger.error(`Failed to parse response: ${H(e)}`);continue}if(o.id===e){const e=t(o);if(void 0!==e)return e}if(l&&l>0&&Date.now()-d>l)throw new a(c)}}catch(e){i={error:e}}finally{try{u||o||!(n=p.return)||(yield n.call(p))}finally{if(i)throw i.error}}})}initialize(){return L(this,arguments,void 0,function*(e={}){if(this.initialized)return this.logger.warn("Protocol already initialized"),{protocolVersion:1,isAuthenticated:this.authenticated};this.logger.info("Waiting for //ready signal..."),yield this.waitForReadySignal();const t=this.nextRequestId(),s={jsonrpc:D,id:t,method:U.INITIALIZE,params:Object.assign({protocolVersion:1,clientCapabilities:{fs:{readTextFile:!0,writeTextFile:!0}}},e)};yield this.transport.send(s),this.logger.info("Sent initialize request");const o=yield this.waitForMessageResponse(t,e=>{var t;if("error"in e)throw new m(`Initialize failed: ${null===(t=e.error)||void 0===t?void 0:t.message}`,e.error);const s=e.result||{};return this.initialized=!0,this.authenticated=s.isAuthenticated||!1,this.logger.info(`Initialized with protocol version: ${s.protocolVersion}, authenticated: ${this.authenticated}`),s},{timeout:1e4,timeoutMsg:"Initialize timeout after 10 seconds"});if(o)return o;throw new m("Connection closed during initialization")})}authenticate(){return L(this,arguments,void 0,function*(e={}){const t=e.methodId||"iflow";if(this.authenticated)return void this.logger.warn("Already authenticated");const s=this.nextRequestId(),o={jsonrpc:D,id:s,method:U.AUTHENTICATE,params:Object.assign(Object.assign({},e),{methodId:t})};yield this.transport.send(o),this.logger.info(`Sent authenticate request with method: ${o.params.methodId}`);if(!(yield this.waitForMessageResponse(s,e=>{var s;if("error"in e)throw new y(`Authentication failed: ${null===(s=e.error)||void 0===s?void 0:s.message}`,e.error);const o=e.result||{};return o.methodId===t?(this.authenticated=!0,this.logger.info(`Authentication successful with method: ${o.methodId}`),!0):(this.authenticated=!0,this.logger.warn(`Unexpected methodId in response: ${o.methodId} (expected ${t})`),!0)},{timeout:1e4,timeoutMsg:"Authentication timeout after 10 seconds"})))throw new y("Connection closed during authentication")})}createSession(){return L(this,arguments,void 0,function*(e={}){this.checkAuthenticated();const t=this.nextRequestId(),s={jsonrpc:D,id:t,method:U.SESSION_NEW,params:Object.assign(Object.assign({},e),{cwd:e.cwd||process.cwd(),mcpServers:e.mcpServers||[]})};yield this.transport.send(s),this.logger.info(`Sent session/new request with cwd: ${e.cwd}`);const o=yield this.waitForMessageResponse(t,e=>{var t;if("error"in e)throw new m(`session/new failed: ${null===(t=e.error)||void 0===t?void 0:t.message}`,e.error);const s=e.result||{};if(s.sessionId)return this.logger.info(`Created session: ${s.sessionId}`),s.sessionId;throw new m(`Invalid session/new response: ${JSON.stringify(s)}`)},{timeout:1e4,timeoutMsg:"Session creation timeout after 10 seconds"});if(o)return o;throw new m("Connection closed while waiting for session/new response")})}loadSession(e){return L(this,void 0,void 0,function*(){this.checkAuthenticated();const t=this.nextRequestId(),s={jsonrpc:D,id:t,method:U.SESSION_LOAD,params:Object.assign(Object.assign({},e),{cwd:e.cwd||process.cwd(),mcpServers:e.mcpServers||[]})};yield this.transport.send(s),this.logger.info(`Sent session/load request for session: ${e.sessionId}`);if(!(yield this.waitForMessageResponse(t,t=>{var s;if("error"in t){if(-32601===t.error.code)throw new m("session/load is not supported by the current iFlow version. Use session/new to create a new session instead.",t.error);throw new m(`session/load failed: ${null===(s=t.error)||void 0===s?void 0:s.message}`,t.error)}return this.logger.info(`Session loaded successfully: ${e.sessionId}`),!0},{timeout:1e4,timeoutMsg:"Session load timeout after 10 seconds"})))throw new m("Connection closed while waiting for session/load response")})}sendPrompt(e){return L(this,void 0,void 0,function*(){this.checkAuthenticated();const t=this.nextRequestId(),s={jsonrpc:D,id:t,method:U.SESSION_PROMPT,params:e};return yield this.transport.send(s),this.logger.info(`Sent prompt with ${e.prompt.length} content blocks`),t})}cancelSession(e){return L(this,void 0,void 0,function*(){this.checkAuthenticated();const t=this.nextRequestId(),s={jsonrpc:D,id:t,method:U.SESSION_CANCEL,params:e};yield this.transport.send(s),this.logger.info("Sent session/cancel request")})}handleMessages(){return M(this,arguments,function*(){var e,t,s,o;try{for(var i,n=!0,r=b(this.transport.receive());!(e=(i=yield C(r.next())).done);n=!0){o=i.value,n=!1;const e=o;if(e.trim().startsWith("//")){this.logger.debug(`Control message: ${e.trim()}`);continue}let t;try{t=JSON.parse(e.trim())}catch(t){throw this.logger.error(`Failed to parse message: ${H(t)}`),new c("Invalid JSON received",e)}q(t)?yield yield C(yield C(this.handleClientMessage(t))):G(t)?yield yield C({type:"response",id:t.id,result:t.result}):Q(t)&&(yield yield C({type:"error",code:t.error.code,error:t.error.message}))}}catch(e){t={error:e}}finally{try{n||e||!(s=r.return)||(yield C(s.call(r)))}finally{if(t)throw t.error}}})}handleClientMessage(e){return L(this,void 0,void 0,function*(){const{method:t}=e;switch(t){case k.FS_READ_TEXT_FILE:return yield this.handleReadTextFile(e);case k.FS_WRITE_TEXT_FILE:return yield this.handleWriteTextFile(e);case k.SESSION_UPDATE:return yield this.handleSessionUpdate(e);case k.SESSION_REQUEST_PERMISSION:return yield this.handleRequestPermission(e);case k.PUSH_TOOL_CALL:return yield this.handlePushToolCall(e);case k.UPDATE_TOOL_CALL:return yield this.handleUpdateToolCall(e);case k.NOTIFY_TASK_FINISH:return yield this.handleNotifyTaskFinish(e);default:return yield this.handleUnknownMessage(e)}})}handleReadTextFile(e){return L(this,void 0,void 0,function*(){const{id:t,method:s,params:o}=e,{path:i,limit:n,line:r}=o||{};let l;if(this.logger.info(`fs/read_text_file request for: ${i}`),!this.fileHandler){const e="File system access not configured";return void 0!==t&&(yield this.sendError(t,-32603,e)),{type:"error",code:-32603,error:e,method:s}}try{l=yield this.fileHandler.readFile(i,r,n)}catch(e){const o=H(e);return this.logger.error(`Error reading file ${i}: ${o}`),void 0!==t&&(yield this.sendError(t,-32603,o)),{type:"error",code:-32603,error:o,method:s}}return void 0!==t&&(yield this.sendResult(t,{content:l})),{type:"file_read",path:i,content:l}})}handleWriteTextFile(e){return L(this,void 0,void 0,function*(){const{id:t,method:s,params:o}=e,{path:i,content:n}=o||{};if(this.logger.info(`fs/write_text_file request for: ${i}`),!this.fileHandler){const e="File system access not configured";return void 0!==t&&(yield this.sendError(t,-32603,e)),{type:"error",code:-32603,error:e,method:s}}try{yield this.fileHandler.writeFile(i,n)}catch(e){const o=H(e);return this.logger.error(`Error writing file ${i}: ${o}`),void 0!==t&&(yield this.sendError(t,-32603,o)),{type:"error",code:-32603,error:o,method:s}}return void 0!==t&&(yield this.sendResult(t,{success:!0})),{type:"file_write",path:i,content:n}})}handleSessionUpdate(e){return L(this,void 0,void 0,function*(){const{params:t}=e,{sessionId:s,update:o}=t;return{type:"session_update",sessionId:s,updateData:o}})}handleRequestPermission(e){return L(this,void 0,void 0,function*(){const{id:t,params:s}=e,o=s.toolCall||{},i=s.options||[];let n,r;if(n=this.permissionMode===S.AUTO||this.permissionMode!==S.MANUAL&&this.autoApproveTypes.includes(o.type||""),n){let e;for(const t of i){const s=t.optionId||"";if("proceed_once"===s){e=s;break}"proceed_always"===s&&(e=s)}!e&&i.length>0&&(e=i[0].optionId||"proceed_once"),r={outcome:{outcome:"selected",optionId:e}}}else r={outcome:{outcome:"cancelled"}};return void 0!==t&&(yield this.sendResult(t,r)),this.logger.info(`Permission request for tool '${o.title||"unknown"}' - Response: ${r.outcome.outcome}`),{type:"tool_confirmation",params:s,response:r}})}handlePushToolCall(e){return L(this,void 0,void 0,function*(){const{id:t,params:s}=e,o=`tool_${this.nextRequestId()}`,i={id:o};return void 0!==t&&(yield this.sendResult(t,i)),{type:"tool_call",id:o,params:s}})}handleUpdateToolCall(e){return L(this,void 0,void 0,function*(){const{id:t,params:s}=e;return void 0!==t&&(yield this.sendResult(t,null)),{type:"tool_update",params:s}})}handleNotifyTaskFinish(e){return L(this,void 0,void 0,function*(){const{id:t,params:s}=e;return void 0!==t&&(yield this.sendResult(t,null)),{type:"task_finish",params:s}})}handleUnknownMessage(e){return L(this,void 0,void 0,function*(){const{id:t,method:s,params:o}=e;return this.logger.warn(`Unknown method: ${s}`),void 0!==t&&(yield this.sendError(t,-32601,"Method not found")),{type:"unknown",method:s,params:o}})}}class J{constructor(e){this.ws=null,this.connected=!1,this.url=e.url,this.logger=e.logger||z,this.timeout=e.timeout||3e5}get isConnected(){return!!this.ws&&this.connected}checkConnected(){if(!this.isConnected)throw new p("Not connected")}connect(){return L(this,void 0,void 0,function*(){if(this.connected)this.logger.warn(`Already connected to ${this.url}`);else try{this.logger.info(`Connecting to ${this.url}`),this.ws=yield new Promise((e,t)=>{const o=new s(this.url),i=setTimeout(()=>{o.close(),t(new a(`Connected to ${this.url} timeout after ${this.timeout/1e3}s`))},this.timeout);o.on("open",()=>{clearTimeout(i),this.connected=!0,this.logger.info(`Connected to ${this.url} succesfully`),e(o)}),o.on("error",e=>{clearTimeout(i),this.connected=!1,t(e)}),o.on("close",(e,s)=>{clearTimeout(i),this.connected=!1,t(new Error(`${s} (code: ${e})`))})})}catch(e){if(e instanceof a)throw e;throw new p(`Failed to connect to ${this.url}: ${H(e)}`)}})}close(){return L(this,void 0,void 0,function*(){if(this.ws&&this.connected)try{this.ws.close(),this.logger.info("Connection closed")}catch(e){this.logger.warn(`Error closing connection: ${H(e)}`)}this.ws=null,this.connected=!1})}send(e){return L(this,void 0,void 0,function*(){this.checkConnected();try{const t="string"==typeof e?e:JSON.stringify(e);yield new Promise((e,s)=>{this.ws.send(t,o=>{o?s(o):(this.logger.debug(`Sent message: ${t}`),e())})})}catch(e){throw this.connected=!1,new g(`Failed to send message: ${H(e)}`)}})}receive(){return M(this,arguments,function*(){for(this.checkConnected();this.isConnected;)try{const e=yield C(this.receiveRawData());this.logger.debug(`Received message: ${e}`),yield yield C(e)}catch(e){if(this.connected=!1,e instanceof p&&e.details.isClosed){this.logger.info("Connection closed");break}throw new g(`Failed to receive message: ${H(e)}`)}})}receiveRawData(){return new Promise((e,t)=>{if(!this.isConnected)return void t(new p("Not connected"));const s=()=>{this.ws&&(this.ws.off("close",o),this.ws.off("error",i),this.ws.off("message",n))},o=()=>{s(),this.connected=!1,t(new p("Connection closed",{isClosed:!0}))},i=e=>{s(),this.connected=!1,t(e)},n=t=>{s(),e(t.toString())};this.ws&&(this.ws.on("close",o),this.ws.on("error",i),this.ws.on("message",n))})}}class V{constructor(e={}){this.cwd=e.cwd||process.cwd(),this.logger=e.logger||z,this.readOnly=e.readOnly||!1,this.maxFileSize=e.maxFileSize||10485760,e.allowedDirs?this.allowedDirs=new Set(e.allowedDirs.map(e=>t.resolve(this.cwd,e))):this.allowedDirs=new Set([this.cwd]),this.logger.info(`File handler initialized with ${this.allowedDirs.size} allowed directories`);for(const e of this.allowedDirs)this.logger.debug(` Allowed: ${e}`)}isPathAllowed(e){try{const s=t.resolve(this.cwd,e);for(const e of this.allowedDirs)if(s.startsWith(e))return!0;return this.logger.warn(`Path not in allowed directories: ${s}`),!1}catch(e){return e instanceof Error&&this.logger.error(`Error checking path: ${e.message}`,e),!1}}readFile(s,i,n){return L(this,void 0,void 0,function*(){if(!this.isPathAllowed(s))throw new f(`Access denied: ${s}`);const r=t.resolve(this.cwd,s);try{if(!e.existsSync(r))throw new w(`File not found: ${s}`);try{yield o.access(r,e.constants.R_OK)}catch(e){throw new f(`Permission denied: ${s}`)}const t=yield o.stat(r);if(!t.isFile())throw new w(`Not a file: ${s}`);if(t.size>this.maxFileSize)throw new w(`File too large: ${t.size} bytes (max: ${this.maxFileSize})`);const l=yield o.readFile(r,"utf-8");if(void 0!==i||void 0!==n){const e=l.split("\n"),t=i?i-1:0,o=n?t+n:e.length,r=Math.max(0,t),a=Math.min(e.length,o);return this.logger.debug(`Read ${a-r} lines from ${s}`),e.slice(r,a).join("\n")}return this.logger.debug(`Read ${l.length} bytes from ${s}`),l}catch(e){if(e instanceof w||e instanceof f)throw e;throw new w(`Failed to read file: ${H(e)}`)}})}writeFile(e,s){return L(this,void 0,void 0,function*(){if(this.readOnly)throw new f("File system is in read-only mode");if(!this.isPathAllowed(e))throw new f(`Access denied: ${e}`);const i=t.resolve(this.cwd,e);try{yield o.mkdir(t.dirname(i),{recursive:!0}),yield o.writeFile(i,s,"utf-8"),this.logger.debug(`Wrote ${s.length} bytes to ${e}`)}catch(e){throw new w(`Failed to write file: ${H(e)}`)}})}addAllowedDir(s){return L(this,void 0,void 0,function*(){const i=t.resolve(this.cwd,s);try{if(!e.existsSync(i))throw new w(`Directory does not exist: ${i}`);if(!(yield o.stat(i)).isDirectory())throw new w(`Not a directory: ${i}`);this.allowedDirs.add(i),this.logger.info(`Added allowed directory: ${i}`)}catch(e){if(e instanceof w)throw e;throw new w(`Failed to add ${i} as allowed directory: ${H(e)}`)}})}removeAllowedDir(e){const s=t.resolve(this.cwd,e);this.allowedDirs.delete(s),this.logger.info(`Removed allowed directory: ${s}`)}}class X{constructor(e={}){this.port=null,this.process=null,this.iflowPath=null,this.logger=e.logger||z,this.startPort=e.startPort||8090}get url(){if(!this.port)throw new h("iFlow process not started");return`ws://localhost:${this.port}/acp`}isRunning(){return!!this.process&&!this.process.killed&&null===this.process.exitCode}which(e){try{return r.execSync(`which ${e}`,{encoding:"utf-8"}).trim()}catch(e){return null}}fileExists(t){try{return e.existsSync(t)&&e.statSync(t).isFile()}catch(e){return!1}}findIflowPath(){const e=this.which("iflow");if(e)return this.logger.debug(`Found iflow at: ${e}`),e;const s=i.homedir(),o=[t.join(s,".npm-global","bin","iflow"),"/usr/local/bin/iflow",t.join(s,".local","bin","iflow"),t.join(s,"node_modules",".bin","iflow"),t.join(s,".yarn","bin","iflow"),t.join(s,"AppData","Roaming","npm","iflow.cmd"),t.join("C:","Program Files","nodejs","iflow.cmd")];for(const e of o)if(this.fileExists(e))return this.logger.debug(`Found iflow at: ${e}`),e;const n=null!==this.which("npm"),r=null!==this.which("node");let l;throw l="win32"===i.platform()?n||r?"iFlow CLI not found. Please use the following command to install:\n npm install -g @iflow-ai/iflow-cli@latest":"iFlow requires Node.js, but it is not installed in the system.\n\nPlease install Node.js first: https://nodejs.org/\n\nAfter installing Node.js, use the following command to install iFlow:\n npm install -g @iflow-ai/iflow-cli@latest":'iFlow CLI not found. Please use the following command to install:\n\n🍎 Mac/Linux/Ubuntu users:\n bash -c "$(curl -fsSL https://cloud.iflow.cn/iflow-cli/install.sh)"\n\n🪟 Windows users:\n npm install -g @iflow-ai/iflow-cli@latest',new d(l)}isPortAvailable(e){return new Promise(t=>{const s=n.createServer();s.listen(e,"localhost",()=>{s.once("close",()=>{t(!0)}),s.close()}),s.once("error",()=>{t(!1)})})}findAvailablePort(){return L(this,void 0,void 0,function*(){for(let e=0;e<100;e++){const t=this.startPort+e;if(yield this.isPortAvailable(t))return this.logger.debug(`Found available port: ${t}`),t}throw new u(`No available port found in range ${this.startPort}-${this.startPort+100}`)})}start(){return L(this,void 0,void 0,function*(){if(this.isRunning())return this.url;this.iflowPath=this.findIflowPath(),this.port=yield this.findAvailablePort();const e=[this.iflowPath,"--experimental-acp","--port",this.port.toString()];this.logger.info(`Starting iFlow process: ${e.join(" ")}`);try{if(this.process=r.spawn(e[0],e.slice(1),{stdio:["ignore","pipe","pipe"],detached:!1}),yield new Promise(e=>setTimeout(e,500)),!this.isRunning()){let e="iFlow process exited immediately";if(this.process.stderr){const t=this.process.stderr.read();t&&(e+=`: ${t.toString("utf-8")}`)}throw new Error(e)}return this.logger.info(`iFlow process started on port ${this.port} (PID: ${this.process.pid})`),this.url}catch(e){throw this.port=null,this.process=null,new h(`Failed to start iFlow process: ${H(e)}`)}})}stop(){return L(this,void 0,void 0,function*(){if(this.process){if(!this.isRunning())return this.port=null,void(this.process=null);this.logger.info(`Stopping iFlow process (PID: ${this.process.pid})`);try{this.process.kill("SIGTERM"),yield Promise.race([new Promise(e=>{this.process?this.process.once("exit",()=>e()):e()}),new Promise(e=>setTimeout(()=>e(),5e3))]),this.isRunning()?(this.logger.warn("iFlow process did not terminate gracefully, forcing kill"),this.process.kill("SIGKILL"),yield new Promise(e=>{this.process?this.process.once("exit",()=>e()):e()})):this.logger.info("iFlow process terminated gracefully")}catch(e){this.logger.error(`Error stopping iFlow process: ${H(e)}`)}finally{this.port=null,this.process=null}}})}}var Y;!function(e){e.ERROR="error",e.RESPONSE="response",e.FILE_READ="file_read",e.FILE_WRITE="file_write",e.SESSION_UPDATE="session_update",e.TOOL_CALL="tool_call",e.TOOL_UPDATE="tool_update",e.TOOL_CONFIRMATION="tool_confirmation",e.TASK_FINISH="task_finish",e.UNKNOWN="unknown"}(Y||(Y={}));class B{constructor(e={}){this.protocol=null,this.transport=null,this.connected=!1,this.authenticated=!1,this.messageTask=null,this.messageQueue=[],this.pendingToolCalls=new Map,this.url=null,this.sessionId=null,this.processManager=null,this.processStarted=!1,this.options=Object.assign({url:"ws://localhost:8090/acp",cwd:process.cwd(),timeout:3e4,logLevel:"INFO",fileMaxSize:10485760,permissionMode:S.AUTO,autoApproveTypes:["read","fetch","list"],authMethodId:"iflow",autoStartProcess:!0,processStartPort:8090},e),this.logger=new W({level:this.options.logLevel})}connect(){return L(this,void 0,void 0,function*(){var e,t;if(this.connected)this.logger.warn("Already connected");else try{if(this.options.autoStartProcess&&((null===(e=this.options.url)||void 0===e?void 0:e.startsWith("ws://localhost:"))||(null===(t=this.options.url)||void 0===t?void 0:t.startsWith("ws://127.0.0.1:")))){const e=new J({url:this.options.url,logger:this.logger,timeout:2e3});try{yield e.connect(),yield e.close(),this.url=this.options.url,this.logger.info(`iFlow already running at ${this.options.url}`)}catch(e){this.logger.info("iFlow not running, starting process..."),this.processManager=new X({logger:this.logger,startPort:this.options.processStartPort});try{const e=yield this.processManager.start();this.url=e,this.processStarted=!0,this.logger.info(`Started iFlow process at ${e}`),yield new Promise(e=>setTimeout(e,1e3))}catch(e){throw e instanceof d?(this.logger.error("iFlow not installed"),d):(this.logger.error(`Failed to start iFlow process: ${H(e)}`),new p(`Failed to start iFlow process: ${H(e)}`))}}}let s=null;this.options.fileAccess&&(s=new V({cwd:this.options.cwd,logger:this.logger,readOnly:this.options.fileReadOnly,maxFileSize:this.options.fileMaxSize,allowedDirs:this.options.fileAllowedDirs}),this.logger.info(`File system access enabled with ${this.options.fileReadOnly?"read-only":"read-write"} mode`)),this.transport=new J({url:this.url,logger:this.logger,timeout:this.options.timeout}),this.protocol=new K({logger:this.logger,transport:this.transport,fileHandler:s,permissionMode:this.options.permissionMode,autoApproveTypes:this.options.autoApproveTypes}),yield this.transport.connect();const o=yield this.protocol.initialize({mcpServers:this.options.mcpServers,hooks:this.options.hooks,commands:this.options.commands,agents:this.options.agents});this.authenticated=o.isAuthenticated||!1,this.authenticated||(yield this.protocol.authenticate({methodId:this.options.authMethodId,methodInfo:this.options.authMethodInfo}),this.authenticated=!0),this.sessionId=yield this.protocol.createSession({cwd:this.options.cwd||process.cwd(),mcpServers:this.options.mcpServers,hooks:this.options.hooks,commands:this.options.commands,agents:this.options.agents,settings:this.options.sessionSettings}),this.connected=!0,this.messageTask=this.handleMessages(),this.logger.info("Connected to iFlow")}catch(e){throw yield this.disconnect(),new p(`Failed to connect: ${H(e)}`)}})}loadSession(e){return L(this,void 0,void 0,function*(){if(!this.connected||!this.protocol)throw new p("Not connected. Call connect() first.");yield this.protocol.loadSession({sessionId:e,cwd:this.options.cwd||process.cwd(),mcpServers:this.options.mcpServers}),this.sessionId=e,this.logger.info(`Loaded session: ${e}`)})}disconnect(){return L(this,void 0,void 0,function*(){this.connected=!1,this.transport&&(yield this.transport.close()),this.processManager&&this.processStarted&&(yield this.processManager.stop()),this.url=null,this.protocol=null,this.transport=null,this.messageTask=null,this.authenticated=!1,this.processManager=null,this.processStarted=!1,this.logger.info("Disconnected from iFlow")})}sendMessage(s,o){return L(this,void 0,void 0,function*(){if(!this.connected||!this.protocol||!this.sessionId)throw new p("Not connected. Call connect() first.");const i=[{type:"text",text:s}];if(null==o?void 0:o.length)for(const s of o){const o=t.resolve(this.options.cwd||process.cwd(),s),n=t.parse(s);if(!e.existsSync(o)){this.logger.warn(`File not found, skipping: ${o}`);continue}const r=n.ext.toLowerCase();if([".png",".jpg",".jpeg",".gif",".bmp",".webp",".svg"].includes(r))try{const t=e.readFileSync(o).toString("base64"),s={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".bmp":"image/bmp",".webp":"image/webp",".svg":"image/svg+xml"};i.push({type:"image",data:t,mimeType:s[r]||"image/unknown"}),this.logger.debug(`Added image file: ${n.base}`)}catch(e){this.logger.error(`Failed to read image file ${o}: ${H(e)}`);continue}else if([".mp3",".wav",".m4a",".ogg",".flac"].includes(r))try{const t=e.readFileSync(o).toString("base64"),s={".mp3":"audio/mpeg",".wav":"audio/wav",".m4a":"audio/mp4",".ogg":"audio/ogg",".flac":"audio/flac"};i.push({type:"audio",data:t,mimeType:s[r]||"audio/unknown"}),this.logger.debug(`Added audio file: ${n.base}`)}catch(e){this.logger.error(`Failed to read audio file ${o}: ${H(e)}`);continue}else{const t=e.statSync(o);i.push({type:"resource_link",uri:`file://${o}`,name:n.base,title:n.name,size:t.size}),this.logger.debug(`Added resource link: ${n.base}`)}}yield this.protocol.sendPrompt({sessionId:this.sessionId,prompt:i})})}interrupt(){return L(this,void 0,void 0,function*(){if(!this.connected||!this.protocol||!this.sessionId)throw new p("Not connected");yield this.protocol.cancelSession({sessionId:this.sessionId}),this.logger.info("Sent interrupt signal")})}receiveMessages(){return M(this,arguments,function*(){if(!this.connected)throw new p("Not connected");for(;this.connected;)try{this.messageQueue.length>0?yield yield C(this.messageQueue.shift()):yield C(new Promise(e=>setTimeout(e,100)))}catch(e){continue}})}approveToolCall(e){return L(this,arguments,void 0,function*(e,t=P.ALLOW){if(!this.pendingToolCalls.has(e))throw new Error(`Unknown tool call: ${e}`);this.logger.info(`Approved tool call ${e} with outcome ${t}`),this.pendingToolCalls.delete(e)})}rejectToolCall(e){return L(this,void 0,void 0,function*(){if(!this.pendingToolCalls.has(e))throw new Error(`Unknown tool call: ${e}`);this.logger.info(`Rejected tool call ${e}`),this.pendingToolCalls.delete(e)})}handleMessages(){return L(this,void 0,void 0,function*(){var e,t,s,o;if(this.protocol)try{try{for(var i,n=!0,r=b(this.protocol.handleMessages());!(e=(i=yield r.next()).done);n=!0){o=i.value,n=!1;const e=o,t=this.processProtocolMessage(e);t&&this.messageQueue.push(t)}}catch(e){t={error:e}}finally{try{n||e||!(s=r.return)||(yield s.call(r))}finally{if(t)throw t.error}}}catch(e){this.logger.error(`Error in message handler: ${H(e)}`);const t={type:F.ERROR,code:-1,message:String(H(e))};this.messageQueue.push(t)}})}processProtocolMessage(e){var t,s,o;switch(e.type){case Y.SESSION_UPDATE:{const{updateData:i}=e;let n,r;switch("agentId"in i&&i.agentId&&(n=i.agentId,r=function(e){const t=e.split("-");return"subagent"!==t[0]||t.length<4?{agentId:e}:4===t.length?{agentId:e,taskId:["null","undefined"].includes(t[1])?void 0:t[1],agentIndex:parseInt(t[2])||void 0,timestamp:parseInt(t[3])||void 0}:{agentId:e,taskId:t.slice(1,-2).join("-"),agentIndex:parseInt(t[t.length-2])||void 0,timestamp:parseInt(t[t.length-1])||void 0}}(n)),i.sessionUpdate){case j.PLAN:{const e=null===(t=i.entries)||void 0===t?void 0:t.map(e=>({content:e.content||"",status:e.status||A.PENDING,priority:e.priority||T.MEDIUM}));return e&&(null==e?void 0:e.length)>0?{type:F.PLAN,entries:e}:null}case j.TOOL_CALL:{const e={type:F.TOOL_CALL,id:i.toolCallId||"",label:i.title||"Tool",icon:{type:$.EMOJI,value:"🔧"},status:i.status||O.IN_PROGRESS,toolName:i.toolName};return n&&(e.agentId=n,e.agentInfo=r),this.pendingToolCalls.set(e.id,e),e}case j.TOOL_CALL_UPDATE:{const e=i.toolCallId;let t;if(this.pendingToolCalls.has(e)?(t=this.pendingToolCalls.get(e),t.status=i.status||O.COMPLETED,i.toolName&&(t.toolName=i.toolName),!t.agentId&&n&&(t.agentId=n),!t.agentInfo&&r&&(t.agentInfo=r)):(t={type:F.TOOL_CALL,id:e,label:i.title||"Tool",icon:{type:$.EMOJI,value:"🔧"},status:i.status||O.COMPLETED,toolName:i.toolName},n&&(t.agentId=n,t.agentInfo=r),this.pendingToolCalls.set(e,t)),i.content&&(null===(s=i.content)||void 0===s?void 0:s.length)>0){let e;const s=[];for(const t of i.content)"args"in t&&(e=t.args),"content"===t.type&&"text"===(null===(o=t.content)||void 0===o?void 0:o.type)&&s.push(t.content.text||"");void 0!==e&&(t.args=e),s.length>0&&(t.output=s.join("\n"))}return t}case j.USER_MESSAGE_CHUNK:{const e=i.content;if("text"===(null==e?void 0:e.type)){const t=e.text||"";if(t)return{type:F.USER,chunks:[{text:t}]}}return null}case j.AGENT_MESSAGE_CHUNK:{const e=i.content;if("text"===(null==e?void 0:e.type)){const t=e.text||"";if(t){const e={type:F.ASSISTANT,chunk:{text:t}};return n&&(e.agentId=n,e.agentInfo=r),e}}return null}case j.AGENT_THOUGHT_CHUNK:{const e=i.content;if("text"===(null==e?void 0:e.type)){const t=e.text||"";if(t){const e={type:F.ASSISTANT,chunk:{thought:t}};return n&&(e.agentId=n,e.agentInfo=r),e}}}default:return null}}case Y.RESPONSE:return"stopReason"in(e.result||{})?{type:F.TASK_FINISH,stopReason:e.result.stopReason}:null;case Y.ERROR:return{type:F.ERROR,code:e.code||-1,message:e.error||"Unknown error"};default:return null}}}function Z(e){let t,s=!1,o="text";if(e.startsWith("//"))s=!0,o="control";else try{t=JSON.parse(e),t&&"method"in t?o=`method:${t.method}`:t&&("result"in t||"error"in t)?o="response":t&&"type"in t&&(o=t.type)}catch(e){}return{isControl:s,messageType:o,rawData:e,jsonData:t,timestamp:Date.now()}}class ee extends B{constructor(e,t=!0){super(e),this.rawQueue=[],this.rawHistory=[],this.rawQueueResolvers=[],this.messageQueueResolvers=[],this.captureRaw=t}handleMessages(){const e=Object.create(null,{handleMessages:{get:()=>super.handleMessages}});return L(this,void 0,void 0,function*(){if(this.protocol)try{if(this.captureRaw&&this.transport){const e=this.captureRawStream(),t=this.handleParsedStream();yield Promise.all([e,t])}else yield e.handleMessages.call(this)}catch(e){this.logger.error(`Error in message handler: ${H(e)}`)}})}captureRawStream(){return L(this,void 0,void 0,function*(){var e,t,s,o;if(this.transport)try{try{for(var i,n=!0,r=b(this.transport.receive());!(e=(i=yield r.next()).done);n=!0){o=i.value,n=!1;const e=o,t=Z("string"==typeof e?e:JSON.stringify(e));this.rawQueue.push(t),this.rawHistory.push(t);const s=this.rawQueueResolvers.shift();s&&s(t)}}catch(e){t={error:e}}finally{try{n||e||!(s=r.return)||(yield s.call(r))}finally{if(t)throw t.error}}}catch(e){this.logger.error(`Error capturing raw stream: ${H(e)}`)}})}handleParsedStream(){return L(this,void 0,void 0,function*(){var e,t,s,o;if(this.protocol)try{for(var i,n=!0,r=b(this.protocol.handleMessages());!(e=(i=yield r.next()).done);n=!0){o=i.value,n=!1;const e=o,t=this.processProtocolMessage(e);if(t){const e=this.messageQueueResolvers.shift();e&&e(t)}}}catch(e){t={error:e}}finally{try{n||e||!(s=r.return)||(yield s.call(r))}finally{if(t)throw t.error}}})}receiveRawMessages(){return M(this,arguments,function*(){for(;this.connected||this.rawQueue.length>0;)try{if(this.rawQueue.length>0)yield yield C(this.rawQueue.shift());else{const e=yield C(Promise.race([new Promise(e=>{this.rawQueueResolvers.push(e)}),new Promise((e,t)=>{setTimeout(()=>t(new Error("Timeout")),100)})]));yield yield C(e)}}catch(e){if(e instanceof Error&&"Timeout"===e.message)continue;throw e}})}receiveDualStream(){return M(this,arguments,function*(){const e=[],t=[];for(;this.connected||this.rawQueue.length>0||e.length>0||t.length>0;)try{let e,t;e=this.rawQueue.length>0?this.rawQueue.shift():yield C(Promise.race([new Promise(e=>{this.rawQueueResolvers.push(e)}),new Promise((e,t)=>{setTimeout(()=>t(new Error("Timeout")),10)})]));try{t=yield C(Promise.race([new Promise(e=>{this.messageQueueResolvers.push(e)}),new Promise((e,t)=>{setTimeout(()=>t(new Error("Timeout")),10)})]))}catch(e){}e.parsedMessage=t,yield yield C([e,t])}catch(e){if(!(e instanceof Error&&"Timeout"===e.message))throw e;try{const e=yield C(Promise.race([new Promise(e=>{this.messageQueueResolvers.push(e)}),new Promise((e,t)=>{setTimeout(()=>t(new Error("Timeout")),10)})])),t=Z("<no-raw-data>");t.messageType="parsed_only",yield yield C([t,e])}catch(e){if(e instanceof Error&&"Timeout"===e.message)continue;throw e}}})}getRawHistory(){return[...this.rawHistory]}getProtocolStats(){const e={totalMessages:this.rawHistory.length,messageTypes:{},controlMessages:0,jsonMessages:0,textMessages:0,errors:0};for(const t of this.rawHistory)t.messageType&&(e.messageTypes[t.messageType]=(e.messageTypes[t.messageType]||0)+1),t.isControl?e.controlMessages++:t.jsonData?e.jsonMessages++:e.textMessages++,t.jsonData&&"error"in t.jsonData&&e.errors++;return e}sendRaw(e){return L(this,void 0,void 0,function*(){if(!this.transport)throw new Error("Not connected");yield this.transport.send(e);const t="string"==typeof e?e:JSON.stringify(e).substring(0,100);this.logger.info(`Sent raw data: ${t}`)})}}function te(e,t,s){return L(this,void 0,void 0,function*(){var o,i,n,r;const l=[],a=new B(s);yield a.connect();try{yield a.sendMessage(e,t);try{for(var c,d=!0,h=b(a.receiveMessages());!(o=(c=yield h.next()).done);d=!0){r=c.value,d=!1;const e=r;if(e.type===F.ASSISTANT&&e.chunk.text)l.push(e.chunk.text);else if(e.type===F.TASK_FINISH)break}}catch(e){i={error:e}}finally{try{d||o||!(n=h.return)||(yield n.call(h))}finally{if(i)throw i.error}}}finally{yield a.disconnect()}return l.join("")})}function se(e,t,s){let o,i;if(te(e,t,s).then(e=>{i=e}).catch(e=>{o=e}),o)throw o;return i}function oe(e,t,s){return M(this,arguments,function*(){var o,i,n,r;const l=new B(s);yield C(l.connect());try{yield C(l.sendMessage(e,t));try{for(var a,c=!0,d=b(l.receiveMessages());!(o=(a=yield C(d.next())).done);c=!0){r=a.value,c=!1;const e=r;if(e.type===F.ASSISTANT&&e.chunk.text)yield yield C(e.chunk.text);else if(e.type===F.TASK_FINISH)break}}catch(e){i={error:e}}finally{try{c||o||!(n=d.return)||(yield C(n.call(d)))}finally{if(i)throw i.error}}}finally{yield C(l.disconnect())}})}export{E as ApprovalMode,y as AuthenticationError,p as ConnectionError,I as HookEventType,B as IFlowClient,l as IFlowError,d as IFlowNotInstalledError,h as IFlowProcessError,c as JSONDecodeError,v as LogLevel,F as MessageType,f as PermissionError,S as PermissionMode,T as PlanPriority,A as PlanStatus,u as PortNotAvailableError,m as ProtocolError,ee as RawDataClient,_ as StopReason,a as TimeoutError,P as ToolCallConfirmationOutcome,N as ToolCallConfirmationType,R as ToolCallContentType,$ as ToolCallIconType,O as ToolCallStatus,g as TransportError,w as ValidationError,te as query,oe as queryStream,se as querySync};
|
|
1
|
+
import*as e from"fs";import*as t from"path";import s from"ws";import*as o from"fs/promises";import*as i from"os";import*as n from"net";import*as r from"child_process";class l extends Error{constructor(e,t){super(e),this.name="IFlowError",this.details=t||{}}}class a extends l{constructor(e,t){super(e,t),this.name="TimeoutError"}}class c extends l{constructor(e,t){super(e,{rawData:t}),this.name="JSONDecodeError",this.rawData=t}}class d extends l{constructor(e,t){super(e,t),this.name="IFlowNotInstalledError"}}class h extends l{constructor(e,t){super(e,t),this.name="IFlowProcessError"}}class u extends l{constructor(e,t){super(e,t),this.name="PortNotAvailableError"}}class p extends l{constructor(e,t){super(e,t),this.name="ConnectionError"}}class g extends l{constructor(e,t){super(e,t),this.name="TransportError"}}class f extends l{constructor(e,t){super(e,t),this.name="PermissionError"}}class w extends l{constructor(e,t){super(e,t),this.name="ValidationError"}}class m extends l{constructor(e,t){super(e,t),this.name="ProtocolError"}}class y extends l{constructor(e,t){super(e,t),this.name="AuthenticationError"}}var v,S,E,I,T,A,_,O,R,N,P,$,F;function L(e,t,s,o){return new(s||(s=Promise))(function(i,n){function r(e){try{a(o.next(e))}catch(e){n(e)}}function l(e){try{a(o.throw(e))}catch(e){n(e)}}function a(e){var t;e.done?i(e.value):(t=e.value,t instanceof s?t:new s(function(e){e(t)})).then(r,l)}a((o=o.apply(e,t||[])).next())})}function x(e){var t="function"==typeof Symbol&&Symbol.iterator,s=t&&e[t],o=0;if(s)return s.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&o>=e.length&&(e=void 0),{value:e&&e[o++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function C(e){return this instanceof C?(this.v=e,this):new C(e)}function M(e,t,s){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var o,i=s.apply(e,t||[]),n=[];return o=Object.create(("function"==typeof AsyncIterator?AsyncIterator:Object).prototype),r("next"),r("throw"),r("return",function(e){return function(t){return Promise.resolve(t).then(e,c)}}),o[Symbol.asyncIterator]=function(){return this},o;function r(e,t){i[e]&&(o[e]=function(t){return new Promise(function(s,o){n.push([e,t,s,o])>1||l(e,t)})},t&&(o[e]=t(o[e])))}function l(e,t){try{(s=i[e](t)).value instanceof C?Promise.resolve(s.value.v).then(a,c):d(n[0][2],s)}catch(e){d(n[0][3],e)}var s}function a(e){l("next",e)}function c(e){l("throw",e)}function d(e,t){e(t),n.shift(),n.length&&l(n[0][0],n[0][1])}}function b(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t,s=e[Symbol.asyncIterator];return s?s.call(e):(e=x(e),t={},o("next"),o("throw"),o("return"),t[Symbol.asyncIterator]=function(){return this},t);function o(s){t[s]=e[s]&&function(t){return new Promise(function(o,i){(function(e,t,s,o){Promise.resolve(o).then(function(t){e({value:t,done:s})},t)})(o,i,(t=e[s](t)).done,t.value)})}}}!function(e){e[e.DEBUG=0]="DEBUG",e[e.INFO=1]="INFO",e[e.WARN=2]="WARN",e[e.ERROR=3]="ERROR"}(v||(v={})),function(e){e.AUTO="auto",e.MANUAL="manual",e.SELECTIVE="selective"}(S||(S={})),function(e){e.DEFAULT="default",e.AUTO_EDIT="autoEdit",e.YOLO="yolo",e.PLAN="plan"}(E||(E={})),function(e){e.PRE_TOOL_USE="PreToolUse",e.POST_TOOL_USE="PostToolUse",e.STOP="Stop",e.SUBAGENT_STOP="SubagentStop",e.SET_UP_ENVIRONMENT="SetUpEnvironment"}(I||(I={})),function(e){e.HIGH="high",e.MEDIUM="medium",e.LOW="low"}(T||(T={})),function(e){e.PENDING="pending",e.IN_PROGRESS="in_progress",e.COMPLETED="completed"}(A||(A={})),function(e){e.END_TURN="end_turn",e.MAX_TOKENS="max_tokens",e.REFUSAL="refusal",e.CANCELLED="cancelled"}(_||(_={})),function(e){e.PENDING="pending",e.IN_PROGRESS="in_progress",e.COMPLETED="completed",e.FAILED="failed"}(O||(O={})),function(e){e.DIFF="diff",e.MARKDOWN="markdown"}(R||(R={})),function(e){e.EDIT="edit",e.EXECUTE="execute",e.MCP="mcp",e.FETCH="fetch",e.OTHER="other"}(N||(N={})),function(e){e.ALLOW="allow",e.ALWAYS_ALLOW="alwaysAllow",e.ALWAYS_ALLOW_TOOL="alwaysAllowTool",e.ALWAYS_ALLOW_MCP_SERVER="alwaysAllowMcpServer",e.REJECT="reject"}(P||(P={})),function(e){e.URL="url",e.EMOJI="emoji"}($||($={})),function(e){e.PLAN="plan",e.USER="user",e.ASSISTANT="assistant",e.TOOL_CALL="tool_call",e.ERROR="error",e.TASK_FINISH="task_finish"}(F||(F={})),"function"==typeof SuppressedError&&SuppressedError;const D="2.0";var U,k,j;function H(e){return e instanceof Error?e.message:e?String(e):"unknown error"}!function(e){e.INITIALIZE="initialize",e.AUTHENTICATE="authenticate",e.SESSION_NEW="session/new",e.SESSION_LOAD="session/load",e.SESSION_PROMPT="session/prompt",e.SESSION_CANCEL="session/cancel"}(U||(U={})),function(e){e.SESSION_UPDATE="session/update",e.SESSION_REQUEST_PERMISSION="session/request_permission",e.FS_READ_TEXT_FILE="fs/read_text_file",e.FS_WRITE_TEXT_FILE="fs/write_text_file",e.PUSH_TOOL_CALL="pushToolCall",e.UPDATE_TOOL_CALL="updateToolCall",e.NOTIFY_TASK_FINISH="notifyTaskFinish"}(k||(k={})),function(e){e.PLAN="plan",e.TOOL_CALL="tool_call",e.TOOL_CALL_UPDATE="tool_call_update",e.USER_MESSAGE_CHUNK="user_message_chunk",e.AGENT_MESSAGE_CHUNK="agent_message_chunk",e.AGENT_THOUGHT_CHUNK="agent_thought_chunk"}(j||(j={}));class W{constructor(e={}){const t=e.level||"INFO";this.level=v[t]}debug(e){this.log(v.DEBUG,e)}info(e){this.log(v.INFO,e)}warn(e){this.log(v.WARN,e)}error(e,t){this.log(v.ERROR,e,t)}log(e,t,s){if(e<this.level)return;const o=`[${(new Date).toLocaleString("sv-SE").replace("T"," ")}] ${v[e]}: ${t}${s?`\n${s.stack}`:""}`;switch(e){case v.DEBUG:console.debug(o);break;case v.INFO:console.info(o);break;case v.WARN:console.warn(o);break;case v.ERROR:console.error(o)}}}const z=new W;function G(e){return!!e&&"id"in e&&"result"in e&&null!=e.result}function Q(e){return!!e&&"id"in e&&"error"in e&&null!=e.error}function q(e){return!!e&&"method"in e&&!("result"in e)&&!("error"in e)}class K{constructor(e){this.requestId=0,this.initialized=!1,this.authenticated=!1,this.logger=e.logger||z,this.transport=e.transport,this.fileHandler=e.fileHandler,this.permissionMode=e.permissionMode||S.AUTO,this.autoApproveTypes=e.autoApproveTypes||["read","fetch","list"]}nextRequestId(){return++this.requestId}checkAuthenticated(){if(!this.initialized)throw new m("Protocol not initialized. Call initialize() first.");if(!this.authenticated)throw new m("Not authenticated. Call authenticate() first.")}sendResult(e,t){return L(this,void 0,void 0,function*(){const s={jsonrpc:D,id:e,result:t};yield this.transport.send(s)})}sendError(e,t,s){return L(this,void 0,void 0,function*(){const o={jsonrpc:D,id:e,error:{code:t,message:s}};yield this.transport.send(o)})}waitForReadySignal(){return L(this,void 0,void 0,function*(){var e,t,s,o;try{for(var i,n=!0,r=b(this.transport.receive());!(e=(i=yield r.next()).done);n=!0){o=i.value,n=!1;const e=o.trim();if("//ready"===e){this.logger.info("Received //ready signal");break}e.startsWith("//")&&this.logger.debug(`Control message: ${e}`)}}catch(e){t={error:e}}finally{try{n||e||!(s=r.return)||(yield s.call(r))}finally{if(t)throw t.error}}})}waitForMessageResponse(e,t,s){return L(this,void 0,void 0,function*(){var o,i,n,r;const{timeout:l,timeoutMsg:c=`Timeout after ${l} seconds`}=s||{},d=Date.now();try{for(var h,u=!0,p=b(this.transport.receive());!(o=(h=yield p.next()).done);u=!0){r=h.value,u=!1;const s=r;if(s.trim().startsWith("//")){this.logger.debug(`Control message: ${s.trim()}`);continue}let o;try{o=JSON.parse(s.trim())}catch(e){this.logger.error(`Failed to parse response: ${H(e)}`);continue}if(o.id===e){const e=t(o);if(void 0!==e)return e}if(l&&l>0&&Date.now()-d>l)throw new a(c)}}catch(e){i={error:e}}finally{try{u||o||!(n=p.return)||(yield n.call(p))}finally{if(i)throw i.error}}})}initialize(){return L(this,arguments,void 0,function*(e={}){if(this.initialized)return this.logger.warn("Protocol already initialized"),{protocolVersion:1,isAuthenticated:this.authenticated};this.logger.info("Waiting for //ready signal..."),yield this.waitForReadySignal();const t=this.nextRequestId(),s={jsonrpc:D,id:t,method:U.INITIALIZE,params:Object.assign({protocolVersion:1,clientCapabilities:{fs:{readTextFile:!0,writeTextFile:!0}}},e)};yield this.transport.send(s),this.logger.info("Sent initialize request");const o=yield this.waitForMessageResponse(t,e=>{var t;if("error"in e)throw new m(`Initialize failed: ${null===(t=e.error)||void 0===t?void 0:t.message}`,e.error);const s=e.result||{};return this.initialized=!0,this.authenticated=s.isAuthenticated||!1,this.logger.info(`Initialized with protocol version: ${s.protocolVersion}, authenticated: ${this.authenticated}`),s},{timeout:1e4,timeoutMsg:"Initialize timeout after 10 seconds"});if(o)return o;throw new m("Connection closed during initialization")})}authenticate(){return L(this,arguments,void 0,function*(e={}){const t=e.methodId||"iflow";if(this.authenticated)return void this.logger.warn("Already authenticated");const s=this.nextRequestId(),o={jsonrpc:D,id:s,method:U.AUTHENTICATE,params:Object.assign(Object.assign({},e),{methodId:t})};yield this.transport.send(o),this.logger.info(`Sent authenticate request with method: ${o.params.methodId}`);if(!(yield this.waitForMessageResponse(s,e=>{var s;if("error"in e)throw new y(`Authentication failed: ${null===(s=e.error)||void 0===s?void 0:s.message}`,e.error);const o=e.result||{};return o.methodId===t?(this.authenticated=!0,this.logger.info(`Authentication successful with method: ${o.methodId}`),!0):(this.authenticated=!0,this.logger.warn(`Unexpected methodId in response: ${o.methodId} (expected ${t})`),!0)},{timeout:1e4,timeoutMsg:"Authentication timeout after 10 seconds"})))throw new y("Connection closed during authentication")})}createSession(){return L(this,arguments,void 0,function*(e={}){this.checkAuthenticated();const t=this.nextRequestId(),s={jsonrpc:D,id:t,method:U.SESSION_NEW,params:Object.assign(Object.assign({},e),{cwd:e.cwd||process.cwd(),mcpServers:e.mcpServers||[]})};yield this.transport.send(s),this.logger.info(`Sent session/new request with cwd: ${e.cwd}`);const o=yield this.waitForMessageResponse(t,e=>{var t;if("error"in e)throw new m(`session/new failed: ${null===(t=e.error)||void 0===t?void 0:t.message}`,e.error);const s=e.result||{};if(s.sessionId)return this.logger.info(`Created session: ${s.sessionId}`),s.sessionId;throw new m(`Invalid session/new response: ${JSON.stringify(s)}`)},{timeout:1e4,timeoutMsg:"Session creation timeout after 10 seconds"});if(o)return o;throw new m("Connection closed while waiting for session/new response")})}loadSession(e){return L(this,void 0,void 0,function*(){this.checkAuthenticated();const t=this.nextRequestId(),s={jsonrpc:D,id:t,method:U.SESSION_LOAD,params:Object.assign(Object.assign({},e),{cwd:e.cwd||process.cwd(),mcpServers:e.mcpServers||[]})};yield this.transport.send(s),this.logger.info(`Sent session/load request for session: ${e.sessionId}`);if(!(yield this.waitForMessageResponse(t,t=>{var s;if("error"in t){if(-32601===t.error.code)throw new m("session/load is not supported by the current iFlow version. Use session/new to create a new session instead.",t.error);throw new m(`session/load failed: ${null===(s=t.error)||void 0===s?void 0:s.message}`,t.error)}return this.logger.info(`Session loaded successfully: ${e.sessionId}`),!0},{timeout:1e4,timeoutMsg:"Session load timeout after 10 seconds"})))throw new m("Connection closed while waiting for session/load response")})}sendPrompt(e){return L(this,void 0,void 0,function*(){this.checkAuthenticated();const t=this.nextRequestId(),s={jsonrpc:D,id:t,method:U.SESSION_PROMPT,params:e};return yield this.transport.send(s),this.logger.info(`Sent prompt with ${e.prompt.length} content blocks`),t})}cancelSession(e){return L(this,void 0,void 0,function*(){this.checkAuthenticated();const t=this.nextRequestId(),s={jsonrpc:D,id:t,method:U.SESSION_CANCEL,params:e};yield this.transport.send(s),this.logger.info("Sent session/cancel request")})}handleMessages(){return M(this,arguments,function*(){var e,t,s,o;try{for(var i,n=!0,r=b(this.transport.receive());!(e=(i=yield C(r.next())).done);n=!0){o=i.value,n=!1;const e=o;if(e.trim().startsWith("//")){this.logger.debug(`Control message: ${e.trim()}`);continue}let t;try{t=JSON.parse(e.trim())}catch(t){throw this.logger.error(`Failed to parse message: ${H(t)}`),new c("Invalid JSON received",e)}q(t)?yield yield C(yield C(this.handleClientMessage(t))):G(t)?yield yield C({type:"response",id:t.id,result:t.result}):Q(t)&&(yield yield C({type:"error",code:t.error.code,error:t.error.message}))}}catch(e){t={error:e}}finally{try{n||e||!(s=r.return)||(yield C(s.call(r)))}finally{if(t)throw t.error}}})}handleClientMessage(e){return L(this,void 0,void 0,function*(){const{method:t}=e;switch(t){case k.FS_READ_TEXT_FILE:return yield this.handleReadTextFile(e);case k.FS_WRITE_TEXT_FILE:return yield this.handleWriteTextFile(e);case k.SESSION_UPDATE:return yield this.handleSessionUpdate(e);case k.SESSION_REQUEST_PERMISSION:return yield this.handleRequestPermission(e);case k.PUSH_TOOL_CALL:return yield this.handlePushToolCall(e);case k.UPDATE_TOOL_CALL:return yield this.handleUpdateToolCall(e);case k.NOTIFY_TASK_FINISH:return yield this.handleNotifyTaskFinish(e);default:return yield this.handleUnknownMessage(e)}})}handleReadTextFile(e){return L(this,void 0,void 0,function*(){const{id:t,method:s,params:o}=e,{path:i,limit:n,line:r}=o||{};let l;if(this.logger.info(`fs/read_text_file request for: ${i}`),!this.fileHandler){const e="File system access not configured";return void 0!==t&&(yield this.sendError(t,-32603,e)),{type:"error",code:-32603,error:e,method:s}}try{l=yield this.fileHandler.readFile(i,r,n)}catch(e){const o=H(e);return this.logger.error(`Error reading file ${i}: ${o}`),void 0!==t&&(yield this.sendError(t,-32603,o)),{type:"error",code:-32603,error:o,method:s}}return void 0!==t&&(yield this.sendResult(t,{content:l})),{type:"file_read",path:i,content:l}})}handleWriteTextFile(e){return L(this,void 0,void 0,function*(){const{id:t,method:s,params:o}=e,{path:i,content:n}=o||{};if(this.logger.info(`fs/write_text_file request for: ${i}`),!this.fileHandler){const e="File system access not configured";return void 0!==t&&(yield this.sendError(t,-32603,e)),{type:"error",code:-32603,error:e,method:s}}try{yield this.fileHandler.writeFile(i,n)}catch(e){const o=H(e);return this.logger.error(`Error writing file ${i}: ${o}`),void 0!==t&&(yield this.sendError(t,-32603,o)),{type:"error",code:-32603,error:o,method:s}}return void 0!==t&&(yield this.sendResult(t,{success:!0})),{type:"file_write",path:i,content:n}})}handleSessionUpdate(e){return L(this,void 0,void 0,function*(){const{params:t}=e,{sessionId:s,update:o}=t;return{type:"session_update",sessionId:s,updateData:o}})}handleRequestPermission(e){return L(this,void 0,void 0,function*(){const{id:t,params:s}=e,o=s.toolCall||{},i=s.options||[];let n,r;if(n=this.permissionMode===S.AUTO||this.permissionMode!==S.MANUAL&&this.autoApproveTypes.includes(o.type||""),n){let e;for(const t of i){const s=t.optionId||"";if("proceed_once"===s){e=s;break}"proceed_always"===s&&(e=s)}!e&&i.length>0&&(e=i[0].optionId||"proceed_once"),r={outcome:{outcome:"selected",optionId:e}}}else r={outcome:{outcome:"cancelled"}};return void 0!==t&&(yield this.sendResult(t,r)),this.logger.info(`Permission request for tool '${o.title||"unknown"}' - Response: ${r.outcome.outcome}`),{type:"tool_confirmation",params:s,response:r}})}handlePushToolCall(e){return L(this,void 0,void 0,function*(){const{id:t,params:s}=e,o=`tool_${this.nextRequestId()}`,i={id:o};return void 0!==t&&(yield this.sendResult(t,i)),{type:"tool_call",id:o,params:s}})}handleUpdateToolCall(e){return L(this,void 0,void 0,function*(){const{id:t,params:s}=e;return void 0!==t&&(yield this.sendResult(t,null)),{type:"tool_update",params:s}})}handleNotifyTaskFinish(e){return L(this,void 0,void 0,function*(){const{id:t,params:s}=e;return void 0!==t&&(yield this.sendResult(t,null)),{type:"task_finish",params:s}})}handleUnknownMessage(e){return L(this,void 0,void 0,function*(){const{id:t,method:s,params:o}=e;return this.logger.warn(`Unknown method: ${s}`),void 0!==t&&(yield this.sendError(t,-32601,"Method not found")),{type:"unknown",method:s,params:o}})}}class J{constructor(e){this.ws=null,this.connected=!1,this.url=e.url,this.logger=e.logger||z,this.timeout=e.timeout||3e5}get isConnected(){return!!this.ws&&this.connected}checkConnected(){if(!this.isConnected)throw new p("Not connected")}connect(){return L(this,void 0,void 0,function*(){if(this.connected)this.logger.warn(`Already connected to ${this.url}`);else try{this.logger.info(`Connecting to ${this.url}`),this.ws=yield new Promise((e,t)=>{const o=new s(this.url),i=setTimeout(()=>{o.close(),t(new a(`Connected to ${this.url} timeout after ${this.timeout/1e3}s`))},this.timeout);o.on("open",()=>{clearTimeout(i),this.connected=!0,this.logger.info(`Connected to ${this.url} succesfully`),e(o)}),o.on("error",e=>{clearTimeout(i),this.connected=!1,t(e)}),o.on("close",(e,s)=>{clearTimeout(i),this.connected=!1,t(new Error(`${s} (code: ${e})`))})})}catch(e){if(e instanceof a)throw e;throw new p(`Failed to connect to ${this.url}: ${H(e)}`)}})}close(){return L(this,void 0,void 0,function*(){if(this.ws&&this.connected)try{this.ws.close(),this.logger.info("Connection closed")}catch(e){this.logger.warn(`Error closing connection: ${H(e)}`)}this.ws=null,this.connected=!1})}send(e){return L(this,void 0,void 0,function*(){this.checkConnected();try{const t="string"==typeof e?e:JSON.stringify(e);yield new Promise((e,s)=>{this.ws.send(t,o=>{o?s(o):(this.logger.debug(`Sent message: ${t}`),e())})})}catch(e){throw this.connected=!1,new g(`Failed to send message: ${H(e)}`)}})}receive(){return M(this,arguments,function*(){for(this.checkConnected();this.isConnected;)try{const e=yield C(this.receiveRawData());this.logger.debug(`Received message: ${e}`),yield yield C(e)}catch(e){if(this.connected=!1,e instanceof p&&e.details.isClosed){this.logger.info("Connection closed");break}throw new g(`Failed to receive message: ${H(e)}`)}})}receiveRawData(){return new Promise((e,t)=>{if(!this.isConnected)return void t(new p("Not connected"));const s=()=>{this.ws&&(this.ws.off("close",o),this.ws.off("error",i),this.ws.off("message",n))},o=()=>{s(),this.connected=!1,t(new p("Connection closed",{isClosed:!0}))},i=e=>{s(),this.connected=!1,t(e)},n=t=>{s(),e(t.toString())};this.ws&&(this.ws.on("close",o),this.ws.on("error",i),this.ws.on("message",n))})}}class V{constructor(e={}){this.cwd=e.cwd||process.cwd(),this.logger=e.logger||z,this.readOnly=e.readOnly||!1,this.maxFileSize=e.maxFileSize||10485760,e.allowedDirs?this.allowedDirs=new Set(e.allowedDirs.map(e=>t.resolve(this.cwd,e))):this.allowedDirs=new Set([this.cwd]),this.logger.info(`File handler initialized with ${this.allowedDirs.size} allowed directories`);for(const e of this.allowedDirs)this.logger.debug(` Allowed: ${e}`)}isPathAllowed(e){try{const s=t.resolve(this.cwd,e);for(const e of this.allowedDirs)if(s.startsWith(e))return!0;return this.logger.warn(`Path not in allowed directories: ${s}`),!1}catch(e){return e instanceof Error&&this.logger.error(`Error checking path: ${e.message}`,e),!1}}readFile(s,i,n){return L(this,void 0,void 0,function*(){if(!this.isPathAllowed(s))throw new f(`Access denied: ${s}`);const r=t.resolve(this.cwd,s);try{if(!e.existsSync(r))throw new w(`File not found: ${s}`);try{yield o.access(r,e.constants.R_OK)}catch(e){throw new f(`Permission denied: ${s}`)}const t=yield o.stat(r);if(!t.isFile())throw new w(`Not a file: ${s}`);if(t.size>this.maxFileSize)throw new w(`File too large: ${t.size} bytes (max: ${this.maxFileSize})`);const l=yield o.readFile(r,"utf-8");if(void 0!==i||void 0!==n){const e=l.split("\n"),t=i?i-1:0,o=n?t+n:e.length,r=Math.max(0,t),a=Math.min(e.length,o);return this.logger.debug(`Read ${a-r} lines from ${s}`),e.slice(r,a).join("\n")}return this.logger.debug(`Read ${l.length} bytes from ${s}`),l}catch(e){if(e instanceof w||e instanceof f)throw e;throw new w(`Failed to read file: ${H(e)}`)}})}writeFile(e,s){return L(this,void 0,void 0,function*(){if(this.readOnly)throw new f("File system is in read-only mode");if(!this.isPathAllowed(e))throw new f(`Access denied: ${e}`);const i=t.resolve(this.cwd,e);try{yield o.mkdir(t.dirname(i),{recursive:!0}),yield o.writeFile(i,s,"utf-8"),this.logger.debug(`Wrote ${s.length} bytes to ${e}`)}catch(e){throw new w(`Failed to write file: ${H(e)}`)}})}addAllowedDir(s){return L(this,void 0,void 0,function*(){const i=t.resolve(this.cwd,s);try{if(!e.existsSync(i))throw new w(`Directory does not exist: ${i}`);if(!(yield o.stat(i)).isDirectory())throw new w(`Not a directory: ${i}`);this.allowedDirs.add(i),this.logger.info(`Added allowed directory: ${i}`)}catch(e){if(e instanceof w)throw e;throw new w(`Failed to add ${i} as allowed directory: ${H(e)}`)}})}removeAllowedDir(e){const s=t.resolve(this.cwd,e);this.allowedDirs.delete(s),this.logger.info(`Removed allowed directory: ${s}`)}}class X{constructor(e={}){this.port=null,this.process=null,this.iflowPath=null,this.logger=e.logger||z,this.startPort=e.startPort||8090}get url(){if(!this.port)throw new h("iFlow process not started");return`ws://localhost:${this.port}/acp`}isRunning(){return!!this.process&&!this.process.killed&&null===this.process.exitCode}which(e){try{return r.execSync(`which ${e}`,{encoding:"utf-8"}).trim()}catch(e){return null}}fileExists(t){try{return e.existsSync(t)&&e.statSync(t).isFile()}catch(e){return!1}}findIflowPath(){const e=this.which("iflow");if(e)return this.logger.debug(`Found iflow at: ${e}`),e;const s=i.homedir(),o=[t.join(s,".npm-global","bin","iflow"),"/usr/local/bin/iflow",t.join(s,".local","bin","iflow"),t.join(s,"node_modules",".bin","iflow"),t.join(s,".yarn","bin","iflow"),t.join(s,"AppData","Roaming","npm","iflow.cmd"),t.join("C:","Program Files","nodejs","iflow.cmd")];for(const e of o)if(this.fileExists(e))return this.logger.debug(`Found iflow at: ${e}`),e;const n=null!==this.which("npm"),r=null!==this.which("node");let l;throw l="win32"===i.platform()?n||r?"iFlow CLI not found. Please use the following command to install:\n npm install -g @iflow-ai/iflow-cli@latest":"iFlow requires Node.js, but it is not installed in the system.\n\nPlease install Node.js first: https://nodejs.org/\n\nAfter installing Node.js, use the following command to install iFlow:\n npm install -g @iflow-ai/iflow-cli@latest":'iFlow CLI not found. Please use the following command to install:\n\n🍎 Mac/Linux/Ubuntu users:\n bash -c "$(curl -fsSL https://cloud.iflow.cn/iflow-cli/install.sh)"\n\n🪟 Windows users:\n npm install -g @iflow-ai/iflow-cli@latest',new d(l)}isPortAvailable(e){return new Promise(t=>{const s=n.createServer();s.listen(e,"localhost",()=>{s.once("close",()=>{t(!0)}),s.close()}),s.once("error",()=>{t(!1)})})}findAvailablePort(){return L(this,void 0,void 0,function*(){for(let e=0;e<100;e++){const t=this.startPort+e;if(yield this.isPortAvailable(t))return this.logger.debug(`Found available port: ${t}`),t}throw new u(`No available port found in range ${this.startPort}-${this.startPort+100}`)})}start(){return L(this,void 0,void 0,function*(){if(this.isRunning())return this.url;this.iflowPath=this.findIflowPath(),this.port=yield this.findAvailablePort();const e=[this.iflowPath,"--experimental-acp","--port",this.port.toString()];this.logger.info(`Starting iFlow process: ${e.join(" ")}`);try{if(this.process=r.spawn(e[0],e.slice(1),{stdio:["ignore","pipe","pipe"],detached:!1}),yield new Promise(e=>setTimeout(e,500)),!this.isRunning()){let e="iFlow process exited immediately";if(this.process.stderr){const t=this.process.stderr.read();t&&(e+=`: ${t.toString("utf-8")}`)}throw new Error(e)}return this.logger.info(`iFlow process started on port ${this.port} (PID: ${this.process.pid})`),this.url}catch(e){throw this.port=null,this.process=null,new h(`Failed to start iFlow process: ${H(e)}`)}})}stop(){return L(this,void 0,void 0,function*(){if(this.process){if(!this.isRunning())return this.port=null,void(this.process=null);this.logger.info(`Stopping iFlow process (PID: ${this.process.pid})`);try{this.process.kill("SIGTERM"),yield Promise.race([new Promise(e=>{this.process?this.process.once("exit",()=>e()):e()}),new Promise(e=>setTimeout(()=>e(),5e3))]),this.isRunning()?(this.logger.warn("iFlow process did not terminate gracefully, forcing kill"),this.process.kill("SIGKILL"),yield new Promise(e=>{this.process?this.process.once("exit",()=>e()):e()})):this.logger.info("iFlow process terminated gracefully")}catch(e){this.logger.error(`Error stopping iFlow process: ${H(e)}`)}finally{this.port=null,this.process=null}}})}}var Y;!function(e){e.ERROR="error",e.RESPONSE="response",e.FILE_READ="file_read",e.FILE_WRITE="file_write",e.SESSION_UPDATE="session_update",e.TOOL_CALL="tool_call",e.TOOL_UPDATE="tool_update",e.TOOL_CONFIRMATION="tool_confirmation",e.TASK_FINISH="task_finish",e.UNKNOWN="unknown"}(Y||(Y={}));class B{constructor(e={}){this.protocol=null,this.transport=null,this.connected=!1,this.authenticated=!1,this.messageTask=null,this.messageQueue=[],this.pendingToolCalls=new Map,this.url=null,this.sessionId=null,this.processManager=null,this.processStarted=!1,this.options=Object.assign({url:"ws://localhost:8090/acp",cwd:process.cwd(),timeout:3e4,logLevel:"INFO",fileMaxSize:10485760,permissionMode:S.AUTO,autoApproveTypes:["read","fetch","list"],authMethodId:"iflow",autoStartProcess:!0,processStartPort:8090},e),this.logger=new W({level:this.options.logLevel})}connect(){return L(this,void 0,void 0,function*(){var e,t;if(this.connected)this.logger.warn("Already connected");else try{if(this.options.autoStartProcess&&((null===(e=this.options.url)||void 0===e?void 0:e.startsWith("ws://localhost:"))||(null===(t=this.options.url)||void 0===t?void 0:t.startsWith("ws://127.0.0.1:")))){const e=new J({url:this.options.url,logger:this.logger,timeout:2e3});try{yield e.connect(),yield e.close(),this.url=this.options.url,this.logger.info(`iFlow already running at ${this.options.url}`)}catch(e){this.logger.info("iFlow not running, starting process..."),this.processManager=new X({logger:this.logger,startPort:this.options.processStartPort});try{const e=yield this.processManager.start();this.url=e,this.processStarted=!0,this.logger.info(`Started iFlow process at ${e}`),yield new Promise(e=>setTimeout(e,1e3))}catch(e){throw e instanceof d?(this.logger.error("iFlow not installed"),d):(this.logger.error(`Failed to start iFlow process: ${H(e)}`),new p(`Failed to start iFlow process: ${H(e)}`))}}}let s=null;this.options.fileAccess&&(s=new V({cwd:this.options.cwd,logger:this.logger,readOnly:this.options.fileReadOnly,maxFileSize:this.options.fileMaxSize,allowedDirs:this.options.fileAllowedDirs}),this.logger.info(`File system access enabled with ${this.options.fileReadOnly?"read-only":"read-write"} mode`)),this.transport=new J({url:this.options.url,logger:this.logger,timeout:this.options.timeout}),this.protocol=new K({logger:this.logger,transport:this.transport,fileHandler:s,permissionMode:this.options.permissionMode,autoApproveTypes:this.options.autoApproveTypes}),yield this.transport.connect();const o=yield this.protocol.initialize({mcpServers:this.options.mcpServers,hooks:this.options.hooks,commands:this.options.commands,agents:this.options.agents});this.authenticated=o.isAuthenticated||!1,this.authenticated||(yield this.protocol.authenticate({methodId:this.options.authMethodId,methodInfo:this.options.authMethodInfo}),this.authenticated=!0),this.sessionId=yield this.protocol.createSession({cwd:this.options.cwd||process.cwd(),mcpServers:this.options.mcpServers,hooks:this.options.hooks,commands:this.options.commands,agents:this.options.agents,settings:this.options.sessionSettings}),this.connected=!0,this.messageTask=this.handleMessages(),this.logger.info("Connected to iFlow")}catch(e){throw yield this.disconnect(),new p(`Failed to connect: ${H(e)}`)}})}loadSession(e){return L(this,void 0,void 0,function*(){if(!this.connected||!this.protocol)throw new p("Not connected. Call connect() first.");yield this.protocol.loadSession({sessionId:e,cwd:this.options.cwd||process.cwd(),mcpServers:this.options.mcpServers}),this.sessionId=e,this.logger.info(`Loaded session: ${e}`)})}disconnect(){return L(this,void 0,void 0,function*(){this.connected=!1,this.transport&&(yield this.transport.close()),this.processManager&&this.processStarted&&(yield this.processManager.stop()),this.url=null,this.protocol=null,this.transport=null,this.messageTask=null,this.authenticated=!1,this.processManager=null,this.processStarted=!1,this.logger.info("Disconnected from iFlow")})}sendMessage(s,o){return L(this,void 0,void 0,function*(){if(!this.connected||!this.protocol||!this.sessionId)throw new p("Not connected. Call connect() first.");const i=[{type:"text",text:s}];if(null==o?void 0:o.length)for(const s of o){const o=t.resolve(this.options.cwd||process.cwd(),s),n=t.parse(s);if(!e.existsSync(o)){this.logger.warn(`File not found, skipping: ${o}`);continue}const r=n.ext.toLowerCase();if([".png",".jpg",".jpeg",".gif",".bmp",".webp",".svg"].includes(r))try{const t=e.readFileSync(o).toString("base64"),s={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".bmp":"image/bmp",".webp":"image/webp",".svg":"image/svg+xml"};i.push({type:"image",data:t,mimeType:s[r]||"image/unknown"}),this.logger.debug(`Added image file: ${n.base}`)}catch(e){this.logger.error(`Failed to read image file ${o}: ${H(e)}`);continue}else if([".mp3",".wav",".m4a",".ogg",".flac"].includes(r))try{const t=e.readFileSync(o).toString("base64"),s={".mp3":"audio/mpeg",".wav":"audio/wav",".m4a":"audio/mp4",".ogg":"audio/ogg",".flac":"audio/flac"};i.push({type:"audio",data:t,mimeType:s[r]||"audio/unknown"}),this.logger.debug(`Added audio file: ${n.base}`)}catch(e){this.logger.error(`Failed to read audio file ${o}: ${H(e)}`);continue}else{const t=e.statSync(o);i.push({type:"resource_link",uri:`file://${o}`,name:n.base,title:n.name,size:t.size}),this.logger.debug(`Added resource link: ${n.base}`)}}yield this.protocol.sendPrompt({sessionId:this.sessionId,prompt:i})})}interrupt(){return L(this,void 0,void 0,function*(){if(!this.connected||!this.protocol||!this.sessionId)throw new p("Not connected");yield this.protocol.cancelSession({sessionId:this.sessionId}),this.logger.info("Sent interrupt signal")})}receiveMessages(){return M(this,arguments,function*(){if(!this.connected)throw new p("Not connected");for(;this.connected;)try{this.messageQueue.length>0?yield yield C(this.messageQueue.shift()):yield C(new Promise(e=>setTimeout(e,100)))}catch(e){continue}})}approveToolCall(e){return L(this,arguments,void 0,function*(e,t=P.ALLOW){if(!this.pendingToolCalls.has(e))throw new Error(`Unknown tool call: ${e}`);this.logger.info(`Approved tool call ${e} with outcome ${t}`),this.pendingToolCalls.delete(e)})}rejectToolCall(e){return L(this,void 0,void 0,function*(){if(!this.pendingToolCalls.has(e))throw new Error(`Unknown tool call: ${e}`);this.logger.info(`Rejected tool call ${e}`),this.pendingToolCalls.delete(e)})}handleMessages(){return L(this,void 0,void 0,function*(){var e,t,s,o;if(this.protocol)try{try{for(var i,n=!0,r=b(this.protocol.handleMessages());!(e=(i=yield r.next()).done);n=!0){o=i.value,n=!1;const e=o,t=this.processProtocolMessage(e);t&&this.messageQueue.push(t)}}catch(e){t={error:e}}finally{try{n||e||!(s=r.return)||(yield s.call(r))}finally{if(t)throw t.error}}}catch(e){this.logger.error(`Error in message handler: ${H(e)}`);const t={type:F.ERROR,code:-1,message:String(H(e))};this.messageQueue.push(t)}})}processProtocolMessage(e){var t,s,o;switch(e.type){case Y.SESSION_UPDATE:{const{updateData:i}=e;let n,r;switch("agentId"in i&&i.agentId&&(n=i.agentId,r=function(e){const t=e.split("-");return"subagent"!==t[0]||t.length<4?{agentId:e}:4===t.length?{agentId:e,taskId:["null","undefined"].includes(t[1])?void 0:t[1],agentIndex:parseInt(t[2])||void 0,timestamp:parseInt(t[3])||void 0}:{agentId:e,taskId:t.slice(1,-2).join("-"),agentIndex:parseInt(t[t.length-2])||void 0,timestamp:parseInt(t[t.length-1])||void 0}}(n)),i.sessionUpdate){case j.PLAN:{const e=null===(t=i.entries)||void 0===t?void 0:t.map(e=>({content:e.content||"",status:e.status||A.PENDING,priority:e.priority||T.MEDIUM}));return e&&(null==e?void 0:e.length)>0?{type:F.PLAN,entries:e}:null}case j.TOOL_CALL:{const e={type:F.TOOL_CALL,id:i.toolCallId||"",label:i.title||"Tool",icon:{type:$.EMOJI,value:"🔧"},status:i.status||O.IN_PROGRESS,toolName:i.toolName};return n&&(e.agentId=n,e.agentInfo=r),this.pendingToolCalls.set(e.id,e),e}case j.TOOL_CALL_UPDATE:{const e=i.toolCallId;let t;if(this.pendingToolCalls.has(e)?(t=this.pendingToolCalls.get(e),t.status=i.status||O.COMPLETED,i.toolName&&(t.toolName=i.toolName),!t.agentId&&n&&(t.agentId=n),!t.agentInfo&&r&&(t.agentInfo=r)):(t={type:F.TOOL_CALL,id:e,label:i.title||"Tool",icon:{type:$.EMOJI,value:"🔧"},status:i.status||O.COMPLETED,toolName:i.toolName},n&&(t.agentId=n,t.agentInfo=r),this.pendingToolCalls.set(e,t)),i.content&&(null===(s=i.content)||void 0===s?void 0:s.length)>0){let e;const s=[];for(const t of i.content)"args"in t&&(e=t.args),"content"===t.type&&"text"===(null===(o=t.content)||void 0===o?void 0:o.type)&&s.push(t.content.text||"");void 0!==e&&(t.args=e),s.length>0&&(t.output=s.join("\n"))}return t}case j.USER_MESSAGE_CHUNK:{const e=i.content;if("text"===(null==e?void 0:e.type)){const t=e.text||"";if(t)return{type:F.USER,chunks:[{text:t}]}}return null}case j.AGENT_MESSAGE_CHUNK:{const e=i.content;if("text"===(null==e?void 0:e.type)){const t=e.text||"";if(t){const e={type:F.ASSISTANT,chunk:{text:t}};return n&&(e.agentId=n,e.agentInfo=r),e}}return null}case j.AGENT_THOUGHT_CHUNK:{const e=i.content;if("text"===(null==e?void 0:e.type)){const t=e.text||"";if(t){const e={type:F.ASSISTANT,chunk:{thought:t}};return n&&(e.agentId=n,e.agentInfo=r),e}}}default:return null}}case Y.RESPONSE:return"stopReason"in(e.result||{})?{type:F.TASK_FINISH,stopReason:e.result.stopReason}:null;case Y.ERROR:return{type:F.ERROR,code:e.code||-1,message:e.error||"Unknown error"};default:return null}}}function Z(e){let t,s=!1,o="text";if(e.startsWith("//"))s=!0,o="control";else try{t=JSON.parse(e),t&&"method"in t?o=`method:${t.method}`:t&&("result"in t||"error"in t)?o="response":t&&"type"in t&&(o=t.type)}catch(e){}return{isControl:s,messageType:o,rawData:e,jsonData:t,timestamp:Date.now()}}class ee extends B{constructor(e,t=!0){super(e),this.rawQueue=[],this.rawHistory=[],this.rawQueueResolvers=[],this.messageQueueResolvers=[],this.captureRaw=t}handleMessages(){const e=Object.create(null,{handleMessages:{get:()=>super.handleMessages}});return L(this,void 0,void 0,function*(){if(this.protocol)try{if(this.captureRaw&&this.transport){const e=this.captureRawStream(),t=this.handleParsedStream();yield Promise.all([e,t])}else yield e.handleMessages.call(this)}catch(e){this.logger.error(`Error in message handler: ${H(e)}`)}})}captureRawStream(){return L(this,void 0,void 0,function*(){var e,t,s,o;if(this.transport)try{try{for(var i,n=!0,r=b(this.transport.receive());!(e=(i=yield r.next()).done);n=!0){o=i.value,n=!1;const e=o,t=Z("string"==typeof e?e:JSON.stringify(e));this.rawQueue.push(t),this.rawHistory.push(t);const s=this.rawQueueResolvers.shift();s&&s(t)}}catch(e){t={error:e}}finally{try{n||e||!(s=r.return)||(yield s.call(r))}finally{if(t)throw t.error}}}catch(e){this.logger.error(`Error capturing raw stream: ${H(e)}`)}})}handleParsedStream(){return L(this,void 0,void 0,function*(){var e,t,s,o;if(this.protocol)try{for(var i,n=!0,r=b(this.protocol.handleMessages());!(e=(i=yield r.next()).done);n=!0){o=i.value,n=!1;const e=o,t=this.processProtocolMessage(e);if(t){const e=this.messageQueueResolvers.shift();e&&e(t)}}}catch(e){t={error:e}}finally{try{n||e||!(s=r.return)||(yield s.call(r))}finally{if(t)throw t.error}}})}receiveRawMessages(){return M(this,arguments,function*(){for(;this.connected||this.rawQueue.length>0;)try{if(this.rawQueue.length>0)yield yield C(this.rawQueue.shift());else{const e=yield C(Promise.race([new Promise(e=>{this.rawQueueResolvers.push(e)}),new Promise((e,t)=>{setTimeout(()=>t(new Error("Timeout")),100)})]));yield yield C(e)}}catch(e){if(e instanceof Error&&"Timeout"===e.message)continue;throw e}})}receiveDualStream(){return M(this,arguments,function*(){const e=[],t=[];for(;this.connected||this.rawQueue.length>0||e.length>0||t.length>0;)try{let e,t;e=this.rawQueue.length>0?this.rawQueue.shift():yield C(Promise.race([new Promise(e=>{this.rawQueueResolvers.push(e)}),new Promise((e,t)=>{setTimeout(()=>t(new Error("Timeout")),10)})]));try{t=yield C(Promise.race([new Promise(e=>{this.messageQueueResolvers.push(e)}),new Promise((e,t)=>{setTimeout(()=>t(new Error("Timeout")),10)})]))}catch(e){}e.parsedMessage=t,yield yield C([e,t])}catch(e){if(!(e instanceof Error&&"Timeout"===e.message))throw e;try{const e=yield C(Promise.race([new Promise(e=>{this.messageQueueResolvers.push(e)}),new Promise((e,t)=>{setTimeout(()=>t(new Error("Timeout")),10)})])),t=Z("<no-raw-data>");t.messageType="parsed_only",yield yield C([t,e])}catch(e){if(e instanceof Error&&"Timeout"===e.message)continue;throw e}}})}getRawHistory(){return[...this.rawHistory]}getProtocolStats(){const e={totalMessages:this.rawHistory.length,messageTypes:{},controlMessages:0,jsonMessages:0,textMessages:0,errors:0};for(const t of this.rawHistory)t.messageType&&(e.messageTypes[t.messageType]=(e.messageTypes[t.messageType]||0)+1),t.isControl?e.controlMessages++:t.jsonData?e.jsonMessages++:e.textMessages++,t.jsonData&&"error"in t.jsonData&&e.errors++;return e}sendRaw(e){return L(this,void 0,void 0,function*(){if(!this.transport)throw new Error("Not connected");yield this.transport.send(e);const t="string"==typeof e?e:JSON.stringify(e).substring(0,100);this.logger.info(`Sent raw data: ${t}`)})}}function te(e,t,s){return L(this,void 0,void 0,function*(){var o,i,n,r;const l=[],a=new B(s);yield a.connect();try{yield a.sendMessage(e,t);try{for(var c,d=!0,h=b(a.receiveMessages());!(o=(c=yield h.next()).done);d=!0){r=c.value,d=!1;const e=r;if(e.type===F.ASSISTANT&&e.chunk.text)l.push(e.chunk.text);else if(e.type===F.TASK_FINISH)break}}catch(e){i={error:e}}finally{try{d||o||!(n=h.return)||(yield n.call(h))}finally{if(i)throw i.error}}}finally{yield a.disconnect()}return l.join("")})}function se(e,t,s){return M(this,arguments,function*(){var o,i,n,r;const l=new B(s);yield C(l.connect());try{yield C(l.sendMessage(e,t));try{for(var a,c=!0,d=b(l.receiveMessages());!(o=(a=yield C(d.next())).done);c=!0){r=a.value,c=!1;const e=r;if(e.type===F.ASSISTANT&&e.chunk.text)yield yield C(e.chunk.text);else if(e.type===F.TASK_FINISH)break}}catch(e){i={error:e}}finally{try{c||o||!(n=d.return)||(yield C(n.call(d)))}finally{if(i)throw i.error}}}finally{yield C(l.disconnect())}})}export{E as ApprovalMode,y as AuthenticationError,p as ConnectionError,I as HookEventType,B as IFlowClient,l as IFlowError,d as IFlowNotInstalledError,h as IFlowProcessError,c as JSONDecodeError,v as LogLevel,F as MessageType,f as PermissionError,S as PermissionMode,T as PlanPriority,A as PlanStatus,u as PortNotAvailableError,m as ProtocolError,ee as RawDataClient,_ as StopReason,a as TimeoutError,P as ToolCallConfirmationOutcome,N as ToolCallConfirmationType,R as ToolCallContentType,$ as ToolCallIconType,O as ToolCallStatus,g as TransportError,w as ValidationError,te as query,se as queryStream};
|