@lcap/wave-sandbox-sdk
v0.0.1
Published
SDK for Wave Sandbox Client
Downloads
132
Maintainers
Keywords
Readme
Wave Sandbox SDK
浏览器端的 Wave Sandbox SDK,用于与 Wave Sandbox Server 进行通信,提供文件系统操作、命令执行、端口监听和项目管理等功能。
安装
npm install wave-sandbox-sdk
# 或
pnpm add wave-sandbox-sdk
# 或
yarn add wave-sandbox-sdk快速开始
import { WaveSandboxClient } from 'wave-sandbox-sdk';
// 创建客户端实例
const client = new WaveSandboxClient({
url: 'http://localhost:3030',
projectId: 'optional-project-id', // 可选,用于工作空间模式
options: {
autoConnect: true,
reconnection: true,
reconnectionDelay: 1000,
reconnectionAttempts: 5,
},
});
// 监听连接事件
client.onConnect(() => {
console.log('已连接到服务器');
});
// 使用各个模块...API 文档
WaveSandboxClient
主客户端类,提供与服务器的连接和各个功能模块。
构造函数
new WaveSandboxClient(options: SDKOptions)参数:
options.url(string): 服务器地址,例如'http://localhost:3030'options.projectId(string, 可选): 项目 ID,用于工作空间模式options.options(object, 可选): Socket.IO 连接选项autoConnect(boolean): 是否自动连接,默认truereconnection(boolean): 是否自动重连,默认truereconnectionDelay(number): 重连延迟(毫秒),默认1000reconnectionAttempts(number): 最大重连次数,默认5
方法
connect(): 手动连接到服务器disconnect(): 断开连接onConnect(callback): 监听连接事件,返回取消监听的函数onDisconnect(callback): 监听断开连接事件,返回取消监听的函数onError(callback): 监听错误事件,返回取消监听的函数
属性
connected(boolean): 是否已连接id(string | undefined): Socket IDexec: 命令执行模块fileSystem/fs: 文件系统模块(fs是fileSystem的简写别名)port: 端口监听模块project: 项目模块agent: Agent 模块
命令执行模块 (ExecModule)
执行命令并监听输出。
方法
exec(sessionId: string, command: string): Promise<number>
执行命令。
参数:
sessionId: 会话 ID,用于标识命令执行会话command: 要执行的命令
返回: Promise 命令退出码
示例:
const exitCode = await client.exec.exec('session-1', 'ls -la');
console.log('退出码:', exitCode);abort(sessionId: string): Promise<void>
中止命令执行。
参数:
sessionId: 会话 ID
示例:
await client.exec.abort('session-1');onOutput(sessionId: string, callback: (data: Uint8Array) => void): () => void
监听命令输出。
参数:
sessionId: 会话 IDcallback: 输出回调函数,接收 Uint8Array 数据
返回: 取消监听的函数
示例:
const unsubscribe = client.exec.onOutput('session-1', (data) => {
const text = new TextDecoder().decode(data);
console.log('输出:', text);
});
// 取消监听
unsubscribe();完整示例:
const sessionId = 'my-session';
// 监听输出
const unsubscribe = client.exec.onOutput(sessionId, (data) => {
const text = new TextDecoder().decode(data);
process.stdout.write(text);
});
try {
// 执行命令
const exitCode = await client.exec.exec(sessionId, 'npm install');
console.log(`命令执行完成,退出码: ${exitCode}`);
} catch (error) {
console.error('执行失败:', error);
} finally {
unsubscribe();
}文件系统模块 (FileSystemModule)
提供文件系统操作功能。
方法
stat(filePath: string): Promise<FileStat>
获取文件状态信息。
参数:
filePath: 文件路径
返回: Promise 文件状态信息
示例:
const stat = await client.fs.stat('package.json');
console.log('文件类型:', stat.type);
console.log('文件大小:', stat.size);
console.log('修改时间:', new Date(stat.mtime));readFile(filePath: string): Promise<string>
读取文件内容(文本形式)。
参数:
filePath: 文件路径
返回: Promise 文件文本内容
示例:
const content = await client.fs.readFile('package.json');
console.log(content);read(filePath: string, asText?: boolean): Promise<string | Blob>
读取文件。
参数:
filePath: 文件路径asText: 是否以文本形式读取,默认false(返回 Blob)
返回: Promise<string | Blob> 文件内容
示例:
// 读取文本文件
const text = await client.fs.read('readme.md', true);
// 读取二进制文件
const blob = await client.fs.read('image.png');
const url = URL.createObjectURL(blob);readdir(filePath: string): Promise<DirectoryItem[]>
读取目录内容。
参数:
filePath: 目录路径
返回: Promise<DirectoryItem[]> 目录项数组,每个项为 [文件名, 文件类型]
示例:
const items = await client.fs.readdir('.');
items.forEach(([name, type]) => {
console.log(`${name} - 类型: ${type}`);
});writeFile(filePath: string, data: string | Blob | ArrayBuffer | Uint8Array, chunkSize?: number): Promise<void>
写入文件(流式)。
参数:
filePath: 文件路径data: 文件数据(可以是字符串、Blob、ArrayBuffer 或 Uint8Array)chunkSize: 分块大小(字节),默认 64KB
示例:
// 写入文本
await client.fs.writeFile('test.txt', 'Hello World');
// 写入二进制数据
const buffer = new Uint8Array([1, 2, 3, 4, 5]);
await client.fs.writeFile('data.bin', buffer);
// 写入 Blob
const blob = new Blob(['content'], { type: 'text/plain' });
await client.fs.writeFile('file.txt', blob);mkdir(filePath: string): Promise<string | undefined>
创建目录。
参数:
filePath: 目录路径
示例:
await client.fs.mkdir('new-folder');rename(oldPath: string, newPath: string): Promise<void>
重命名文件或目录。
参数:
oldPath: 原路径newPath: 新路径
示例:
await client.fs.rename('old.txt', 'new.txt');rm(filePath: string): Promise<void>
删除文件或目录。
参数:
filePath: 文件或目录路径
示例:
await client.fs.rm('file.txt');
await client.fs.rm('directory');watch(paths: string[], ignored: string[], callback: (event: FileChangeEvent) => void): () => void
监听文件变化。
参数:
paths: 要监听的文件路径数组ignored: 要忽略的文件路径数组callback: 文件变化回调函数
返回: 取消监听的函数
示例:
const unsubscribe = client.fs.watch(
['.'],
['node_modules', '.git'],
(event) => {
console.log(`文件 ${event.type}: ${event.path}`);
}
);
// 取消监听
unsubscribe();端口监听模块 (PortModule)
监听端口状态变化。
方法
getPorts(count?: number): Promise<number[]>
获取可用端口。
参数:
count: 需要获取的端口数量,默认2
返回: Promise<number[]> 可用端口数组
示例:
const ports = await client.port.getPorts(3);
console.log('可用端口:', ports); // [6606, 6607, 6608]startWatch(ports: number[]): Promise<void>
开始监听端口状态。
参数:
ports: 要监听的端口数组
示例:
await client.port.startWatch([3000, 3001]);stopWatch(): Promise<void>
停止监听端口状态。
示例:
await client.port.stopWatch();onStatusChanged(callback: (event: PortStatusChangedEvent) => void): () => void
监听端口状态变化。
参数:
callback: 端口状态变化回调函数
返回: 取消监听的函数
示例:
const unsubscribe = client.port.onStatusChanged((event) => {
console.log(`端口 ${event.port} 状态: ${event.type}`);
});
// 取消监听
unsubscribe();完整示例:
// 获取可用端口
const ports = await client.port.getPorts(2);
// 监听端口状态变化
const unsubscribe = client.port.onStatusChanged((event) => {
if (event.type === 'open') {
console.log(`端口 ${event.port} 已打开`);
} else {
console.log(`端口 ${event.port} 已关闭`);
}
});
// 开始监听
await client.port.startWatch(ports);
// 停止监听
await client.port.stopWatch();
unsubscribe();项目模块 (ProjectModule)
管理项目信息和文件。
方法
getInfo(): Promise<ProjectInfo>
获取项目信息。
返回: Promise 项目信息
示例:
const info = await client.project.getInfo();
console.log('项目 ID:', info.projectId);
console.log('工作目录:', info.workdir);
console.log('工作空间模式:', info.workspace);getFiles(): Promise<ProjectFile[]>
获取项目文件列表。
返回: Promise<ProjectFile[]> 项目文件数组
示例:
const files = await client.project.getFiles();
files.forEach((file) => {
console.log('文件:', file.path);
});watch(): Promise<void>
开始监听项目变化。
示例:
await client.project.watch();unwatch(): Promise<void>
停止监听项目变化。
示例:
await client.project.unwatch();onFileChange(callback: (event: unknown) => void): () => void
监听项目文件变化。
参数:
callback: 文件变化回调函数
返回: 取消监听的函数
示例:
const unsubscribe = client.project.onFileChange((event) => {
console.log('项目文件变化:', event);
});
// 取消监听
unsubscribe();Agent 模块 (AgentModule)
与 AI Agent 进行交互,发送消息并监听 Agent 的各种事件。
方法
sendMessage(options: SendMessageOptions): Promise<string>
发送消息给 Agent。
参数:
options.id: 消息 IDoptions.sessionId: 会话 IDoptions.message: 消息内容options.attachments: 附件数组(可选)
返回: Promise 返回 assistantMessageId
示例:
const assistantMessageId = await client.agent.sendMessage({
id: 'msg-1',
sessionId: 'session-1',
message: 'Hello, agent!',
attachments: [
{
path: './file.txt',
mimeType: 'text/plain',
},
],
});
console.log('Assistant Message ID:', assistantMessageId);abortMessage(messageId: string): Promise<void>
中止消息处理。
参数:
messageId: 要中止的消息 ID
示例:
await client.agent.abortMessage('msg-1');removeSession(sessionId: string): Promise<void>
删除 session,包括日志记录和 agent 对象。如果当前正在处理该 session 的消息,则抛出错误。
参数:
sessionId: 要删除的会话 ID
抛出:
- 如果当前正在处理该 session 的消息,则抛出错误
示例:
try {
await client.agent.removeSession('session-1');
console.log('Session 已删除');
} catch (error) {
console.error('删除失败:', error.message);
// 如果当前正在处理该 session 的消息,会抛出错误
}事件监听
onMessageSend(callback: (event: MessageSendEvent) => void): () => void
监听消息发送事件。
示例:
const unsubscribe = client.agent.onMessageSend((event) => {
console.log('消息已发送:', event.assistantMessageId);
});onMessageRunning(callback: (event: MessageRunningEvent) => void): () => void
监听消息运行事件。
示例:
const unsubscribe = client.agent.onMessageRunning((event) => {
console.log('消息运行中:', event.assistantMessageId);
});onMessageFinished(callback: (event: MessageFinishedEvent) => void): () => void
监听消息完成事件。
示例:
const unsubscribe = client.agent.onMessageFinished((event) => {
console.log('消息完成:', event.status);
});onMessageQueueChanged(callback: (event: MessageQueueChangedEvent) => void): () => void
监听消息队列变化事件。
示例:
const unsubscribe = client.agent.onMessageQueueChanged((event) => {
console.log('队列长度:', event.queue.length);
console.log('当前消息:', event.current);
});onInitializing(callback: (event: InitializingEvent) => void): () => void
监听 Agent 初始化事件。
示例:
const unsubscribe = client.agent.onInitializing((event) => {
console.log('Agent 初始化中:', event.sessionId);
});onInitialized(callback: (event: InitializedEvent) => void): () => void
监听 Agent 初始化完成事件。
示例:
const unsubscribe = client.agent.onInitialized((event) => {
console.log('Agent 初始化完成:', event.sessionId);
});onMessageBlockAdded(callback: (event: MessageBlockAddedEvent) => void): () => void
监听消息块添加事件。
示例:
const unsubscribe = client.agent.onMessageBlockAdded((event) => {
event.data.blocks.forEach((block) => {
console.log('添加块:', block.type);
});
});onMessageBlockUpdated(callback: (event: MessageBlockUpdatedEvent) => void): () => void
监听消息块更新事件(用于流式内容更新)。
示例:
const unsubscribe = client.agent.onMessageBlockUpdated((event) => {
console.log('消息块更新:', event.data.type, event.data.content);
});onMessageToolBlockUpdated(callback: (event: MessageToolBlockUpdatedEvent) => void): () => void
监听工具块更新事件。
示例:
const unsubscribe = client.agent.onMessageToolBlockUpdated((event) => {
console.log('工具块更新:', event.data.name, event.data.stage);
});onMessageSubagentBlockStatusUpdated(callback: (event: MessageSubagentBlockStatusUpdatedEvent) => void): () => void
监听子代理块状态更新事件。
示例:
const unsubscribe = client.agent.onMessageSubagentBlockStatusUpdated((event) => {
console.log('子代理状态更新:', event.data.status);
});onMessageSubagentBlockContentUpdated(callback: (event: MessageSubagentBlockContentUpdatedEvent) => void): () => void
监听子代理块内容更新事件。
示例:
const unsubscribe = client.agent.onMessageSubagentBlockContentUpdated((event) => {
console.log('子代理内容更新:', event.data.content);
});onMessageErrorBlockAdded(callback: (event: MessageErrorBlockAddedEvent) => void): () => void
监听错误块添加事件。
示例:
const unsubscribe = client.agent.onMessageErrorBlockAdded((event) => {
console.error('错误:', event.data.error);
});onMessageCommandOutputMessageAdded(callback: (event: MessageCommandOutputMessageAddedEvent) => void): () => void
监听命令输出消息添加事件。
示例:
const unsubscribe = client.agent.onMessageCommandOutputMessageAdded((event) => {
console.log('命令输出开始:', event.data.command);
});onMessageCommandOutputMessageUpdated(callback: (event: MessageCommandOutputMessageUpdatedEvent) => void): () => void
监听命令输出消息更新事件。
示例:
const unsubscribe = client.agent.onMessageCommandOutputMessageUpdated((event) => {
console.log('命令输出更新:', event.data.command, event.data.output);
});onMessageCommandOutputMessageCompleted(callback: (event: MessageCommandOutputMessageCompletedEvent) => void): () => void
监听命令输出消息完成事件。
示例:
const unsubscribe = client.agent.onMessageCommandOutputMessageCompleted((event) => {
console.log('命令完成:', event.data.command, '退出码:', event.data.exitCode);
});onMcpServersChange(callback: (event: McpServersChangeEvent) => void): () => void
监听 MCP 服务器变化事件。
示例:
const unsubscribe = client.agent.onMcpServersChange((event) => {
console.log('MCP 服务器变化:', event.servers);
});onDocumentParseStart(callback: (event: DocumentParseStartEvent) => void): () => void
监听文档解析开始事件。
示例:
const unsubscribe = client.agent.onDocumentParseStart((event) => {
console.log('文档解析开始:', event.url, event.mimeType);
});onDocumentParseComplete(callback: (event: DocumentParseCompleteEvent) => void): () => void
监听文档解析完成事件。
示例:
const unsubscribe = client.agent.onDocumentParseComplete((event) => {
console.log('文档解析完成:', event.outputPath, `共 ${event.pageCount} 页`);
});onDocumentParseError(callback: (event: DocumentParseErrorEvent) => void): () => void
监听文档解析错误事件。
示例:
const unsubscribe = client.agent.onDocumentParseError((event) => {
console.error('文档解析失败:', event.error);
});on<T = unknown>(eventName: string, callback: (event: T) => void): () => void
通用事件监听方法,用于监听自定义事件。事件名称必须以 'agent:' 开头。支持泛型参数指定事件数据类型。
示例:
// 监听自定义事件,使用泛型指定事件类型
interface CustomEventData {
data: string;
timestamp: number;
}
const unsubscribe = client.agent.on<CustomEventData>('agent:custom-event', (event) => {
console.log('自定义事件:', event.data);
console.log('时间戳:', event.timestamp);
// event 的类型自动推断为 CustomEventData,无需类型断言
});
// 监听其他自定义事件,使用泛型
const unsubscribe2 = client.agent.on<{ message: string }>('agent:another-custom-event', (event) => {
console.log('消息:', event.message);
});
// 不指定泛型时,event 类型为 unknown
const unsubscribe3 = client.agent.on('agent:unknown-event', (event) => {
// event 类型为 unknown,需要类型断言
const typedEvent = event as { value: number };
console.log('值:', typedEvent.value);
});完整示例:
const sessionId = 'my-session';
// 监听消息完成事件
const unsubscribeFinished = client.agent.onMessageFinished((event) => {
console.log('消息处理完成:', event.status);
});
// 监听消息块添加事件
const unsubscribeBlockAdded = client.agent.onMessageBlockAdded((event) => {
event.data.blocks.forEach((block) => {
if (block.type === 'text') {
console.log('文本块:', block.content);
} else if (block.type === 'tool') {
console.log('工具块:', block.name);
}
});
});
try {
// 发送消息
const assistantMessageId = await client.agent.sendMessage({
id: 'msg-1',
sessionId,
message: '请帮我创建一个文件',
});
console.log('消息已发送,等待处理...');
} catch (error) {
console.error('发送失败:', error);
} finally {
// 取消监听
unsubscribeFinished();
unsubscribeBlockAdded();
}类型定义
FileStat
interface FileStat {
type: FileType; // 文件类型
size: number; // 文件大小(字节)
ctime: number; // 创建时间(毫秒时间戳)
mtime: number; // 修改时间(毫秒时间戳)
}FileType
enum FileType {
Unknown = 0,
File = 1,
Directory = 2,
SymbolicLink = 64,
}FileChangeEvent
interface FileChangeEvent {
type: 'add' | 'change' | 'unlink' | 'addDir' | 'unlinkDir';
path: string;
}PortStatusChangedEvent
interface PortStatusChangedEvent {
port: number;
type: 'open' | 'close';
}ProjectInfo
interface ProjectInfo {
projectId: string;
workdir: string;
workspace: boolean;
}SendMessageOptions
interface SendMessageOptions {
id: string;
sessionId: string;
message: string;
attachments?: Attachment[];
}Attachment
interface Attachment {
url?: string;
path?: string;
mimeType: string;
content?: string;
}MessageSendEvent
interface MessageSendEvent {
sessionId: string;
assistantMessageId: string;
senderMessageId: string;
options: SendMessageOptions;
}MessageRunningEvent
interface MessageRunningEvent {
sessionId: string;
assistantMessageId: string;
senderMessageId: string;
}MessageFinishedEvent
interface MessageFinishedEvent {
sessionId: string;
assistantMessageId?: string;
senderMessageId: string;
status: 'pending' | 'running' | 'finished' | 'error' | 'aborted';
}MessageQueueChangedEvent
interface MessageQueueChangedEvent {
queue: ProcessQueueItem[];
current: {
sessionId: string;
assistantMessageId?: string;
senderMessageId: string;
};
}MessageBlockAddedEvent
interface MessageBlockAddedEvent {
sessionId: string;
assistantMessageId?: string;
senderMessageId: string;
data: {
blocks: Array<TextBlock | ToolBlock | ErrorBlock | SubagentBlock>;
};
}MessageBlockUpdatedEvent
interface MessageBlockUpdatedEvent {
sessionId: string;
assistantMessageId?: string;
senderMessageId: string;
data: {
type: 'text';
content: string;
};
}MessageToolBlockUpdatedEvent
interface MessageToolBlockUpdatedEvent {
sessionId: string;
assistantMessageId?: string;
senderMessageId: string;
data: ToolBlock;
}DocumentParseStartEvent
interface DocumentParseStartEvent {
sessionId: string;
senderMessageId: string;
index: number;
url: string;
mimeType: string;
}DocumentParseCompleteEvent
interface DocumentParseCompleteEvent {
sessionId: string;
senderMessageId: string;
index: number;
url: string;
mimeType: string;
outputPath: string;
contentLength?: number;
pageCount?: number;
}DocumentParseErrorEvent
interface DocumentParseErrorEvent {
sessionId: string;
senderMessageId: string;
index: number;
url: string;
mimeType: string;
error: string;
}AgentEventMap
Agent 预定义事件名称到事件数据类型的映射,用于类型定义和类型推断。
type AgentEventMap = {
'agent:message-send': MessageSendEvent;
'agent:message-running': MessageRunningEvent;
'agent:message-finished': MessageFinishedEvent;
'agent:message-queue-changed': MessageQueueChangedEvent;
'agent:initializing': InitializingEvent;
'agent:initialized': InitializedEvent;
'agent:message-block-added': MessageBlockAddedEvent;
'agent:message-block-updated': MessageBlockUpdatedEvent;
'agent:message-tool-block-updated': MessageToolBlockUpdatedEvent;
'agent:message-subagent-block-status-updated': MessageSubagentBlockStatusUpdatedEvent;
'agent:message-subagent-block-content-updated': MessageSubagentBlockContentUpdatedEvent;
'agent:message-error-block-added': MessageErrorBlockAddedEvent;
'agent:message-command-output-message-added': MessageCommandOutputMessageAddedEvent;
'agent:message-command-output-message-updated': MessageCommandOutputMessageUpdatedEvent;
'agent:message-command-output-message-completed': MessageCommandOutputMessageCompletedEvent;
'agent:mcp-servers-change': McpServersChangeEvent;
'agent:document-parse-start': DocumentParseStartEvent;
'agent:document-parse-complete': DocumentParseCompleteEvent;
'agent:document-parse-error': DocumentParseErrorEvent;
};AgentEventName
Agent 预定义事件名称类型,是 AgentEventMap 的键类型。
type AgentEventName = keyof AgentEventMap;完整示例
import { WaveSandboxClient } from 'wave-sandbox-sdk';
async function main() {
// 创建客户端
const client = new WaveSandboxClient({
url: 'http://localhost:3030',
projectId: 'my-project',
});
// 等待连接
await new Promise<void>((resolve) => {
if (client.connected) {
resolve();
} else {
client.onConnect(() => resolve());
}
});
try {
// 读取文件
const content = await client.fs.readFile('package.json');
console.log('文件内容:', content);
// 写入文件
await client.fs.writeFile('test.txt', 'Hello World');
// 执行命令
const sessionId = 'session-1';
client.exec.onOutput(sessionId, (data) => {
console.log(new TextDecoder().decode(data));
});
const exitCode = await client.exec.exec(sessionId, 'ls -la');
console.log('退出码:', exitCode);
// 获取可用端口
const ports = await client.port.getPorts(2);
console.log('可用端口:', ports);
// 监听文件变化
const unsubscribe = client.fs.watch(['.'], ['node_modules'], (event) => {
console.log(`文件 ${event.type}: ${event.path}`);
});
// 使用 Agent 模块
const sessionId = 'my-session';
client.agent.onMessageFinished((event) => {
console.log('Agent 消息完成:', event.status);
});
const assistantMessageId = await client.agent.sendMessage({
id: 'msg-1',
sessionId,
message: 'Hello, agent!',
});
console.log('Assistant Message ID:', assistantMessageId);
// 删除 session(确保没有正在处理的消息)
try {
await client.agent.removeSession(sessionId);
console.log('Session 已删除');
} catch (error) {
console.error('删除失败:', error.message);
}
// 5 秒后取消监听
setTimeout(() => {
unsubscribe();
}, 5000);
} catch (error) {
console.error('错误:', error);
} finally {
// 断开连接
client.disconnect();
}
}
main();License
MIT
