懒人
一个模拟Slack服务器,用于端到端测试Slack bots. 它会说"黑网"
API 和 Socket 模式, 因此是真实的 @slack/bolt 应用程序连接到它不变
(仅限 clientOptions.slackApiUrl 页:1 信息,线程,反应,
文件、模式和辅助线程被存储,以 JSONL 为日记,以及
作为Slack- looking HTML为截图提供.
修建于 间谍群 黑融会. Bun + 类型脚本, 没有运行时间依赖.
安装
bun add -d @desplega.ai/slack-mock # from npm (once published)
bun add -d github:desplega-ai/slack-mock # or straight from the repo (Bun runs the TypeScript sources)
快速启动( 从离职)
bun install
bun run start # slack-mock serve --port 4040
bun run demo # same, seeded with threads, blocks, files, an ephemeral and a DM
用你的机器人指着它:
SLACK_BOT_TOKEN=xoxb-mock-bot-token \
SLACK_APP_TOKEN=xapp-mock-app-token \
SLACK_API_URL=http://127.0.0.1:4040/api/ \
bun src/http.ts # agent-swarm reads SLACK_API_URL into clientOptions.slackApiUrl
以人之相与机器人相会并相会而相会:
curl -X POST http://127.0.0.1:4040/mock/messages -H 'content-type: application/json' \
-d '{"channel":"general","user":"alice","text":"<@U0BOT00000> hello"}'
open http://127.0.0.1:4040/c/general # live view: new messages arrive over SSE and flash (?live=0 turns it off, ?refresh=2 polls instead)
bun src/cli.ts screenshot http://127.0.0.1:4040/c/general --out general.png
用户
使用相机和名称芯片从每个作曲家中选择谁发帖.
浏览器会记住你跨频道和线程的选择.
打开 /c/support?as=taras 选择塔拉斯。 页面删除 as 从选取后的 URL 中.
公共工作空间在介绍者签名后显示芯片.
可选用户状态文本出现在用户表和芯片的用户列表中的名字旁边.
每个消息都提供反应和线程图标,包括没有回复的信息.
线程图标打开线程而无需聚焦作曲家.
图标在手机和触摸屏上保持可见. 桌面显示在悬浮或键盘焦点上 .
从信件旁边的拾取器中选择一个emoji, 或者选择一个已有的反应来添加或去除自己的反应 .
反应使用芯片中的身份,并要求介绍者在公共工作空间中签名.
700px下方,侧边栏会成为带有通道切换器的上行栏.
线索填充了电话宽度. 作曲家遵循可见的取景口,并包括了为iOS家用栏杆所铺垫.
抓取电话布局 bun test test/phone-ui.test.ts (须克来.
PNG 保存给 test/artifacts/phone-support-thread.png 390 x 844 时.
在测试中
import { App } from "@slack/bolt";
import { SlackMock } from "@desplega.ai/slack-mock";
const slack = await SlackMock.start({ port: 0, manifest: "slack-manifest.json" });
const app = new App({
token: slack.env.SLACK_BOT_TOKEN,
appToken: slack.env.SLACK_APP_TOKEN,
socketMode: true,
clientOptions: { slackApiUrl: slack.env.SLACK_API_URL },
});
await app.start();
await slack.waitForConnection();
const ask = await slack.postMessage({ channel: "general", user: "alice", text: `<@${slack.bot.userId}> hi` });
const reply = await slack.waitForMessage({ channel: "general", thread_ts: ask.ts, from: "bot" });
测试能做什么:
| 人类会 | postMessage (文本、线索、文件), editMessage, (中文(简体) ), deleteMessage, (中文(简体) ), addReaction, (中文(简体) ), removeReaction, (中文(简体) ), slashCommand, (中文(简体) ), clickButton, (中文(简体) ), submitView, (中文(简体) ), startAssistantThread, (中文(简体) ), changeAssistantContext, (中文(简体) ), addUser, (中文(简体) ), addChannel, (中文(简体) ), openDm, (中文(简体) ), invite |
|---|---|
| 观察 | messages, (中文(简体) ), thread, (中文(简体) ), ephemeralMessages, (中文(简体) ), findMessages, (中文(简体) ), waitForMessage, (中文(简体) ), apiCalls, (中文(简体) ), waitForApiCall, (中文(简体) ), deliveries (每个信封和它的阿克), assistantThread |
| 断开东西 | injectFault({ method, error, httpStatus, retryAfterSec, extra }), (中文(简体) ), disconnectSockets("refresh_requested")选项 ackTimeoutMs, (中文(简体) ), maxRetries, (中文(简体) ), triggerIdTtlMs, (中文(简体) ), echoBotMessages, (中文(简体) ), subscribedEvents |
HTTP 下也有同样的操作 /mock/* 用于其他用途
进程(见 docs/design.md) (中文(简体) ).
HTTP 模式( 签名请求)
对于使用 Slack 的 HTTP 传输的应用程序, 模拟器可以发送到请求 URL 而不是
把他们推到一个 WebSocket上. 每个请求都携带 X-Slack-Request-Timestamp 还有一个
X-Slack-Signature (单位:千美元)v0= 目标 v0:<timestamp>:<raw body>用签名的秘密制作的
你给它.
slack-mock serve --http-events-url http://127.0.0.1:3013/slack/events --signing-secret "$SLACK_SIGNING_SECRET" \
[--http-interactivity-url URL] [--http-commands-url URL] [--http-retry-delays-ms 1000,5000,30000]
const slack = await SlackMock.start({
httpDelivery: { eventsUrl, signingSecret, interactivityUrl, commandsUrl, retryDelaysMs: [1000, 5000], timeoutMs: 3000 },
});
| 交付 | 请求 |
|---|---|
| 事件 API | JSON 体型 event_callback 有效载荷)。 在非-2xx,超时(timeoutMs,默认 3s)或拒绝连接,与 X-Slack-Retry-Num 财务报告和审定财务报表 X-Slack-Retry-Reason (单位:千美元)http_error, (中文(简体) ), http_timeout, (中文(简体) ), connection_failed),每个之后 retryDelaysMs 条目(默认为1分、5分、30分). |
| 斜线命令 | 窗体编码字段. 贴出一回. 一个JSON反应机体就是负载. |
| 互动 | 带有一个表格 payload 字段。 贴出一回. 一个JSON反应机体就是负载. |
交互和斜线命令 eventsUrl 除非设置了自己的 URL . deliveries() 列表中
请求的尝试和状态. new HttpDelivery(...).verifyUrl() 运行 url_verification
挑战。 套接字模式保留默认值; 与 httpDelivery 设置不需要应用程序连接.
日记中的框架
记录的运行 dataFile 每一次触碰一个事件,可以重放到一个PNG中
线程( 或无线程, 通道): 每条线程之后的视图 message.add, (中文(简体) ),
message.update, (中文(简体) ), message.delete, (中文(简体) ), reaction.add 财务报告和审定财务报表 reaction.remove 线条,在日记中
顺序,加 final-thread.png (最后一帧的副本)和 final-desktop.png (全文)
带线面板的UI,1280x900. 没有服务: 日记在记忆中重放
每页由无头 Chrome 帮助器从临时文件中截取
screenshotA级 file.add 线条没有带消息,所以共享文件首先出现在
共享此信息的信息框.
slack-mock frames --journal run.jsonl --channel C0GENERAL0 --thread 1788518410.672000 --out ./frames
# 5 message.add /abs/frames/01-message.add.png
# 6 reaction.add /abs/frames/02-reaction.add.png
# ...
# final-thread=/abs/frames/final-thread.png
# final-desktop=/abs/frames/final-desktop.png
别管了 --thread 用于频道视图. --manifest app.json (机器人显示名称),
--width, (中文(简体) ), --height 财务报告和审定财务报表 --no-desktop 是可选的。 代码相同 :
import { frames } from "@desplega.ai/slack-mock";
const result = await frames({ journal: "run.jsonl", channel: "general", thread: ask.ts, out: "./frames" });
// result.frames[1] = { index: 6, kind: "reaction.add", path: "/abs/frames/02-reaction.add.png" }
// result.finalThread, result.finalDesktop
如果您想要运动, 将 PNGs 插入 ffmpeg 的 GIF 中; 模拟只产生帧 .
模拟的黑行为
- 套接字模式 :
apps.connections.open, (中文(简体) ),hello,信封用于events_api, (中文(简体) ),slash_commands财务报告和审定财务报表interactive与反应有效载荷相撞, 以retry_attempt当一个信封没有被击中时, 服务器 叮当,disconnect留言,重新连接. - 活动 :
message(渠道、团体、im),app_mention, (中文(简体) ),message_changed, (中文(简体) ),message_deleted, (中文(简体) ),file_share, (中文(简体) ),reaction_added/removed, (中文(简体) ),member_joined_channel, (中文(简体) ),assistant_thread_started, (中文(简体) ),assistant_thread_context_changed。机器人自己的信息被回放 就像Slack那样(鲍尔特的)ignoreSelf放下他们. - Web API: 认证,聊天(后置,更新,删除,ephemeral,permalink, creams,),
markdown_text保持作为消息文本,并作为Markdown,markdown_text_conflict旁边text或者说blocks, (中文(简体) ), 对话(列表、信息、创建、加入、邀请、离开、档案、历史、, 回复, 成员, 打开), 用户( info, list, lookupByEmail), 反应, 文件 (info,上传v2流量,以无记名符号下载),视图(打开,更新, 请按下,助手. 线索(状态,标题,提示),代理. sessions. setstatus, 针头 球杆 球队. - (原始内容存档于2018-09-21) (英语). UI: Block Kit
markdown块会变成Markdown(头,粗体,斜体, 攻击、链接、清单、代码;table财务报告和审定财务报表data_table改为表格 (单位:千美元)column_settings对齐,data_table页: 1page_size,默认5);data_visualization将馅饼、条子、行和区域图变成SVG。 他们 文档限制(行数、单元格、标题、每封信件2个图表、图表标签) 匹配axis_config.categories拒绝invalid_blocks打开chat.postMessage财务报告和审定财务报表chat.update。未知块显示灰色unsupported: <type>框中输入. 错误归来为{ ok: false, error }带有真实代码 (单位:千美元)not_in_channel, (中文(简体) ),already_reacted, (中文(简体) ),message_not_found, (中文(简体) ),name_taken, (中文(简体) ),expired_trigger_id, (中文(简体) ),message_not_in_streaming_state(中文(简体) ). - 斜线命令和交互式
response_urls由模拟器提供 (单位:千美元)ephemeral编号 :in_channel, (中文(简体) ),replace_original, (中文(简体) ),delete_original) (中文(简体) ).
图标
bun test # unit and integration tests (real Bolt client)
bun run test:e2e # boots ../agent-swarm against the mock (AGENT_SWARM_REPO to override; needs agent-swarm PR #1310)
bun run typecheck
bun run lint
bun run build # dist/ (JS for Bun + .d.ts). CI publishes to npm when the version in package.json changes on main
主机演示
https://demo.slack-mock.dev (英语) 运行 scripts/demo-server.ts: 模拟加一个小
演示机器人( e)scripts/demo-bot.ts在一个集装箱内,从Fly.io部署
main 以 .github/workflows/deploy.yml (单位:千美元)fly.toml, (中文(简体) ), Dockerfile) (中文(简体) ). 状态
住在JSONL的日记里, 自己运行它:
docker build -t slack-mock-demo . && docker run -p 8080:8080 -e ADMIN_AUTH=demo:secret slack-mock-demo
PUBLIC_URL, (中文(简体) ), ADMIN_AUTH (原始内容存档于2018-09-30) (UI和 /mock/*, (中文(简体) ), DATA_FILE, (中文(简体) ),
RESET_EVERY_HOURS 财务报告和审定财务报表 MANIFEST 配置它。 {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}这上面有同样的把手
CLI (中文(简体) )--public-url, (中文(简体) ), --auth),并且作为 SlackMockOptions (单位:千美元)publicUrl, (中文(简体) ), adminAuth) (中文(简体) ).
同样的图像也为一个 外部 鲍特,Swarm探员在
https://swarm-demo.slack-mock.dev (英语) (单位:千美元)fly.swarm.toml应用 slack-mock-swarm) (中文(简体) ). 制取键
可能的话,所有读取 scripts/demo-server.ts数字 :
| 信封 | 效果 |
|---|---|
DEMO_BOT=off | 跳过内置的演示机器人;一些其他的Bolt应用在Socket Mode上连接. |
SLACK_MOCK_BOT_TOKEN, (中文(简体) ), SLACK_MOCK_APP_TOKEN | 应用程序必须显示的符号(botToken 编号 : appToken 选项)。 默认是公开的,所以将这些设置在任何共享主机上. |
APP_NAME | 瓶子显示名( T)appName) (中文(简体) ). |
SEED_FILE | JSON 跟着 users, (中文(简体) ), channels, (中文(简体) ), messages 财务报告和审定财务报表 driver.prompts (单位:千美元)scripts/seed.ts; 替换内置 #general 并且当日记没有频道时应用,所以每次重置后工作空间都会回来. seeds/agent-swarm-demo.json 是已运出的实例. |
UI_PUBLIC=true | 保留 / 财务报告和审定财务报表 /c/... 在无证书的情况下可读 ADMIN_AUTH 静门 /mock/* (单位:千美元)publicUi 选项)。 作曲者然后显示一个签入而不是浏览器的基本-自动提示. |
PRESENTER_AUTH | user:password 允许 POST /mock/messages, (中文(简体) ), POST /mock/reactions,以及 GET /mock/presenter (单位:千美元)presenterAuth 选项)。 介绍者可以在没有管理员证明的情况下发布消息并管理反应. 开幕 /c/<channel>#presenter=user:password 显示浏览器 . |
DRIVER_INTERVAL_MINUTES | 每N分钟贴出下一个 driver.prompts 输入为该用户,同时提及bot,同时一个应用程序被连接(scripts/driver.ts) (中文(简体) ). 0 关闭它. |
文档
skills/slack-mock/SKILL.md:如何使用来自另一个 repo(代理人和人类)的包裹.docs/design.md:架构,决定,状态.docs/research/:其背后的研究(特务-swarm出入境) 黑地表、博尔特和套接字模式内部、有效载荷形状、协议 文件和以前的艺术,e2e公约,Block Kit表面).