@beeos-ai/bma-executor-sdk (英语)
将您的机器(手)或自己的代理(大脑)连接到 BMA —— 执行器、 控制器和代理端 bma.executor 协议.
@beeos-ai/bma-sdk 驱动和使用代理(REST/外观客户端); bma-executor-sdk 将手或大脑连接到BMA.
执行者( E)ExecutorClient),取用(Harness)和BMA的代理端
执行者协议 bma.executor.v1.1 (和 v1),具有相同的三部分和
行为作为 走开 executor 模块。议定书类型是:
从合同中产生(src/generated/executor.ts, (中文(简体) ),
快照和锁定 contracts/bma/executor(三);
运行时间是手写的。 传输: WebSocket, 一个 Unix 域上的 WebSocket
套接字或名为 Windows 的管道(unix://, (中文(简体) ), npipe://),进行中.
| 版本 | 1.0.0 (计数) v1.0.0,参见 变化 |
| 议定书 | bma.executor.v1.1 (合同1.1.0, lock.json(中文(简体) ) |
| 节点.js | 20个或较新的;无害环境管理,取决于 ws 财务报告和审定财务报表 @types/ws (声明的使用) ws 类型) |
| 融合指南 | 文件/执行员 (单位:千美元)页:1(中文(简体) ) |
npm install @beeos-ai/[email protected]
REST / 外观客户端是单独的软件包
@beeos-ai/bma-sdk。 。 。 .
执行器快速启动
import { ExecutorClient } from "@beeos-ai/bma-executor-sdk";
const client = new ExecutorClient({
baseUrl: process.env.BMA_BASE_URL, // required: see below
environmentKey: process.env.BMA_ENVIRONMENT_KEY,
environmentId: process.env.BMA_ENVIRONMENT_ID!,
executor: { name: "my-executor", os: process.platform, arch: process.arch, version: "0.1.0" },
});
client.tools.bash.handle(async (input, { signal, progress }) => { // input: BashInput
progress("running");
const r = await run(input.command, { cwd: input.cwd, env: input.env, signal });
return { stdout: r.stdout, stderr: r.stderr, exitCode: r.code }; // rendered like Go Core
});
client.tools.read.handle(async ({ path, offset, limit }) => readText(path, offset, limit)); // string or content blocks
await client.start();
await client.waitClosed(); // rejects when the client ends for good
设定 baseUrl 到您的 BMA 部署 : 主机服务在早期访问和默认情况下
DEFAULT_BASE_URL (单位:千美元)https://api.bma.beeos.ai)尚未解决。 这是部署
源,与 BMA_BASE_URL 在bma-sdk中(例如 https://api.staging.bma.beeos.ai(三);
客户端张贴环境键 {baseUrl}/v1/executors/token 落下一条线索 /api/v1。SDK不读
BMA_BASE_URL 自己来 A 类 tokenSource 携带自己的频道 URL并忽略 baseUrl。 。 。 .
机器扫描器必须声明 process 或者说 agent
空着 environmentId (一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一作一 拒绝对既未登广告的执行人进行登记 process 也没有 agent 能力: 它回答了 executor.register,然后关闭 4002 "跑步时间注册被拒绝". 壳和档案都是这样的执行者。 声明 process 服务 process.* (或 serveAgent),与 executor.version 作为 MAJOR.MINOR.PATCH数字 :
const client = new ExecutorClient({
baseUrl: process.env.BMA_BASE_URL,
environmentKey: process.env.BMA_MACHINE_TOKEN, // the machine token
environmentId: '', // machine scope
executor: { name: 'my-machine', os: process.platform, arch: process.arch, version: '1.0.0' },
capabilities: { process: { enabled: true } },
})
client.onRequest('process.start', async (params) => { /* start it, answer with the result */ })
// ... onRequest for process.read / write / interrupt / terminate / list as needed
await client.start()
await client.waitReady(30_000) // registered and still open one heartbeat later
SDK将拒绝视为配置错误:在连续三次拒绝注册之后 executor.register (关闭) 4002 "注册时间被拒绝"或 executor.register 错误 capability_unavailable 编号 : invalid_params, (中文(简体) ), waitClosed() 拒绝方式 RegistrationRefusedError; 其他 4002 关闭( 例如“ 守护运行时间结束 ” ) 重新连接 . state 实值 ready 尽快 executor.register 返回,拒绝登记者也这样做; waitReady(timeoutMs?) 只在注册保持一个心跳间隔后解决,并用结束的客户端的错误拒绝.
执行者生命周期、取消和结果
tool.cancel中止处理器signal(对)deadline_ms财务报告和审定财务报表stop()); 客户端回答{"canceled":true}和报告outcome: "canceled"重复tool.callid 确认, 不运行 两次 每个内置工具都有一个打入的插槽client.tools.<name>.handle(fn)(单位:千美元)bash, (中文(简体) ),read, (中文(简体) ),write, (中文(简体) ),edit, (中文(简体) ),glob, (中文(简体) ),grep, (中文(简体) ),list_files; 数据computer_*工具在合同确定输入时获得插槽) 输入是合同的<Tool>Input。输入缺失需要的成员 无法调用( n)bash requires command)在操作者运行之前. A 类 处理器返回字符串、内容块或{ content, isError, artifacts }; 击打可能返回{ stdout, stderr, exitCode, truncated? }, (中文(简体) ), 由Go Core完成(Stout, stderr,exit_code: N,切入到 Core 的 预览超出INLINE_RESULT_BYTES) (中文(简体) ).throw new ToolError(msg)报告 工具级错误( q)is_error: true;任何其他例外是:outcome: "failed"A级tool.call没有处理器的工具被拒绝 {\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}在撞击之前-32012(单位:千美元)data.capability: "tool:<name>"),作为去 科里拒绝.- 这个
shell财务报告和审定财务报表files在操作时启用了能力 组已注册,除非您设定enabled: false(胜利,就像 MCP的音乐RegisteredTool.enabled); 之后注册的处理器start()发送executor.capabilities.update,作为 MCP 服务器发送tools/list_changed。 。 。 . - 打电话
sessionReady工作空间/MCP设置后sessionEnded之后 清净相.tool.result正在重审-32009, (中文(简体) ),-32004或者说data.retryable: true时tool_call_id; 当每次尝试 失败onToolResultLost获得持续的结果,并重放. - 重新连接: 直到
stop()默认的,以指数倒置(1 s base, ×2, 60 s 盖, 焦急),每个拨号一个新鲜的代币和resume(单位:千美元)executor_id, (中文(简体) ),last_connection_id, (中文(简体) ),active_sessions) (中文(简体) ). 只有关闭代码4003和4004和3 连续拒绝注册,是终端。 阳性maxReconnectAttempts限制尝试.await client.waitClosed()解决stop()编号 :executor.close和拒绝 与ChannelClosedError(4003/4004), (中文(简体) ),RegistrationRefusedError, (中文(简体) ),CredentialRejectedError(符号) 端点回答 401/403 关于重接: 吊销或无效证书, 不 (经重新审理)或ReconnectExhaustedError; 在拒绝时退出进程 主管可以重启 . openMcpChannel(sessionId, serverKey)打开原始 MCP 频道 (单位:千美元)?channel=mcp&session_id=&server_key=(三);read()编号 :write()携带 MCP JSON-RPC框架不变.- 一个能扔出
RpcError保持它的密码和数据在电线上.onRequest('process.start', (params) => …)服务process.*(读取)sessionContext(params.process_id)在那里拒绝RpcError.withReason(code, ErrorReason.X, msg); 见 会议背景, (中文(简体) ),terminal.*, (中文(简体) ),skill.install财务报告和审定财务报表workspace.backup与合同 参数和结果类型;call(method, params)财务报告和审定财务报表notify(method, params)发送执行器到harness 方法键入相同 方式( e)MethodParamsMap编号 :MethodResultMap) (中文(简体) ).
快速启动
import { Harness } from "@beeos-ai/bma-executor-sdk";
const harness = new Harness({ authenticate: (request) => verify(request) }); // omit only on loopback
const { url } = await harness.listen(); // or harness.attach(httpServer)
const executor = await harness.waitExecutor();
const session = await executor.assignSession({ session_id: "sess_1" });
await session.ready();
const result = await session.tools.bash.call({ command: "ls" }); // or callTool("bash", { command: "ls" }, { toolCallId })
const mcp = await session.mcp("echo"); // raw MCP JSON-RPC
await session.stop("done");
语义上与去相匹配 Harness数字 : callTool 由 toolCallId· ;
一个未知的呼叫 tool.result 实值 -32002,外国会议 -32007· ;
届会和待处理的电话在内部重新连接 leaseTtlMs; 较新的
连接以4004取代旧的;租赁期满或 executor.close
无法使用 ToolOutcomeUnknownError。 。 。 .
运输
每个传送器上的信息是相同的;谁拨号独立于
协议角色( 执行器总是发送) executor.register (第一编).
| 运输 | 执行器结束 | 调和结束 |
|---|---|---|
| WebSocket(云,执行器拨号) | 默认,或 webSocketDialer(...) | listen(), (中文(简体) ), attach(server), (中文(简体) ), handleUpgrade(...) |
| 本地套接字、 执行器拨号 | webSocketDialer({ ..., tokenSource: staticToken('unix:///path.sock', token) }) | new Harness({ authenticate: bearerAuthenticator(token) }).listenLocal(path) |
| 本地套接字, 拨号( bmad 听) | listenExecutor({ path, token }) → new ExecutorClient({ dialer: listener.dialer }) | harness.dialExecutor(listener.url, { token }) |
| 进行中 | dialer: harness.inProcessDialer() | —— 说 |
本地套接字带有与云( 子protocol) 相同的 WebSocket 协议
通过 Unix 域名套接字谈判、 无记名符号、 关闭代码
(单位:千美元)unix:///path.sock, 0700目录, 0600 套接字)或名为管的 Windows
(单位:千美元)npipe:////./pipe/<name>就像Go和Python SDK一样 每个开始写一个
新鲜的本地标志( n)createLocalToken, 0600);环境密钥从未使用
当地(见 src/local.ts) (中文(简体) ). 当吊带
拨打执行器,也可以拨打会话 MCP 频道(session.mcp) (中文(简体) ).
代理执行器
client.serveAgent(
{
openTurn: async (p) => ({ accepted: true, turn_id: p.turn_id, executor_session_ref: "conv_1", resumed: false, effective: {} }),
runTurn: async (turn, signal) => {
const answer = await turn.requestInteraction({ kind: "permission", tool_use_id: "tu_1", tool_name: "bash" }, signal);
turn.emit({ type: "agent.message", content: [{ type: "text", text: answer.outcome }] });
},
closeSession: async () => {},
},
{ models: [{ id: "my-model" }] },
);
SDK 指定事件 ID 和 顺序, 发送事件顺序
ACKs, 重新连接后重新发送, 和帧每个转动
session.status_running 财务报告和审定财务报表 session.status_idle (单位:千美元)completed, (中文(简体) ), canceled, (中文(简体) ),
failed) (中文(简体) ). 绳子边是 HarnessOptions.agent (单位:千美元)AgentPlatform+) 加上 (中文(简体) )
executor.startTurn / sendTurnInput / cancelTurn / closeAgentSession / respondInteraction; 序列间隙答案 -32013 与
data.expected_sequence。 。 。 .
实例
examples (单位:千美元)npm install 首先:
executor-minimal (云 执行者与出击), harness-loopback (血型)
本地套接字:执行器监听、拨号, agent-minimal (代理人)
执行器和一个过程中的模拟平台).
转到 QQ 类型脚本
前进( G)github.com/beeos-ai/bma-executor-sdk(中文(简体) ) | 类型脚本( T)@beeos-ai/bma-executor-sdk(中文(简体) ) |
|---|---|
NewClient(Options) 编号 : Start 编号 : Stop | new ExecutorClient(options) 编号 : start() 编号 : stop() |
Options.TokenSource, (中文(简体) ), StaticToken | tokenSource, (中文(简体) ), staticToken (或 dialer(中文(简体) ) |
Tools.<Name>.Handle(func(ctx, input, tool)) | tools.<name>.handle(input, { signal, progress }) |
OnSessionAssign 编号 : OnSessionStop 编号 : OnDrain | onSessionAssign 编号 : onSessionStop 编号 : onDrain |
Requests.ProcessStart.Handle(client, fn) 编号 : Calls.X.Call(ctx, client, p) 编号 : Notifications.X.Notify(ctx, client, p) | onRequest('process.start', fn) 编号 : call('x', p) 编号 : notify('x', p) |
SessionReady 编号 : SessionEnded 编号 : ReportToolResult | sessionReady 编号 : sessionEnded 编号 : reportToolResult |
SendSessionStatus 编号 : SendToolProgress 编号 : SendExecutorCapabilitiesUpdate | sessionStatus 编号 : toolProgress 编号 : updateCapabilities |
OpenMCPChannel → MCPChannel | openMcpChannel → FrameChannel |
ServeAgent(AgentHandler, AgentCapability) | serveAgent(handler, capability) |
AgentTurn.Emit/EmitWithID/Delta/Flush/Inputs/RequestInteraction/CancelInteraction | emit/emitWithId/delta/flush/inputs/requestInteraction/cancelInteraction |
NewHarness(HarnessOptions) (单位:千美元)http.Handler(中文(简体) ) | new Harness(options) + 键 listen/listenLocal/attach/handleUpgrade/accept/dialExecutor/inProcessDialer |
Harness.WaitExecutor 编号 : Executors | waitExecutor 编号 : executors |
Executor.AssignSession/Drain/StartTurn/SendTurnInput/CancelTurn/CloseAgentSession/RespondInteraction | HarnessExecutor.assignSession/drain/startTurn/sendTurnInput/cancelTurn/closeAgentSession/respondInteraction |
Session.Ready/CallTool/CancelTool/Stop/MCP/Done/EndReason | HarnessSession.ready/callTool/cancelTool/stop/mcp/done/endReason |
AgentPlatform | AgentPlatform |
*RPCError, (中文(简体) ), ErrNotConnected, (中文(简体) ), ErrClientStopped, (中文(简体) ), ErrSessionEnded, (中文(简体) ), ErrToolOutcomeUnknown, (中文(简体) ), ErrAssignRejected | RpcError, (中文(简体) ), NotConnectedError, (中文(简体) ), ClientStoppedError, (中文(简体) ), SessionEndedError, (中文(简体) ), ToolOutcomeUnknownError, (中文(简体) ), AssignRejectedError |
Core (bash/files/stio MCP) (中文(简体) ) | 未提供 |
StaticToken("unix://…"), (中文(简体) ), ListenUnixSocket + 键 Harness.DialExecutor, (中文(简体) ), InProcessDialer | Harness.listenLocal 编号 : listenExecutor + 键 Harness.dialExecutor 编号 : inProcessDialer (Go中命名为管: ListenNamedPipe, (中文(简体) ), NamedPipeListener; Python 语: serve_npipe(中文(简体) ) |
测试
npm test 运行符合性示例
双端 TS 端 (test/conformance.test.ts),执行者
通过重新连接和租赁,利用所有运输工具
(单位:千美元)test/executor.test.ts),代理能力
(单位:千美元)test/agent.test.ts),并与GO SDK对接
(单位:千美元)test/interop.test.ts: TS执行者 . . . .
代理 QQGO 平台, TS 控制 QQGO 执行器; 需要 GO), 并与该平台交互
在 Unix 套接字上的 WebSocket 上的 Python SDK
(单位:千美元)test/interop-python.test.ts: TS 执行者 {}
Python 牵引装置, Python 执行器 QQ TS 牵引装置; BMA_PYTHON_SDK=<python dir with .venv>跳过Unix套接字
(单位:千美元)test/interop-go-unix.test.ts) (中文(简体) ).