@iflow-ai/iflow-cli-sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README_CN.md ADDED
@@ -0,0 +1,401 @@
1
+ # iFlow CLI TypeScript SDK
2
+
3
+ [![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
4
+ [![WebSocket Protocol](https://img.shields.io/badge/protocol-ACP%20v1-orange)](docs/protocol.md)
5
+
6
+ [English](README.md) | [中文](README_CN.md)
7
+
8
+ 一个强大的 TypeScript SDK,使用代理通信协议(ACP)与 iFlow CLI 进行交互。构建具有对话、工具执行和子代理编排完全控制的 AI 驱动应用程序。
9
+
10
+ **✨ 核心特性:SDK 自动管理 iFlow 进程 - 无需手动配置!**
11
+
12
+ ## 功能特性
13
+
14
+ - 🚀 **自动进程管理** - 零配置设置!SDK 自动启动和管理 iFlow CLI
15
+ - 🔌 **智能端口检测** - 自动查找可用端口,无冲突
16
+ - 🔄 **双向通信** - 实时流式传输消息和响应
17
+ - 🛠️ **工具调用管理** - 通过细粒度权限处理和控制工具执行
18
+ - 🤖 **子代理支持** - 通过 `agentId` 传播跟踪和管理多个 AI 代理
19
+ - 📋 **任务规划** - 接收和处理结构化任务计划
20
+ - 🔍 **原始数据访问** - 调试和检查协议级消息
21
+ - ⚡ **异步支持** - 现代异步 Python,完整类型提示
22
+ - 🎯 **简单和高级 API** - 从一行查询到复杂对话管理
23
+ - 📦 **完整 ACP v1 协议** - 代理通信协议的完整实现
24
+ - 🚦 **高级审批模式** - 包括 DEFAULT、AUTO_EDIT、YOLO 和 PLAN 模式
25
+ - 🔗 **MCP 服务器集成** - 支持模型上下文协议服务器
26
+ - 🪝 **生命周期钩子** - 在对话的不同阶段执行命令
27
+ - 🎮 **会话设置** - 对模型行为和工具的细粒度控制
28
+ - 🤖 **自定义代理** - 定义具有自定义提示和工具的专用代理
29
+
30
+ ## 安装
31
+
32
+ ### 1. 安装 iFlow CLI
33
+
34
+ 如果您还没有安装 iFlow CLI:
35
+
36
+ **Mac/Linux/Ubuntu:**
37
+
38
+ ```bash
39
+ bash -c "$(curl -fsSL https://cloud.iflow.cn/iflow-cli/install.sh)"
40
+ ```
41
+
42
+ **Windows:**
43
+
44
+ ```bash
45
+ npm install -g @iflow-ai/iflow-cli@latest
46
+ ```
47
+
48
+ ### 2. 安装 SDK
49
+
50
+ **Install from NPM:**
51
+
52
+ ```bash
53
+ npm install --save @iflow-ai/iflow-cli-sdk
54
+ ```
55
+
56
+ ## 快速开始
57
+
58
+ SDK **自动管理 iFlow 进程** - 无需手动设置!
59
+
60
+ ### 默认用法(自动进程管理)
61
+
62
+ ```ts
63
+ import { IFlowClient } from "@iflow-ai/iflow-cli-sdk";
64
+
65
+ async function main() {
66
+ // SDK automatically:
67
+ // 1. Detects if iFlow is installed
68
+ // 2. Starts iFlow process if not running
69
+ // 3. Finds an available port
70
+ // 4. Cleans up on exit
71
+ const client = new IFlowClient();
72
+
73
+ await client.connect();
74
+ await client.sendMessage("Hello, iFlow!");
75
+
76
+ for await (const message in client.receiveMessages()) {
77
+ console.log(message);
78
+ // Process messages...
79
+ }
80
+ }
81
+ ```
82
+
83
+ **无需手动启动 iFlow!** SDK 为您处理一切。
84
+
85
+ ### 高级:手动进程控制
86
+
87
+ 如果您需要自己管理 iFlow:
88
+
89
+ ```ts
90
+ import { IFlowClient } from "@iflow-ai/iflow-cli-sdk";
91
+
92
+ async function main() {
93
+ // Disable automatic process management
94
+ const client = new IFlowClient({
95
+ url: "ws://localhost:8090/acp", // Connect to existing iFlow
96
+ autoStartProcess: false,
97
+ });
98
+
99
+ await client.connect();
100
+ await client.sendMessage("Hello, iFlow!");
101
+ }
102
+ ```
103
+
104
+ **注意:** 手动模式需要您单独启动 iFlow:
105
+
106
+ ```bash
107
+ iflow --experimental-acp --port 8090
108
+ ```
109
+
110
+ ### 简单示例
111
+
112
+ #### 简单查询
113
+
114
+ ```ts
115
+ import { query } from "@iflow-ai/iflow-cli-sdk";
116
+
117
+ async function main() {
118
+ const response = await query("What is the capital of France?");
119
+ console.log(response); // "The capital of France is Paris."
120
+ }
121
+ ```
122
+
123
+ #### 交互式对话
124
+
125
+ ```ts
126
+ import { IFlowClient, MessageType } from "@iflow-ai/iflow-cli-sdk";
127
+
128
+ async function main() {
129
+ const client = new IFlowClient();
130
+
131
+ await client.connect();
132
+ await client.sendMessage("Explain quantum computing");
133
+
134
+ for await (const message in client.receiveMessages()) {
135
+ if (message.type === MessageType.ASSISTANT && message.chunk.text) {
136
+ console.log(message.chunk.text);
137
+ } else if (message.type === MessageType.TASK_FINISH) {
138
+ break;
139
+ }
140
+ }
141
+ }
142
+ ```
143
+
144
+ #### 工具调用控制与代理信息
145
+
146
+ ```ts
147
+ import { IFlowClient, PermissionMode, MessageType } from "@iflow-ai/iflow-cli-sdk";
148
+
149
+ async function main() {
150
+ const client = new IFlowClient({
151
+ permissionMode: PermissionMode.AUTO,
152
+ })
153
+
154
+ await client.connect();
155
+ await client.sendMessage("Create a file called test.txt");
156
+
157
+ for await (const message in client.receiveMessages()) {
158
+ if (message.type === MessageType.TOOL_CALL) {
159
+ console.log(`Tool name: ${message.toolName}`);
160
+ console.log(`Tool status: ${message.status}`);
161
+
162
+ if (message.agentInfo) {
163
+ console.log(`Agent ID: ${message.agentInfo.agentId}`);
164
+ console.log(`Task ID: ${message.agentInfo.taskId}`);
165
+ console.log(`Agent index: ${message.agentInfo.agentIndex}`);
166
+ }
167
+
168
+ if (message.args) {
169
+ console.log(message.args);
170
+ }
171
+ if (message.output) {
172
+ console.log(message.output);
173
+ }
174
+ } else if (message.type === MessageType.TASK_FINISH) {
175
+ break;
176
+ }
177
+ }
178
+ }
179
+ ```
180
+
181
+ #### 使用 AgentInfo
182
+
183
+ ```ts
184
+ import { IFlowClient, MessageType } from "@iflow-ai/iflow-cli-sdk";
185
+
186
+ const options: IFlowOptions = {
187
+ agents: [
188
+ {
189
+ agentType: "code-reviewer",
190
+ name: "reviewer",
191
+ description: "Code review specialist",
192
+ whenToUse: "For code review and quality checks",
193
+ allowedTools: ["fs", "grep"],
194
+ allowedMcps: ["eslint", "prettier"],
195
+ systemPrompt: "You are a code review expert.",
196
+ proactive: False,
197
+ location: "project",
198
+ },
199
+ {
200
+ agentType: "test-writer",
201
+ name: "tester",
202
+ description: "Test writing specialist",
203
+ whenToUse: "For writing unit and integration tests",
204
+ allowedTools: ["fs", "bash"],
205
+ systemPrompt: "You are a test writing expert.",
206
+ location: "project",
207
+ },
208
+ ],
209
+ };
210
+
211
+ async function main() {
212
+ const client = new IFlowClient(options)
213
+
214
+ await client.connect();
215
+ await client.sendMessage("$test-writer Write a unit test");
216
+
217
+ for await (const message in client.receiveMessages()) {
218
+ if (message.type === MessageType.TOOL_CALL) {
219
+ console.log(`Tool name: ${message.toolName}`);
220
+
221
+ if (message.args) {
222
+ console.log(message.args);
223
+ }
224
+ if (message.output) {
225
+ console.log(message.output);
226
+ }
227
+ } if (message.type === MessageType.ASSISTANT && message.chunk.text) {
228
+ console.log(message.chunk.text);
229
+ } else if (message.type === MessageType.TASK_FINISH) {
230
+ break;
231
+ }
232
+ }
233
+ }
234
+ ```
235
+
236
+ #### 高级协议特性
237
+
238
+ ```ts
239
+ import { IFlowClient, IFlowOptions, ApprovalMode, HookEventType } from "@iflow-ai/iflow-cli-sdk";
240
+
241
+ const options: IFlowOptions = {
242
+ mcpServers: [
243
+ {
244
+ name: "filesystem",
245
+ command: "mcp-server-filesystem",
246
+ args: ["--allowed-dirs", "/workspace"],
247
+ env: [
248
+ {
249
+ name: "DEBUG",
250
+ value: "1",
251
+ },
252
+ ],
253
+ },
254
+ ],
255
+
256
+ sessionSettings: {
257
+ allowed_tools: ["read_file", "write_file", "execute_code"],
258
+ system_prompt: "You are an expert Python developer",
259
+ permission_mode: ApprovalMode.AUTO_EDIT,
260
+ max_turns: 100,
261
+ },
262
+
263
+ hooks: {
264
+ [HookEventType.PRE_TOOL_USE]: [
265
+ {
266
+ hooks: {
267
+ command: "echo 'Processing request...'",
268
+ timeout: 5,
269
+ },
270
+ },
271
+ ],
272
+ },
273
+
274
+ commands: [
275
+ {
276
+ name: "test",
277
+ content: "pytest --verbose",
278
+ },
279
+ ],
280
+
281
+ agents: [
282
+ {
283
+ agentType: "python-expert",
284
+ whenToUse: "For Python development tasks",
285
+ allowedTools: ["edit_file", "run_python", "debug"],
286
+ systemPrompt: "You are a Python expert focused on clean, efficient code",
287
+ name: "Python Expert",
288
+ description: "Specialized in Python development",
289
+ },
290
+ ],
291
+ };
292
+
293
+ async function main() {
294
+ const client = new IFlowClient(options);
295
+
296
+ await client.connect();
297
+ await client.sendMessage("$test-writer Write a unit test");
298
+
299
+ // Process responses...
300
+ }
301
+ ```
302
+
303
+ ## API 参考
304
+
305
+ ### 核心类
306
+
307
+ - **`IFlowClient`**: 双向通信的主客户端
308
+ - **`IFlowOptions`**: 配置选项
309
+ - **`RawDataClient`**: 访问原始协议数据
310
+
311
+ ### 消息类型
312
+
313
+ - **`AssistantMessage`**: AI 助手响应,包含可选的代理信息
314
+ - **`ToolCallMessage`**: 工具执行请求,包含执行详情(toolName, args, output)和代理信息
315
+ - **`PlanMessage`**: 带优先级和状态的结构化任务计划
316
+ - **`TaskFinishMessage`**: 带停止原因的任务完成信号 (end_turn, max_tokens, refusal, cancelled)
317
+
318
+ ### 代理信息
319
+
320
+ - **`AgentInfo`**: 从 iFlow 的 agentId 格式提取的代理元数据(agent_id, task_id, agent_index, timestamp)
321
+
322
+ ### 便捷函数
323
+
324
+ - `query(prompt)`: 简单同步查询
325
+ - `querySync(prompt)`: 带超时的同步查询
326
+ - `queryStream(prompt)`: 流式响应
327
+
328
+ ## 项目结构
329
+
330
+ ```
331
+ src/
332
+ ├── internals/
333
+ │ ├── FileHandler.ts # 文件访问处理器
334
+ │ ├── ProcessManager.ts # iFlow 进程管理
335
+ │ ├── Protocol.ts # ACP 协议处理器
336
+ │ └── Transport.ts # WebSocket 传输层
337
+ ├── types/
338
+ │ ├── acp.ts # ACP 数据类型
339
+ │ ├── messages.ts # 消息类型
340
+ │ └── options.ts # iFlow 选项的类型
341
+ ├── utils/
342
+ │ ├── logger.ts # 日志
343
+ │ └── parseAgentId.ts # 解析 agent id
344
+ ├── IFlowClient.ts # 主 IFlowClient 实现
345
+ ├── RawDataClient.ts # 原始协议访问
346
+ ├── query.ts # 简单查询函数
347
+ └── index.ts # 主导出文件
348
+ ```
349
+
350
+ ## 开发
351
+
352
+ ### 运行测试
353
+
354
+ ```bash
355
+ npm test
356
+ ```
357
+
358
+ ### 代码质量
359
+
360
+ ```bash
361
+ # 代码检查
362
+ npm run lint
363
+
364
+ # 格式化代码
365
+ npm run format
366
+ ```
367
+
368
+ ## 协议支持
369
+
370
+ SDK 实现了代理通信协议(ACP)v1 并支持完整的扩展功能,包括:
371
+
372
+ - **会话管理**:创建、加载和管理带有高级设置的对话会话
373
+ - **消息类型**:
374
+ - `agent_message_chunk` - 助手响应
375
+ - `agent_thought_chunk` - 内部推理
376
+ - `tool_call` / `tool_call_update` - 工具执行生命周期
377
+ - `plan` - 带优先级的结构化任务规划
378
+ - `user_message_chunk` - 用户消息回显
379
+ - `stop_reason` - 任务完成原因(end_turn、max_tokens、refusal、cancelled)
380
+ - **身份验证**:内置 iFlow 身份验证并支持令牌
381
+ - **文件系统访问**:可配置限制的读/写文件权限
382
+ - **子代理支持**:完整的 `agentId` 跟踪和管理
383
+ - **高级功能**:
384
+ - **MCP 服务器**:集成模型上下文协议服务器以扩展功能
385
+ - **审批模式**:DEFAULT、AUTO_EDIT、YOLO(自动批准所有)、PLAN 模式
386
+ - **会话设置**:控制允许的工具、系统提示、模型选择
387
+ - **生命周期钩子**:在对话的不同阶段执行命令
388
+ - **自定义命令**:定义和执行自定义命令
389
+ - **专用代理**:创建具有特定专业知识和工具访问权限的代理
390
+
391
+ ## 贡献
392
+
393
+ 欢迎贡献!请参阅 [CONTRIBUTING.md](CONTRIBUTING.md) 了解指南。
394
+
395
+ ## 许可证
396
+
397
+ 本项目根据 MIT 许可证授权 - 详情请参阅 [LICENSE](LICENSE) 文件。
398
+
399
+ ---
400
+
401
+ 用 ❤️ 为 AI 开发社区构建
@@ -0,0 +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};