dsh-lark-bot 0.2.8 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -42,7 +42,7 @@ npm install -g dsh-feishu-bot
42
42
 
43
43
  安装完成后,对应命令分别为 `dsh-lark-bot` 和 `dsh-feishu-bot`。
44
44
 
45
- ### 2. 启动并绑定飞书
45
+ ### 2. 启动后台服务并绑定飞书
46
46
 
47
47
  ```bash
48
48
  dsh-lark-bot start
@@ -54,7 +54,7 @@ dsh-lark-bot start
54
54
  dsh-feishu-bot start
55
55
  ```
56
56
 
57
- 首次启动会:
57
+ `start` 会自动在本机安装一个**后台服务**:加入系统开机自启列表,并在进程退出、崩溃或出错时自动重启。首次启动会:
58
58
 
59
59
  1. 在终端显示二维码。
60
60
  2. 用飞书 / Lark App 扫码。
@@ -62,6 +62,8 @@ dsh-feishu-bot start
62
62
  4. 绑定成功后,bot 会向你的私聊发送欢迎卡片。
63
63
  5. 私聊直接发消息;群聊或话题里 `@bot`。
64
64
 
65
+ 绑定完成后 bot 转入后台运行,终端可以随时关闭。
66
+
65
67
  如果你已经有 PersonalAgent 应用,也可以跳过扫码:
66
68
 
67
69
  ```bash
@@ -71,7 +73,18 @@ dsh-lark-bot start \
71
73
  --tenant feishu
72
74
  ```
73
75
 
74
- ### 3. 基本使用
76
+ ### 3. 服务管理命令
77
+
78
+ | 命令 | 作用 |
79
+ | :--- | :--- |
80
+ | `dsh-lark-bot start` | 安装后台服务、加入开机自启并启动(首次运行会先扫码绑定) |
81
+ | `dsh-lark-bot status` | 查看服务状态(退出码 0=运行中,1=未运行) |
82
+ | `dsh-lark-bot restart` | 重启后台服务(保留开机自启) |
83
+ | `dsh-lark-bot stop` | 停止后台服务并移出开机自启 |
84
+
85
+ 后台服务的运行日志写入 `~/.dsh-lark/profiles/<profile>/logs/bot.log`。
86
+
87
+ ### 4. 基本使用
75
88
 
76
89
  在飞书里向 bot 发送普通消息即可开始工作,常用命令:
77
90
 
@@ -82,18 +95,22 @@ dsh-lark-bot start \
82
95
  | `/ws list` | 查看命名工作空间 |
83
96
  | `/ws save <name>` | 保存当前工作空间 |
84
97
  | `/ws use <name>` | 切换到命名工作空间 |
98
+ | `/ws remove <name>` | 删除命名工作空间 |
85
99
  | `/status` | 查看当前状态 |
86
100
  | `/resume` | 查看当前会话最近上下文 |
87
101
  | `/stop` | 终止当前任务 |
88
- | `/timeout [N|off|default]` | 查看或设置当前会话运行超时 |
89
- | `/invite user|admin|group <id>`、`/invite list`、`/invite remove user|group <id>` | 管理访问白名单 |
102
+ | `/timeout [N\|off\|default]` | 查看或设置当前会话运行超时 |
103
+ | `/density [compact\|standard\|detailed]` | 查看或设置卡片密度 |
104
+ | `/ask <问题>` | 发送问答卡,回答写入会话上下文 |
105
+ | `/invite user\|admin\|group <id>`、`/invite list`、`/invite remove user\|group <id>` | 管理访问白名单 |
90
106
  | `/help` | 查看帮助 |
91
107
 
92
108
  飞书消息中的图片会下载到本地 media 目录并传给 dsh;文本类文件会读取内容并注入任务上下文。
93
109
 
94
- ### 4. 卸载
110
+ ### 5. 卸载
95
111
 
96
112
  ```bash
113
+ dsh-lark-bot stop
97
114
  npm uninstall -g dsh-lark-bot
98
115
  rm -rf ~/.dsh-lark
99
116
  ```
@@ -114,8 +131,8 @@ rm -rf ~/.dsh-lark
114
131
 
115
132
  ## 目标 · Goals
116
133
 
117
- - **一条命令启动**:clone 后一键安装运行,最终发布到 npm,`npx dsh-lark-bot` 即可拉起。
118
- - **飞书原生体验**:流式卡片、交互按钮、图片 / 文件、文档评论,全程双语。
134
+ - **一条命令启动**:clone 后一键安装运行,最终发布到 npm,`npm i -g dsh-lark-bot && dsh-lark-bot start` 即可拉起后台服务。
135
+ - **飞书原生体验**:流式卡片、交互按钮、图片 / 文件,全程双语(文档评论为规划中能力)。
119
136
  - **完整工作区管理**:多项目隔离、git worktree、项目级规则注入、上下文持久化。
120
137
 
121
138
  - **One-command start**: clone and run in one step, eventually published to npm as `npx dsh-lark-bot`.
@@ -124,10 +141,14 @@ rm -rf ~/.dsh-lark
124
141
 
125
142
  ## 兼容性 · Compatibility
126
143
 
127
- - **DeepSeek Harness(`dsh`)**:developer preview(v0.12026-08 发布),通过 ACP / JSON-RPC SDK 接入。
128
- - **运行时**:Node.js 22(桥接层要求 ≥ 20.12,统一采用 ≥ 22)。
144
+ - **DeepSeek Harness(`dsh`)**:已验证 **dsh 0.1.0-rc.6**(2026-08-14:SDK JSON-RPC / ACP runtime 握手 +
145
+ 真实任务流式验证),通过官方 `@deepseek-ai/dsh-sdk-client` / `@deepseek-ai/dsh-acp` 接入;
146
+ 具体锁定版本与漂移策略见 [`docs/adapter-notes.md`](docs/adapter-notes.md)。
147
+ - **运行时**:Node.js ≥ 22.19(见 `package.json` engines)。
129
148
  - **平台**:Linux / macOS / Windows(飞书 WebSocket 出站长连接,免公网服务器 / 域名 / 内网穿透)。
130
- - 当前 adapter 采用 **headless 子进程 fallback**,通过可配置的 `dsh` 命令与参数驱动,尚未锁定具体 dsh mainline commit;接入 ACP / SDK 的正式版本将在 P2 锁版后声明。
149
+ - 默认 adapter 为官方 **`@deepseek-ai/dsh-sdk-client`**(SDK JSON-RPC runtime,原生 session 续跑 +
150
+ token 级流式事件);`DSH_LARK_ADAPTER=acp` 切到官方 **ACP server**(审批卡);`headless` 保留旧版
151
+ 子进程 fallback。首次启动自动在 `~/.dsh/profiles/dsh-lark`(或 `dsh-lark-acp`)创建 runtime profile。
131
152
 
132
153
  ## 配置 · Configuration
133
154
 
@@ -138,7 +159,8 @@ rm -rf ~/.dsh-lark
138
159
 
139
160
  会话运行在 Git 仓库中时,会自动在 `~/.dsh-lark/profiles/<profile>/worktrees/<scope>/` 创建隔离 worktree,并复制项目级 `AGENTS.md`。
140
161
 
141
- 每个飞书 scope 会保存最近 40 条对话消息,下一次消息会作为上下文传入 dsh headless,从而在无状态 headless 子进程上实现会话记忆。
162
+ 每个飞书 scope 会保存最近 40 条对话消息;SDK 模式下 dsh 原生 session 续跑,headless 模式
163
+ 则把历史注入下一次 prompt 实现近似记忆。
142
164
 
143
165
  当前核心环境变量:
144
166
 
@@ -146,10 +168,15 @@ rm -rf ~/.dsh-lark
146
168
  | :--- | :--- | :--- |
147
169
  | `DSH_LARK_HOME` | `~/.dsh-lark` | 本地状态根目录 |
148
170
  | `DSH_LARK_TENANT` | `feishu` | `feishu` 或 `lark` |
171
+ | `DSH_LARK_WORKSPACE` | 未设置 | 新会话默认工作目录 |
149
172
  | `DSH_LARK_DSH_COMMAND` | `自动发现` | dsh 启动命令;通常无需设置 |
150
173
  | `DSH_LARK_DSH_ARGS` | `自动发现` | dsh 启动参数,逗号分隔;通常无需设置 |
174
+ | `DSH_LARK_ADAPTER` | `sdk` | `sdk`(默认)/ `acp`(审批)/ `headless`(legacy) |
151
175
  | `DSH_LARK_PROVIDER` | `deepseek-official` | 模型 provider |
152
176
  | `DSH_LARK_MODEL` | `deepseek-v4-flash` | 默认模型 |
177
+ | `DSH_LARK_MAX_TOKENS` | 未设置 | SDK agent 每请求输出 token 上限 |
178
+ | `DSH_LARK_ACCESS_DEFAULT_DENY` | `false` | 无白名单时拒绝私聊 |
179
+ | `DSH_LARK_EVENT_FRESHNESS_MS` | `600000` | 过期消息拒绝窗口(0 关闭) |
153
180
  | `DSH_LARK_RUN_TIMEOUT_MS` | `300000` | 单次运行墙钟超时 |
154
181
  | `DSH_LARK_STOP_GRACE_MS` | `5000` | SIGTERM 后等待优雅退出再 SIGKILL 的宽限期 |
155
182
 
@@ -162,7 +189,7 @@ rm -rf ~/.dsh-lark
162
189
  - **飞书凭据**:PersonalAgent 应用的 `app_id` / `app_secret`,明文写入本机 `~/.dsh-lark/config.json`(文件权限 600)。
163
190
  - **文件系统**:读取 / 写入你通过 `/cd`、`/ws` 指定的工作目录(含执行 shell 命令、修改文件)。
164
191
  - **网络**:向飞书开放平台建立 WebSocket 出站长连接收发消息;向 DeepSeek API 发送任务上下文。
165
- - **进程**:spawn 本机 `dsh` 子进程执行 agent 任务。
192
+ - **进程**:spawn 本机 `dsh` runtime 子进程(`dsh-sdk-jsonrpc-server` / `dsh-acp` profile)执行 agent 任务。
166
193
 
167
194
  所有数据仅在本机与飞书、DeepSeek 之间流转,不收集、不上传任何遥测。密钥不会提交进仓库(见 `.gitignore`)。
168
195
 
@@ -176,7 +203,8 @@ rm -rf ~/.dsh-lark
176
203
  - **agent 无响应**:发送 `/status` 查看当前 scope、cwd 和 active run;发送 `/stop` 终止当前任务;超过 `DSH_LARK_RUN_TIMEOUT_MS` 时看门狗会自动终止。
177
204
  - **首次扫码失败**:确认本机时间准确、网络可访问飞书开放平台;已拿到 App ID/Secret 时可用 `--app-id` / `--app-secret` 跳过扫码。
178
205
 
179
- 日志当前为 stderr JSON Lines,`~/.dsh-lark/profiles/<profile>/logs/` 为后续文件日志保留目录。
206
+ 以后台服务方式运行时,日志写入 `~/.dsh-lark/profiles/<profile>/logs/bot.log`(JSON Lines,
207
+ stdout 与 stderr 合并);当前进程的 stderr 仍为 JSON Lines。
180
208
 
181
209
  ## 开发 · Development
182
210
 
@@ -205,6 +233,8 @@ pnpm publish:dual
205
233
 
206
234
  - **许可证**:GNU Affero General Public License v3.0(见 `LICENSE`)。
207
235
  - **安全报告**:如发现安全漏洞,请通过 GitHub Security Advisory 私下报告,勿公开 issue。
236
+ - **安全模型**:默认拒绝、密钥脱敏、路径 containment、SSRF 防护、过期事件拒绝与交互工具
237
+ 默认禁用——详见 [`SECURITY.md`](SECURITY.md)。
208
238
 
209
239
  ## 文档 · Documentation
210
240
 
@@ -223,6 +253,7 @@ pnpm publish:dual
223
253
  | [`docs/ECOSYSTEM.md`](docs/ECOSYSTEM.md) | 生态兼容与交付标准(实现工程师必读)<br>Ecosystem & delivery standards (for engineers) |
224
254
  | [`docs/roadmap.md`](docs/roadmap.md) | 路线图与里程碑<br>Roadmap & milestones |
225
255
  | [`docs/PLAN.md`](docs/PLAN.md) | 主线开发计划与验收标准<br>Development plan & acceptance criteria |
256
+ | [`SECURITY.md`](SECURITY.md) | 安全模型与报告渠道<br>Security model & reporting |
226
257
  | [`AGENTS.md`](AGENTS.md) | AI Agent 开发工作流规范<br>AI agent workflow spec |
227
258
 
228
259
  ## 架构 · Architecture
@@ -233,9 +264,9 @@ pnpm publish:dual
233
264
  飞书 / Lark ──WebSocket 长连接──▶ bridge/ ──▶ session/ ──▶ workspace/ ──▶ adapters/ ──▶ dsh ──▶ DeepSeek V4
234
265
  ```
235
266
 
236
- 核心思路:**飞书通道与 agent 后端解耦**。桥接层复刻 `lark-channel-bridge` 的成熟做法(WebSocket 长连接 + 流式卡片 + 会话路由),agent 后端通过 adapter 抽象,默认挂接 DeepSeek Harness(当前 headless fallback,ACP 正式接入规划在 P2),可切换 claude / codex / opencode
267
+ 核心思路:**飞书通道与 agent 后端解耦**。桥接层复刻 `lark-channel-bridge` 的成熟做法(WebSocket 长连接 + 流式卡片 + 会话路由),agent 后端通过 adapter 抽象,默认挂接官方 DeepSeek Harness SDK(`DSH_LARK_ADAPTER=sdk`),可选 ACP 审批模式与 legacy headless
237
268
 
238
- The core idea: **decouple the Feishu channel from the agent backend**. The bridge layer follows the battle-tested `lark-channel-bridge` approach (WebSocket long-connection + streaming cards + session routing); the agent backend is abstracted behind an adapter, defaulting to DeepSeek Harness (currently headless fallback, with ACP planned for P2) and swappable to claude / codex / opencode.
269
+ The core idea: **decouple the Feishu channel from the agent backend**. The bridge layer follows the battle-tested `lark-channel-bridge` approach (WebSocket long-connection + streaming cards + session routing); the agent backend is abstracted behind an adapter, defaulting to the official DeepSeek Harness SDK (`DSH_LARK_ADAPTER=sdk`), with an optional ACP approval mode and the legacy headless fallback.
239
270
 
240
271
  ## 目录结构 · Directory Structure
241
272
 
@@ -245,13 +276,16 @@ The core idea: **decouple the Feishu channel from the agent backend**. The bridg
245
276
  | `src/onboard/` | 首次扫码创建 / 绑定 PersonalAgent 应用<br>First-run QR onboarding |
246
277
  | `src/session/` | 会话路由、排队、访问控制<br>Session routing, queueing, access control |
247
278
  | `src/workspace/` | 项目工作区、git worktree 隔离与规则注入<br>Project workspace, git worktree isolation & rule injection |
248
- | `src/adapters/` | agent 后端适配器(dsh 优先)<br>Agent backend adapters (dsh first) |
279
+ | `src/adapters/` | agent 后端适配器(sdk 默认 / acp 审批 / headless legacy)<br>Agent backend adapters (sdk / acp / headless) |
249
280
  | `src/card/` | 流式卡片状态与渲染<br>Streaming card state & rendering |
250
- | `src/bot/` | 运行注册、消息排队<br>Run registry & message queueing |
281
+ | `src/bot/` | 运行注册、消息排队、审批/问答注册表<br>Run registry, queueing, approval/question registries |
251
282
  | `src/commands/` | 斜杠命令(/cd /ws /new …)<br>Slash commands |
283
+ | `src/cli/` | CLI 入口与 start / status / restart / stop / doctor 命令<br>CLI entry & service commands |
252
284
  | `src/config/` | profile / 配置管理<br>Profile & config |
253
285
  | `src/core/` | 结构化日志<br>Structured logging |
286
+ | `src/media/` | 附件下载与文本注入<br>Attachment download & text injection |
254
287
  | `src/platform/` | 跨平台原子写入<br>Cross-platform atomic writes |
288
+ | `src/service/` | 后台服务管理(systemd / launchd / 计划任务 / 便携 supervisor)<br>Background service management |
255
289
  | `docs/` | 架构、路线图等文档<br>Architecture, roadmap & docs |
256
290
  | `reference/` | 参考研究用的克隆仓库(不提交)<br>Cloned reference repos (not committed) |
257
291
 
package/SECURITY.md ADDED
@@ -0,0 +1,46 @@
1
+ # 安全说明 · Security
2
+
3
+ > dsh-lark-bot 把本机 DeepSeek Harness(`dsh`)暴露给飞书 / Lark IM。本文件说明威胁模型、
4
+ > 默认安全姿态与报告渠道。Security model for a bridge that exposes a local coding agent to Feishu / Lark.
5
+
6
+ ## 威胁模型 · Threat model
7
+
8
+ - **凭据泄露**:飞书 `app_id` / `app_secret`、DeepSeek API key、会话内容可能在日志、卡片或进程环境中出现。
9
+ - **越权访问**:未授权用户 / 群聊驱动本机 coding agent 执行命令、读写文件。
10
+ - **路径逃逸 / 符号链接逃逸**:附件、worktree、`/cd` 相关路径穿越到 bot 状态目录之外。
11
+ - **SSRF**:agent 或桥接层被诱导访问内网 / 环回地址。
12
+ - **消息重放 / 过期事件**:旧消息或重复事件被当作新指令处理。
13
+ - **交互工具不可达**:`ask_user_question`、终端类工具在 IM 场景下无法回达,应默认禁用。
14
+
15
+ ## 安全姿态 · Security posture
16
+
17
+ 1. **默认拒绝**:
18
+ - 群聊 / 话题必须 `@bot` 才响应(传输层强制,`requireMention: true`)。
19
+ - 配置了白名单后,私聊切换为 allowlist 模式(`dmMode: 'allowlist'`)。
20
+ - 可通过 `DSH_LARK_ACCESS_DEFAULT_DENY=1` 在无白名单时也拒绝私聊(默认关闭以兼容首次扫码绑定)。
21
+ 2. **密钥脱敏**:结构化日志按字段名(`secret/token/password/api_key`)脱敏;
22
+ 自由文本日志与卡片文本对 `Bearer …`、`sk-…`、`api_key=…` 做正则脱敏(`src/config/security.ts`)。
23
+ 3. **路径 containment**:媒体下载目标、git worktree 目标必须落在各自根目录内
24
+ (realpath 校验,拒绝符号链接逃逸,`isPathWithin`)。
25
+ 4. **UTF-8 安全截断**:附件文本、卡片摘要按字节截断且不切断多字节字符(`truncateUtf8Safe`)。
26
+ 5. **过期事件拒绝**:消息时间戳超出窗口即拒绝(`isEventFresh`)。
27
+ 6. **SSRF 防护**:仅允许 http(s) 公网地址;环回、私有、链路本地、CGNAT、IPv6 ULA 全部拒绝
28
+ (`isSafeHttpUrl`)。
29
+ 7. **交互工具默认禁用**:SDK / ACP runtime profile 禁用 `user-questions`;
30
+ `DEFAULT_DENIED_INTERACTIVE_TOOLS` 提供工具级黑名单。
31
+ 8. **审批**:ACP 模式下敏感操作通过 `session/request_permission` 以飞书审批卡一问一答;
32
+ run 结束 / dispose 时所有挂起审批卡结算为拒绝(`src/bot/approvals.ts`)。
33
+
34
+ ## 数据与凭据 · Data & credentials
35
+
36
+ - 本地配置 `~/.dsh-lark/config.json` 以 `0600` 权限写入。
37
+ - 飞书凭据明文保存在本机配置文件;日志与卡片不输出真实密钥。
38
+ - 后台服务把 `DEEPSEEK_API_KEY`、`DSH_LARK_*`、`PATH` 等环境快照到
39
+ `~/.dsh-lark/service/service.env`(`0600`);systemd / launchd 单元文件中的 `EnvironmentFile`
40
+ 只引用该文件,不内联密钥。
41
+ - 后台运行日志写入 `~/.dsh-lark/profiles/<profile>/logs/bot.log`(JSON Lines,密钥字段脱敏后输出)。
42
+ - 所有数据仅在本机、飞书开放平台与 DeepSeek API 之间流转;无遥测。
43
+
44
+ ## 报告渠道 · Reporting
45
+
46
+ 发现安全漏洞请通过 GitHub Security Advisory 私下报告,**不要**公开 issue。