npm package: @iflow-ai/iflow-cli-sdk
Description: TypeScript SDK for iFlow CLI
Latest version: 0.2.2

# iFlow CLI TypeScript SDK

[![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
[![WebSocket Protocol](https://img.shields.io/badge/protocol-ACP%20v1-orange)](docs/protocol.md)

[English](README.md) | [中文](README_CN.md)

A powerful TypeScript SDK for interacting with iFlow CLI using the Agent Communication Protocol (ACP). Build AI-powered applications with full control over conversations, tool execution, and SubAgent orchestration.

**✨ Key Feature: The SDK automatically manages the iFlow process - no manual setup required!**

## Features

- 🚀 **Automatic Process Management** - Zero-config setup! SDK auto-starts and manages iFlow CLI
- 🔌 **Smart Port Detection** - Automatically finds available ports, no conflicts
- 🔄 **Bidirectional Communication** - Real-time streaming of messages and responses
- 🛠️ **Tool Call Management** - Handle and control tool executions
- 🔐 **Permission Request Handling** - Manage and respond to tool execution permission requests
- 💬 **Interactive Questions** - AI can ask users questions during execution
- 📝 **Plan Approval** - Review and approve AI plans before execution
- ⚡ **Async/Await Support** - Modern asynchronous TypeScript with full type hints
- 🎯 **Simple & Advanced APIs** - From one-line queries to complex conversation management

## Installation

### 1. Install iFlow CLI

If you haven't installed iFlow CLI yet:

**Mac/Linux/Ubuntu:**

```bash
bash -c "$(curl -fsSL https://cloud.iflow.cn/iflow-cli/install.sh)"
```

**Windows:**

```bash
npm install -g @iflow-ai/iflow-cli@latest
```

### 2. Install the SDK

**Install from NPM:**

```bash
npm install --save @iflow-ai/iflow-cli-sdk
```

## Quick Start

The SDK **automatically manages the iFlow process** - no manual setup required!

```ts
import { IFlowClient } from "@iflow-ai/iflow-cli-sdk";

async function main() {
  // SDK automatically:
  // 1. Detects if iFlow is installed
  // 2. Starts iFlow process if not running
  // 3. Finds an available port
  // 4. Cleans up on exit
  const client = new IFlowClient();

  await client.connect();
  await client.sendMessage("Hello, iFlow!");

  for await (const message of client.receiveMessages()) {
    console.log(message);
    // Process messages...
  }

  await client.disconnect();
}
```

**No need to manually start iFlow!** The SDK handles everything for you.

## Examples

### Simple Query

Use the convenience function for one-off queries:

```ts
import { query } from "@iflow-ai/iflow-cli-sdk";

const response = await query("What is the capital of France?");
console.log(response);
```

### Interactive Conversation

For more control over the conversation:

```ts
import { IFlowClient } from "@iflow-ai/iflow-cli-sdk";

const client = new IFlowClient();

await client.connect();
await client.sendMessage("Explain quantum computing");

for await (const message of client.receiveMessages()) {
  if (message.type === "assistant" && message.chunk.text) {
    console.log(message.chunk.text);
  } else if (message.type === "task_finish") {
    break;
  }
}

await client.disconnect();
```

### Tool Call Monitoring

Monitor tool executions:

```ts
import { IFlowClient } from "@iflow-ai/iflow-cli-sdk";

const client = new IFlowClient({ permissionMode: "auto" });

await client.connect();
await client.sendMessage("Create a file called test.txt");

for await (const message of client.receiveMessages()) {
  if (message.type === "tool_call") {
    console.log(`Tool: ${message.toolName}, Status: ${message.status}`);
    if (message.output) {
      console.log(`Output: ${message.output}`);
    }
  } else if (message.type === "task_finish") {
    break;
  }
}

await client.disconnect();
```

### Enhanced File Types

The SDK supports multiple file types beyond simple file paths:

```ts
import { IFlowClient } from "@iflow-ai/iflow-cli-sdk";

const client = new IFlowClient();
await client.connect();

// 1. Use image data
const image = {
  type: "image" as const,
  data: "base64-encoded-image-data",
  mimeType: "image/png"
};
await client.sendMessage("Analyze this image", [image]);

// 2. Use text selection
const selection = {
  type: "selection" as const,
  data: "const sum = (a, b) => a + b;",
  uri: "file:///path/to/file.ts",
  line: { start: 1, end: 2 }
};
await client.sendMessage("Explain this code", [selection]);

// 3. Mix different file types
await client.sendMessage("Analyze these files", [
  "package.json",  // File path
  image,          // Image data
  selection       // Text selection
]);

await client.disconnect();
```

### Interactive Questions

Handle AI questions during execution:

```ts
import { IFlowClient } from "@iflow-ai/iflow-cli-sdk";

const client = new IFlowClient();
await client.connect();
await client.sendMessage("Help me create a web server");

for await (const message of client.receiveMessages()) {
  if (message.type === "ask_user_questions") {
    // Display questions
    message.questions.forEach(q => {
      console.log(`${q.question}`);
      q.options.forEach(opt => console.log(`- ${opt.label}`));
    });

    // Collect and send answers
    const answers = {
      [message.questions[0].header]: message.questions[0].options[0].label
    };
    await client.respondToAskUserQuestions(answers);
  } else if (message.type === "task_finish") {
    break;
  }
}

await client.disconnect();
```

### Plan Approval

Review and approve AI plans:

```ts
import { IFlowClient } from "@iflow-ai/iflow-cli-sdk";

const client = new IFlowClient();
await client.connect();
await client.sendMessage("Refactor the authentication module");

for await (const message of client.receiveMessages()) {
  if (message.type === "exit_plan_mode") {
    console.log("AI Plan:", message.plan);
    
    // Approve or reject the plan
    const approved = true;
    await client.respondToExitPlanMode(approved);
  } else if (message.type === "task_finish") {
    break;
  }
}

await client.disconnect();
```

### Permission Request Handling

Handle tool execution permission requests from AI:

```ts
import { IFlowClient } from "@iflow-ai/iflow-cli-sdk";

const client = new IFlowClient();
await client.connect();
await client.sendMessage("Create a file and write some code");

for await (const message of client.receiveMessages()) {
  if (message.type === "permission_request") {
    console.log(`Tool permission request: ${message.toolCall.title}`);
    console.log(`Request ID: ${message.requestId}`);
    
    // Display available options
    console.log("Available options:");
    message.options.forEach(option => {
      console.log(`- ${option.optionId}`);
    });
    
    // Based on user input, either approve or cancel
    const userChoice = "proceed_once"; // or based on user input
    
    if (userChoice === "cancel") {
      await client.cancelToolConfirmation(message.requestId);
      console.log("Permission request cancelled");
    } else {
      await client.respondToToolConfirmation(message.requestId, userChoice);
      console.log(`Permission approved with option: ${userChoice}`);
    }
  } else if (message.type === "task_finish") {
    break;
  }
}

await client.disconnect();
```

### Configuration Management

Manage session configuration for models and modes:

```ts
import { IFlowClient } from "@iflow-ai/iflow-cli-sdk";

const client = new IFlowClient();
await client.connect();

// Get available models and modes
const models = await client.config.get("models");
const modes = await client.config.get("modes");

console.log("Available models:", models);
console.log("Available modes:", modes);

// Get current configuration
const currentModel = await client.config.get("model");
const currentMode = await client.config.get("mode");

console.log("Current model:", currentModel);
console.log("Current mode:", currentMode);

// Set new configuration
await client.config.set("model", "glm-4.7");
await client.config.set("mode", "plan");

console.log("Switched to glm-4.7 model and plan mode");

await client.disconnect();
```

### Complete Configuration Example

```ts
import { IFlowClient } from "@iflow-ai/iflow-cli-sdk";

async function configExample() {
  const client = new IFlowClient();
  
  try {
    await client.connect();
    
    // Get all available configuration
    const models = await client.config.get("models");
    const modes = await client.config.get("modes");
    const commands = await client.config.get("commands");
    const agents = await client.config.get("agents");
    const skills = await client.config.get("skills");
    const mcpServers = await client.config.get("mcpServers");
    
    console.log("=== Configuration Information ===");
    console.log("Available models:", models);
    console.log("Available modes:", modes);
    console.log("Available commands:", commands);
    console.log("Available agents:", agents);
    console.log("Available skills:", skills);
    console.log("Available MCP servers:", mcpServers);
    
    // Save original configuration
    const originalModel = await client.config.get("model");
    const originalMode = await client.config.get("mode");
    
    // Temporarily switch configuration
    await client.config.set("model", "glm-4.7");
    await client.config.set("mode", "plan");
    
    console.log("Switched to glm-4.7 model and plan mode");
    
    // Restore original configuration
    await client.config.set("model", originalModel);
    await client.config.set("mode", originalMode);
    
    console.log("Restored original configuration");
    
  } finally {
    await client.disconnect();
  }
}

configExample().catch(console.error);
```

## API Reference

详细的 API 文档请查看 [API_REFERENCE.md](API_REFERENCE.md)

### 核心类

- **`IFlowClient`** - 主要客户端类
- **`query()`** / **`queryStream()`** - 便捷查询函数

### 主要消息类型

- `AssistantMessage` - AI 响应
- `ToolCallMessage` - 工具调用
- `TaskFinishMessage` - 任务完成
- `AskUserQuestionsMessage` - 用户问题
- `ExitPlanModeMessage` - 计划审批
- `PermissionRequestMessage` - 权限请求
- `ErrorMessage` - 错误消息

## Project Structure

```
src/
├── internals/
│   ├── FileHandler.ts        # File access
│   ├── ProcessManager.ts     # iFlow process management
│   ├── Protocol.ts           # ACP protocol handler
│   └── Transport.ts          # WebSocket transport layer
├── types/
│   ├── acp.ts                # ACP data types
│   ├── messages.ts           # Message types
│   └── options.ts            # iFlow options
├── utils/
│   ├── logger.ts             # Logs util
│   └── parseAgentId.ts       # Parse agent id
├── IFlowClient.ts            # Main IFlowClient implementation
├── RawDataClient.ts          # Raw protocol access
├── query.ts                  # Simple query functions
└── index.ts                  # Main entry
```

## Development

### Build dev package
```bash
npm run dev
```

### Running Tests

```bash
npm test
```

> 💡 **Testing Tool**: See [`mock-server/`](./mock-server/) directory for the ACP Mock Server, useful for testing and development without a real CLI.

### Code Quality

```bash
# Lint code
npm run lint

# Format code
npm run format
```

## Protocol Support

本 SDK 完整实现了 Agent Communication Protocol (ACP) v1，支持：

- 会话管理和消息流式传输
- 工具调用和权限控制
- 用户交互（提问和计划审批）
- 完整的错误处理

## Contributing

Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

---

Built with ❤️ for the AI development community