@iflow-ai/iflow-cli-sdk
v0.2.2
Published
TypeScript SDK for iFlow CLI
Readme
iFlow CLI TypeScript SDK
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 -c "$(curl -fsSL https://cloud.iflow.cn/iflow-cli/install.sh)"Windows:
npm install -g @iflow-ai/iflow-cli@latest2. Install the SDK
Install from NPM:
npm install --save @iflow-ai/iflow-cli-sdkQuick Start
The SDK automatically manages the iFlow process - no manual setup required!
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:
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:
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:
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:
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:
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:
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:
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:
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
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
核心类
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 entryDevelopment
Build dev package
npm run devRunning Tests
npm test💡 Testing Tool: See
mock-server/directory for the ACP Mock Server, useful for testing and development without a real CLI.
Code Quality
# Lint code
npm run lint
# Format code
npm run formatProtocol Support
本 SDK 完整实现了 Agent Communication Protocol (ACP) v1,支持:
- 会话管理和消息流式传输
- 工具调用和权限控制
- 用户交互(提问和计划审批)
- 完整的错误处理
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Built with ❤️ for the AI development community
