npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@syllm/brickly-test-host

v0.14.0

Published

Brickly 真宿主测试工件:HostGrpcServer + 控制面(故障注入/请求录制/host→runtime 驱动面),供各端 SDK 契约测试使用

Readme

@syllm/brickly-test-host

Brickly 真宿主测试工件:把生产级 HostGrpcServer(含真 BrickStorageService 内存版)+ 测试控制面打成零依赖单文件 bundle,供各端 SDK 的契约 / conformance 测试使用。

  • 协议:brickly.runtime.v1,版本号与 SDK 发布线对齐(0.11.0 起)
  • 定位:替代各端手写 FakeHost 的"演好人"职责;SDK 单测仍需假宿主做低层故障注入时,可继续用本包的控制面故障注入(SetNextError 语义)

交付物

npm i -D @syllm/brickly-test-host 后得到:

| 文件 | 用途 | |------|------| | dist/host.cjs | 独立宿主进程入口(bin:brickly-test-host),零 npm 依赖,Node ≥18 即可运行 | | dist/index.cjs | Node 库入口:startTestHost(进程内)/ spawnTestHost(子进程) | | dist/sources.lst | bundle 输入文件清单(可追溯打进来的源码) |

跨语言用法(Go / .NET / Python 等)

1. spawn 协议

node node_modules/@syllm/brickly-test-host/dist/host.cjs
# 或安装后:npx brickly-test-host
  • stdout 首行输出就绪 JSON:

    {"dataEndpoint":"127.0.0.1:50051","controlEndpoint":"127.0.0.1:50052","runtimeToHostToken":"..."}
  • 关闭:stdin 结束 或 SIGINT/SIGTERM → 宿主优雅退出

  • dataEndpoint 是 gRPC 数据面;runtimeToHostToken 是 SDK 连接宿主要带的运行时凭据

2. 控制面 HTTP(仅 127.0.0.1)

故障注入与录制(runtime→host 方向)

| 方法 | 路径 | 请求体 | 说明 | |------|------|--------|------| | POST | /faults | {path, brickCode?, action?, ms?, match?, sequence?, count?} | 故障注入(剧本面):命中 path 的下 count 次调用(默认 1)按规则作恶,无副作用(真 handler 不执行) | | POST | /reset | {} | 清空故障规则、调用录制、UI/搜索罐头响应与各自调用记录(不清 storage 数据) | | GET | /calls | — | {"calls":[{"path","at","invocationId"?,"intent"?,"request"?,"frames"}]} 调用录制:invocationId/intent 取自 x-brickly-invocation-id/x-brickly-intent 头;request 为首个入站请求消息体(bytes 字段归一化为 {$bytes:"<base64>"});frames 为入站消息总数(client-streaming 分帧计数用) |

path 为完整 gRPC 方法路径,如 /brickly.runtime.v1.BrickStorageService/KvGet; brickCode 为协议错误码,如 BRICK_STORAGE_NOT_FOUND、LIMIT_EXCEEDED。

/faults 规则形态(三选一):

  • error(旧形态兼容):{path, brickCode, message?, count?}——短路返回该 brick 错误;
  • hang:{path, action:"hang"}——调用永不应答,挂到客户端 deadline;
  • delay:{path, action:"delay", ms}——处理与响应整体推后 ms;
  • sequence:{path, sequence:[{action:"error",brickCode},{action:"delay",ms},{action:"hang"}]}——按调用次序逐条消费,耗尽后放行;
  • match(可叠加于以上任一):{path, match:{...}}——对首个入站请求体做深部分匹配(递归字段子集),命中才消费规则作恶,未命中直接放行且不消耗次数;match+delay 时延迟窗口内的后续消息与 half-close 被缓冲、延迟结束后按原序释放。

驱动面(host→runtime 方向)

| 方法 | 路径 | 请求体 | 响应 | |------|------|--------|------| | POST | /spawn | {brickId, instanceId?, origin?, version?} | 完整 spawn 凭据 {spawnId, bootstrapToken, runtimeToHostToken, hostToRuntimeToken, brickId, instanceId}——铸给第二个 runtime 用(依赖调用等场景) | | POST | /invoke | {spawnId?, commandId, input?, timeoutMs?, invocationId?} | {ok:true,invocationId,result} 或 {ok:false,invocationId,error:{brickCode?,message,grpcStatus?}};缺省 spawnId 用首个 spawn,invocationId 缺省自动生成(驱动 command scope 语义) | | POST | /interact | 同 /invoke | 批量模式:{ok:true,invocationId,events:[...],result} 或 {ok:false,...} | | POST | /interact-script | {spawnId?, commandId?, input?, open?, invocationId?, timeoutMs?, expectTimeoutMs?, steps:[...]} | 裸帧剧本:{ok,state,received};语义违规帧注入(首帧非 open、sequence 跳号、坏 messageId、中途 cancel_request、挂死) | | POST | /events/push | {spawnId?, topic, payload?, delayMs?} | {},经真 HostEventBus 送达该 runtime 的事件订阅流;delayMs 延迟投递 | | POST | /ui-handler | {method, result} | 注册 UI 方法罐头响应;method 限 createBrowserWindow / callWindow / closeWindow / forceCloseWindow / listWindows / sendToChild / replyToChild / emitToChild,未知名返回 400 | | POST | /platform-handler | {method, result} | 注册任意 wire 平台方法罐头(clipboard.readContent/screen.*/input.*/system.*/runtime.invoke 等),重复注册覆盖;$interact 为 PlatformService.Interact 最终结果罐头(runtime.call/interact 意图用),$interact.request 为 request 应答罐头。安装后所有非 ui.window.* 平台调用都走本桩,未注册方法报 宿主未接入 <method> | | GET | /ui-calls | — | {"calls":[{"method","args","at"}]} runtime 真实发起的 UI 调用记录;callWindow 的 args 为 [caller, instanceId, windowId, method, args, parentRequestId] | | POST | /search-handler | {method, result} | 注册 search.* 平台方法罐头响应;method 限 query / activate / runAction,未知名返回 400;与 /platform-handler 共用同一罐头桩(两者装的是同一个 handler) | | GET | /search-calls | — | {"calls":[{"method","input","callerBrickId","at"}]} runtime 真实发起的 search.* 调用记录 | | GET | /runtimes | — | {"runtimes":[{"spawnId","brickId","instanceId"}]} 已注册 runtime 句柄 | | POST | /kernel/dependency | {commands?: string[]} | 接通依赖调用内核:runtime 侧 dependencies.require(alias).start() / handle invoke 经真 ConnectorApplicationService 路由到已注册 runtime;catalog 按 spawn 动态合成——每个 brick 对其他 brick 通配声明 commands:['*'] 依赖,commands 参数声明目标 brick 暴露的命令面 |

典型流程:POST /spawn 拿凭据 → 测试进程按 BRICKLY_HOST_ENDPOINT / BRICKLY_BOOTSTRAP_TOKEN / BRICKLY_RUNTIME_TO_HOST_TOKEN / BRICKLY_HOST_TO_RUNTIME_TOKEN 环境变量起 SDK runtime → POST /invoke 反向调用命令 → POST /ui-handler + GET /ui-calls 验证 UI 调用链。

/interact-script 步进 DSL(host→runtime 裸 ClientFrame 剧本,替代 FakeInteractSession):

  • 顶层 commandId/input 且 open 缺省 true 时,开流自动发 open 帧(open:false 则首帧由剧本自定——首帧违规用例);
  • 步形态:{open:{commandId?,input?}} {event:<js>} {request:<js>,as:"别名"} {cancelRequest:"别名|hex"} {raw:{sequence?,messageId?,replyTo?,open?|event?|request?|cancelRequest?}} {halfClose:true} {cancel:true} {sleepMs:n} {hang:true} {expect:<深部分匹配>} {expectTimeoutMs:n};
  • 出站 sequence 自动从 1 递增,raw 步可显式覆盖构造乱序;request 自动生成 16-byte messageId 并可用 as 记别名;
  • 入站帧归一化为 {kind:'opened'|'event'|'response'|'final', sequence, replyTo?, event?, response?, final?};远端半关闭/流错误入队为 {kind:'end'}/{kind:'error',error} 伪帧;
  • expect 对下一入站帧做深部分匹配(与 /faults match 同规则),失配 → state:'script-error' 并带 failedStep;
  • hang 停止执行剩余步、保持流开,直到远端终止或 timeoutMs 到期(返回 state:'hang');
  • 返回 {ok,state,received,error?,failedStep?}:state ∈ ended|error|cancelled|hang|open|timeout|script-error;received 为全量入站录制(expect 消费不动它)。

示例——验证 runtime 对"首帧非 open"的拒绝:

POST /interact-script
{ "open": false,
  "steps": [ {"event": {"n":1}}, {"expect": {"kind":"error"}} ] }
→ { "ok": true, "state": "error", "received": [{"kind":"error","error":"13 INTERNAL: PROTOCOL_VIOLATION: 首帧必须是 open 且 sequence=1"}] }

依赖场景:先 POST /kernel/dependency 接通内核,再 /spawn 铸第二套凭据起依赖目标 runtime;调用方 runtime 需额外注入 BRICKLY_DEPENDENCY_BINDINGS(JSON:alias → {brickId, origin, version})。命令内 require(alias).start() 得到跟这次 Call 的 ToolHandle,handle.invoke/interact 由内核路由到目标 runtime 通道。

3. 探针参考实现

check/ 目录有 Go / .NET / Python 的最小探针(spawn → 就绪行 → /calls → /reset),可直接照抄到各独立仓库。

Node 用法

import { spawnTestHost } from '@syllm/brickly-test-host'

const host = await spawnTestHost()          // 拉起子进程
const client = new HostBrickStorageClient(host.dataEndpoint, host.runtimeToHostToken)

await host.setFault({ path: '/brickly.runtime.v1.BrickStorageService/KvSet', brickCode: 'LIMIT_EXCEEDED' })
const calls = await host.recordedCalls()
await host.reset()
await host.close()                          // 关 stdin,等退出(超时自动 SIGKILL)

进程内装配(不需要子进程隔离时):startTestHost() 返回 { host, control, endpoint, spawnCredentials, close }。

本地验证

npm run check --workspace @syllm/brickly-test-host
# 或仓库根:npm run test-host:check

执行:构建 bundle → Node 库自检 → Node spawn+gRPC 全链路 → Go/.NET/Python spawn 探针(工具链缺失则跳过该项)。